Bug 1732115 - Part 3. Refactor decoder pipeline to partially use Unoriented/OrientedPixel. r=tnikkel

Rather than change every use of IntSize/Rect/Point in image/, this patch
attempts to draw the line at the relevant parts of the decoding pipeline
to prevent confusion about which size and orientation we are working
with.

Differential Revision: https://phabricator.services.mozilla.com/D126381
This commit is contained in:
Andrew Osmond 2021-10-06 14:41:17 +00:00
parent e2050d4c94
commit 09266efcbc
30 changed files with 294 additions and 307 deletions

View file

@ -266,12 +266,12 @@ void Decoder::CompleteDecode() {
} }
} }
void Decoder::SetOutputSize(const gfx::IntSize& aSize) { void Decoder::SetOutputSize(const OrientedIntSize& aSize) {
mOutputSize = Some(aSize); mOutputSize = Some(aSize);
mHaveExplicitOutputSize = true; mHaveExplicitOutputSize = true;
} }
Maybe<gfx::IntSize> Decoder::ExplicitOutputSize() const { Maybe<OrientedIntSize> Decoder::ExplicitOutputSize() const {
MOZ_ASSERT_IF(mHaveExplicitOutputSize, mOutputSize); MOZ_ASSERT_IF(mHaveExplicitOutputSize, mOutputSize);
return mHaveExplicitOutputSize ? mOutputSize : Nothing(); return mHaveExplicitOutputSize ? mOutputSize : Nothing();
} }
@ -448,10 +448,11 @@ void Decoder::PostSize(int32_t aWidth, int32_t aHeight,
// Set our output size if it's not already set. // Set our output size if it's not already set.
if (!mOutputSize) { if (!mOutputSize) {
mOutputSize = Some(IntSize(aWidth, aHeight)); mOutputSize = Some(mImageMetadata.GetSize());
} }
MOZ_ASSERT(mOutputSize->width <= aWidth && mOutputSize->height <= aHeight, MOZ_ASSERT(mOutputSize->width <= mImageMetadata.GetSize().width &&
mOutputSize->height <= mImageMetadata.GetSize().height,
"Output size will result in upscaling"); "Output size will result in upscaling");
// Record this notification. // Record this notification.
@ -486,7 +487,8 @@ void Decoder::PostFrameStop(Opacity aFrameOpacity) {
// If we're not sending partial invalidations, then we send an invalidation // If we're not sending partial invalidations, then we send an invalidation
// here when the first frame is complete. // here when the first frame is complete.
if (!ShouldSendPartialInvalidations()) { if (!ShouldSendPartialInvalidations()) {
mInvalidRect.UnionRect(mInvalidRect, IntRect(IntPoint(), Size())); mInvalidRect.UnionRect(mInvalidRect,
OrientedIntRect(OrientedIntPoint(), Size()));
} }
// If we dispose of the first frame by clearing it, then the first frame's // If we dispose of the first frame by clearing it, then the first frame's
@ -498,7 +500,7 @@ void Decoder::PostFrameStop(Opacity aFrameOpacity) {
case DisposalMethod::CLEAR: case DisposalMethod::CLEAR:
case DisposalMethod::CLEAR_ALL: case DisposalMethod::CLEAR_ALL:
case DisposalMethod::RESTORE_PREVIOUS: case DisposalMethod::RESTORE_PREVIOUS:
mFirstFrameRefreshArea = IntRect(IntPoint(), Size()); mFirstFrameRefreshArea = IntRect(IntPoint(), Size().ToUnknownSize());
break; break;
case DisposalMethod::KEEP: case DisposalMethod::KEEP:
case DisposalMethod::NOT_SPECIFIED: case DisposalMethod::NOT_SPECIFIED:
@ -512,8 +514,8 @@ void Decoder::PostFrameStop(Opacity aFrameOpacity) {
} }
} }
void Decoder::PostInvalidation(const gfx::IntRect& aRect, void Decoder::PostInvalidation(const OrientedIntRect& aRect,
const Maybe<gfx::IntRect>& aRectAtOutputSize const Maybe<OrientedIntRect>& aRectAtOutputSize
/* = Nothing() */) { /* = Nothing() */) {
// We should be mid-frame // We should be mid-frame
MOZ_ASSERT(mInFrame, "Can't invalidate when not mid-frame!"); MOZ_ASSERT(mInFrame, "Can't invalidate when not mid-frame!");
@ -523,7 +525,8 @@ void Decoder::PostInvalidation(const gfx::IntRect& aRect,
// or we're past the first frame. // or we're past the first frame.
if (ShouldSendPartialInvalidations() && mFrameCount == 1) { if (ShouldSendPartialInvalidations() && mFrameCount == 1) {
mInvalidRect.UnionRect(mInvalidRect, aRect); mInvalidRect.UnionRect(mInvalidRect, aRect);
mCurrentFrame->ImageUpdated(aRectAtOutputSize.valueOr(aRect)); mCurrentFrame->ImageUpdated(
aRectAtOutputSize.valueOr(aRect).ToUnknownRect());
} }
} }

View file

@ -157,8 +157,8 @@ class Decoder {
* TakeInvalidRect() returns only the invalidation region accumulated since * TakeInvalidRect() returns only the invalidation region accumulated since
* the last call to TakeInvalidRect(). * the last call to TakeInvalidRect().
*/ */
nsIntRect TakeInvalidRect() { OrientedIntRect TakeInvalidRect() {
nsIntRect invalidRect = mInvalidRect; OrientedIntRect invalidRect = mInvalidRect;
mInvalidRect.SetEmpty(); mInvalidRect.SetEmpty();
return invalidRect; return invalidRect;
} }
@ -211,7 +211,7 @@ class Decoder {
* *
* This must be called before Init() is called. * This must be called before Init() is called.
*/ */
void SetOutputSize(const gfx::IntSize& aSize); void SetOutputSize(const OrientedIntSize& aSize);
/** /**
* @return the output size of this decoder. If this is smaller than the * @return the output size of this decoder. If this is smaller than the
@ -220,7 +220,7 @@ class Decoder {
* *
* Illegal to call if HasSize() returns false. * Illegal to call if HasSize() returns false.
*/ */
gfx::IntSize OutputSize() const { OrientedIntSize OutputSize() const {
MOZ_ASSERT(HasSize()); MOZ_ASSERT(HasSize());
return *mOutputSize; return *mOutputSize;
} }
@ -229,13 +229,13 @@ class Decoder {
* @return either the size passed to SetOutputSize() or Nothing(), indicating * @return either the size passed to SetOutputSize() or Nothing(), indicating
* that SetOutputSize() was not explicitly called. * that SetOutputSize() was not explicitly called.
*/ */
Maybe<gfx::IntSize> ExplicitOutputSize() const; Maybe<OrientedIntSize> ExplicitOutputSize() const;
/** /**
* Sets the expected image size of this decoder. Decoding will fail if this * Sets the expected image size of this decoder. Decoding will fail if this
* does not match. * does not match.
*/ */
void SetExpectedSize(const gfx::IntSize& aSize) { void SetExpectedSize(const OrientedIntSize& aSize) {
mExpectedSize.emplace(aSize); mExpectedSize.emplace(aSize);
} }
@ -342,7 +342,7 @@ class Decoder {
* *
* Illegal to call if HasSize() returns false. * Illegal to call if HasSize() returns false.
*/ */
gfx::IntSize Size() const { OrientedIntSize Size() const {
MOZ_ASSERT(HasSize()); MOZ_ASSERT(HasSize());
return mImageMetadata.GetSize(); return mImageMetadata.GetSize();
} }
@ -354,8 +354,8 @@ class Decoder {
* *
* Illegal to call if HasSize() returns false. * Illegal to call if HasSize() returns false.
*/ */
gfx::IntRect FullFrame() const { OrientedIntRect FullFrame() const {
return gfx::IntRect(gfx::IntPoint(), Size()); return OrientedIntRect(OrientedIntPoint(), Size());
} }
/** /**
@ -369,8 +369,18 @@ class Decoder {
* *
* Illegal to call if HasSize() returns false. * Illegal to call if HasSize() returns false.
*/ */
gfx::IntRect FullOutputFrame() const { OrientedIntRect FullOutputFrame() const {
return gfx::IntRect(gfx::IntPoint(), OutputSize()); return OrientedIntRect(OrientedIntPoint(), OutputSize());
}
/**
* @return the orientation of the image.
*
* Illegal to call if HasSize() returns false.
*/
Orientation GetOrientation() const {
MOZ_ASSERT(HasSize());
return mImageMetadata.GetOrientation();
} }
/// @return final status information about this decoder. Should be called /// @return final status information about this decoder. Should be called
@ -514,8 +524,8 @@ class Decoder {
* be supplied if we're downscaling during decode. * be supplied if we're downscaling during decode.
*/ */
void PostInvalidation( void PostInvalidation(
const gfx::IntRect& aRect, const OrientedIntRect& aRect,
const Maybe<gfx::IntRect>& aRectAtOutputSize = Nothing()); const Maybe<OrientedIntRect>& aRectAtOutputSize = Nothing());
// Called by the decoders when they have successfully decoded the image. This // Called by the decoders when they have successfully decoded the image. This
// may occur as the result of the decoder getting to the appropriate point in // may occur as the result of the decoder getting to the appropriate point in
@ -586,14 +596,14 @@ class Decoder {
ImageMetadata mImageMetadata; ImageMetadata mImageMetadata;
gfx::IntRect OrientedIntRect
mInvalidRect; // Tracks new rows as the current frame is decoded. mInvalidRect; // Tracks new rows as the current frame is decoded.
gfx::IntRect mRestoreDirtyRect; // Tracks an invalidation region between the gfx::IntRect mRestoreDirtyRect; // Tracks an invalidation region between the
// restore frame and the previous frame. // restore frame and the previous frame.
gfx::IntRect mRecycleRect; // Tracks an invalidation region between the gfx::IntRect mRecycleRect; // Tracks an invalidation region between the
// recycled frame and the current frame. // recycled frame and the current frame.
Maybe<gfx::IntSize> mOutputSize; // The size of our output surface. Maybe<OrientedIntSize> mOutputSize; // The size of our output surface.
Maybe<gfx::IntSize> mExpectedSize; // The expected size of the image. Maybe<OrientedIntSize> mExpectedSize; // The expected size of the image.
Progress mProgress; Progress mProgress;
uint32_t mFrameCount; // Number of frames, including anything in-progress uint32_t mFrameCount; // Number of frames, including anything in-progress

View file

@ -170,7 +170,7 @@ nsresult DecoderFactory::CreateDecoder(
// Initialize the decoder. // Initialize the decoder.
decoder->SetMetadataDecode(false); decoder->SetMetadataDecode(false);
decoder->SetIterator(aSourceBuffer->Iterator()); decoder->SetIterator(aSourceBuffer->Iterator());
decoder->SetOutputSize(aOutputSize); decoder->SetOutputSize(OrientedIntSize::FromUnknownSize(aOutputSize));
decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY); decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY);
decoder->SetSurfaceFlags(aSurfaceFlags); decoder->SetSurfaceFlags(aSurfaceFlags);
@ -320,7 +320,8 @@ already_AddRefed<IDecodingTask> DecoderFactory::CreateMetadataDecoder(
already_AddRefed<Decoder> DecoderFactory::CreateDecoderForICOResource( already_AddRefed<Decoder> DecoderFactory::CreateDecoderForICOResource(
DecoderType aType, SourceBufferIterator&& aIterator, DecoderType aType, SourceBufferIterator&& aIterator,
NotNull<nsICODecoder*> aICODecoder, bool aIsMetadataDecode, NotNull<nsICODecoder*> aICODecoder, bool aIsMetadataDecode,
const Maybe<IntSize>& aExpectedSize, const Maybe<uint32_t>& aDataOffset const Maybe<OrientedIntSize>& aExpectedSize,
const Maybe<uint32_t>& aDataOffset
/* = Nothing() */) { /* = Nothing() */) {
// Create the decoder. // Create the decoder.
RefPtr<Decoder> decoder; RefPtr<Decoder> decoder;
@ -389,7 +390,7 @@ already_AddRefed<Decoder> DecoderFactory::CreateAnonymousDecoder(
// Set an output size for downscale-during-decode if requested. // Set an output size for downscale-during-decode if requested.
if (aOutputSize) { if (aOutputSize) {
decoder->SetOutputSize(*aOutputSize); decoder->SetOutputSize(OrientedIntSize::FromUnknownSize(*aOutputSize));
} }
if (NS_FAILED(decoder->Init())) { if (NS_FAILED(decoder->Init())) {

View file

@ -13,6 +13,7 @@
#include "mozilla/NotNull.h" #include "mozilla/NotNull.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "Orientation.h"
#include "SurfaceFlags.h" #include "SurfaceFlags.h"
namespace mozilla::image { namespace mozilla::image {
@ -154,7 +155,7 @@ class DecoderFactory {
static already_AddRefed<Decoder> CreateDecoderForICOResource( static already_AddRefed<Decoder> CreateDecoderForICOResource(
DecoderType aType, SourceBufferIterator&& aIterator, DecoderType aType, SourceBufferIterator&& aIterator,
NotNull<nsICODecoder*> aICODecoder, bool aIsMetadataDecode, NotNull<nsICODecoder*> aICODecoder, bool aIsMetadataDecode,
const Maybe<gfx::IntSize>& aExpectedSize, const Maybe<OrientedIntSize>& aExpectedSize,
const Maybe<uint32_t>& aDataOffset = Nothing()); const Maybe<uint32_t>& aDataOffset = Nothing());
/** /**

View file

@ -467,7 +467,7 @@ LookupResult FrameAnimator::GetCompositedFrame(AnimationState& aState,
// getting called which calls UpdateState. The reason we care about this // getting called which calls UpdateState. The reason we care about this
// is that img.decode promises won't resolve until GetCompositedFrame // is that img.decode promises won't resolve until GetCompositedFrame
// returns a frame. // returns a frame.
UnorientedIntRect rect = UnorientedIntRect::FromUnknownRect( OrientedIntRect rect = OrientedIntRect::FromUnknownRect(
aState.UpdateStateInternal(result, mSize)); aState.UpdateStateInternal(result, mSize));
if (!rect.IsEmpty()) { if (!rect.IsEmpty()) {

View file

@ -65,8 +65,7 @@ void IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
// calls we make off-main-thread and the notifications that RasterImage // calls we make off-main-thread and the notifications that RasterImage
// actually receives, which would cause bugs. // actually receives, which would cause bugs.
Progress progress = aDecoder->TakeProgress(); Progress progress = aDecoder->TakeProgress();
UnorientedIntRect invalidRect = OrientedIntRect invalidRect = aDecoder->TakeInvalidRect();
UnorientedIntRect::FromUnknownRect(aDecoder->TakeInvalidRect());
Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount(); Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
DecoderFlags decoderFlags = aDecoder->GetDecoderFlags(); DecoderFlags decoderFlags = aDecoder->GetDecoderFlags();
SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags(); SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
@ -106,8 +105,7 @@ void IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
ImageMetadata metadata = aDecoder->GetImageMetadata(); ImageMetadata metadata = aDecoder->GetImageMetadata();
DecoderTelemetry telemetry = aDecoder->Telemetry(); DecoderTelemetry telemetry = aDecoder->Telemetry();
Progress progress = aDecoder->TakeProgress(); Progress progress = aDecoder->TakeProgress();
UnorientedIntRect invalidRect = OrientedIntRect invalidRect = aDecoder->TakeInvalidRect();
UnorientedIntRect::FromUnknownRect(aDecoder->TakeInvalidRect());
Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount(); Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
DecoderFlags decoderFlags = aDecoder->GetDecoderFlags(); DecoderFlags decoderFlags = aDecoder->GetDecoderFlags();
SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags(); SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();

View file

@ -56,21 +56,24 @@ class ImageMetadata {
void SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation, void SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation,
Resolution aResolution) { Resolution aResolution) {
if (!HasSize()) { if (!HasSize()) {
mSize.emplace(nsIntSize(aWidth, aHeight)); mSize.emplace(
aOrientation.ToOriented(UnorientedIntSize(aWidth, aHeight)));
mOrientation.emplace(aOrientation); mOrientation.emplace(aOrientation);
mResolution = aResolution; mResolution = aResolution;
} }
} }
nsIntSize GetSize() const { return *mSize; } OrientedIntSize GetSize() const { return *mSize; }
bool HasSize() const { return mSize.isSome(); } bool HasSize() const { return mSize.isSome(); }
void AddNativeSize(const nsIntSize& aSize) { void AddNativeSize(const OrientedIntSize& aSize) {
mNativeSizes.AppendElement(aSize); mNativeSizes.AppendElement(aSize);
} }
Resolution GetResolution() const { return mResolution; } Resolution GetResolution() const { return mResolution; }
const nsTArray<nsIntSize>& GetNativeSizes() const { return mNativeSizes; } const nsTArray<OrientedIntSize>& GetNativeSizes() const {
return mNativeSizes;
}
Orientation GetOrientation() const { return *mOrientation; } Orientation GetOrientation() const { return *mOrientation; }
bool HasOrientation() const { return mOrientation.isSome(); } bool HasOrientation() const { return mOrientation.isSome(); }
@ -98,11 +101,11 @@ class ImageMetadata {
// loops. // loops.
Maybe<gfx::IntRect> mFirstFrameRefreshArea; Maybe<gfx::IntRect> mFirstFrameRefreshArea;
Maybe<nsIntSize> mSize; Maybe<OrientedIntSize> mSize;
Maybe<Orientation> mOrientation; Maybe<Orientation> mOrientation;
// Sizes the image can natively decode to. // Sizes the image can natively decode to.
CopyableTArray<nsIntSize> mNativeSizes; CopyableTArray<OrientedIntSize> mNativeSizes;
bool mHasAnimation = false; bool mHasAnimation = false;
}; };

View file

@ -165,7 +165,7 @@ RasterImage::RequestRefresh(const TimeStamp& aTime) {
// once for all frames that we've now passed (if AdvanceFrame() was called // once for all frames that we've now passed (if AdvanceFrame() was called
// more than once). // more than once).
if (!res.mDirtyRect.IsEmpty() || res.mFrameAdvanced) { if (!res.mDirtyRect.IsEmpty() || res.mFrameAdvanced) {
auto dirtyRect = UnorientedIntRect::FromUnknownRect(res.mDirtyRect); auto dirtyRect = OrientedIntRect::FromUnknownRect(res.mDirtyRect);
NotifyProgress(NoProgress, dirtyRect); NotifyProgress(NoProgress, dirtyRect);
} }
@ -279,7 +279,7 @@ RasterImage::GetProducerId(uint32_t* aId) {
return NS_OK; return NS_OK;
} }
LookupResult RasterImage::LookupFrameInternal(const UnorientedIntSize& aSize, LookupResult RasterImage::LookupFrameInternal(const OrientedIntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
PlaybackType aPlaybackType, PlaybackType aPlaybackType,
bool aMarkUsed) { bool aMarkUsed) {
@ -311,7 +311,7 @@ LookupResult RasterImage::LookupFrameInternal(const UnorientedIntSize& aSize,
aMarkUsed); aMarkUsed);
} }
LookupResult RasterImage::LookupFrame(const UnorientedIntSize& aSize, LookupResult RasterImage::LookupFrame(const OrientedIntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
PlaybackType aPlaybackType, PlaybackType aPlaybackType,
bool aMarkUsed) { bool aMarkUsed) {
@ -323,8 +323,8 @@ LookupResult RasterImage::LookupFrame(const UnorientedIntSize& aSize,
aFlags &= ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA; aFlags &= ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA;
} }
UnorientedIntSize requestedSize = OrientedIntSize requestedSize =
CanDownscaleDuringDecode(aSize, aFlags) ? aSize : ToUnoriented(mSize); CanDownscaleDuringDecode(aSize, aFlags) ? aSize : mSize;
if (requestedSize.IsEmpty()) { if (requestedSize.IsEmpty()) {
// Can't decode to a surface of zero size. // Can't decode to a surface of zero size.
return LookupResult(MatchType::NOT_FOUND); return LookupResult(MatchType::NOT_FOUND);
@ -356,8 +356,7 @@ LookupResult RasterImage::LookupFrame(const UnorientedIntSize& aSize,
// decode at. This should only happen if we accept substitutions. // decode at. This should only happen if we accept substitutions.
if (!result.SuggestedSize().IsEmpty()) { if (!result.SuggestedSize().IsEmpty()) {
MOZ_ASSERT(!syncDecode && (aFlags & FLAG_HIGH_QUALITY_SCALING)); MOZ_ASSERT(!syncDecode && (aFlags & FLAG_HIGH_QUALITY_SCALING));
requestedSize = requestedSize = OrientedIntSize::FromUnknownSize(result.SuggestedSize());
UnorientedIntSize::FromUnknownSize(result.SuggestedSize());
} }
bool ranSync = false, failed = false; bool ranSync = false, failed = false;
@ -439,10 +438,9 @@ RasterImage::WillDrawOpaqueNow() {
return false; return false;
} }
auto size = ToUnoriented(mSize);
LookupResult result = SurfaceCache::LookupBestMatch( LookupResult result = SurfaceCache::LookupBestMatch(
ImageKey(this), ImageKey(this),
RasterSurfaceKey(size.ToUnknownSize(), DefaultSurfaceFlags(), RasterSurfaceKey(mSize.ToUnknownSize(), DefaultSurfaceFlags(),
PlaybackType::eStatic), PlaybackType::eStatic),
/* aMarkUsed = */ false); /* aMarkUsed = */ false);
MatchType matchType = result.Type(); MatchType matchType = result.Type();
@ -482,10 +480,9 @@ void RasterImage::OnSurfaceDiscardedInternal(bool aAnimatedFramesDiscarded) {
MOZ_ASSERT(StaticPrefs::image_mem_animated_discardable_AtStartup()); MOZ_ASSERT(StaticPrefs::image_mem_animated_discardable_AtStartup());
ReleaseImageContainer(); ReleaseImageContainer();
auto size = ToUnoriented(mSize); IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
IntRect rect = mAnimationState->UpdateState(this, size.ToUnknownSize());
auto dirtyRect = UnorientedIntRect::FromUnknownRect(rect); auto dirtyRect = OrientedIntRect::FromUnknownRect(rect);
NotifyProgress(NoProgress, dirtyRect); NotifyProgress(NoProgress, dirtyRect);
} }
@ -578,9 +575,8 @@ RasterImage::GetFrameInternal(const IntSize& aSize,
// Get the frame. If it's not there, it's probably the caller's fault for // Get the frame. If it's not there, it's probably the caller's fault for
// not waiting for the data to be loaded from the network or not passing // not waiting for the data to be loaded from the network or not passing
// FLAG_SYNC_DECODE. // FLAG_SYNC_DECODE.
LookupResult result = LookupResult result = LookupFrame(size, aFlags, ToPlaybackType(aWhichFrame),
LookupFrame(ToUnoriented(size), aFlags, ToPlaybackType(aWhichFrame), /* aMarkUsed = */ true);
/* aMarkUsed = */ true);
auto resultSuggestedSize = auto resultSuggestedSize =
UnorientedIntSize::FromUnknownSize(result.SuggestedSize()); UnorientedIntSize::FromUnknownSize(result.SuggestedSize());
@ -637,7 +633,7 @@ Tuple<ImgDrawResult, IntSize> RasterImage::GetImageContainerSize(
} }
auto requestedSize = OrientedIntSize::FromUnknownSize(aRequestedSize); auto requestedSize = OrientedIntSize::FromUnknownSize(aRequestedSize);
if (!CanDownscaleDuringDecode(ToUnoriented(requestedSize), aFlags)) { if (!CanDownscaleDuringDecode(requestedSize, aFlags)) {
return MakeTuple(ImgDrawResult::SUCCESS, mSize.ToUnknownSize()); return MakeTuple(ImgDrawResult::SUCCESS, mSize.ToUnknownSize());
} }
@ -688,7 +684,7 @@ bool RasterImage::SetMetadata(const ImageMetadata& aMetadata,
mResolution = aMetadata.GetResolution(); mResolution = aMetadata.GetResolution();
if (aMetadata.HasSize()) { if (aMetadata.HasSize()) {
auto metadataSize = UnorientedIntSize::FromUnknownSize(aMetadata.GetSize()); auto metadataSize = aMetadata.GetSize();
if (metadataSize.width < 0 || metadataSize.height < 0) { if (metadataSize.width < 0 || metadataSize.height < 0) {
NS_WARNING("Image has negative intrinsic size"); NS_WARNING("Image has negative intrinsic size");
DoError(); DoError();
@ -700,7 +696,7 @@ bool RasterImage::SetMetadata(const ImageMetadata& aMetadata,
// If we already have a size, check the new size against the old one. // If we already have a size, check the new size against the old one.
if (LoadHasSize() && if (LoadHasSize() &&
(metadataSize != ToUnoriented(mSize) || orientation != mOrientation)) { (metadataSize != mSize || orientation != mOrientation)) {
NS_WARNING( NS_WARNING(
"Image changed size or orientation on redecode! " "Image changed size or orientation on redecode! "
"This should not happen!"); "This should not happen!");
@ -710,11 +706,10 @@ bool RasterImage::SetMetadata(const ImageMetadata& aMetadata,
// Set the size and flag that we have it. // Set the size and flag that we have it.
mOrientation = orientation; mOrientation = orientation;
mSize = ToOriented(metadataSize); mSize = metadataSize;
mNativeSizes.Clear(); mNativeSizes.Clear();
for (const auto& nativeSize : aMetadata.GetNativeSizes()) { for (const auto& nativeSize : aMetadata.GetNativeSizes()) {
mNativeSizes.AppendElement( mNativeSizes.AppendElement(nativeSize);
ToOriented(UnorientedIntSize::FromUnknownSize(nativeSize)));
} }
StoreHasSize(true); StoreHasSize(true);
} }
@ -722,8 +717,7 @@ bool RasterImage::SetMetadata(const ImageMetadata& aMetadata,
if (LoadHasSize() && aMetadata.HasAnimation() && !mAnimationState) { if (LoadHasSize() && aMetadata.HasAnimation() && !mAnimationState) {
// We're becoming animated, so initialize animation stuff. // We're becoming animated, so initialize animation stuff.
mAnimationState.emplace(mAnimationMode); mAnimationState.emplace(mAnimationMode);
mFrameAnimator = mFrameAnimator = MakeUnique<FrameAnimator>(this, mSize.ToUnknownSize());
MakeUnique<FrameAnimator>(this, ToUnoriented(mSize).ToUnknownSize());
if (!StaticPrefs::image_mem_animated_discardable_AtStartup()) { if (!StaticPrefs::image_mem_animated_discardable_AtStartup()) {
// We don't support discarding animated images (See bug 414259). // We don't support discarding animated images (See bug 414259).
@ -846,7 +840,7 @@ RasterImage::ResetAnimation() {
mFrameAnimator->ResetAnimation(*mAnimationState); mFrameAnimator->ResetAnimation(*mAnimationState);
IntRect area = mAnimationState->FirstFrameRefreshArea(); IntRect area = mAnimationState->FirstFrameRefreshArea();
NotifyProgress(NoProgress, UnorientedIntRect::FromUnknownRect(area)); NotifyProgress(NoProgress, OrientedIntRect::FromUnknownRect(area));
// Start the animation again. It may not have been running before, if // Start the animation again. It may not have been running before, if
// mAnimationFinished was true before entering this function. // mAnimationFinished was true before entering this function.
@ -1008,10 +1002,9 @@ void RasterImage::Discard() {
if (mAnimationState) { if (mAnimationState) {
ReleaseImageContainer(); ReleaseImageContainer();
auto size = ToUnoriented(mSize); IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
IntRect rect = mAnimationState->UpdateState(this, size.ToUnknownSize());
auto dirtyRect = UnorientedIntRect::FromUnknownRect(rect); auto dirtyRect = OrientedIntRect::FromUnknownRect(rect);
NotifyProgress(NoProgress, dirtyRect); NotifyProgress(NoProgress, dirtyRect);
} }
@ -1057,8 +1050,7 @@ bool RasterImage::StartDecodingWithResult(uint32_t aFlags,
uint32_t flags = (aFlags & FLAG_ASYNC_NOTIFY) | FLAG_SYNC_DECODE_IF_FAST | uint32_t flags = (aFlags & FLAG_ASYNC_NOTIFY) | FLAG_SYNC_DECODE_IF_FAST |
FLAG_HIGH_QUALITY_SCALING; FLAG_HIGH_QUALITY_SCALING;
LookupResult result = LookupResult result = RequestDecodeForSizeInternal(mSize, flags, aWhichFrame);
RequestDecodeForSizeInternal(ToUnoriented(mSize), flags, aWhichFrame);
DrawableSurface surface = std::move(result.Surface()); DrawableSurface surface = std::move(result.Surface());
return surface && surface->IsFinished(); return surface && surface->IsFinished();
} }
@ -1072,8 +1064,7 @@ imgIContainer::DecodeResult RasterImage::RequestDecodeWithResult(
} }
uint32_t flags = aFlags | FLAG_ASYNC_NOTIFY; uint32_t flags = aFlags | FLAG_ASYNC_NOTIFY;
LookupResult result = LookupResult result = RequestDecodeForSizeInternal(mSize, flags, aWhichFrame);
RequestDecodeForSizeInternal(ToUnoriented(mSize), flags, aWhichFrame);
DrawableSurface surface = std::move(result.Surface()); DrawableSurface surface = std::move(result.Surface());
if (surface && surface->IsFinished()) { if (surface && surface->IsFinished()) {
return imgIContainer::DECODE_SURFACE_AVAILABLE; return imgIContainer::DECODE_SURFACE_AVAILABLE;
@ -1093,15 +1084,14 @@ RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
RequestDecodeForSizeInternal( RequestDecodeForSizeInternal(OrientedIntSize::FromUnknownSize(aSize), aFlags,
ToUnoriented(OrientedIntSize::FromUnknownSize(aSize)), aFlags, aWhichFrame);
aWhichFrame);
return NS_OK; return NS_OK;
} }
LookupResult RasterImage::RequestDecodeForSizeInternal( LookupResult RasterImage::RequestDecodeForSizeInternal(
const UnorientedIntSize& aSize, uint32_t aFlags, uint32_t aWhichFrame) { const OrientedIntSize& aSize, uint32_t aFlags, uint32_t aWhichFrame) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (aWhichFrame > FRAME_MAX_VALUE) { if (aWhichFrame > FRAME_MAX_VALUE) {
@ -1155,7 +1145,7 @@ static bool LaunchDecodingTask(IDecodingTask* aTask, RasterImage* aImage,
return false; return false;
} }
void RasterImage::Decode(const UnorientedIntSize& aSize, uint32_t aFlags, void RasterImage::Decode(const OrientedIntSize& aSize, uint32_t aFlags,
PlaybackType aPlaybackType, bool& aOutRanSync, PlaybackType aPlaybackType, bool& aOutRanSync,
bool& aOutFailed) { bool& aOutFailed) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
@ -1212,14 +1202,13 @@ void RasterImage::Decode(const UnorientedIntSize& aSize, uint32_t aFlags,
if (animated) { if (animated) {
size_t currentFrame = mAnimationState->GetCurrentAnimationFrameIndex(); size_t currentFrame = mAnimationState->GetCurrentAnimationFrameIndex();
rv = DecoderFactory::CreateAnimationDecoder( rv = DecoderFactory::CreateAnimationDecoder(
mDecoderType, WrapNotNull(this), mSourceBuffer, mDecoderType, WrapNotNull(this), mSourceBuffer, mSize.ToUnknownSize(),
ToUnoriented(mSize).ToUnknownSize(), decoderFlags, surfaceFlags, decoderFlags, surfaceFlags, currentFrame, getter_AddRefs(task));
currentFrame, getter_AddRefs(task));
} else { } else {
rv = DecoderFactory::CreateDecoder( rv = DecoderFactory::CreateDecoder(mDecoderType, WrapNotNull(this),
mDecoderType, WrapNotNull(this), mSourceBuffer, mSourceBuffer, mSize.ToUnknownSize(),
ToUnoriented(mSize).ToUnknownSize(), aSize.ToUnknownSize(), aSize.ToUnknownSize(), decoderFlags,
decoderFlags, surfaceFlags, getter_AddRefs(task)); surfaceFlags, getter_AddRefs(task));
} }
if (rv == NS_ERROR_ALREADY_INITIALIZED) { if (rv == NS_ERROR_ALREADY_INITIALIZED) {
@ -1238,8 +1227,7 @@ void RasterImage::Decode(const UnorientedIntSize& aSize, uint32_t aFlags,
#ifdef DEBUG #ifdef DEBUG
IntRect rect = IntRect rect =
#endif #endif
mAnimationState->UpdateState(this, ToUnoriented(mSize).ToUnknownSize(), mAnimationState->UpdateState(this, mSize.ToUnknownSize(), false);
false);
MOZ_ASSERT(rect.IsEmpty()); MOZ_ASSERT(rect.IsEmpty());
} }
@ -1279,7 +1267,7 @@ RasterImage::DecodeMetadata(uint32_t aFlags) {
return NS_OK; return NS_OK;
} }
void RasterImage::RecoverFromInvalidFrames(const UnorientedIntSize& aSize, void RasterImage::RecoverFromInvalidFrames(const OrientedIntSize& aSize,
uint32_t aFlags) { uint32_t aFlags) {
if (!LoadHasSize()) { if (!LoadHasSize()) {
return; return;
@ -1300,8 +1288,8 @@ void RasterImage::RecoverFromInvalidFrames(const UnorientedIntSize& aSize,
// Animated images require some special handling, because we normally require // Animated images require some special handling, because we normally require
// that they never be discarded. // that they never be discarded.
if (mAnimationState) { if (mAnimationState) {
Decode(ToUnoriented(mSize), aFlags | FLAG_SYNC_DECODE, Decode(mSize, aFlags | FLAG_SYNC_DECODE, PlaybackType::eAnimated, unused1,
PlaybackType::eAnimated, unused1, unused2); unused2);
ResetAnimation(); ResetAnimation();
return; return;
} }
@ -1310,7 +1298,7 @@ void RasterImage::RecoverFromInvalidFrames(const UnorientedIntSize& aSize,
Decode(aSize, aFlags, PlaybackType::eStatic, unused1, unused2); Decode(aSize, aFlags, PlaybackType::eStatic, unused1, unused2);
} }
bool RasterImage::CanDownscaleDuringDecode(const UnorientedIntSize& aSize, bool RasterImage::CanDownscaleDuringDecode(const OrientedIntSize& aSize,
uint32_t aFlags) { uint32_t aFlags) {
// Check basic requirements: downscale-during-decode is enabled, Skia is // Check basic requirements: downscale-during-decode is enabled, Skia is
// available, this image isn't transient, we have all the source data and know // available, this image isn't transient, we have all the source data and know
@ -1327,8 +1315,7 @@ bool RasterImage::CanDownscaleDuringDecode(const UnorientedIntSize& aSize,
} }
// Never upscale. // Never upscale.
UnorientedIntSize ourSize = ToUnoriented(mSize); if (aSize.width >= mSize.width || aSize.height >= mSize.height) {
if (aSize.width >= ourSize.width || aSize.height >= ourSize.height) {
return false; return false;
} }
@ -1347,7 +1334,7 @@ bool RasterImage::CanDownscaleDuringDecode(const UnorientedIntSize& aSize,
ImgDrawResult RasterImage::DrawInternal(DrawableSurface&& aSurface, ImgDrawResult RasterImage::DrawInternal(DrawableSurface&& aSurface,
gfxContext* aContext, gfxContext* aContext,
const UnorientedIntSize& aSize, const OrientedIntSize& aSize,
const ImageRegion& aRegion, const ImageRegion& aRegion,
SamplingFilter aSamplingFilter, SamplingFilter aSamplingFilter,
uint32_t aFlags, float aOpacity) { uint32_t aFlags, float aOpacity) {
@ -1422,7 +1409,7 @@ RasterImage::Draw(gfxContext* aContext, const IntSize& aSize,
? aFlags ? aFlags
: aFlags & ~FLAG_HIGH_QUALITY_SCALING; : aFlags & ~FLAG_HIGH_QUALITY_SCALING;
auto size = ToUnoriented(OrientedIntSize::FromUnknownSize(aSize)); auto size = OrientedIntSize::FromUnknownSize(aSize);
LookupResult result = LookupFrame(size, flags, ToPlaybackType(aWhichFrame), LookupResult result = LookupFrame(size, flags, ToPlaybackType(aWhichFrame),
/* aMarkUsed = */ true); /* aMarkUsed = */ true);
if (!result) { if (!result) {
@ -1436,26 +1423,9 @@ RasterImage::Draw(gfxContext* aContext, const IntSize& aSize,
bool shouldRecordTelemetry = bool shouldRecordTelemetry =
!mDrawStartTime.IsNull() && result.Surface()->IsFinished(); !mDrawStartTime.IsNull() && result.Surface()->IsFinished();
ImgDrawResult drawResult; ImgDrawResult drawResult =
{ DrawInternal(std::move(result.Surface()), aContext, size, aRegion,
gfxContextMatrixAutoSaveRestore asr; aSamplingFilter, flags, aOpacity);
ImageRegion region(aRegion);
if (!mOrientation.IsIdentity()) {
// Apply a transform so that the unoriented image is drawn in the
// orientation expected by the caller.
gfxMatrix matrix = OrientationMatrix(size);
asr.SetContext(aContext);
aContext->Multiply(matrix);
// Convert the region to unoriented coordinates.
gfxMatrix inverseMatrix = OrientationMatrix(size, /* aInvert = */ true);
region.TransformBoundsBy(inverseMatrix);
}
drawResult = DrawInternal(std::move(result.Surface()), aContext, size,
region, aSamplingFilter, flags, aOpacity);
}
if (shouldRecordTelemetry) { if (shouldRecordTelemetry) {
TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime; TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime;
@ -1560,7 +1530,7 @@ void RasterImage::DoError() {
SurfaceCache::RemoveImage(ImageKey(this)); SurfaceCache::RemoveImage(ImageKey(this));
// Invalidate to get rid of any partially-drawn image content. // Invalidate to get rid of any partially-drawn image content.
auto dirtyRect = UnorientedIntRect({0, 0}, ToUnoriented(mSize)); auto dirtyRect = OrientedIntRect({0, 0}, mSize);
NotifyProgress(NoProgress, dirtyRect); NotifyProgress(NoProgress, dirtyRect);
MOZ_LOG(gImgLog, LogLevel::Error, MOZ_LOG(gImgLog, LogLevel::Error,
@ -1603,7 +1573,7 @@ RasterImage::GetFramesNotified(uint32_t* aFramesNotified) {
void RasterImage::NotifyProgress( void RasterImage::NotifyProgress(
Progress aProgress, Progress aProgress,
const UnorientedIntRect& aInvalidRect /* = UnorientedIntRect() */, const OrientedIntRect& aInvalidRect /* = OrientedIntRect() */,
const Maybe<uint32_t>& aFrameCount /* = Nothing() */, const Maybe<uint32_t>& aFrameCount /* = Nothing() */,
DecoderFlags aDecoderFlags /* = DefaultDecoderFlags() */, DecoderFlags aDecoderFlags /* = DefaultDecoderFlags() */,
SurfaceFlags aSurfaceFlags /* = DefaultSurfaceFlags() */) { SurfaceFlags aSurfaceFlags /* = DefaultSurfaceFlags() */) {
@ -1612,7 +1582,7 @@ void RasterImage::NotifyProgress(
// Ensure that we stay alive long enough to finish notifying. // Ensure that we stay alive long enough to finish notifying.
RefPtr<RasterImage> image = this; RefPtr<RasterImage> image = this;
UnorientedIntRect invalidRect = aInvalidRect; OrientedIntRect invalidRect = aInvalidRect;
if (!(aDecoderFlags & DecoderFlags::FIRST_FRAME_ONLY)) { if (!(aDecoderFlags & DecoderFlags::FIRST_FRAME_ONLY)) {
// We may have decoded new animation frames; update our animation state. // We may have decoded new animation frames; update our animation state.
@ -1628,32 +1598,29 @@ void RasterImage::NotifyProgress(
} }
if (mAnimationState) { if (mAnimationState) {
auto size = ToUnoriented(mSize); IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
IntRect rect = mAnimationState->UpdateState(this, size.ToUnknownSize());
invalidRect.UnionRect(invalidRect, invalidRect.UnionRect(invalidRect,
UnorientedIntRect::FromUnknownRect(rect)); OrientedIntRect::FromUnknownRect(rect));
} }
} }
const bool wasDefaultFlags = aSurfaceFlags == DefaultSurfaceFlags(); const bool wasDefaultFlags = aSurfaceFlags == DefaultSurfaceFlags();
auto orientedInvalidRect = ToOriented(invalidRect); if (!invalidRect.IsEmpty() && wasDefaultFlags) {
if (!orientedInvalidRect.IsEmpty() && wasDefaultFlags) {
// Update our image container since we're invalidating. // Update our image container since we're invalidating.
UpdateImageContainer(Some(orientedInvalidRect.ToUnknownRect())); UpdateImageContainer(Some(invalidRect.ToUnknownRect()));
} }
// Tell the observers what happened. // Tell the observers what happened.
image->mProgressTracker->SyncNotifyProgress( image->mProgressTracker->SyncNotifyProgress(aProgress,
aProgress, orientedInvalidRect.ToUnknownRect()); invalidRect.ToUnknownRect());
} }
void RasterImage::NotifyDecodeComplete( void RasterImage::NotifyDecodeComplete(
const DecoderFinalStatus& aStatus, const ImageMetadata& aMetadata, const DecoderFinalStatus& aStatus, const ImageMetadata& aMetadata,
const DecoderTelemetry& aTelemetry, Progress aProgress, const DecoderTelemetry& aTelemetry, Progress aProgress,
const UnorientedIntRect& aInvalidRect, const Maybe<uint32_t>& aFrameCount, const OrientedIntRect& aInvalidRect, const Maybe<uint32_t>& aFrameCount,
DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags) { DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
@ -1668,8 +1635,7 @@ void RasterImage::NotifyDecodeComplete(
// This indicates a serious error that requires us to discard all existing // This indicates a serious error that requires us to discard all existing
// surfaces and redecode to recover. We'll drop the results from this // surfaces and redecode to recover. We'll drop the results from this
// decoder on the floor, since they aren't valid. // decoder on the floor, since they aren't valid.
RecoverFromInvalidFrames(ToUnoriented(mSize), RecoverFromInvalidFrames(mSize, FromSurfaceFlags(aSurfaceFlags));
FromSurfaceFlags(aSurfaceFlags));
return; return;
} }
@ -1704,11 +1670,10 @@ void RasterImage::NotifyDecodeComplete(
// expect anymore. // expect anymore.
mAnimationState->NotifyDecodeComplete(); mAnimationState->NotifyDecodeComplete();
auto size = ToUnoriented(mSize); IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
IntRect rect = mAnimationState->UpdateState(this, size.ToUnknownSize());
if (!rect.IsEmpty()) { if (!rect.IsEmpty()) {
auto dirtyRect = UnorientedIntRect::FromUnknownRect(rect); auto dirtyRect = OrientedIntRect::FromUnknownRect(rect);
NotifyProgress(NoProgress, dirtyRect); NotifyProgress(NoProgress, dirtyRect);
} }
} }
@ -1750,9 +1715,9 @@ void RasterImage::NotifyDecodeComplete(
// If we were a metadata decode and a full decode was requested, do it. // If we were a metadata decode and a full decode was requested, do it.
if (LoadWantFullDecode()) { if (LoadWantFullDecode()) {
StoreWantFullDecode(false); StoreWantFullDecode(false);
RequestDecodeForSize(mSize.ToUnknownSize(), RequestDecodeForSizeInternal(
DECODE_FLAGS_DEFAULT | FLAG_HIGH_QUALITY_SCALING, mSize, DECODE_FLAGS_DEFAULT | FLAG_HIGH_QUALITY_SCALING,
FRAME_CURRENT); FRAME_CURRENT);
} }
} }
} }
@ -1806,7 +1771,7 @@ IntSize RasterImage::OptimalImageSizeForDest(const gfxSize& aDest,
IntSize::Ceil(aDest.width, aDest.height)); IntSize::Ceil(aDest.width, aDest.height));
if (aSamplingFilter == SamplingFilter::GOOD && if (aSamplingFilter == SamplingFilter::GOOD &&
CanDownscaleDuringDecode(ToUnoriented(dest), aFlags)) { CanDownscaleDuringDecode(dest, aFlags)) {
return dest.ToUnknownSize(); return dest.ToUnknownSize();
} }

View file

@ -194,12 +194,11 @@ class RasterImage final : public ImageResource,
* these notifications, or DefaultSurfaceFlags() if the * these notifications, or DefaultSurfaceFlags() if the
* notifications don't come from a decoder. * notifications don't come from a decoder.
*/ */
void NotifyProgress( void NotifyProgress(Progress aProgress,
Progress aProgress, const OrientedIntRect& aInvalidRect = OrientedIntRect(),
const UnorientedIntRect& aInvalidRect = UnorientedIntRect(), const Maybe<uint32_t>& aFrameCount = Nothing(),
const Maybe<uint32_t>& aFrameCount = Nothing(), DecoderFlags aDecoderFlags = DefaultDecoderFlags(),
DecoderFlags aDecoderFlags = DefaultDecoderFlags(), SurfaceFlags aSurfaceFlags = DefaultSurfaceFlags());
SurfaceFlags aSurfaceFlags = DefaultSurfaceFlags());
/** /**
* Records decoding results, sends out any final notifications, updates the * Records decoding results, sends out any final notifications, updates the
@ -222,7 +221,7 @@ class RasterImage final : public ImageResource,
void NotifyDecodeComplete( void NotifyDecodeComplete(
const DecoderFinalStatus& aStatus, const ImageMetadata& aMetadata, const DecoderFinalStatus& aStatus, const ImageMetadata& aMetadata,
const DecoderTelemetry& aTelemetry, Progress aProgress, const DecoderTelemetry& aTelemetry, Progress aProgress,
const UnorientedIntRect& aInvalidRect, const Maybe<uint32_t>& aFrameCount, const OrientedIntRect& aInvalidRect, const Maybe<uint32_t>& aFrameCount,
DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags); DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags);
// Helper method for NotifyDecodeComplete. // Helper method for NotifyDecodeComplete.
@ -281,16 +280,16 @@ class RasterImage final : public ImageResource,
* @return a drawable surface, which may be empty if the requested surface * @return a drawable surface, which may be empty if the requested surface
* could not be found. * could not be found.
*/ */
LookupResult LookupFrame(const UnorientedIntSize& aSize, uint32_t aFlags, LookupResult LookupFrame(const OrientedIntSize& aSize, uint32_t aFlags,
PlaybackType aPlaybackType, bool aMarkUsed); PlaybackType aPlaybackType, bool aMarkUsed);
/// Helper method for LookupFrame(). /// Helper method for LookupFrame().
LookupResult LookupFrameInternal(const UnorientedIntSize& aSize, LookupResult LookupFrameInternal(const OrientedIntSize& aSize,
uint32_t aFlags, PlaybackType aPlaybackType, uint32_t aFlags, PlaybackType aPlaybackType,
bool aMarkUsed); bool aMarkUsed);
ImgDrawResult DrawInternal(DrawableSurface&& aFrameRef, gfxContext* aContext, ImgDrawResult DrawInternal(DrawableSurface&& aFrameRef, gfxContext* aContext,
const UnorientedIntSize& aSize, const OrientedIntSize& aSize,
const ImageRegion& aRegion, const ImageRegion& aRegion,
gfx::SamplingFilter aSamplingFilter, gfx::SamplingFilter aSamplingFilter,
uint32_t aFlags, float aOpacity); uint32_t aFlags, float aOpacity);
@ -322,7 +321,7 @@ class RasterImage final : public ImageResource,
* aOutRanSync is set to true if the decode was run synchronously. * aOutRanSync is set to true if the decode was run synchronously.
* aOutFailed is set to true if failed to start a decode. * aOutFailed is set to true if failed to start a decode.
*/ */
void Decode(const UnorientedIntSize& aSize, uint32_t aFlags, void Decode(const OrientedIntSize& aSize, uint32_t aFlags,
PlaybackType aPlaybackType, bool& aOutRanSync, bool& aOutFailed); PlaybackType aPlaybackType, bool& aOutRanSync, bool& aOutFailed);
/** /**
@ -358,8 +357,7 @@ class RasterImage final : public ImageResource,
* RecoverFromInvalidFrames discards all existing frames and redecodes using * RecoverFromInvalidFrames discards all existing frames and redecodes using
* the provided @aSize and @aFlags. * the provided @aSize and @aFlags.
*/ */
void RecoverFromInvalidFrames(const UnorientedIntSize& aSize, void RecoverFromInvalidFrames(const OrientedIntSize& aSize, uint32_t aFlags);
uint32_t aFlags);
void OnSurfaceDiscardedInternal(bool aAnimatedFramesDiscarded); void OnSurfaceDiscardedInternal(bool aAnimatedFramesDiscarded);
@ -463,8 +461,7 @@ class RasterImage final : public ImageResource,
// Determines whether we can downscale during decode with the given // Determines whether we can downscale during decode with the given
// parameters. // parameters.
bool CanDownscaleDuringDecode(const UnorientedIntSize& aSize, bool CanDownscaleDuringDecode(const OrientedIntSize& aSize, uint32_t aFlags);
uint32_t aFlags);
// Error handling. // Error handling.
void DoError(); void DoError();
@ -491,7 +488,7 @@ class RasterImage final : public ImageResource,
bool IsOpaque(); bool IsOpaque();
LookupResult RequestDecodeForSizeInternal(const UnorientedIntSize& aSize, LookupResult RequestDecodeForSizeInternal(const OrientedIntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
uint32_t aWhichFrame); uint32_t aWhichFrame);

View file

@ -26,7 +26,7 @@ Maybe<SurfaceInvalidRect> AbstractSurfaceSink::TakeInvalidRect() {
invalidRect.mInputSpaceRect = invalidRect.mOutputSpaceRect = mInvalidRect; invalidRect.mInputSpaceRect = invalidRect.mOutputSpaceRect = mInvalidRect;
// Forget about the invalid rect we're returning. // Forget about the invalid rect we're returning.
mInvalidRect = IntRect(); mInvalidRect = OrientedIntRect();
return Some(invalidRect); return Some(invalidRect);
} }
@ -51,7 +51,7 @@ uint8_t* AbstractSurfaceSink::DoAdvanceRow() {
// to change. // to change.
int32_t invalidY = mFlipVertically ? InputSize().height - (mRow + 1) : mRow; int32_t invalidY = mFlipVertically ? InputSize().height - (mRow + 1) : mRow;
mInvalidRect.UnionRect(mInvalidRect, mInvalidRect.UnionRect(mInvalidRect,
IntRect(0, invalidY, InputSize().width, 1)); OrientedIntRect(0, invalidY, InputSize().width, 1));
mRow = min(uint32_t(InputSize().height), mRow + 1); mRow = min(uint32_t(InputSize().height), mRow + 1);

View file

@ -35,6 +35,7 @@
#include "mozilla/Variant.h" #include "mozilla/Variant.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "Orientation.h"
namespace mozilla { namespace mozilla {
namespace image { namespace image {
@ -47,8 +48,9 @@ class Decoder;
* of the output surface (after all SurfaceFilters). * of the output surface (after all SurfaceFilters).
*/ */
struct SurfaceInvalidRect { struct SurfaceInvalidRect {
gfx::IntRect mInputSpaceRect; /// The invalid rect in pre-SurfacePipe space. OrientedIntRect
gfx::IntRect mInputSpaceRect; /// The invalid rect in pre-SurfacePipe space.
OrientedIntRect
mOutputSpaceRect; /// The invalid rect in post-SurfacePipe space. mOutputSpaceRect; /// The invalid rect in post-SurfacePipe space.
}; };
@ -774,7 +776,7 @@ class AbstractSurfaceSink : public SurfaceFilter {
uint8_t* DoAdvanceRow() final; uint8_t* DoAdvanceRow() final;
virtual uint8_t* GetRowPointer() const = 0; virtual uint8_t* GetRowPointer() const = 0;
gfx::IntRect OrientedIntRect
mInvalidRect; /// The region of the surface that has been written mInvalidRect; /// The region of the surface that has been written
/// to since the last call to TakeInvalidRect(). /// to since the last call to TakeInvalidRect().
uint8_t* mImageData; /// A pointer to the beginning of the surface data. uint8_t* mImageData; /// A pointer to the beginning of the surface data.

View file

@ -89,8 +89,8 @@ class SurfacePipeFactory {
* initialized. * initialized.
*/ */
static Maybe<SurfacePipe> CreateSurfacePipe( static Maybe<SurfacePipe> CreateSurfacePipe(
Decoder* aDecoder, const nsIntSize& aInputSize, Decoder* aDecoder, const OrientedIntSize& aInputSize,
const nsIntSize& aOutputSize, const nsIntRect& aFrameRect, const OrientedIntSize& aOutputSize, const OrientedIntRect& aFrameRect,
gfx::SurfaceFormat aInFormat, gfx::SurfaceFormat aOutFormat, gfx::SurfaceFormat aInFormat, gfx::SurfaceFormat aOutFormat,
const Maybe<AnimationParams>& aAnimParams, qcms_transform* aTransform, const Maybe<AnimationParams>& aAnimParams, qcms_transform* aTransform,
SurfacePipeFlags aFlags) { SurfacePipeFlags aFlags) {
@ -101,7 +101,7 @@ class SurfacePipeFactory {
bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY); bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY);
const bool downscale = aInputSize != aOutputSize; const bool downscale = aInputSize != aOutputSize;
const bool removeFrameRect = !aFrameRect.IsEqualEdges( const bool removeFrameRect = !aFrameRect.IsEqualEdges(
nsIntRect(0, 0, aInputSize.width, aInputSize.height)); OrientedIntRect(OrientedIntPoint(0, 0), aInputSize));
const bool blendAnimation = aAnimParams.isSome(); const bool blendAnimation = aAnimParams.isSome();
const bool colorManagement = aTransform != nullptr; const bool colorManagement = aTransform != nullptr;
const bool premultiplyAlpha = const bool premultiplyAlpha =
@ -174,13 +174,13 @@ class SurfacePipeFactory {
// account. // account.
DeinterlacingConfig<uint32_t> deinterlacingConfig{progressiveDisplay}; DeinterlacingConfig<uint32_t> deinterlacingConfig{progressiveDisplay};
ADAM7InterpolatingConfig interpolatingConfig; ADAM7InterpolatingConfig interpolatingConfig;
RemoveFrameRectConfig removeFrameRectConfig{aFrameRect}; RemoveFrameRectConfig removeFrameRectConfig{aFrameRect.ToUnknownRect()};
BlendAnimationConfig blendAnimationConfig{aDecoder}; BlendAnimationConfig blendAnimationConfig{aDecoder};
DownscalingConfig downscalingConfig{aInputSize, aOutFormat}; DownscalingConfig downscalingConfig{aInputSize.ToUnknownSize(), aOutFormat};
ColorManagementConfig colorManagementConfig{aTransform}; ColorManagementConfig colorManagementConfig{aTransform};
SwizzleConfig swizzleConfig{aInFormat, aOutFormat, premultiplyAlpha}; SwizzleConfig swizzleConfig{aInFormat, aOutFormat, premultiplyAlpha};
SurfaceConfig surfaceConfig{aDecoder, aOutputSize, aOutFormat, SurfaceConfig surfaceConfig{aDecoder, aOutputSize.ToUnknownSize(),
flipVertically, aAnimParams}; aOutFormat, flipVertically, aAnimParams};
Maybe<SurfacePipe> pipe; Maybe<SurfacePipe> pipe;

View file

@ -1376,8 +1376,10 @@ nsAVIFDecoder::DecodeResult nsAVIFDecoder::Decode(
AccumulateCategorical(LABELS_AVIF_ALPHA::absent); AccumulateCategorical(LABELS_AVIF_ALPHA::absent);
} }
IntSize rgbSize = Size(); IntSize rgbSize = decodedData.mPicSize;
MOZ_ASSERT(rgbSize == decodedData.mPicSize); MOZ_ASSERT(
rgbSize ==
GetImageMetadata().GetOrientation().ToUnoriented(Size()).ToUnknownSize());
if (parsedImg.nclx_colour_information && if (parsedImg.nclx_colour_information &&
parsedImg.icc_colour_information.data) { parsedImg.icc_colour_information.data) {
@ -1553,7 +1555,7 @@ nsAVIFDecoder::DecodeResult nsAVIFDecoder::Decode(
MOZ_LOG(sAVIFLog, LogLevel::Debug, MOZ_LOG(sAVIFLog, LogLevel::Debug,
("[this=%p] calling SurfacePipeFactory::CreateSurfacePipe", this)); ("[this=%p] calling SurfacePipeFactory::CreateSurfacePipe", this));
Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe( Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
this, rgbSize, OutputSize(), FullFrame(), format, format, Nothing(), this, Size(), OutputSize(), FullFrame(), format, format, Nothing(),
mTransform, SurfacePipeFlags()); mTransform, SurfacePipeFlags());
if (!pipe) { if (!pipe) {

View file

@ -141,7 +141,7 @@ void nsGIFDecoder2::BeginGIF() {
PostSize(mGIFStruct.screen_width, mGIFStruct.screen_height); PostSize(mGIFStruct.screen_width, mGIFStruct.screen_height);
} }
bool nsGIFDecoder2::CheckForTransparency(const IntRect& aFrameRect) { bool nsGIFDecoder2::CheckForTransparency(const OrientedIntRect& aFrameRect) {
// Check if the image has a transparent color in its palette. // Check if the image has a transparent color in its palette.
if (mGIFStruct.is_transparent) { if (mGIFStruct.is_transparent) {
PostHasTransparency(); PostHasTransparency();
@ -154,7 +154,8 @@ bool nsGIFDecoder2::CheckForTransparency(const IntRect& aFrameRect) {
// If we need padding on the first frame, that means we don't draw into part // If we need padding on the first frame, that means we don't draw into part
// of the image at all. Report that as transparency. // of the image at all. Report that as transparency.
IntRect imageRect(0, 0, mGIFStruct.screen_width, mGIFStruct.screen_height); OrientedIntRect imageRect(0, 0, mGIFStruct.screen_width,
mGIFStruct.screen_height);
if (!imageRect.IsEqualEdges(aFrameRect)) { if (!imageRect.IsEqualEdges(aFrameRect)) {
PostHasTransparency(); PostHasTransparency();
mSawTransparency = true; // Make sure we don't optimize it away. mSawTransparency = true; // Make sure we don't optimize it away.
@ -165,7 +166,7 @@ bool nsGIFDecoder2::CheckForTransparency(const IntRect& aFrameRect) {
} }
//****************************************************************************** //******************************************************************************
nsresult nsGIFDecoder2::BeginImageFrame(const IntRect& aFrameRect, nsresult nsGIFDecoder2::BeginImageFrame(const OrientedIntRect& aFrameRect,
uint16_t aDepth, bool aIsInterlaced) { uint16_t aDepth, bool aIsInterlaced) {
MOZ_ASSERT(HasSize()); MOZ_ASSERT(HasSize());
@ -176,7 +177,7 @@ nsresult nsGIFDecoder2::BeginImageFrame(const IntRect& aFrameRect,
Maybe<AnimationParams> animParams; Maybe<AnimationParams> animParams;
if (!IsFirstFrameDecode()) { if (!IsFirstFrameDecode()) {
animParams.emplace(aFrameRect, animParams.emplace(aFrameRect.ToUnknownRect(),
FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time), FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time),
uint32_t(mGIFStruct.images_decoded), BlendMethod::OVER, uint32_t(mGIFStruct.images_decoded), BlendMethod::OVER,
DisposalMethod(mGIFStruct.disposal_method)); DisposalMethod(mGIFStruct.disposal_method));
@ -752,7 +753,7 @@ LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadImageDescriptor(
LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::FinishImageDescriptor( LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::FinishImageDescriptor(
const char* aData) { const char* aData) {
IntRect frameRect; OrientedIntRect frameRect;
// Get image offsets with respect to the screen origin. // Get image offsets with respect to the screen origin.
frameRect.SetRect( frameRect.SetRect(

View file

@ -50,7 +50,7 @@ class nsGIFDecoder2 : public Decoder {
* @param aDepth The palette depth of this frame. * @param aDepth The palette depth of this frame.
* @param aIsInterlaced If true, this frame is an interlaced frame. * @param aIsInterlaced If true, this frame is an interlaced frame.
*/ */
nsresult BeginImageFrame(const gfx::IntRect& aFrameRect, uint16_t aDepth, nsresult BeginImageFrame(const OrientedIntRect& aFrameRect, uint16_t aDepth,
bool aIsInterlaced); bool aIsInterlaced);
/// Called when we finish decoding a frame. /// Called when we finish decoding a frame.
@ -76,7 +76,7 @@ class nsGIFDecoder2 : public Decoder {
/// Checks if we have transparency, either because the header indicates that /// Checks if we have transparency, either because the header indicates that
/// there's alpha, or because the frame rect doesn't cover the entire image. /// there's alpha, or because the frame rect doesn't cover the entire image.
bool CheckForTransparency(const gfx::IntRect& aFrameRect); bool CheckForTransparency(const OrientedIntRect& aFrameRect);
// @return the clear code used for LZW decompression. // @return the clear code used for LZW decompression.
int ClearCode() const { int ClearCode() const {

View file

@ -154,7 +154,7 @@ LexerTransition<ICOState> nsICODecoder::ReadDirEntry(const char* aData) {
e.mBitCount = LittleEndian::readUint16(aData + 6); e.mBitCount = LittleEndian::readUint16(aData + 6);
e.mBytesInRes = LittleEndian::readUint32(aData + 8); e.mBytesInRes = LittleEndian::readUint32(aData + 8);
e.mImageOffset = offset; e.mImageOffset = offset;
e.mSize = IntSize(e.mWidth, e.mHeight); e.mSize = OrientedIntSize(e.mWidth, e.mHeight);
// Only accept entries with sufficient resource data to actually contain // Only accept entries with sufficient resource data to actually contain
// some image data. // some image data.
@ -234,7 +234,7 @@ LexerTransition<ICOState> nsICODecoder::FinishDirEntry() {
// If an explicit output size was specified, we'll try to select the resource // If an explicit output size was specified, we'll try to select the resource
// that matches it best below. // that matches it best below.
const Maybe<IntSize> desiredSize = ExplicitOutputSize(); const Maybe<OrientedIntSize> desiredSize = ExplicitOutputSize();
// Determine the biggest resource. We always use the biggest resource for the // Determine the biggest resource. We always use the biggest resource for the
// intrinsic size, and if we don't have a specific desired size, we select it // intrinsic size, and if we don't have a specific desired size, we select it
@ -309,7 +309,7 @@ LexerTransition<ICOState> nsICODecoder::FinishDirEntry() {
// //
// TODO(aosmond): This is the last user of Downscaler. We should switch this // TODO(aosmond): This is the last user of Downscaler. We should switch this
// to SurfacePipe as well so we can remove the code from tree. // to SurfacePipe as well so we can remove the code from tree.
mDownscaler.emplace(OutputSize()); mDownscaler.emplace(OutputSize().ToUnknownSize());
} }
size_t offsetToResource = mDirEntry->mImageOffset - FirstResourceOffset(); size_t offsetToResource = mDirEntry->mImageOffset - FirstResourceOffset();
@ -348,7 +348,7 @@ LexerTransition<ICOState> nsICODecoder::SniffResource(const char* aData) {
// Create a PNG decoder which will do the rest of the work for us. // Create a PNG decoder which will do the rest of the work for us.
bool metadataDecode = mReturnIterator.isSome(); bool metadataDecode = mReturnIterator.isSome();
Maybe<IntSize> expectedSize = Maybe<OrientedIntSize> expectedSize =
metadataDecode ? Nothing() : Some(mDirEntry->mSize); metadataDecode ? Nothing() : Some(mDirEntry->mSize);
mContainedDecoder = DecoderFactory::CreateDecoderForICOResource( mContainedDecoder = DecoderFactory::CreateDecoderForICOResource(
DecoderType::PNG, std::move(containedIterator.ref()), WrapNotNull(this), DecoderType::PNG, std::move(containedIterator.ref()), WrapNotNull(this),
@ -412,7 +412,7 @@ LexerTransition<ICOState> nsICODecoder::ReadBIH(const char* aData) {
// Create a BMP decoder which will do most of the work for us; the exception // Create a BMP decoder which will do most of the work for us; the exception
// is the AND mask, which isn't present in standalone BMPs. // is the AND mask, which isn't present in standalone BMPs.
bool metadataDecode = mReturnIterator.isSome(); bool metadataDecode = mReturnIterator.isSome();
Maybe<IntSize> expectedSize = Maybe<OrientedIntSize> expectedSize =
metadataDecode ? Nothing() : Some(mDirEntry->mSize); metadataDecode ? Nothing() : Some(mDirEntry->mSize);
mContainedDecoder = DecoderFactory::CreateDecoderForICOResource( mContainedDecoder = DecoderFactory::CreateDecoderForICOResource(
DecoderType::BMP, std::move(containedIterator.ref()), WrapNotNull(this), DecoderType::BMP, std::move(containedIterator.ref()), WrapNotNull(this),
@ -491,10 +491,10 @@ LexerTransition<ICOState> nsICODecoder::PrepareForMask() {
mDownscaler->TargetSize().width * mDownscaler->TargetSize().width *
mDownscaler->TargetSize().height * sizeof(uint32_t)); mDownscaler->TargetSize().height * sizeof(uint32_t));
mMaskBuffer = MakeUnique<uint8_t[]>(bmpDecoder->GetImageDataLength()); mMaskBuffer = MakeUnique<uint8_t[]>(bmpDecoder->GetImageDataLength());
nsresult rv = nsresult rv = mDownscaler->BeginFrame(mDirEntry->mSize.ToUnknownSize(),
mDownscaler->BeginFrame(mDirEntry->mSize, Nothing(), mMaskBuffer.get(), Nothing(), mMaskBuffer.get(),
/* aHasAlpha = */ true, /* aHasAlpha = */ true,
/* aFlipVertically = */ true); /* aFlipVertically = */ true);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return Transition::TerminateFailure(); return Transition::TerminateFailure();
} }

View file

@ -78,7 +78,7 @@ class nsICODecoder : public Decoder {
LexerTransition<ICOState> FinishResource(); LexerTransition<ICOState> FinishResource();
struct IconDirEntryEx : public IconDirEntry { struct IconDirEntryEx : public IconDirEntry {
gfx::IntSize mSize; OrientedIntSize mSize;
}; };
StreamingLexer<ICOState, 32> mLexer; // The lexer. StreamingLexer<ICOState, 32> mLexer; // The lexer.

View file

@ -134,7 +134,7 @@ LexerTransition<nsJXLDecoder::State> nsJXLDecoder::ReadJXLData(
} }
case JXL_DEC_FULL_IMAGE: { case JXL_DEC_FULL_IMAGE: {
gfx::IntSize size(mInfo.xsize, mInfo.ysize); OrientedIntSize size(mInfo.xsize, mInfo.ysize);
Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe( Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
this, size, OutputSize(), FullFrame(), SurfaceFormat::R8G8B8A8, this, size, OutputSize(), FullFrame(), SurfaceFormat::R8G8B8A8,
SurfaceFormat::OS_RGBA, Nothing(), nullptr, SurfacePipeFlags()); SurfaceFormat::OS_RGBA, Nothing(), nullptr, SurfacePipeFlags());

View file

@ -130,7 +130,7 @@ nsPNGDecoder::~nsPNGDecoder() {
} }
nsPNGDecoder::TransparencyType nsPNGDecoder::GetTransparencyType( nsPNGDecoder::TransparencyType nsPNGDecoder::GetTransparencyType(
const IntRect& aFrameRect) { const OrientedIntRect& aFrameRect) {
// Check if the image has a transparent color in its palette. // Check if the image has a transparent color in its palette.
if (HasAlphaChannel()) { if (HasAlphaChannel()) {
return TransparencyType::eAlpha; return TransparencyType::eAlpha;
@ -194,7 +194,7 @@ nsresult nsPNGDecoder::CreateFrame(const FrameInfo& aFrameInfo) {
} }
animParams.emplace( animParams.emplace(
AnimationParams{aFrameInfo.mFrameRect, AnimationParams{aFrameInfo.mFrameRect.ToUnknownRect(),
FrameTimeout::FromRawMilliseconds(mAnimInfo.mTimeout), FrameTimeout::FromRawMilliseconds(mAnimInfo.mTimeout),
mNumFrames, mAnimInfo.mBlend, mAnimInfo.mDispose}); mNumFrames, mAnimInfo.mBlend, mAnimInfo.mDispose});
} }
@ -527,7 +527,7 @@ void nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) {
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, &compression_type, &filter_type); &interlace_type, &compression_type, &filter_type);
const IntRect frameRect(0, 0, width, height); const OrientedIntRect frameRect(0, 0, width, height);
// Post our size to the superclass // Post our size to the superclass
decoder->PostSize(frameRect.Width(), frameRect.Height()); decoder->PostSize(frameRect.Width(), frameRect.Height());
@ -930,10 +930,11 @@ void nsPNGDecoder::frame_info_callback(png_structp png_ptr,
// Save the information necessary to create the frame; we'll actually create // Save the information necessary to create the frame; we'll actually create
// it when we return from the yield. // it when we return from the yield.
const IntRect frameRect(png_get_next_frame_x_offset(png_ptr, decoder->mInfo), const OrientedIntRect frameRect(
png_get_next_frame_y_offset(png_ptr, decoder->mInfo), png_get_next_frame_x_offset(png_ptr, decoder->mInfo),
png_get_next_frame_width(png_ptr, decoder->mInfo), png_get_next_frame_y_offset(png_ptr, decoder->mInfo),
png_get_next_frame_height(png_ptr, decoder->mInfo)); png_get_next_frame_width(png_ptr, decoder->mInfo),
png_get_next_frame_height(png_ptr, decoder->mInfo));
const bool isInterlaced = bool(decoder->interlacebuf); const bool isInterlaced = bool(decoder->interlacebuf);
# ifndef MOZ_EMBEDDED_LIBPNG # ifndef MOZ_EMBEDDED_LIBPNG

View file

@ -42,7 +42,7 @@ class nsPNGDecoder : public Decoder {
/// The information necessary to create a frame. /// The information necessary to create a frame.
struct FrameInfo { struct FrameInfo {
gfx::IntRect mFrameRect; OrientedIntRect mFrameRect;
bool mIsInterlaced; bool mIsInterlaced;
}; };
@ -56,7 +56,7 @@ class nsPNGDecoder : public Decoder {
enum class TransparencyType { eNone, eAlpha, eFrameRect }; enum class TransparencyType { eNone, eAlpha, eFrameRect };
TransparencyType GetTransparencyType(const gfx::IntRect& aFrameRect); TransparencyType GetTransparencyType(const OrientedIntRect& aFrameRect);
void PostHasTransparencyIfNeeded(TransparencyType aTransparencyType); void PostHasTransparencyIfNeeded(TransparencyType aTransparencyType);
void PostInvalidationIfNeeded(); void PostInvalidationIfNeeded();
@ -92,7 +92,7 @@ class nsPNGDecoder : public Decoder {
public: public:
png_structp mPNG; png_structp mPNG;
png_infop mInfo; png_infop mInfo;
nsIntRect mFrameRect; OrientedIntRect mFrameRect;
uint8_t* mCMSLine; uint8_t* mCMSLine;
uint8_t* interlacebuf; uint8_t* interlacebuf;
gfx::SurfaceFormat mFormat; gfx::SurfaceFormat mFormat;

View file

@ -195,7 +195,7 @@ LexerResult nsWebPDecoder::UpdateBuffer(SourceBufferIterator& aIterator,
return ReadData(); return ReadData();
} }
nsresult nsWebPDecoder::CreateFrame(const nsIntRect& aFrameRect) { nsresult nsWebPDecoder::CreateFrame(const OrientedIntRect& aFrameRect) {
MOZ_ASSERT(HasSize()); MOZ_ASSERT(HasSize());
MOZ_ASSERT(!mDecoder); MOZ_ASSERT(!mDecoder);
@ -257,7 +257,8 @@ nsresult nsWebPDecoder::CreateFrame(const nsIntRect& aFrameRect) {
Maybe<AnimationParams> animParams; Maybe<AnimationParams> animParams;
if (!IsFirstFrameDecode()) { if (!IsFirstFrameDecode()) {
animParams.emplace(aFrameRect, mTimeout, mCurrentFrame, mBlend, mDisposal); animParams.emplace(aFrameRect.ToUnknownRect(), mTimeout, mCurrentFrame,
mBlend, mDisposal);
} }
Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe( Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
@ -430,7 +431,7 @@ LexerResult nsWebPDecoder::ReadPayload(WebPDemuxer* aDemuxer,
} }
LexerResult nsWebPDecoder::ReadSingle(const uint8_t* aData, size_t aLength, LexerResult nsWebPDecoder::ReadSingle(const uint8_t* aData, size_t aLength,
const IntRect& aFrameRect) { const OrientedIntRect& aFrameRect) {
MOZ_ASSERT(!IsMetadataDecode()); MOZ_ASSERT(!IsMetadataDecode());
MOZ_ASSERT(aData); MOZ_ASSERT(aData);
MOZ_ASSERT(aLength > 0); MOZ_ASSERT(aLength > 0);
@ -560,7 +561,8 @@ LexerResult nsWebPDecoder::ReadMultiple(WebPDemuxer* aDemuxer,
mFormat = iter.has_alpha || mCurrentFrame > 0 ? SurfaceFormat::OS_RGBA mFormat = iter.has_alpha || mCurrentFrame > 0 ? SurfaceFormat::OS_RGBA
: SurfaceFormat::OS_RGBX; : SurfaceFormat::OS_RGBX;
mTimeout = FrameTimeout::FromRawMilliseconds(iter.duration); mTimeout = FrameTimeout::FromRawMilliseconds(iter.duration);
nsIntRect frameRect(iter.x_offset, iter.y_offset, iter.width, iter.height); OrientedIntRect frameRect(iter.x_offset, iter.y_offset, iter.width,
iter.height);
rv = ReadSingle(iter.fragment.bytes, iter.fragment.size, frameRect); rv = ReadSingle(iter.fragment.bytes, iter.fragment.size, frameRect);
complete = complete && !WebPDemuxNextFrame(&iter); complete = complete && !WebPDemuxNextFrame(&iter);

View file

@ -41,11 +41,11 @@ class nsWebPDecoder final : public Decoder {
LexerResult ReadHeader(WebPDemuxer* aDemuxer, bool aIsComplete); LexerResult ReadHeader(WebPDemuxer* aDemuxer, bool aIsComplete);
LexerResult ReadPayload(WebPDemuxer* aDemuxer, bool aIsComplete); LexerResult ReadPayload(WebPDemuxer* aDemuxer, bool aIsComplete);
nsresult CreateFrame(const nsIntRect& aFrameRect); nsresult CreateFrame(const OrientedIntRect& aFrameRect);
void EndFrame(); void EndFrame();
LexerResult ReadSingle(const uint8_t* aData, size_t aLength, LexerResult ReadSingle(const uint8_t* aData, size_t aLength,
const gfx::IntRect& aFrameRect); const OrientedIntRect& aFrameRect);
LexerResult ReadMultiple(WebPDemuxer* aDemuxer, bool aIsComplete); LexerResult ReadMultiple(WebPDemuxer* aDemuxer, bool aIsComplete);
@ -75,7 +75,7 @@ class nsWebPDecoder final : public Decoder {
gfx::SurfaceFormat mFormat; gfx::SurfaceFormat mFormat;
/// Frame rect for the current frame. /// Frame rect for the current frame.
gfx::IntRect mFrameRect; OrientedIntRect mFrameRect;
/// The last row of decoded pixels written to mPipe. /// The last row of decoded pixels written to mPipe.
int mLastRow; int mLastRow;

View file

@ -277,13 +277,13 @@ already_AddRefed<Decoder> CreateTrivialDecoder() {
} }
void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter, void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter,
const gfx::IntRect& aInputSpaceRect, const IntRect& aInputSpaceRect,
const gfx::IntRect& aOutputSpaceRect) { const IntRect& aOutputSpaceRect) {
EXPECT_TRUE(aFilter->IsSurfaceFinished()); EXPECT_TRUE(aFilter->IsSurfaceFinished());
Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect(); Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(aInputSpaceRect, invalidRect->mInputSpaceRect); EXPECT_EQ(aInputSpaceRect, invalidRect->mInputSpaceRect.ToUnknownRect());
EXPECT_EQ(aOutputSpaceRect, invalidRect->mOutputSpaceRect); EXPECT_EQ(aOutputSpaceRect, invalidRect->mOutputSpaceRect.ToUnknownRect());
} }
void CheckGeneratedImage(Decoder* aDecoder, const IntRect& aRect, void CheckGeneratedImage(Decoder* aDecoder, const IntRect& aRect,

View file

@ -151,21 +151,22 @@ TEST_F(ImageDecodeToSurface, ICOMultipleSizes) {
buffer, nsDependentCString(testCase.mMimeType), metadata); buffer, nsDependentCString(testCase.mMimeType), metadata);
EXPECT_TRUE(NS_SUCCEEDED(rv)); EXPECT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(metadata.HasSize()); ASSERT_TRUE(metadata.HasSize());
EXPECT_EQ(testCase.mSize, metadata.GetSize()); EXPECT_EQ(testCase.mSize, metadata.GetSize().ToUnknownSize());
const nsTArray<IntSize>& nativeSizes = metadata.GetNativeSizes(); const nsTArray<OrientedIntSize>& nativeSizes = metadata.GetNativeSizes();
ASSERT_EQ(6u, nativeSizes.Length()); ASSERT_EQ(6u, nativeSizes.Length());
IntSize expectedSizes[] = { OrientedIntSize expectedSizes[] = {
IntSize(16, 16), IntSize(32, 32), IntSize(64, 64), OrientedIntSize(16, 16), OrientedIntSize(32, 32),
IntSize(128, 128), IntSize(256, 256), IntSize(256, 128), OrientedIntSize(64, 64), OrientedIntSize(128, 128),
OrientedIntSize(256, 256), OrientedIntSize(256, 128),
}; };
for (int i = 0; i < 6; ++i) { for (int i = 0; i < 6; ++i) {
EXPECT_EQ(expectedSizes[i], nativeSizes[i]); EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
// Request decoding at native size // Request decoding at native size
testCase.mOutputSize = nativeSizes[i]; testCase.mOutputSize = nativeSizes[i].ToUnknownSize();
RunDecodeToSurface(testCase, buffer); RunDecodeToSurface(testCase, buffer);
} }
} }

View file

@ -58,7 +58,7 @@ static already_AddRefed<SourceSurface> CheckDecoderState(
bool(progress & FLAG_IS_ANIMATED)); bool(progress & FLAG_IS_ANIMATED));
// The decoder should get the correct size. // The decoder should get the correct size.
IntSize size = aDecoder->Size(); OrientedIntSize size = aDecoder->Size();
EXPECT_EQ(aTestCase.mSize.width, size.width); EXPECT_EQ(aTestCase.mSize.width, size.width);
EXPECT_EQ(aTestCase.mSize.height, size.height); EXPECT_EQ(aTestCase.mSize.height, size.height);
@ -316,7 +316,7 @@ static void CheckAnimationDecoderResults(const ImageTestCase& aTestCase,
} }
// The decoder should get the correct size. // The decoder should get the correct size.
IntSize size = aDecoder->Size(); OrientedIntSize size = aDecoder->Size();
EXPECT_EQ(aTestCase.mSize.width, size.width); EXPECT_EQ(aTestCase.mSize.width, size.width);
EXPECT_EQ(aTestCase.mSize.height, size.height); EXPECT_EQ(aTestCase.mSize.height, size.height);

View file

@ -44,7 +44,7 @@ static void CheckDecoderState(const ImageTestCase& aTestCase,
bool(progress & FLAG_IS_ANIMATED)); bool(progress & FLAG_IS_ANIMATED));
// The decoder should get the correct size. // The decoder should get the correct size.
IntSize size = aDecoder->Size(); OrientedIntSize size = aDecoder->Size();
EXPECT_EQ(aTestCase.mSize.width, size.width); EXPECT_EQ(aTestCase.mSize.width, size.width);
EXPECT_EQ(aTestCase.mSize.height, size.height); EXPECT_EQ(aTestCase.mSize.height, size.height);

View file

@ -424,7 +424,7 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsOutput1_1) {
void WriteRowAndCheckInterlacerOutput(image::Decoder* aDecoder, void WriteRowAndCheckInterlacerOutput(image::Decoder* aDecoder,
SurfaceFilter* aFilter, BGRAColor aColor, SurfaceFilter* aFilter, BGRAColor aColor,
WriteState aNextState, WriteState aNextState,
IntRect aInvalidRect, OrientedIntRect aInvalidRect,
uint32_t aFirstHaeberliRow, uint32_t aFirstHaeberliRow,
uint32_t aLastHaeberliRow) { uint32_t aLastHaeberliRow) {
uint32_t count = 0; uint32_t count = 0;
@ -474,7 +474,7 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) {
// the end of the first pass. // the end of the first pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 0, 7, 7), 0, 4); OrientedIntRect(0, 0, 7, 7), 0, 4);
// Second pass. Rows are positioned at 8n + 4. // Second pass. Rows are positioned at 8n + 4.
@ -482,7 +482,7 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) {
// the end of the second pass. // the end of the second pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 0, 7, 7), 1, 4); OrientedIntRect(0, 0, 7, 7), 1, 4);
// Third pass. Rows are positioned at 4n + 2. // Third pass. Rows are positioned at 4n + 2.
@ -491,13 +491,13 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) {
// previous passes when seeking to the next output row (rows 4 and 5). // previous passes when seeking to the next output row (rows 4 and 5).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 2, 7, 4), 2, 3); OrientedIntRect(0, 2, 7, 4), 2, 3);
// Output row 6. The invalid rect is the entire image because this is // Output row 6. The invalid rect is the entire image because this is
// the end of the third pass. // the end of the third pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 0, 7, 7), 6, 6); OrientedIntRect(0, 0, 7, 7), 6, 6);
// Fourth pass. Rows are positioned at 2n + 1. // Fourth pass. Rows are positioned at 2n + 1.
@ -506,21 +506,21 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) {
// previous passes when seeking to the next output row (row 2). // previous passes when seeking to the next output row (row 2).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 1, 7, 2), 1, 1); OrientedIntRect(0, 1, 7, 2), 1, 1);
// Output row 3. The invalid rect contains the Haeberli rows for this // Output row 3. The invalid rect contains the Haeberli rows for this
// output row (just row 3) as well as the rows that we copy from // output row (just row 3) as well as the rows that we copy from
// previous passes when seeking to the next output row (row 4). // previous passes when seeking to the next output row (row 4).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 3, 7, 2), 3, 3); OrientedIntRect(0, 3, 7, 2), 3, 3);
// Output row 5. The invalid rect contains the Haeberli rows for this // Output row 5. The invalid rect contains the Haeberli rows for this
// output row (just row 5) as well as the rows that we copy from // output row (just row 5) as well as the rows that we copy from
// previous passes when seeking to the next output row (row 6). // previous passes when seeking to the next output row (row 6).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
WriteState::FINISHED, WriteState::FINISHED,
IntRect(0, 5, 7, 2), 5, 5); OrientedIntRect(0, 5, 7, 2), 5, 5);
// Assert that we're in the expected final state. // Assert that we're in the expected final state.
EXPECT_TRUE(aFilter->IsSurfaceFinished()); EXPECT_TRUE(aFilter->IsSurfaceFinished());
@ -557,7 +557,7 @@ TEST_F(ImageDeinterlacingFilter,
// the end of the first pass. // the end of the first pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 0, 7, 7), 0, 0); OrientedIntRect(0, 0, 7, 7), 0, 0);
// Second pass. Rows are positioned at 8n + 4. // Second pass. Rows are positioned at 8n + 4.
@ -565,7 +565,7 @@ TEST_F(ImageDeinterlacingFilter,
// the end of the second pass. // the end of the second pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 0, 7, 7), 4, 4); OrientedIntRect(0, 0, 7, 7), 4, 4);
// Third pass. Rows are positioned at 4n + 2. // Third pass. Rows are positioned at 4n + 2.
@ -574,13 +574,13 @@ TEST_F(ImageDeinterlacingFilter,
// previous passes when seeking to the next output row (rows 4 and 5). // previous passes when seeking to the next output row (rows 4 and 5).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 2, 7, 4), 2, 2); OrientedIntRect(0, 2, 7, 4), 2, 2);
// Output row 6. The invalid rect is the entire image because this is // Output row 6. The invalid rect is the entire image because this is
// the end of the third pass. // the end of the third pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 0, 7, 7), 6, 6); OrientedIntRect(0, 0, 7, 7), 6, 6);
// Fourth pass. Rows are positioned at 2n + 1. // Fourth pass. Rows are positioned at 2n + 1.
@ -589,21 +589,21 @@ TEST_F(ImageDeinterlacingFilter,
// previous passes when seeking to the next output row (row 2). // previous passes when seeking to the next output row (row 2).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 1, 7, 2), 1, 1); OrientedIntRect(0, 1, 7, 2), 1, 1);
// Output row 3. The invalid rect contains the Haeberli rows for this // Output row 3. The invalid rect contains the Haeberli rows for this
// output row (just row 3) as well as the rows that we copy from // output row (just row 3) as well as the rows that we copy from
// previous passes when seeking to the next output row (row 4). // previous passes when seeking to the next output row (row 4).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
WriteState::NEED_MORE_DATA, WriteState::NEED_MORE_DATA,
IntRect(0, 3, 7, 2), 3, 3); OrientedIntRect(0, 3, 7, 2), 3, 3);
// Output row 5. The invalid rect contains the Haeberli rows for this // Output row 5. The invalid rect contains the Haeberli rows for this
// output row (just row 5) as well as the rows that we copy from // output row (just row 5) as well as the rows that we copy from
// previous passes when seeking to the next output row (row 6). // previous passes when seeking to the next output row (row 6).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
WriteState::FINISHED, WriteState::FINISHED,
IntRect(0, 5, 7, 2), 5, 5); OrientedIntRect(0, 5, 7, 2), 5, 5);
// Assert that we're in the expected final state. // Assert that we're in the expected final state.
EXPECT_TRUE(aFilter->IsSurfaceFinished()); EXPECT_TRUE(aFilter->IsSurfaceFinished());

View file

@ -79,7 +79,7 @@ static void CheckMetadata(const ImageTestCase& aTestCase,
// Check that we got the expected metadata. // Check that we got the expected metadata.
EXPECT_TRUE(metadataProgress & FLAG_SIZE_AVAILABLE); EXPECT_TRUE(metadataProgress & FLAG_SIZE_AVAILABLE);
IntSize metadataSize = decoder->Size(); OrientedIntSize metadataSize = decoder->Size();
EXPECT_EQ(aTestCase.mSize.width, metadataSize.width); EXPECT_EQ(aTestCase.mSize.width, metadataSize.width);
if (aBMPWithinICO == BMPWithinICO::YES) { if (aBMPWithinICO == BMPWithinICO::YES) {
// Half the data is considered to be part of the AND mask if embedded // Half the data is considered to be part of the AND mask if embedded
@ -120,7 +120,7 @@ static void CheckMetadata(const ImageTestCase& aTestCase,
EXPECT_EQ(fullProgress, metadataProgress | fullProgress); EXPECT_EQ(fullProgress, metadataProgress | fullProgress);
// The full decoder and the metadata decoder should agree on the image's size. // The full decoder and the metadata decoder should agree on the image's size.
IntSize fullSize = decoder->Size(); OrientedIntSize fullSize = decoder->Size();
EXPECT_EQ(metadataSize.width, fullSize.width); EXPECT_EQ(metadataSize.width, fullSize.width);
EXPECT_EQ(metadataSize.height, fullSize.height); EXPECT_EQ(metadataSize.height, fullSize.height);

View file

@ -48,8 +48,8 @@ void CheckSurfacePipeMethodResults(SurfacePipe* aPipe, image::Decoder* aDecoder,
EXPECT_TRUE(aPipe->IsSurfaceFinished()); EXPECT_TRUE(aPipe->IsSurfaceFinished());
Maybe<SurfaceInvalidRect> invalidRect = aPipe->TakeInvalidRect(); Maybe<SurfaceInvalidRect> invalidRect = aPipe->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect);
// Check the generated image. // Check the generated image.
CheckGeneratedImage(aDecoder, aRect); CheckGeneratedImage(aDecoder, aRect);
@ -71,8 +71,8 @@ void CheckSurfacePipeMethodResults(SurfacePipe* aPipe, image::Decoder* aDecoder,
EXPECT_TRUE(aPipe->IsSurfaceFinished()); EXPECT_TRUE(aPipe->IsSurfaceFinished());
invalidRect = aPipe->TakeInvalidRect(); invalidRect = aPipe->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect);
aPipe->ResetToFirstRow(); aPipe->ResetToFirstRow();
EXPECT_FALSE(aPipe->IsSurfaceFinished()); EXPECT_FALSE(aPipe->IsSurfaceFinished());

View file

@ -222,63 +222,63 @@ TEST(ImageSurfaceSink, SurfaceSinkWritePixelsEarlyExit)
TEST(ImageSurfaceSink, SurfaceSinkWritePixelsToRow) TEST(ImageSurfaceSink, SurfaceSinkWritePixelsToRow)
{ {
WithSurfaceSink<Orient::NORMAL>( WithSurfaceSink<Orient::NORMAL>([](image::Decoder* aDecoder,
[](image::Decoder* aDecoder, SurfaceSink* aSink) { SurfaceSink* aSink) {
// Write the first 99 rows of our 100x100 surface and verify that even // Write the first 99 rows of our 100x100 surface and verify that even
// though our lambda will yield pixels forever, only one row is written // though our lambda will yield pixels forever, only one row is written
// per call to WritePixelsToRow(). // per call to WritePixelsToRow().
for (int row = 0; row < 99; ++row) { for (int row = 0; row < 99; ++row) {
uint32_t count = 0; uint32_t count = 0;
WriteState result = aSink->WritePixelsToRow<uint32_t>([&] { WriteState result = aSink->WritePixelsToRow<uint32_t>([&] {
++count; ++count;
return AsVariant(BGRAColor::Green().AsPixel()); return AsVariant(BGRAColor::Green().AsPixel());
});
EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
EXPECT_EQ(100u, count);
EXPECT_FALSE(aSink->IsSurfaceFinished());
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mOutputSpaceRect);
CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, row + 1));
}
// Write the final line, which should finish the surface.
uint32_t count = 0;
WriteState result = aSink->WritePixelsToRow<uint32_t>([&] {
++count;
return AsVariant(BGRAColor::Green().AsPixel());
});
EXPECT_EQ(WriteState::FINISHED, result);
EXPECT_EQ(100u, count);
// Note that the final invalid rect we expect here is only the last row;
// that's because we called TakeInvalidRect() repeatedly in the loop
// above.
AssertCorrectPipelineFinalState(aSink, IntRect(0, 99, 100, 1),
IntRect(0, 99, 100, 1));
// Check that the generated image is correct.
CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 100));
// Attempt to write more and make sure that nothing gets written.
count = 0;
result = aSink->WritePixelsToRow<uint32_t>([&] {
count++;
return AsVariant(BGRAColor::Red().AsPixel());
});
EXPECT_EQ(WriteState::FINISHED, result);
EXPECT_EQ(0u, count);
EXPECT_TRUE(aSink->IsSurfaceFinished());
// Check that the generated image is still correct.
CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 100));
}); });
EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
EXPECT_EQ(100u, count);
EXPECT_FALSE(aSink->IsSurfaceFinished());
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(OrientedIntRect(0, row, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, row, 100, 1), invalidRect->mOutputSpaceRect);
CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, row + 1));
}
// Write the final line, which should finish the surface.
uint32_t count = 0;
WriteState result = aSink->WritePixelsToRow<uint32_t>([&] {
++count;
return AsVariant(BGRAColor::Green().AsPixel());
});
EXPECT_EQ(WriteState::FINISHED, result);
EXPECT_EQ(100u, count);
// Note that the final invalid rect we expect here is only the last row;
// that's because we called TakeInvalidRect() repeatedly in the loop
// above.
AssertCorrectPipelineFinalState(aSink, IntRect(0, 99, 100, 1),
IntRect(0, 99, 100, 1));
// Check that the generated image is correct.
CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 100));
// Attempt to write more and make sure that nothing gets written.
count = 0;
result = aSink->WritePixelsToRow<uint32_t>([&] {
count++;
return AsVariant(BGRAColor::Red().AsPixel());
});
EXPECT_EQ(WriteState::FINISHED, result);
EXPECT_EQ(0u, count);
EXPECT_TRUE(aSink->IsSurfaceFinished());
// Check that the generated image is still correct.
CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 100));
});
} }
TEST(ImageSurfaceSink, SurfaceSinkWritePixelsToRowEarlyExit) TEST(ImageSurfaceSink, SurfaceSinkWritePixelsToRowEarlyExit)
@ -673,8 +673,8 @@ TEST(ImageSurfaceSink, SurfaceSinkWritePixelBlocksPartialRow)
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect(); Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mInputSpaceRect); EXPECT_EQ(OrientedIntRect(0, row, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mOutputSpaceRect); EXPECT_EQ(OrientedIntRect(0, row, 100, 1), invalidRect->mOutputSpaceRect);
CheckGeneratedImage(aDecoder, IntRect(20, 0, 60, row + 1)); CheckGeneratedImage(aDecoder, IntRect(20, 0, 60, row + 1));
} }
@ -794,8 +794,8 @@ TEST(ImageSurfaceSink, SurfaceSinkInvalidRect)
// Assert that we have the right invalid rect. // Assert that we have the right invalid rect.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect(); Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mInputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 0, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mOutputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 0, 100, 1), invalidRect->mOutputSpaceRect);
} }
{ {
@ -815,8 +815,8 @@ TEST(ImageSurfaceSink, SurfaceSinkInvalidRect)
// Assert that we have the right invalid rect. // Assert that we have the right invalid rect.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect(); Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mInputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 1, 100, 8), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mOutputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 1, 100, 8), invalidRect->mOutputSpaceRect);
} }
{ {
@ -857,8 +857,8 @@ TEST(ImageSurfaceSink, SurfaceSinkInvalidRect)
// left and right halves of this row now that we've completed it. // left and right halves of this row now that we've completed it.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect(); Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mInputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 9, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mOutputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 9, 100, 1), invalidRect->mOutputSpaceRect);
} }
{ {
@ -887,8 +887,8 @@ TEST(ImageSurfaceSink, SurfaceSinkInvalidRect)
// Assert that we have the right invalid rect. // Assert that we have the right invalid rect.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect(); Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mInputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 10, 100, 90), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mOutputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 10, 100, 90), invalidRect->mOutputSpaceRect);
// Check that the generated image is correct. // Check that the generated image is correct.
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
@ -948,8 +948,8 @@ TEST(ImageSurfaceSink, SurfaceSinkFlipVertically)
// *bottom* (since we're flipping vertically) 25 rows of the image. // *bottom* (since we're flipping vertically) 25 rows of the image.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect(); Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome()); EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mInputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 75, 100, 25), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mOutputSpaceRect); EXPECT_EQ(OrientedIntRect(0, 75, 100, 25), invalidRect->mOutputSpaceRect);
// Check that the generated image is correct. // Check that the generated image is correct.
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();