nsIntSize ClippedImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, SamplingFilter aSamplingFilter, uint32_t aFlags) { if (!ShouldClip()) { return InnerImage()->OptimalImageSizeForDest(aDest, aWhichFrame, aSamplingFilter, aFlags); } int32_t imgWidth, imgHeight; bool needScale = false; bool forceUniformScaling = false; if (mSVGViewportSize && !mSVGViewportSize->IsEmpty()) { imgWidth = mSVGViewportSize->width; imgHeight = mSVGViewportSize->height; needScale = true; forceUniformScaling = (aFlags & imgIContainer::FLAG_FORCE_UNIFORM_SCALING); } else if (NS_SUCCEEDED(InnerImage()->GetWidth(&imgWidth)) && NS_SUCCEEDED(InnerImage()->GetHeight(&imgHeight))) { needScale = true; } if (needScale) { // To avoid ugly sampling artifacts, ClippedImage needs the image size to // be chosen such that the clipping region lies on pixel boundaries. // First, we select a scale that's good for ClippedImage. An integer // multiple of the size of the clipping region is always fine. IntSize scale = IntSize::Ceil(aDest.width / mClip.width, aDest.height / mClip.height); if (forceUniformScaling) { scale.width = scale.height = max(scale.height, scale.width); } // Determine the size we'd prefer to render the inner image at, and ask the // inner image what size we should actually use. gfxSize desiredSize(imgWidth * scale.width, imgHeight * scale.height); nsIntSize innerDesiredSize = InnerImage()->OptimalImageSizeForDest(desiredSize, aWhichFrame, aSamplingFilter, aFlags); // To get our final result, we take the inner image's desired size and // determine how large the clipped region would be at that scale. (Again, we // ensure an integer multiple of the size of the clipping region.) IntSize finalScale = IntSize::Ceil(double(innerDesiredSize.width) / imgWidth, double(innerDesiredSize.height) / imgHeight); return mClip.Size() * finalScale; } MOZ_ASSERT(false, "If ShouldClip() led us to draw then we should never get here"); return InnerImage()->OptimalImageSizeForDest(aDest, aWhichFrame, aSamplingFilter, aFlags); }
ClippedImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) { if (!ShouldClip()) { return InnerImage()->GetImageSpaceInvalidationRect(aRect); } nsIntRect rect(InnerImage()->GetImageSpaceInvalidationRect(aRect)); rect = rect.Intersect(mClip); rect.MoveBy(-mClip.x, -mClip.y); return rect; }
ClippedImage::Draw(gfxContext* aContext, const nsIntSize& aSize, const ImageRegion& aRegion, uint32_t aWhichFrame, SamplingFilter aSamplingFilter, const Maybe<SVGImageContext>& aSVGContext, uint32_t aFlags, float aOpacity) { if (!ShouldClip()) { return InnerImage()->Draw(aContext, aSize, aRegion, aWhichFrame, aSamplingFilter, aSVGContext, aFlags, aOpacity); } // Check for tiling. If we need to tile then we need to create a // gfxCallbackDrawable to handle drawing for us. if (MustCreateSurface(aContext, aSize, aRegion, aFlags)) { // Create a temporary surface containing a single tile of this image. // GetFrame will call DrawSingleTile internally. DrawResult result; RefPtr<SourceSurface> surface; Tie(result, surface) = GetFrameInternal(aSize, aSVGContext, aWhichFrame, aFlags, aOpacity); if (!surface) { MOZ_ASSERT(result != DrawResult::SUCCESS); return result; } // Create a drawable from that surface. RefPtr<gfxSurfaceDrawable> drawable = new gfxSurfaceDrawable(surface, aSize); // Draw. gfxUtils::DrawPixelSnapped(aContext, drawable, aSize, aRegion, SurfaceFormat::B8G8R8A8, aSamplingFilter, aOpacity); return result; } return DrawSingleTile(aContext, aSize, aRegion, aWhichFrame, aSamplingFilter, aSVGContext, aFlags, aOpacity); }
nsIntSize ClippedImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, GraphicsFilter aFilter, uint32_t aFlags) { if (!ShouldClip()) { return InnerImage()->OptimalImageSizeForDest(aDest, aWhichFrame, aFilter, aFlags); } int32_t imgWidth, imgHeight; if (NS_SUCCEEDED(InnerImage()->GetWidth(&imgWidth)) && NS_SUCCEEDED(InnerImage()->GetHeight(&imgHeight))) { // To avoid ugly sampling artifacts, ClippedImage needs the image size to // be chosen such that the clipping region lies on pixel boundaries. // First, we select a scale that's good for ClippedImage. An integer // multiple of the size of the clipping region is always fine. nsIntSize scale(ceil(aDest.width / mClip.width), ceil(aDest.height / mClip.height)); // Determine the size we'd prefer to render the inner image at, and ask the // inner image what size we should actually use. gfxSize desiredSize(imgWidth * scale.width, imgHeight * scale.height); nsIntSize innerDesiredSize = InnerImage()->OptimalImageSizeForDest(desiredSize, aWhichFrame, aFilter, aFlags); // To get our final result, we take the inner image's desired size and // determine how large the clipped region would be at that scale. (Again, we // ensure an integer multiple of the size of the clipping region.) nsIntSize finalScale(ceil(double(innerDesiredSize.width) / imgWidth), ceil(double(innerDesiredSize.height) / imgHeight)); return mClip.Size() * finalScale; } else { MOZ_ASSERT(false, "If ShouldClip() led us to draw then we should never get here"); return InnerImage()->OptimalImageSizeForDest(aDest, aWhichFrame, aFilter, aFlags); } }