Bug 1709622 - Apply EXIF resolution to SurfaceFromElement. r=tnikkel,jrmuizel,jgilbert
And make sure we return the surface of the right size for canvas, which makes that assumption in a bunch of places. Depends on D114686 Differential Revision: https://phabricator.services.mozilla.com/D114687
This commit is contained in:
@@ -2185,6 +2185,7 @@ already_AddRefed<CanvasPattern> CanvasRenderingContext2D::CreatePattern(
|
||||
// The canvas spec says that createPattern should use the first frame
|
||||
// of animated images
|
||||
auto flags = nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE |
|
||||
nsLayoutUtils::SFE_EXACT_SIZE_SURFACE |
|
||||
nsLayoutUtils::SFE_TO_SRGB_COLORSPACE;
|
||||
SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(element, flags, mTarget);
|
||||
@@ -4528,6 +4529,7 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
||||
// of animated images. We also don't want to rasterize vector images.
|
||||
uint32_t sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE |
|
||||
nsLayoutUtils::SFE_NO_RASTERIZING_VECTORS |
|
||||
nsLayoutUtils::SFE_EXACT_SIZE_SURFACE |
|
||||
nsLayoutUtils::SFE_TO_SRGB_COLORSPACE;
|
||||
|
||||
SurfaceFromElementResult res =
|
||||
|
||||
@@ -165,6 +165,7 @@ Maybe<webgl::TexUnpackBlobDesc> FromDomElem(const ClientWebGLContext& webgl,
|
||||
// same as drawImage.
|
||||
uint32_t flags = nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE |
|
||||
nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR |
|
||||
nsLayoutUtils::SFE_EXACT_SIZE_SURFACE |
|
||||
nsLayoutUtils::SFE_ALLOW_NON_PREMULT;
|
||||
const auto& unpacking = webgl.State().mPixelUnpackState;
|
||||
if (unpacking.mColorspaceConversion == LOCAL_GL_NONE) {
|
||||
|
||||
@@ -6982,6 +6982,29 @@ SurfaceFromElementResult nsLayoutUtils::SurfaceFromOffscreenCanvas(
|
||||
return result;
|
||||
}
|
||||
|
||||
static RefPtr<SourceSurface> ScaleSourceSurface(SourceSurface& aSurface,
|
||||
const IntSize& aTargetSize) {
|
||||
const IntSize surfaceSize = aSurface.GetSize();
|
||||
|
||||
MOZ_ASSERT(surfaceSize != aTargetSize);
|
||||
MOZ_ASSERT(!surfaceSize.IsEmpty());
|
||||
MOZ_ASSERT(!aTargetSize.IsEmpty());
|
||||
|
||||
RefPtr<DrawTarget> dt = Factory::CreateDrawTarget(
|
||||
gfxVars::ContentBackend(), aTargetSize, aSurface.GetFormat());
|
||||
|
||||
if (!dt || !dt->IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
|
||||
MOZ_ASSERT(context);
|
||||
|
||||
dt->DrawSurface(&aSurface, Rect(Point(), Size(aTargetSize)),
|
||||
Rect(Point(), Size(surfaceSize)));
|
||||
return dt->GetBackingSurface();
|
||||
}
|
||||
|
||||
SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(
|
||||
nsIImageLoadingContent* aElement, uint32_t aSurfaceFlags,
|
||||
RefPtr<DrawTarget>& aTarget) {
|
||||
@@ -7039,11 +7062,13 @@ SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(
|
||||
}
|
||||
imgContainer = OrientImage(imgContainer, orientation);
|
||||
|
||||
uint32_t noRasterize = aSurfaceFlags & SFE_NO_RASTERIZING_VECTORS;
|
||||
const bool noRasterize = aSurfaceFlags & SFE_NO_RASTERIZING_VECTORS;
|
||||
|
||||
uint32_t whichFrame = (aSurfaceFlags & SFE_WANT_FIRST_FRAME_IF_IMAGE)
|
||||
uint32_t whichFrame = aSurfaceFlags & SFE_WANT_FIRST_FRAME_IF_IMAGE
|
||||
? (uint32_t)imgIContainer::FRAME_FIRST
|
||||
: (uint32_t)imgIContainer::FRAME_CURRENT;
|
||||
const bool exactSize = aSurfaceFlags & SFE_EXACT_SIZE_SURFACE;
|
||||
|
||||
uint32_t frameFlags =
|
||||
imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY;
|
||||
if (aSurfaceFlags & SFE_NO_COLORSPACE_CONVERSION)
|
||||
@@ -7066,9 +7091,9 @@ SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(
|
||||
rv = imgContainer->GetWidth(&imgWidth);
|
||||
nsresult rv2 = imgContainer->GetHeight(&imgHeight);
|
||||
if (NS_FAILED(rv) || NS_FAILED(rv2)) return result;
|
||||
imgContainer->GetResolution().ApplyTo(imgWidth, imgHeight);
|
||||
}
|
||||
result.mSize = IntSize(imgWidth, imgHeight);
|
||||
result.mIntrinsicSize = IntSize(imgWidth, imgHeight);
|
||||
result.mSize = result.mIntrinsicSize = IntSize(imgWidth, imgHeight);
|
||||
|
||||
if (!noRasterize || imgContainer->GetType() == imgIContainer::TYPE_RASTER) {
|
||||
result.mSourceSurface =
|
||||
@@ -7076,6 +7101,13 @@ SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(
|
||||
if (!result.mSourceSurface) {
|
||||
return result;
|
||||
}
|
||||
if (exactSize && result.mSourceSurface->GetSize() != result.mSize) {
|
||||
result.mSourceSurface =
|
||||
ScaleSourceSurface(*result.mSourceSurface, result.mSize);
|
||||
if (!result.mSourceSurface) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// The surface we return is likely to be cached. We don't want to have to
|
||||
// convert to a surface that's compatible with aTarget each time it's used
|
||||
// (that would result in terrible performance), so we convert once here
|
||||
|
||||
@@ -2165,6 +2165,12 @@ class nsLayoutUtils {
|
||||
/* Instead of converting the colorspace to the display's colorspace,
|
||||
use sRGB. */
|
||||
SFE_TO_SRGB_COLORSPACE = 1 << 5,
|
||||
/* Ensure that the returned surface has a size that matches the
|
||||
* SurfaceFromElementResult::mSize. This is mostly a convenience thing so
|
||||
* that callers who want this don't have to deal with it themselves.
|
||||
* The surface might be different for, e.g., a EXIF-scaled raster image, if
|
||||
* we don't rescale during decode. */
|
||||
SFE_EXACT_SIZE_SURFACE = 1 << 6,
|
||||
};
|
||||
|
||||
// This function can be called on any thread.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[density-corrected-image-in-canvas.html]
|
||||
[resources/exif-resolution-valid-hires.jpg: 2d]
|
||||
expected: FAIL
|
||||
[resources/exif-resolution-valid-lores.jpg: 2d]
|
||||
expected: FAIL
|
||||
Reference in New Issue
Block a user