CanvasRenderingContext2D.drawImage should ignore the EXIF orientation if the image-orientation is none
https://bugs.webkit.org/show_bug.cgi?id=209849
Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-04-06
Reviewed by Darin Adler.
Source/WebCore:
drawImage() will get the image-orientation of the HTMLImageElement from
its computed style. This will be passed to GraphicsContext::drawImage()
in the ImagePaintingOptions. Previously we were passing FromImage always.
Test: fast/images/image-orientation-none-canvas.html
* html/canvas/CanvasRenderingContext2DBase.cpp:
(WebCore::CanvasRenderingContext2DBase::drawImage):
* html/canvas/CanvasRenderingContext2DBase.h:
LayoutTests:
* fast/images/image-orientation-none-canvas-expected.html: Added.
* fast/images/image-orientation-none-canvas.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@259567 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 03f1276..cf601bd 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2020-04-06 Said Abou-Hallawa <sabouhallawa@apple.com>
+
+ CanvasRenderingContext2D.drawImage should ignore the EXIF orientation if the image-orientation is none
+ https://bugs.webkit.org/show_bug.cgi?id=209849
+
+ Reviewed by Darin Adler.
+
+ * fast/images/image-orientation-none-canvas-expected.html: Added.
+ * fast/images/image-orientation-none-canvas.html: Added.
+
2020-04-05 Manuel Rego Casasnovas <rego@igalia.com>
Computed style for "outline-offset" is wrong when "outline-style" is "none"
diff --git a/LayoutTests/fast/images/image-orientation-none-canvas-expected.html b/LayoutTests/fast/images/image-orientation-none-canvas-expected.html
new file mode 100644
index 0000000..e1dc592
--- /dev/null
+++ b/LayoutTests/fast/images/image-orientation-none-canvas-expected.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<style>
+ div.container {
+ display: inline-block;
+ margin-right: 20px;
+ margin-bottom: 10px;
+ width: 100px;
+ vertical-align: top;
+ }
+ div.box {
+ width: 102px;
+ height: 52px;
+ }
+ canvas {
+ border: 1px solid black;
+ width: 100px;
+ height: 50px;
+ }
+</style>
+<body>
+ <b>CanvasRenderingContext2D.drawImage() should ignore the image's EXIF orientation if its style image-orientation is set to "none".</b>
+ <br>
+ <br>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas1"></canvas>
+ </div>
+ <br>Normal
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas2"></canvas>
+ </div>
+ <br>Flipped horizontally
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas3"></canvas>
+ </div>
+ <br>Rotated 180°
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas4"></canvas>
+ </div>
+ <br>Flipped vertically
+ </div>
+ <br>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas5"></canvas>
+ </div>
+ <br>Rotated 90° CCW and flipped vertically
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas6"></canvas>
+ </div>
+ <br>Rotated 90° CCW
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas7"></canvas>
+ </div>
+ <br>Rotated 90° CW and flipped vertically
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas8"></canvas>
+ </div>
+ <br>Rotated 90° CW
+ </div>
+ <br>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas9"></canvas>
+ </div>
+ <br>Undefined (invalid value)
+ </div>
+ <script>
+ if (window.testRunner)
+ window.testRunner.waitUntilDone();
+
+ window.onload = function() {
+ var image = new Image;
+ image.src = "resources/exif-orientation-1-ul.jpg";
+ image.decode().then(() => {
+ let canvases = document.querySelectorAll("canvas");
+ for (const canvas of canvases) {
+ canvas.width = canvas.offsetWidth - 2;
+ canvas.height = canvas.offsetHeight - 2;
+ let context = canvas.getContext("2d");
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
+ }
+ if (window.testRunner)
+ window.testRunner.notifyDone();
+ });
+ }
+ </script>
+</body>
diff --git a/LayoutTests/fast/images/image-orientation-none-canvas.html b/LayoutTests/fast/images/image-orientation-none-canvas.html
new file mode 100644
index 0000000..c1da234
--- /dev/null
+++ b/LayoutTests/fast/images/image-orientation-none-canvas.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<style>
+ div.container {
+ display: inline-block;
+ margin-right: 20px;
+ margin-bottom: 10px;
+ width: 100px;
+ vertical-align: top;
+ }
+ div.box {
+ width: 102px;
+ height: 52px;
+ }
+ canvas {
+ border: 1px solid black;
+ width: 100px;
+ height: 50px;
+ }
+</style>
+<body>
+ <b>CanvasRenderingContext2D.drawImage() should ignore the image's EXIF orientation if its style image-orientation is set to "none".</b>
+ <br>
+ <br>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas1"></canvas>
+ </div>
+ <br>Normal
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas2"></canvas>
+ </div>
+ <br>Flipped horizontally
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas3"></canvas>
+ </div>
+ <br>Rotated 180°
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas4"></canvas>
+ </div>
+ <br>Flipped vertically
+ </div>
+ <br>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas5"></canvas>
+ </div>
+ <br>Rotated 90° CCW and flipped vertically
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas6"></canvas>
+ </div>
+ <br>Rotated 90° CCW
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas7"></canvas>
+ </div>
+ <br>Rotated 90° CW and flipped vertically
+ </div>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas8"></canvas>
+ </div>
+ <br>Rotated 90° CW
+ </div>
+ <br>
+ <div class ="container">
+ <div class ="box">
+ <canvas id="canvas9"></canvas>
+ </div>
+ <br>Undefined (invalid value)
+ </div>
+ <script>
+ if (window.testRunner)
+ window.testRunner.waitUntilDone();
+
+ window.onload = function() {
+ var names = [
+ { resource: "resources/exif-orientation-1-ul.jpg", id : "canvas1" },
+ { resource: "resources/exif-orientation-2-ur.jpg", id : "canvas2" },
+ { resource: "resources/exif-orientation-3-lr.jpg", id : "canvas3" },
+ { resource: "resources/exif-orientation-4-lol.jpg", id : "canvas4" },
+ { resource: "resources/exif-orientation-5-lu.jpg", id : "canvas5" },
+ { resource: "resources/exif-orientation-6-ru.jpg", id : "canvas6" },
+ { resource: "resources/exif-orientation-7-rl.jpg", id : "canvas7" },
+ { resource: "resources/exif-orientation-8-llo.jpg", id : "canvas8" },
+ { resource: "resources/exif-orientation-9-u.jpg", id : "canvas9" }
+ ];
+
+ var drawCount = 0;
+
+ names.forEach(function(name) {
+ var image = new Image;
+ image.style.imageOrientation = "none";
+ image.style.display = "none";
+ image.src = name.resource;
+ document.body.appendChild(image);
+ image.decode().then(() => {
+ let canvas = document.getElementById(name.id);
+ canvas.width = canvas.offsetWidth - 2;
+ canvas.height = canvas.offsetHeight - 2;
+ let context = canvas.getContext("2d");
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
+ if (++drawCount == names.length) {
+ if (window.testRunner)
+ window.testRunner.notifyDone();
+ }
+ });
+ });
+ }
+ </script>
+</body>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 03172d5..b6621ef 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,20 @@
+2020-04-06 Said Abou-Hallawa <sabouhallawa@apple.com>
+
+ CanvasRenderingContext2D.drawImage should ignore the EXIF orientation if the image-orientation is none
+ https://bugs.webkit.org/show_bug.cgi?id=209849
+
+ Reviewed by Darin Adler.
+
+ drawImage() will get the image-orientation of the HTMLImageElement from
+ its computed style. This will be passed to GraphicsContext::drawImage()
+ in the ImagePaintingOptions. Previously we were passing FromImage always.
+
+ Test: fast/images/image-orientation-none-canvas.html
+
+ * html/canvas/CanvasRenderingContext2DBase.cpp:
+ (WebCore::CanvasRenderingContext2DBase::drawImage):
+ * html/canvas/CanvasRenderingContext2DBase.h:
+
2020-04-05 Rob Buis <rbuis@igalia.com>
Remove code that has no effect from loadURL
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp
index d47235c..7c33eef 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp
@@ -1464,7 +1464,11 @@
return { };
FloatRect imageRect = FloatRect(FloatPoint(), size(imageElement, ImageSizeType::BeforeDevicePixelRatio));
- auto result = drawImage(imageElement.document(), imageElement.cachedImage(), imageElement.renderer(), imageRect, srcRect, dstRect, op, blendMode);
+ auto orientation = ImageOrientation::FromImage;
+ if (auto* computedStyle = imageElement.computedStyle())
+ orientation = computedStyle->imageOrientation();
+
+ auto result = drawImage(imageElement.document(), imageElement.cachedImage(), imageElement.renderer(), imageRect, srcRect, dstRect, op, blendMode, orientation);
if (!result.hasException())
checkOrigin(&imageElement);
@@ -1487,7 +1491,7 @@
}
#endif
-ExceptionOr<void> CanvasRenderingContext2DBase::drawImage(Document& document, CachedImage* cachedImage, const RenderObject* renderer, const FloatRect& imageRect, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const BlendMode& blendMode)
+ExceptionOr<void> CanvasRenderingContext2DBase::drawImage(Document& document, CachedImage* cachedImage, const RenderObject* renderer, const FloatRect& imageRect, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const BlendMode& blendMode, ImageOrientation orientation)
{
if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfinite(dstRect.width()) || !std::isfinite(dstRect.height())
|| !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::isfinite(srcRect.width()) || !std::isfinite(srcRect.height()))
@@ -1543,7 +1547,7 @@
downcast<BitmapImage>(*image).updateFromSettings(document.settings());
}
- ImagePaintingOptions options = { op, blendMode, ImageOrientation::FromImage };
+ ImagePaintingOptions options = { op, blendMode, orientation };
if (rectContainsCanvas(normalizedDstRect)) {
c->drawImage(*image, normalizedDstRect, normalizedSrcRect, options);
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h b/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h
index c6a880b..a9e58ea 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h
@@ -333,7 +333,7 @@
ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect);
ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&);
ExceptionOr<void> drawImage(CanvasBase&, const FloatRect& srcRect, const FloatRect& dstRect);
- ExceptionOr<void> drawImage(Document&, CachedImage*, const RenderObject*, const FloatRect& imageRect, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&);
+ ExceptionOr<void> drawImage(Document&, CachedImage*, const RenderObject*, const FloatRect& imageRect, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&, ImageOrientation = ImageOrientation::FromImage);
#if ENABLE(VIDEO)
ExceptionOr<void> drawImage(HTMLVideoElement&, const FloatRect& srcRect, const FloatRect& dstRect);
#endif