Commit 13b0436d authored by Stephen Chenney's avatar Stephen Chenney Committed by Chromium LUCI CQ

Maintain aspect ratio when object-fit: cover used on a rotated image

When a bitmapped image is rotated (due to embedded EXIF orientation
information) the ImagePainter::PaintIntoRect function incorrectly
computed the source rectangle using the unrotated image. This CL
corrects that shortcoming, ensuring that the image's aspect ratio is
maintained.

From a patch by Eric Lawrence now with tests.

Bug: 1082669
Change-Id: I667883481132986cb5a33edd269ab10ac1d29ee7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2639804
Commit-Queue: Stephen Chenney <schenney@chromium.org>
Reviewed-by: default avatarFredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#845213}
parent 69031e66
...@@ -205,10 +205,13 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context, ...@@ -205,10 +205,13 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
if (!image || image->IsNull()) if (!image || image->IsNull())
return; return;
// Do not respect the image orientation when computing the source rect. It is // Get the oriented source rect in order to correctly clip. We check the
// in the un-orientated dimensions. // default orientation first to avoid expensive transform operations.
FloatRect src_rect(FloatPoint(), auto respect_orientation = image->HasDefaultOrientation()
image->SizeAsFloat(kDoNotRespectImageOrientation)); ? kDoNotRespectImageOrientation
: image_resource.ImageOrientation();
FloatRect src_rect(FloatPoint(), image->SizeAsFloat(respect_orientation));
// If the content rect requires clipping, adjust |srcRect| and // If the content rect requires clipping, adjust |srcRect| and
// |pixelSnappedDestRect| over using a clip. // |pixelSnappedDestRect| over using a clip.
if (!content_rect.Contains(dest_rect)) { if (!content_rect.Contains(dest_rect)) {
...@@ -221,6 +224,13 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context, ...@@ -221,6 +224,13 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
pixel_snapped_dest_rect = pixel_snapped_content_rect; pixel_snapped_dest_rect = pixel_snapped_content_rect;
} }
// Undo the image orientation in the source rect because subsequent code
// expects the source rect in unoriented image space.
if (respect_orientation == kRespectImageOrientation) {
src_rect = image->CorrectSrcRectForImageOrientation(
image->SizeAsFloat(respect_orientation), src_rect);
}
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data", "data",
inspector_paint_image_event::Data(layout_image_, src_rect, inspector_paint_image_event::Data(layout_image_, src_rect,
...@@ -254,7 +264,7 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context, ...@@ -254,7 +264,7 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
context.DrawImage(image.get(), decode_mode, context.DrawImage(image.get(), decode_mode,
FloatRect(pixel_snapped_dest_rect), &src_rect, FloatRect(pixel_snapped_dest_rect), &src_rect,
layout_image_.StyleRef().HasFilterInducingProperty(), layout_image_.StyleRef().HasFilterInducingProperty(),
SkBlendMode::kSrcOver, image_resource.ImageOrientation()); SkBlendMode::kSrcOver, respect_orientation);
if (ImageResourceContent* image_content = image_resource.CachedImage()) { if (ImageResourceContent* image_content = image_resource.CachedImage()) {
if ((IsA<HTMLImageElement>(node) || IsA<HTMLVideoElement>(node)) && if ((IsA<HTMLImageElement>(node) || IsA<HTMLVideoElement>(node)) &&
......
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Images Module Level 3: image-orientation: from-image</title>
<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
<link rel="match" href="reference/image-orientation-img-object-fit-ref.html">
<meta name=fuzzy content="0-5;0-375">
<style>
body {
overflow: hidden;
image-orientation: from-image;
}
img {
position: absolute;
vertical-align: top;
}
.cover {
object-fit: cover;
top: 10px;
}
.contain {
object-fit: contain;
top: 150px;
}
.wide {
width: 100px;
height: 50px;
left: 10px;
}
.tall {
width: 50px;
height: 100px;
left: 150px;
}
</style>
</head>
<body>
<img class="cover wide" src="support/exif-orientation-5-lu.jpg"/>
<img class="cover tall" src="support/exif-orientation-5-lu.jpg"/>
<img class="contain wide" src="support/exif-orientation-5-lu.jpg"/>
<img class="contain tall" src="support/exif-orientation-5-lu.jpg"/>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Images Module Level 3: image-orientation: from-image</title>
<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
<style>
body {
overflow: hidden;
image-orientation: from-image;
}
img {
position: absolute;
vertical-align: top;
}
.cover {
object-fit: cover;
top: 10px;
}
.contain {
object-fit: contain;
top: 150px;
}
.wide {
width: 100px;
height: 50px;
left: 10px;
}
.tall {
width: 50px;
height: 100px;
left: 150px;
}
</style>
</head>
<body>
<img class="cover wide" src="../support/exif-orientation-5-lu-pre-rotated.jpg"/>
<img class="cover tall" src="../support/exif-orientation-5-lu-pre-rotated.jpg"/>
<img class="contain wide" src="../support/exif-orientation-5-lu-pre-rotated.jpg"/>
<img class="contain tall" src="../support/exif-orientation-5-lu-pre-rotated.jpg"/>
</body>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment