mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1060609 (Part 2) - Add downscale-during-decode support for the PNG decoder. r=tn,f=glennrp
This commit is contained in:
parent
a48abe736b
commit
f274dd5c30
@ -35,9 +35,8 @@ ImageFactory::Initialize()
|
||||
static bool
|
||||
ShouldDownscaleDuringDecode(const nsCString& aMimeType)
|
||||
{
|
||||
return aMimeType.EqualsLiteral(IMAGE_JPEG) ||
|
||||
aMimeType.EqualsLiteral(IMAGE_JPG) ||
|
||||
aMimeType.EqualsLiteral(IMAGE_PJPEG);
|
||||
DecoderType type = DecoderFactory::GetDecoderType(aMimeType.get());
|
||||
return type == DecoderType::JPEG || type == DecoderType::PNG;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
@ -141,6 +141,20 @@ nsPNGDecoder::~nsPNGDecoder()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPNGDecoder::SetTargetSize(const nsIntSize& aSize)
|
||||
{
|
||||
// Make sure the size is reasonable.
|
||||
if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Create a downscaler that we'll filter our output through.
|
||||
mDownscaler.emplace(aSize);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPNGDecoder::CheckForTransparency(SurfaceFormat aFormat,
|
||||
const IntRect& aFrameRect)
|
||||
@ -174,7 +188,16 @@ nsPNGDecoder::CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
|
||||
format = gfx::SurfaceFormat::B8G8R8A8;
|
||||
}
|
||||
|
||||
nsresult rv = AllocateFrame(mNumFrames, GetSize(), frameRect, format);
|
||||
// Make sure there's no animation or padding if we're downscaling.
|
||||
MOZ_ASSERT_IF(mDownscaler, !GetImageMetadata().HasAnimation());
|
||||
MOZ_ASSERT_IF(mDownscaler,
|
||||
IntRect(IntPoint(), GetSize()).IsEqualEdges(frameRect));
|
||||
|
||||
IntSize targetSize = mDownscaler ? mDownscaler->TargetSize()
|
||||
: GetSize();
|
||||
IntRect targetFrameRect = mDownscaler ? IntRect(IntPoint(), targetSize)
|
||||
: frameRect;
|
||||
nsresult rv = AllocateFrame(mNumFrames, targetSize, targetFrameRect, format);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -198,6 +221,14 @@ nsPNGDecoder::CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mDownscaler) {
|
||||
bool hasAlpha = aFormat != SurfaceFormat::B8G8R8X8;
|
||||
rv = mDownscaler->BeginFrame(frameRect.Size(), mImageData, hasAlpha);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -593,6 +624,12 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
bool isAnimated = png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL);
|
||||
if (isAnimated) {
|
||||
decoder->PostIsAnimated(GetNextFrameDelay(png_ptr, info_ptr));
|
||||
|
||||
if (decoder->mDownscaler && !decoder->IsFirstFrameDecode()) {
|
||||
MOZ_ASSERT_UNREACHABLE("Doing downscale-during-decode "
|
||||
"for an animated image?");
|
||||
decoder->mDownscaler.reset();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -645,6 +682,33 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPNGDecoder::PostPartialInvalidation(const IntRect& aInvalidRegion)
|
||||
{
|
||||
if (!mDownscaler) {
|
||||
PostInvalidation(aInvalidRegion);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mDownscaler->HasInvalidation()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect();
|
||||
PostInvalidation(invalidRect.mOriginalSizeRect,
|
||||
Some(invalidRect.mTargetSizeRect));
|
||||
}
|
||||
|
||||
void
|
||||
nsPNGDecoder::PostFullInvalidation()
|
||||
{
|
||||
PostInvalidation(mFrameRect);
|
||||
|
||||
if (mDownscaler) {
|
||||
mDownscaler->ResetForNextProgressivePass();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
|
||||
png_uint_32 row_num, int pass)
|
||||
@ -688,7 +752,12 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_row) {
|
||||
// If |new_row| is null, that indicates that this is an interlaced image and
|
||||
// |row_callback| is being called for a row that hasn't changed. Ordinarily
|
||||
// we don't need to do anything in this case, but if we're downscaling, the
|
||||
// downscaler doesn't store the rows from previous passes, so we still need to
|
||||
// process the row.
|
||||
if (new_row || decoder->mDownscaler) {
|
||||
int32_t width = decoder->mFrameRect.width;
|
||||
uint32_t iwidth = decoder->mFrameRect.width;
|
||||
|
||||
@ -699,7 +768,9 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
|
||||
}
|
||||
|
||||
uint32_t bpr = width * sizeof(uint32_t);
|
||||
uint32_t* cptr32 = (uint32_t*)(decoder->mImageData + (row_num*bpr));
|
||||
uint32_t* cptr32 = decoder->mDownscaler
|
||||
? reinterpret_cast<uint32_t*>(decoder->mDownscaler->RowBuffer())
|
||||
: reinterpret_cast<uint32_t*>(decoder->mImageData + (row_num*bpr));
|
||||
|
||||
if (decoder->mTransform) {
|
||||
if (decoder->mCMSLine) {
|
||||
@ -763,14 +834,17 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
|
||||
png_longjmp(decoder->mPNG, 1);
|
||||
}
|
||||
|
||||
if (decoder->mDownscaler) {
|
||||
decoder->mDownscaler->CommitRow();
|
||||
}
|
||||
|
||||
if (!decoder->interlacebuf) {
|
||||
// Do line-by-line partial invalidations for non-interlaced images
|
||||
decoder->PostInvalidation(IntRect(0, row_num, width, 1));
|
||||
// Do line-by-line partial invalidations for non-interlaced images.
|
||||
decoder->PostPartialInvalidation(IntRect(0, row_num, width, 1));
|
||||
} else if (row_num ==
|
||||
static_cast<png_uint_32>(decoder->mFrameRect.height - 1)) {
|
||||
// Do only one full image invalidation for each pass (Bug 1187569)
|
||||
decoder->PostInvalidation(IntRect(0, 0, width,
|
||||
decoder->mFrameRect.height));
|
||||
// Do only one full image invalidation for each pass. (Bug 1187569)
|
||||
decoder->PostFullInvalidation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define mozilla_image_decoders_nsPNGDecoder_h
|
||||
|
||||
#include "Decoder.h"
|
||||
#include "Downscaler.h"
|
||||
|
||||
#include "gfxTypes.h"
|
||||
|
||||
@ -26,6 +27,8 @@ class nsPNGDecoder : public Decoder
|
||||
public:
|
||||
virtual ~nsPNGDecoder();
|
||||
|
||||
virtual nsresult SetTargetSize(const nsIntSize& aSize) override;
|
||||
|
||||
virtual void InitInternal() override;
|
||||
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
|
||||
virtual Telemetry::ID SpeedHistogram() override;
|
||||
@ -77,8 +80,12 @@ private:
|
||||
// XXX(seth): nsICODecoder is temporarily an exception to this rule.
|
||||
explicit nsPNGDecoder(RasterImage* aImage);
|
||||
|
||||
void PostPartialInvalidation(const IntRect& aInvalidRegion);
|
||||
void PostFullInvalidation();
|
||||
|
||||
public:
|
||||
png_structp mPNG;
|
||||
Maybe<Downscaler> mDownscaler;
|
||||
png_infop mInfo;
|
||||
nsIntRect mFrameRect;
|
||||
uint8_t* mCMSLine;
|
||||
|
Loading…
Reference in New Issue
Block a user