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);
mHaveExplicitOutputSize = true;
}
Maybe<gfx::IntSize> Decoder::ExplicitOutputSize() const {
Maybe<OrientedIntSize> Decoder::ExplicitOutputSize() const {
MOZ_ASSERT_IF(mHaveExplicitOutputSize, mOutputSize);
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.
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");
// Record this notification.
@ -486,7 +487,8 @@ void Decoder::PostFrameStop(Opacity aFrameOpacity) {
// If we're not sending partial invalidations, then we send an invalidation
// here when the first frame is complete.
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
@ -498,7 +500,7 @@ void Decoder::PostFrameStop(Opacity aFrameOpacity) {
case DisposalMethod::CLEAR:
case DisposalMethod::CLEAR_ALL:
case DisposalMethod::RESTORE_PREVIOUS:
mFirstFrameRefreshArea = IntRect(IntPoint(), Size());
mFirstFrameRefreshArea = IntRect(IntPoint(), Size().ToUnknownSize());
break;
case DisposalMethod::KEEP:
case DisposalMethod::NOT_SPECIFIED:
@ -512,8 +514,8 @@ void Decoder::PostFrameStop(Opacity aFrameOpacity) {
}
}
void Decoder::PostInvalidation(const gfx::IntRect& aRect,
const Maybe<gfx::IntRect>& aRectAtOutputSize
void Decoder::PostInvalidation(const OrientedIntRect& aRect,
const Maybe<OrientedIntRect>& aRectAtOutputSize
/* = Nothing() */) {
// We should be 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.
if (ShouldSendPartialInvalidations() && mFrameCount == 1) {
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
* the last call to TakeInvalidRect().
*/
nsIntRect TakeInvalidRect() {
nsIntRect invalidRect = mInvalidRect;
OrientedIntRect TakeInvalidRect() {
OrientedIntRect invalidRect = mInvalidRect;
mInvalidRect.SetEmpty();
return invalidRect;
}
@ -211,7 +211,7 @@ class Decoder {
*
* 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
@ -220,7 +220,7 @@ class Decoder {
*
* Illegal to call if HasSize() returns false.
*/
gfx::IntSize OutputSize() const {
OrientedIntSize OutputSize() const {
MOZ_ASSERT(HasSize());
return *mOutputSize;
}
@ -229,13 +229,13 @@ class Decoder {
* @return either the size passed to SetOutputSize() or Nothing(), indicating
* 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
* does not match.
*/
void SetExpectedSize(const gfx::IntSize& aSize) {
void SetExpectedSize(const OrientedIntSize& aSize) {
mExpectedSize.emplace(aSize);
}
@ -342,7 +342,7 @@ class Decoder {
*
* Illegal to call if HasSize() returns false.
*/
gfx::IntSize Size() const {
OrientedIntSize Size() const {
MOZ_ASSERT(HasSize());
return mImageMetadata.GetSize();
}
@ -354,8 +354,8 @@ class Decoder {
*
* Illegal to call if HasSize() returns false.
*/
gfx::IntRect FullFrame() const {
return gfx::IntRect(gfx::IntPoint(), Size());
OrientedIntRect FullFrame() const {
return OrientedIntRect(OrientedIntPoint(), Size());
}
/**
@ -369,8 +369,18 @@ class Decoder {
*
* Illegal to call if HasSize() returns false.
*/
gfx::IntRect FullOutputFrame() const {
return gfx::IntRect(gfx::IntPoint(), OutputSize());
OrientedIntRect FullOutputFrame() const {
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
@ -514,8 +524,8 @@ class Decoder {
* be supplied if we're downscaling during decode.
*/
void PostInvalidation(
const gfx::IntRect& aRect,
const Maybe<gfx::IntRect>& aRectAtOutputSize = Nothing());
const OrientedIntRect& aRect,
const Maybe<OrientedIntRect>& aRectAtOutputSize = Nothing());
// 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
@ -586,14 +596,14 @@ class Decoder {
ImageMetadata mImageMetadata;
gfx::IntRect
OrientedIntRect
mInvalidRect; // Tracks new rows as the current frame is decoded.
gfx::IntRect mRestoreDirtyRect; // Tracks an invalidation region between the
// restore frame and the previous frame.
gfx::IntRect mRecycleRect; // Tracks an invalidation region between the
// recycled frame and the current frame.
Maybe<gfx::IntSize> mOutputSize; // The size of our output surface.
Maybe<gfx::IntSize> mExpectedSize; // The expected size of the image.
gfx::IntRect mRestoreDirtyRect; // Tracks an invalidation region between the
// restore frame and the previous frame.
gfx::IntRect mRecycleRect; // Tracks an invalidation region between the
// recycled frame and the current frame.
Maybe<OrientedIntSize> mOutputSize; // The size of our output surface.
Maybe<OrientedIntSize> mExpectedSize; // The expected size of the image.
Progress mProgress;
uint32_t mFrameCount; // Number of frames, including anything in-progress

View File

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

View File

@ -13,6 +13,7 @@
#include "mozilla/NotNull.h"
#include "mozilla/gfx/2D.h"
#include "nsCOMPtr.h"
#include "Orientation.h"
#include "SurfaceFlags.h"
namespace mozilla::image {
@ -154,7 +155,7 @@ class DecoderFactory {
static already_AddRefed<Decoder> CreateDecoderForICOResource(
DecoderType aType, SourceBufferIterator&& aIterator,
NotNull<nsICODecoder*> aICODecoder, bool aIsMetadataDecode,
const Maybe<gfx::IntSize>& aExpectedSize,
const Maybe<OrientedIntSize>& aExpectedSize,
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
// is that img.decode promises won't resolve until GetCompositedFrame
// returns a frame.
UnorientedIntRect rect = UnorientedIntRect::FromUnknownRect(
OrientedIntRect rect = OrientedIntRect::FromUnknownRect(
aState.UpdateStateInternal(result, mSize));
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
// actually receives, which would cause bugs.
Progress progress = aDecoder->TakeProgress();
UnorientedIntRect invalidRect =
UnorientedIntRect::FromUnknownRect(aDecoder->TakeInvalidRect());
OrientedIntRect invalidRect = aDecoder->TakeInvalidRect();
Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
DecoderFlags decoderFlags = aDecoder->GetDecoderFlags();
SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
@ -106,8 +105,7 @@ void IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
ImageMetadata metadata = aDecoder->GetImageMetadata();
DecoderTelemetry telemetry = aDecoder->Telemetry();
Progress progress = aDecoder->TakeProgress();
UnorientedIntRect invalidRect =
UnorientedIntRect::FromUnknownRect(aDecoder->TakeInvalidRect());
OrientedIntRect invalidRect = aDecoder->TakeInvalidRect();
Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
DecoderFlags decoderFlags = aDecoder->GetDecoderFlags();
SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();

View File

@ -56,21 +56,24 @@ class ImageMetadata {
void SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation,
Resolution aResolution) {
if (!HasSize()) {
mSize.emplace(nsIntSize(aWidth, aHeight));
mSize.emplace(
aOrientation.ToOriented(UnorientedIntSize(aWidth, aHeight)));
mOrientation.emplace(aOrientation);
mResolution = aResolution;
}
}
nsIntSize GetSize() const { return *mSize; }
OrientedIntSize GetSize() const { return *mSize; }
bool HasSize() const { return mSize.isSome(); }
void AddNativeSize(const nsIntSize& aSize) {
void AddNativeSize(const OrientedIntSize& aSize) {
mNativeSizes.AppendElement(aSize);
}
Resolution GetResolution() const { return mResolution; }
const nsTArray<nsIntSize>& GetNativeSizes() const { return mNativeSizes; }
const nsTArray<OrientedIntSize>& GetNativeSizes() const {
return mNativeSizes;
}
Orientation GetOrientation() const { return *mOrientation; }
bool HasOrientation() const { return mOrientation.isSome(); }
@ -98,11 +101,11 @@ class ImageMetadata {
// loops.
Maybe<gfx::IntRect> mFirstFrameRefreshArea;
Maybe<nsIntSize> mSize;
Maybe<OrientedIntSize> mSize;
Maybe<Orientation> mOrientation;
// Sizes the image can natively decode to.
CopyableTArray<nsIntSize> mNativeSizes;
CopyableTArray<OrientedIntSize> mNativeSizes;
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
// more than once).
if (!res.mDirtyRect.IsEmpty() || res.mFrameAdvanced) {
auto dirtyRect = UnorientedIntRect::FromUnknownRect(res.mDirtyRect);
auto dirtyRect = OrientedIntRect::FromUnknownRect(res.mDirtyRect);
NotifyProgress(NoProgress, dirtyRect);
}
@ -279,7 +279,7 @@ RasterImage::GetProducerId(uint32_t* aId) {
return NS_OK;
}
LookupResult RasterImage::LookupFrameInternal(const UnorientedIntSize& aSize,
LookupResult RasterImage::LookupFrameInternal(const OrientedIntSize& aSize,
uint32_t aFlags,
PlaybackType aPlaybackType,
bool aMarkUsed) {
@ -311,7 +311,7 @@ LookupResult RasterImage::LookupFrameInternal(const UnorientedIntSize& aSize,
aMarkUsed);
}
LookupResult RasterImage::LookupFrame(const UnorientedIntSize& aSize,
LookupResult RasterImage::LookupFrame(const OrientedIntSize& aSize,
uint32_t aFlags,
PlaybackType aPlaybackType,
bool aMarkUsed) {
@ -323,8 +323,8 @@ LookupResult RasterImage::LookupFrame(const UnorientedIntSize& aSize,
aFlags &= ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA;
}
UnorientedIntSize requestedSize =
CanDownscaleDuringDecode(aSize, aFlags) ? aSize : ToUnoriented(mSize);
OrientedIntSize requestedSize =
CanDownscaleDuringDecode(aSize, aFlags) ? aSize : mSize;
if (requestedSize.IsEmpty()) {
// Can't decode to a surface of zero size.
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.
if (!result.SuggestedSize().IsEmpty()) {
MOZ_ASSERT(!syncDecode && (aFlags & FLAG_HIGH_QUALITY_SCALING));
requestedSize =
UnorientedIntSize::FromUnknownSize(result.SuggestedSize());
requestedSize = OrientedIntSize::FromUnknownSize(result.SuggestedSize());
}
bool ranSync = false, failed = false;
@ -439,10 +438,9 @@ RasterImage::WillDrawOpaqueNow() {
return false;
}
auto size = ToUnoriented(mSize);
LookupResult result = SurfaceCache::LookupBestMatch(
ImageKey(this),
RasterSurfaceKey(size.ToUnknownSize(), DefaultSurfaceFlags(),
RasterSurfaceKey(mSize.ToUnknownSize(), DefaultSurfaceFlags(),
PlaybackType::eStatic),
/* aMarkUsed = */ false);
MatchType matchType = result.Type();
@ -482,10 +480,9 @@ void RasterImage::OnSurfaceDiscardedInternal(bool aAnimatedFramesDiscarded) {
MOZ_ASSERT(StaticPrefs::image_mem_animated_discardable_AtStartup());
ReleaseImageContainer();
auto size = ToUnoriented(mSize);
IntRect rect = mAnimationState->UpdateState(this, size.ToUnknownSize());
IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
auto dirtyRect = UnorientedIntRect::FromUnknownRect(rect);
auto dirtyRect = OrientedIntRect::FromUnknownRect(rect);
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
// not waiting for the data to be loaded from the network or not passing
// FLAG_SYNC_DECODE.
LookupResult result =
LookupFrame(ToUnoriented(size), aFlags, ToPlaybackType(aWhichFrame),
/* aMarkUsed = */ true);
LookupResult result = LookupFrame(size, aFlags, ToPlaybackType(aWhichFrame),
/* aMarkUsed = */ true);
auto resultSuggestedSize =
UnorientedIntSize::FromUnknownSize(result.SuggestedSize());
@ -637,7 +633,7 @@ Tuple<ImgDrawResult, IntSize> RasterImage::GetImageContainerSize(
}
auto requestedSize = OrientedIntSize::FromUnknownSize(aRequestedSize);
if (!CanDownscaleDuringDecode(ToUnoriented(requestedSize), aFlags)) {
if (!CanDownscaleDuringDecode(requestedSize, aFlags)) {
return MakeTuple(ImgDrawResult::SUCCESS, mSize.ToUnknownSize());
}
@ -688,7 +684,7 @@ bool RasterImage::SetMetadata(const ImageMetadata& aMetadata,
mResolution = aMetadata.GetResolution();
if (aMetadata.HasSize()) {
auto metadataSize = UnorientedIntSize::FromUnknownSize(aMetadata.GetSize());
auto metadataSize = aMetadata.GetSize();
if (metadataSize.width < 0 || metadataSize.height < 0) {
NS_WARNING("Image has negative intrinsic size");
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 (LoadHasSize() &&
(metadataSize != ToUnoriented(mSize) || orientation != mOrientation)) {
(metadataSize != mSize || orientation != mOrientation)) {
NS_WARNING(
"Image changed size or orientation on redecode! "
"This should not happen!");
@ -710,11 +706,10 @@ bool RasterImage::SetMetadata(const ImageMetadata& aMetadata,
// Set the size and flag that we have it.
mOrientation = orientation;
mSize = ToOriented(metadataSize);
mSize = metadataSize;
mNativeSizes.Clear();
for (const auto& nativeSize : aMetadata.GetNativeSizes()) {
mNativeSizes.AppendElement(
ToOriented(UnorientedIntSize::FromUnknownSize(nativeSize)));
mNativeSizes.AppendElement(nativeSize);
}
StoreHasSize(true);
}
@ -722,8 +717,7 @@ bool RasterImage::SetMetadata(const ImageMetadata& aMetadata,
if (LoadHasSize() && aMetadata.HasAnimation() && !mAnimationState) {
// We're becoming animated, so initialize animation stuff.
mAnimationState.emplace(mAnimationMode);
mFrameAnimator =
MakeUnique<FrameAnimator>(this, ToUnoriented(mSize).ToUnknownSize());
mFrameAnimator = MakeUnique<FrameAnimator>(this, mSize.ToUnknownSize());
if (!StaticPrefs::image_mem_animated_discardable_AtStartup()) {
// We don't support discarding animated images (See bug 414259).
@ -846,7 +840,7 @@ RasterImage::ResetAnimation() {
mFrameAnimator->ResetAnimation(*mAnimationState);
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
// mAnimationFinished was true before entering this function.
@ -1008,10 +1002,9 @@ void RasterImage::Discard() {
if (mAnimationState) {
ReleaseImageContainer();
auto size = ToUnoriented(mSize);
IntRect rect = mAnimationState->UpdateState(this, size.ToUnknownSize());
IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
auto dirtyRect = UnorientedIntRect::FromUnknownRect(rect);
auto dirtyRect = OrientedIntRect::FromUnknownRect(rect);
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 |
FLAG_HIGH_QUALITY_SCALING;
LookupResult result =
RequestDecodeForSizeInternal(ToUnoriented(mSize), flags, aWhichFrame);
LookupResult result = RequestDecodeForSizeInternal(mSize, flags, aWhichFrame);
DrawableSurface surface = std::move(result.Surface());
return surface && surface->IsFinished();
}
@ -1072,8 +1064,7 @@ imgIContainer::DecodeResult RasterImage::RequestDecodeWithResult(
}
uint32_t flags = aFlags | FLAG_ASYNC_NOTIFY;
LookupResult result =
RequestDecodeForSizeInternal(ToUnoriented(mSize), flags, aWhichFrame);
LookupResult result = RequestDecodeForSizeInternal(mSize, flags, aWhichFrame);
DrawableSurface surface = std::move(result.Surface());
if (surface && surface->IsFinished()) {
return imgIContainer::DECODE_SURFACE_AVAILABLE;
@ -1093,15 +1084,14 @@ RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags,
return NS_ERROR_FAILURE;
}
RequestDecodeForSizeInternal(
ToUnoriented(OrientedIntSize::FromUnknownSize(aSize)), aFlags,
aWhichFrame);
RequestDecodeForSizeInternal(OrientedIntSize::FromUnknownSize(aSize), aFlags,
aWhichFrame);
return NS_OK;
}
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());
if (aWhichFrame > FRAME_MAX_VALUE) {
@ -1155,7 +1145,7 @@ static bool LaunchDecodingTask(IDecodingTask* aTask, RasterImage* aImage,
return false;
}
void RasterImage::Decode(const UnorientedIntSize& aSize, uint32_t aFlags,
void RasterImage::Decode(const OrientedIntSize& aSize, uint32_t aFlags,
PlaybackType aPlaybackType, bool& aOutRanSync,
bool& aOutFailed) {
MOZ_ASSERT(NS_IsMainThread());
@ -1212,14 +1202,13 @@ void RasterImage::Decode(const UnorientedIntSize& aSize, uint32_t aFlags,
if (animated) {
size_t currentFrame = mAnimationState->GetCurrentAnimationFrameIndex();
rv = DecoderFactory::CreateAnimationDecoder(
mDecoderType, WrapNotNull(this), mSourceBuffer,
ToUnoriented(mSize).ToUnknownSize(), decoderFlags, surfaceFlags,
currentFrame, getter_AddRefs(task));
mDecoderType, WrapNotNull(this), mSourceBuffer, mSize.ToUnknownSize(),
decoderFlags, surfaceFlags, currentFrame, getter_AddRefs(task));
} else {
rv = DecoderFactory::CreateDecoder(
mDecoderType, WrapNotNull(this), mSourceBuffer,
ToUnoriented(mSize).ToUnknownSize(), aSize.ToUnknownSize(),
decoderFlags, surfaceFlags, getter_AddRefs(task));
rv = DecoderFactory::CreateDecoder(mDecoderType, WrapNotNull(this),
mSourceBuffer, mSize.ToUnknownSize(),
aSize.ToUnknownSize(), decoderFlags,
surfaceFlags, getter_AddRefs(task));
}
if (rv == NS_ERROR_ALREADY_INITIALIZED) {
@ -1238,8 +1227,7 @@ void RasterImage::Decode(const UnorientedIntSize& aSize, uint32_t aFlags,
#ifdef DEBUG
IntRect rect =
#endif
mAnimationState->UpdateState(this, ToUnoriented(mSize).ToUnknownSize(),
false);
mAnimationState->UpdateState(this, mSize.ToUnknownSize(), false);
MOZ_ASSERT(rect.IsEmpty());
}
@ -1279,7 +1267,7 @@ RasterImage::DecodeMetadata(uint32_t aFlags) {
return NS_OK;
}
void RasterImage::RecoverFromInvalidFrames(const UnorientedIntSize& aSize,
void RasterImage::RecoverFromInvalidFrames(const OrientedIntSize& aSize,
uint32_t aFlags) {
if (!LoadHasSize()) {
return;
@ -1300,8 +1288,8 @@ void RasterImage::RecoverFromInvalidFrames(const UnorientedIntSize& aSize,
// Animated images require some special handling, because we normally require
// that they never be discarded.
if (mAnimationState) {
Decode(ToUnoriented(mSize), aFlags | FLAG_SYNC_DECODE,
PlaybackType::eAnimated, unused1, unused2);
Decode(mSize, aFlags | FLAG_SYNC_DECODE, PlaybackType::eAnimated, unused1,
unused2);
ResetAnimation();
return;
}
@ -1310,7 +1298,7 @@ void RasterImage::RecoverFromInvalidFrames(const UnorientedIntSize& aSize,
Decode(aSize, aFlags, PlaybackType::eStatic, unused1, unused2);
}
bool RasterImage::CanDownscaleDuringDecode(const UnorientedIntSize& aSize,
bool RasterImage::CanDownscaleDuringDecode(const OrientedIntSize& aSize,
uint32_t aFlags) {
// Check basic requirements: downscale-during-decode is enabled, Skia is
// 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.
UnorientedIntSize ourSize = ToUnoriented(mSize);
if (aSize.width >= ourSize.width || aSize.height >= ourSize.height) {
if (aSize.width >= mSize.width || aSize.height >= mSize.height) {
return false;
}
@ -1347,7 +1334,7 @@ bool RasterImage::CanDownscaleDuringDecode(const UnorientedIntSize& aSize,
ImgDrawResult RasterImage::DrawInternal(DrawableSurface&& aSurface,
gfxContext* aContext,
const UnorientedIntSize& aSize,
const OrientedIntSize& aSize,
const ImageRegion& aRegion,
SamplingFilter aSamplingFilter,
uint32_t aFlags, float aOpacity) {
@ -1422,7 +1409,7 @@ RasterImage::Draw(gfxContext* aContext, const IntSize& aSize,
? aFlags
: aFlags & ~FLAG_HIGH_QUALITY_SCALING;
auto size = ToUnoriented(OrientedIntSize::FromUnknownSize(aSize));
auto size = OrientedIntSize::FromUnknownSize(aSize);
LookupResult result = LookupFrame(size, flags, ToPlaybackType(aWhichFrame),
/* aMarkUsed = */ true);
if (!result) {
@ -1436,26 +1423,9 @@ RasterImage::Draw(gfxContext* aContext, const IntSize& aSize,
bool shouldRecordTelemetry =
!mDrawStartTime.IsNull() && result.Surface()->IsFinished();
ImgDrawResult drawResult;
{
gfxContextMatrixAutoSaveRestore asr;
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);
}
ImgDrawResult drawResult =
DrawInternal(std::move(result.Surface()), aContext, size, aRegion,
aSamplingFilter, flags, aOpacity);
if (shouldRecordTelemetry) {
TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime;
@ -1560,7 +1530,7 @@ void RasterImage::DoError() {
SurfaceCache::RemoveImage(ImageKey(this));
// 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);
MOZ_LOG(gImgLog, LogLevel::Error,
@ -1603,7 +1573,7 @@ RasterImage::GetFramesNotified(uint32_t* aFramesNotified) {
void RasterImage::NotifyProgress(
Progress aProgress,
const UnorientedIntRect& aInvalidRect /* = UnorientedIntRect() */,
const OrientedIntRect& aInvalidRect /* = OrientedIntRect() */,
const Maybe<uint32_t>& aFrameCount /* = Nothing() */,
DecoderFlags aDecoderFlags /* = DefaultDecoderFlags() */,
SurfaceFlags aSurfaceFlags /* = DefaultSurfaceFlags() */) {
@ -1612,7 +1582,7 @@ void RasterImage::NotifyProgress(
// Ensure that we stay alive long enough to finish notifying.
RefPtr<RasterImage> image = this;
UnorientedIntRect invalidRect = aInvalidRect;
OrientedIntRect invalidRect = aInvalidRect;
if (!(aDecoderFlags & DecoderFlags::FIRST_FRAME_ONLY)) {
// We may have decoded new animation frames; update our animation state.
@ -1628,32 +1598,29 @@ void RasterImage::NotifyProgress(
}
if (mAnimationState) {
auto size = ToUnoriented(mSize);
IntRect rect = mAnimationState->UpdateState(this, size.ToUnknownSize());
IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
invalidRect.UnionRect(invalidRect,
UnorientedIntRect::FromUnknownRect(rect));
OrientedIntRect::FromUnknownRect(rect));
}
}
const bool wasDefaultFlags = aSurfaceFlags == DefaultSurfaceFlags();
auto orientedInvalidRect = ToOriented(invalidRect);
if (!orientedInvalidRect.IsEmpty() && wasDefaultFlags) {
if (!invalidRect.IsEmpty() && wasDefaultFlags) {
// Update our image container since we're invalidating.
UpdateImageContainer(Some(orientedInvalidRect.ToUnknownRect()));
UpdateImageContainer(Some(invalidRect.ToUnknownRect()));
}
// Tell the observers what happened.
image->mProgressTracker->SyncNotifyProgress(
aProgress, orientedInvalidRect.ToUnknownRect());
image->mProgressTracker->SyncNotifyProgress(aProgress,
invalidRect.ToUnknownRect());
}
void RasterImage::NotifyDecodeComplete(
const DecoderFinalStatus& aStatus, const ImageMetadata& aMetadata,
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) {
MOZ_ASSERT(NS_IsMainThread());
@ -1668,8 +1635,7 @@ void RasterImage::NotifyDecodeComplete(
// This indicates a serious error that requires us to discard all existing
// surfaces and redecode to recover. We'll drop the results from this
// decoder on the floor, since they aren't valid.
RecoverFromInvalidFrames(ToUnoriented(mSize),
FromSurfaceFlags(aSurfaceFlags));
RecoverFromInvalidFrames(mSize, FromSurfaceFlags(aSurfaceFlags));
return;
}
@ -1704,11 +1670,10 @@ void RasterImage::NotifyDecodeComplete(
// expect anymore.
mAnimationState->NotifyDecodeComplete();
auto size = ToUnoriented(mSize);
IntRect rect = mAnimationState->UpdateState(this, size.ToUnknownSize());
IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
if (!rect.IsEmpty()) {
auto dirtyRect = UnorientedIntRect::FromUnknownRect(rect);
auto dirtyRect = OrientedIntRect::FromUnknownRect(rect);
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 (LoadWantFullDecode()) {
StoreWantFullDecode(false);
RequestDecodeForSize(mSize.ToUnknownSize(),
DECODE_FLAGS_DEFAULT | FLAG_HIGH_QUALITY_SCALING,
FRAME_CURRENT);
RequestDecodeForSizeInternal(
mSize, DECODE_FLAGS_DEFAULT | FLAG_HIGH_QUALITY_SCALING,
FRAME_CURRENT);
}
}
}
@ -1806,7 +1771,7 @@ IntSize RasterImage::OptimalImageSizeForDest(const gfxSize& aDest,
IntSize::Ceil(aDest.width, aDest.height));
if (aSamplingFilter == SamplingFilter::GOOD &&
CanDownscaleDuringDecode(ToUnoriented(dest), aFlags)) {
CanDownscaleDuringDecode(dest, aFlags)) {
return dest.ToUnknownSize();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -141,7 +141,7 @@ void nsGIFDecoder2::BeginGIF() {
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.
if (mGIFStruct.is_transparent) {
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
// 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)) {
PostHasTransparency();
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) {
MOZ_ASSERT(HasSize());
@ -176,7 +177,7 @@ nsresult nsGIFDecoder2::BeginImageFrame(const IntRect& aFrameRect,
Maybe<AnimationParams> animParams;
if (!IsFirstFrameDecode()) {
animParams.emplace(aFrameRect,
animParams.emplace(aFrameRect.ToUnknownRect(),
FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time),
uint32_t(mGIFStruct.images_decoded), BlendMethod::OVER,
DisposalMethod(mGIFStruct.disposal_method));
@ -752,7 +753,7 @@ LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadImageDescriptor(
LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::FinishImageDescriptor(
const char* aData) {
IntRect frameRect;
OrientedIntRect frameRect;
// Get image offsets with respect to the screen origin.
frameRect.SetRect(

View File

@ -50,7 +50,7 @@ class nsGIFDecoder2 : public Decoder {
* @param aDepth The palette depth of this 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);
/// 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
/// 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.
int ClearCode() const {

View File

@ -154,7 +154,7 @@ LexerTransition<ICOState> nsICODecoder::ReadDirEntry(const char* aData) {
e.mBitCount = LittleEndian::readUint16(aData + 6);
e.mBytesInRes = LittleEndian::readUint32(aData + 8);
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
// 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
// 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
// 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
// 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();
@ -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.
bool metadataDecode = mReturnIterator.isSome();
Maybe<IntSize> expectedSize =
Maybe<OrientedIntSize> expectedSize =
metadataDecode ? Nothing() : Some(mDirEntry->mSize);
mContainedDecoder = DecoderFactory::CreateDecoderForICOResource(
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
// is the AND mask, which isn't present in standalone BMPs.
bool metadataDecode = mReturnIterator.isSome();
Maybe<IntSize> expectedSize =
Maybe<OrientedIntSize> expectedSize =
metadataDecode ? Nothing() : Some(mDirEntry->mSize);
mContainedDecoder = DecoderFactory::CreateDecoderForICOResource(
DecoderType::BMP, std::move(containedIterator.ref()), WrapNotNull(this),
@ -491,10 +491,10 @@ LexerTransition<ICOState> nsICODecoder::PrepareForMask() {
mDownscaler->TargetSize().width *
mDownscaler->TargetSize().height * sizeof(uint32_t));
mMaskBuffer = MakeUnique<uint8_t[]>(bmpDecoder->GetImageDataLength());
nsresult rv =
mDownscaler->BeginFrame(mDirEntry->mSize, Nothing(), mMaskBuffer.get(),
/* aHasAlpha = */ true,
/* aFlipVertically = */ true);
nsresult rv = mDownscaler->BeginFrame(mDirEntry->mSize.ToUnknownSize(),
Nothing(), mMaskBuffer.get(),
/* aHasAlpha = */ true,
/* aFlipVertically = */ true);
if (NS_FAILED(rv)) {
return Transition::TerminateFailure();
}

View File

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

View File

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

View File

@ -130,7 +130,7 @@ nsPNGDecoder::~nsPNGDecoder() {
}
nsPNGDecoder::TransparencyType nsPNGDecoder::GetTransparencyType(
const IntRect& aFrameRect) {
const OrientedIntRect& aFrameRect) {
// Check if the image has a transparent color in its palette.
if (HasAlphaChannel()) {
return TransparencyType::eAlpha;
@ -194,7 +194,7 @@ nsresult nsPNGDecoder::CreateFrame(const FrameInfo& aFrameInfo) {
}
animParams.emplace(
AnimationParams{aFrameInfo.mFrameRect,
AnimationParams{aFrameInfo.mFrameRect.ToUnknownRect(),
FrameTimeout::FromRawMilliseconds(mAnimInfo.mTimeout),
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,
&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
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
// it when we return from the yield.
const IntRect frameRect(png_get_next_frame_x_offset(png_ptr, decoder->mInfo),
png_get_next_frame_y_offset(png_ptr, decoder->mInfo),
png_get_next_frame_width(png_ptr, decoder->mInfo),
png_get_next_frame_height(png_ptr, decoder->mInfo));
const OrientedIntRect frameRect(
png_get_next_frame_x_offset(png_ptr, decoder->mInfo),
png_get_next_frame_y_offset(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);
# ifndef MOZ_EMBEDDED_LIBPNG

View File

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

View File

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

View File

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

View File

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

View File

@ -151,21 +151,22 @@ TEST_F(ImageDecodeToSurface, ICOMultipleSizes) {
buffer, nsDependentCString(testCase.mMimeType), metadata);
EXPECT_TRUE(NS_SUCCEEDED(rv));
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());
IntSize expectedSizes[] = {
IntSize(16, 16), IntSize(32, 32), IntSize(64, 64),
IntSize(128, 128), IntSize(256, 256), IntSize(256, 128),
OrientedIntSize expectedSizes[] = {
OrientedIntSize(16, 16), OrientedIntSize(32, 32),
OrientedIntSize(64, 64), OrientedIntSize(128, 128),
OrientedIntSize(256, 256), OrientedIntSize(256, 128),
};
for (int i = 0; i < 6; ++i) {
EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
// Request decoding at native size
testCase.mOutputSize = nativeSizes[i];
testCase.mOutputSize = nativeSizes[i].ToUnknownSize();
RunDecodeToSurface(testCase, buffer);
}
}

View File

@ -58,7 +58,7 @@ static already_AddRefed<SourceSurface> CheckDecoderState(
bool(progress & FLAG_IS_ANIMATED));
// 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.height, size.height);
@ -316,7 +316,7 @@ static void CheckAnimationDecoderResults(const ImageTestCase& aTestCase,
}
// 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.height, size.height);

View File

@ -44,7 +44,7 @@ static void CheckDecoderState(const ImageTestCase& aTestCase,
bool(progress & FLAG_IS_ANIMATED));
// 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.height, size.height);

View File

@ -424,7 +424,7 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsOutput1_1) {
void WriteRowAndCheckInterlacerOutput(image::Decoder* aDecoder,
SurfaceFilter* aFilter, BGRAColor aColor,
WriteState aNextState,
IntRect aInvalidRect,
OrientedIntRect aInvalidRect,
uint32_t aFirstHaeberliRow,
uint32_t aLastHaeberliRow) {
uint32_t count = 0;
@ -474,7 +474,7 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) {
// the end of the first pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
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.
@ -482,7 +482,7 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) {
// the end of the second pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
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.
@ -491,13 +491,13 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) {
// previous passes when seeking to the next output row (rows 4 and 5).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
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
// the end of the third pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
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.
@ -506,21 +506,21 @@ TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) {
// previous passes when seeking to the next output row (row 2).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
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 (just row 3) as well as the rows that we copy from
// previous passes when seeking to the next output row (row 4).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
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 (just row 5) as well as the rows that we copy from
// previous passes when seeking to the next output row (row 6).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
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.
EXPECT_TRUE(aFilter->IsSurfaceFinished());
@ -557,7 +557,7 @@ TEST_F(ImageDeinterlacingFilter,
// the end of the first pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
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.
@ -565,7 +565,7 @@ TEST_F(ImageDeinterlacingFilter,
// the end of the second pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
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.
@ -574,13 +574,13 @@ TEST_F(ImageDeinterlacingFilter,
// previous passes when seeking to the next output row (rows 4 and 5).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
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
// the end of the third pass.
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
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.
@ -589,21 +589,21 @@ TEST_F(ImageDeinterlacingFilter,
// previous passes when seeking to the next output row (row 2).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
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 (just row 3) as well as the rows that we copy from
// previous passes when seeking to the next output row (row 4).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
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 (just row 5) as well as the rows that we copy from
// previous passes when seeking to the next output row (row 6).
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
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.
EXPECT_TRUE(aFilter->IsSurfaceFinished());

View File

@ -79,7 +79,7 @@ static void CheckMetadata(const ImageTestCase& aTestCase,
// Check that we got the expected metadata.
EXPECT_TRUE(metadataProgress & FLAG_SIZE_AVAILABLE);
IntSize metadataSize = decoder->Size();
OrientedIntSize metadataSize = decoder->Size();
EXPECT_EQ(aTestCase.mSize.width, metadataSize.width);
if (aBMPWithinICO == BMPWithinICO::YES) {
// 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);
// 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.height, fullSize.height);

View File

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

View File

@ -222,63 +222,63 @@ TEST(ImageSurfaceSink, SurfaceSinkWritePixelsEarlyExit)
TEST(ImageSurfaceSink, SurfaceSinkWritePixelsToRow)
{
WithSurfaceSink<Orient::NORMAL>(
[](image::Decoder* aDecoder, SurfaceSink* aSink) {
// 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
// per call to WritePixelsToRow().
for (int row = 0; row < 99; ++row) {
uint32_t count = 0;
WriteState result = aSink->WritePixelsToRow<uint32_t>([&] {
++count;
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));
WithSurfaceSink<Orient::NORMAL>([](image::Decoder* aDecoder,
SurfaceSink* aSink) {
// 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
// per call to WritePixelsToRow().
for (int row = 0; row < 99; ++row) {
uint32_t count = 0;
WriteState result = aSink->WritePixelsToRow<uint32_t>([&] {
++count;
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(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)
@ -673,8 +673,8 @@ TEST(ImageSurfaceSink, SurfaceSinkWritePixelBlocksPartialRow)
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);
EXPECT_EQ(OrientedIntRect(0, row, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, row, 100, 1), invalidRect->mOutputSpaceRect);
CheckGeneratedImage(aDecoder, IntRect(20, 0, 60, row + 1));
}
@ -794,8 +794,8 @@ TEST(ImageSurfaceSink, SurfaceSinkInvalidRect)
// Assert that we have the right invalid rect.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mOutputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 0, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 0, 100, 1), invalidRect->mOutputSpaceRect);
}
{
@ -815,8 +815,8 @@ TEST(ImageSurfaceSink, SurfaceSinkInvalidRect)
// Assert that we have the right invalid rect.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mOutputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 1, 100, 8), invalidRect->mInputSpaceRect);
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.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mOutputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 9, 100, 1), invalidRect->mInputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 9, 100, 1), invalidRect->mOutputSpaceRect);
}
{
@ -887,8 +887,8 @@ TEST(ImageSurfaceSink, SurfaceSinkInvalidRect)
// Assert that we have the right invalid rect.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mOutputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 10, 100, 90), invalidRect->mInputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 10, 100, 90), invalidRect->mOutputSpaceRect);
// Check that the generated image is correct.
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
@ -948,8 +948,8 @@ TEST(ImageSurfaceSink, SurfaceSinkFlipVertically)
// *bottom* (since we're flipping vertically) 25 rows of the image.
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isSome());
EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mInputSpaceRect);
EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mOutputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 75, 100, 25), invalidRect->mInputSpaceRect);
EXPECT_EQ(OrientedIntRect(0, 75, 100, 25), invalidRect->mOutputSpaceRect);
// Check that the generated image is correct.
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();