[iOS] Position image information should respect the image orientation
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Aug 2019 19:13:11 +0000 (19:13 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Aug 2019 19:13:11 +0000 (19:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200487

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2019-08-08
Reviewed by Simon Fraser.

Source/WebCore:

Re-factor CachedImage::imageSizeForRenderer() into another overriding
function which does not scale the imageSize. Therefore the new function
returns FloatSize while the original function returns LayoutSize.

* loader/cache/CachedImage.cpp:
(WebCore::CachedImage::imageSizeForRenderer const):
* loader/cache/CachedImage.h:
* rendering/RenderElement.h:

Source/WebKit:

imagePositionInformation() should respect the image orientation when
drawing an Image to a ShareableBitmap context.

boundsPositionInformation() already takes care of the image orientation
because it gets RenderImage::enclosingBoundingBox().

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::imagePositionInformation):

Tools:

Add an API test to verify the position image information is drawn rotated
because of respecting its image orientation.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/WKRequestActivatedElementInfo.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitCocoa/exif-orientation-8-llo.jpg: Added.
* TestWebKitAPI/Tests/WebKitCocoa/img-with-rotated-image.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248438 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/loader/cache/CachedImage.cpp
Source/WebCore/loader/cache/CachedImage.h
Source/WebCore/rendering/RenderElement.h
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/WKRequestActivatedElementInfo.mm
Tools/TestWebKitAPI/Tests/WebKitCocoa/exif-orientation-8-llo.jpg [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKitCocoa/img-with-rotated-image.html [new file with mode: 0644]

index b71da4c..d14e2e9 100644 (file)
@@ -1,3 +1,19 @@
+2019-08-08  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        [iOS] Position image information should respect the image orientation
+        https://bugs.webkit.org/show_bug.cgi?id=200487
+
+        Reviewed by Simon Fraser.
+
+        Re-factor CachedImage::imageSizeForRenderer() into another overriding
+        function which does not scale the imageSize. Therefore the new function
+        returns FloatSize while the original function returns LayoutSize.
+
+        * loader/cache/CachedImage.cpp:
+        (WebCore::CachedImage::imageSizeForRenderer const):
+        * loader/cache/CachedImage.h:
+        * rendering/RenderElement.h:
+
 2019-08-08  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: rename `queryObjects` to `queryInstances` for clarity
index a7c1000..f312907 100644 (file)
@@ -275,23 +275,26 @@ void CachedImage::setContainerContextForClient(const CachedImageClient& client,
     m_svgImageCache->setContainerContextForClient(client, containerSize, containerZoom, imageURL);
 }
 
-LayoutSize CachedImage::imageSizeForRenderer(const RenderElement* renderer, float multiplier, SizeType sizeType)
+FloatSize CachedImage::imageSizeForRenderer(const RenderElement* renderer, SizeType sizeType) const
 {
     if (!m_image)
-        return LayoutSize();
-
-    LayoutSize imageSize;
+        return { };
 
     if (is<BitmapImage>(*m_image) && renderer && renderer->shouldRespectImageOrientation() == RespectImageOrientation)
-        imageSize = LayoutSize(downcast<BitmapImage>(*m_image).sizeRespectingOrientation());
-    else if (is<SVGImage>(*m_image) && sizeType == UsedSize)
-        imageSize = LayoutSize(m_svgImageCache->imageSizeForRenderer(renderer));
-    else
-        imageSize = LayoutSize(m_image->size());
+        return downcast<BitmapImage>(*m_image).sizeRespectingOrientation();
 
-    if (multiplier == 1.0f)
+    if (is<SVGImage>(*m_image) && sizeType == UsedSize)
+        return m_svgImageCache->imageSizeForRenderer(renderer);
+
+    return m_image->size();
+}
+
+LayoutSize CachedImage::imageSizeForRenderer(const RenderElement* renderer, float multiplier, SizeType sizeType) const
+{
+    LayoutSize imageSize = LayoutSize(imageSizeForRenderer(renderer, sizeType));
+    if (imageSize.isEmpty() || multiplier == 1.0f)
         return imageSize;
-        
+
     // Don't let images that have a width/height >= 1 shrink below 1 when zoomed.
     float widthScale = m_image->hasRelativeWidth() ? 1.0f : multiplier;
     float heightScale = m_image->hasRelativeHeight() ? 1.0f : multiplier;
index d3b87fc..4ab3553 100644 (file)
@@ -75,8 +75,9 @@ public:
         UsedSize,
         IntrinsicSize
     };
+    WEBCORE_EXPORT FloatSize imageSizeForRenderer(const RenderElement* renderer, SizeType = UsedSize) const;
     // This method takes a zoom multiplier that can be used to increase the natural size of the image by the zoom.
-    LayoutSize imageSizeForRenderer(const RenderElement*, float multiplier, SizeType = UsedSize); // returns the size of the complete image.
+    LayoutSize imageSizeForRenderer(const RenderElement*, float multiplier, SizeType = UsedSize) const; // returns the size of the complete image.
     void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
 
     bool isManuallyCached() const { return m_isManuallyCached; }
index be22e43..63824e4 100644 (file)
@@ -204,7 +204,7 @@ public:
     RenderBlock* containingBlockForFixedPosition() const;
     RenderBlock* containingBlockForAbsolutePosition() const;
 
-    RespectImageOrientationEnum shouldRespectImageOrientation() const;
+    WEBCORE_EXPORT RespectImageOrientationEnum shouldRespectImageOrientation() const;
 
     void removeFromRenderFragmentedFlow();
     virtual void resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants(RenderFragmentedFlow*);
index 52c4b4f..9274dd9 100644 (file)
@@ -1,3 +1,19 @@
+2019-08-08  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        [iOS] Position image information should respect the image orientation
+        https://bugs.webkit.org/show_bug.cgi?id=200487
+
+        Reviewed by Simon Fraser.
+
+        imagePositionInformation() should respect the image orientation when
+        drawing an Image to a ShareableBitmap context.
+
+        boundsPositionInformation() already takes care of the image orientation
+        because it gets RenderImage::enclosingBoundingBox().
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::imagePositionInformation):
+
 2019-08-08  Timothy Hatcher  <timothy@apple.com>
 
         Set WKWebView opaque based on drawsBackground in PageConfiguration.
index f3672ca..30c0cbe 100644 (file)
@@ -2620,9 +2620,12 @@ static void imagePositionInformation(WebPage& page, Element& element, const Inte
         return;
 
     FloatSize screenSizeInPixels = screenSize();
+    FloatSize imageSize = renderImage.cachedImage()->imageSizeForRenderer(&renderImage);
+    
     screenSizeInPixels.scale(page.corePage()->deviceScaleFactor());
-    FloatSize scaledSize = largestRectWithAspectRatioInsideRect(image->size().width() / image->size().height(), FloatRect(0, 0, screenSizeInPixels.width(), screenSizeInPixels.height())).size();
-    FloatSize bitmapSize = scaledSize.width() < image->size().width() ? scaledSize : image->size();
+    FloatSize scaledSize = largestRectWithAspectRatioInsideRect(imageSize.width() / imageSize.height(), FloatRect(0, 0, screenSizeInPixels.width(), screenSizeInPixels.height())).size();
+    FloatSize bitmapSize = scaledSize.width() < imageSize.width() ? scaledSize : imageSize;
+    
     // FIXME: Only select ExtendedColor on images known to need wide gamut
     ShareableBitmap::Configuration bitmapConfiguration;
     bitmapConfiguration.colorSpace.cgColorSpace = screenColorSpace(page.corePage()->mainFrame().view());
@@ -2635,7 +2638,8 @@ static void imagePositionInformation(WebPage& page, Element& element, const Inte
     if (!graphicsContext)
         return;
 
-    graphicsContext->drawImage(*image, FloatRect(0, 0, bitmapSize.width(), bitmapSize.height()));
+    auto shouldRespectImageOrientation = renderImage.shouldRespectImageOrientation();
+    graphicsContext->drawImage(*image, FloatRect(0, 0, bitmapSize.width(), bitmapSize.height()), ImageOrientationDescription(shouldRespectImageOrientation));
     info.image = sharedBitmap;
 }
 
index 2496039..00db337 100644 (file)
@@ -1,3 +1,19 @@
+2019-08-08  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        [iOS] Position image information should respect the image orientation
+        https://bugs.webkit.org/show_bug.cgi?id=200487
+
+        Reviewed by Simon Fraser.
+
+        Add an API test to verify the position image information is drawn rotated
+        because of respecting its image orientation.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/WKRequestActivatedElementInfo.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/exif-orientation-8-llo.jpg: Added.
+        * TestWebKitAPI/Tests/WebKitCocoa/img-with-rotated-image.html: Added.
+
 2019-08-08  Claudio Saavedra  <csaavedra@igalia.com>
 
         [GTK] Fix WebContext languages test
index 8d82d85..80b4e02 100644 (file)
                6B9ABE122086952F00D75DE6 /* HTTPParsers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B9ABE112086952F00D75DE6 /* HTTPParsers.cpp */; };
                6BFD294C1D5E6C1D008EC968 /* HashCountedSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A38D7E51C752D5F004F157D /* HashCountedSet.cpp */; };
                725C3EF322058A5B007C36FC /* AdditionalSupportedImageTypes.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 725C3EF2220584BA007C36FC /* AdditionalSupportedImageTypes.html */; };
+               7283A9D022FA754900B21C7D /* img-with-rotated-image.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7283A9CE22FA6BBE00B21C7D /* img-with-rotated-image.html */; };
+               7283A9D222FB1E0600B21C7D /* exif-orientation-8-llo.jpg in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7283A9D122FB1D9700B21C7D /* exif-orientation-8-llo.jpg */; };
                751B05D61F8EAC410028A09E /* DatabaseTrackerTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 751B05D51F8EAC1A0028A09E /* DatabaseTrackerTest.mm */; };
                754CEC811F6722F200D0039A /* AutoFillAvailable.mm in Sources */ = {isa = PBXBuildFile; fileRef = 754CEC801F6722DC00D0039A /* AutoFillAvailable.mm */; };
                7673499D1930C5BB00E44DF9 /* StopLoadingDuringDidFailProvisionalLoad_bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7673499A1930182E00E44DF9 /* StopLoadingDuringDidFailProvisionalLoad_bundle.cpp */; };
                                F407FE391F1D0DFC0017CF25 /* enormous.svg in Copy Resources */,
                                07492B3C1DF8B86600633DE1 /* enumerateMediaDevices.html in Copy Resources */,
                                C5E1AFFE16B221F1006CC1F2 /* execCopy.html in Copy Resources */,
+                               7283A9D222FB1E0600B21C7D /* exif-orientation-8-llo.jpg in Copy Resources */,
                                CDA29B2B20FD358400F15CED /* ExitFullscreenOnEnterPiP.html in Copy Resources */,
                                F41AB9A31EF4696B0083FA08 /* file-uploading.html in Copy Resources */,
                                BC2D006412AA04CE00E732A3 /* file-with-anchor.html in Copy Resources */,
                                F41AB9A51EF4696B0083FA08 /* image-and-textarea.html in Copy Resources */,
                                F4DEF6ED1E9B4DB60048EF61 /* image-in-link-and-input.html in Copy Resources */,
                                F45B63FB1F197F4A009D38B9 /* image-map.html in Copy Resources */,
+                               7283A9D022FA754900B21C7D /* img-with-rotated-image.html in Copy Resources */,
                                935786CD20F6A2910000CDFC /* IndexedDB.sqlite3 in Copy Resources */,
                                935786CE20F6A2A10000CDFC /* IndexedDB.sqlite3-shm in Copy Resources */,
                                935786CC20F6A2700000CDFC /* IndexedDB.sqlite3-wal in Copy Resources */,
                6B4E861B2220A5520022F389 /* RegistrableDomain.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RegistrableDomain.cpp; sourceTree = "<group>"; };
                6B9ABE112086952F00D75DE6 /* HTTPParsers.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HTTPParsers.cpp; sourceTree = "<group>"; };
                725C3EF2220584BA007C36FC /* AdditionalSupportedImageTypes.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = AdditionalSupportedImageTypes.html; sourceTree = "<group>"; };
+               7283A9CE22FA6BBE00B21C7D /* img-with-rotated-image.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "img-with-rotated-image.html"; sourceTree = "<group>"; };
+               7283A9D122FB1D9700B21C7D /* exif-orientation-8-llo.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "exif-orientation-8-llo.jpg"; sourceTree = "<group>"; };
                751B05D51F8EAC1A0028A09E /* DatabaseTrackerTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DatabaseTrackerTest.mm; sourceTree = "<group>"; };
                754CEC801F6722DC00D0039A /* AutoFillAvailable.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AutoFillAvailable.mm; sourceTree = "<group>"; };
                7560917719259C59009EF06E /* MemoryCacheAddImageToCacheIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryCacheAddImageToCacheIOS.mm; sourceTree = "<group>"; };
                                51C8E1A81F27F47300BF731B /* EmptyGrandfatheredResourceLoadStatistics.plist */,
                                F4C2AB211DD6D94100E06D5B /* enormous-video-with-sound.html */,
                                F407FE381F1D0DE60017CF25 /* enormous.svg */,
+                               7283A9D122FB1D9700B21C7D /* exif-orientation-8-llo.jpg */,
                                CDA29B2A20FD344E00F15CED /* ExitFullscreenOnEnterPiP.html */,
                                F41AB99B1EF4692C0083FA08 /* file-uploading.html */,
                                A17EAC542083056E0084B41B /* find.pdf */,
                                F41AB9931EF4692C0083FA08 /* image-and-textarea.html */,
                                F4DEF6EC1E9B4D950048EF61 /* image-in-link-and-input.html */,
                                F45B63FA1F197F33009D38B9 /* image-map.html */,
+                               7283A9CE22FA6BBE00B21C7D /* img-with-rotated-image.html */,
                                934FA5C720F69FEE0040DC1B /* IndexedDB.sqlite3 */,
                                934FA5C620F69FED0040DC1B /* IndexedDB.sqlite3-shm */,
                                934FA5C520F69FED0040DC1B /* IndexedDB.sqlite3-wal */,
index 6e793d0..556a5a9 100644 (file)
@@ -96,7 +96,51 @@ TEST(WebKit, RequestActivatedElementInfoForImage)
     
     TestWebKitAPI::Util::run(&finished);
 }
-    
+
+TEST(WebKit, RequestActivatedElementInfoForRotatedImage)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"img-with-rotated-image" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
+
+    [webView loadRequest:request];
+    [webView _test_waitForDidFinishNavigation];
+
+    __block bool finished = false;
+    [webView _requestActivatedElementAtPosition:CGPointMake(50, 50) completionBlock: ^(_WKActivatedElementInfo *elementInfo) {
+
+        auto image = elementInfo.image.CGImage;
+        auto data = adoptCF(CGDataProviderCopyData(CGImageGetDataProvider(image)));
+        auto buffer = reinterpret_cast<const unsigned*>(CFDataGetBytePtr(data.get()));
+
+        auto pixelAt = [&](unsigned x, unsigned y) {
+            unsigned i = y * elementInfo.image.size.width + x;
+            return buffer[i];
+        };
+        
+        static const unsigned yellow = 0xFFFFFF00;
+        static const unsigned red = 0xFFF51900;
+        static const unsigned green = 0xFF278000;
+        static const unsigned blue = 0xFF0000FF;
+
+        EXPECT_TRUE(elementInfo.type == _WKActivatedElementTypeImage);
+        EXPECT_WK_STREQ(elementInfo.imageURL.lastPathComponent, "exif-orientation-8-llo.jpg");
+        EXPECT_NOT_NULL(elementInfo.image);
+        EXPECT_EQ(elementInfo.boundingRect.size.width, 50);
+        EXPECT_EQ(elementInfo.boundingRect.size.height, 100);
+        EXPECT_EQ(elementInfo.image.size.width, 50);
+        EXPECT_EQ(elementInfo.image.size.height, 100);
+
+        EXPECT_EQ(pixelAt(0, 0), yellow);
+        EXPECT_EQ(pixelAt(elementInfo.image.size.width - 1, 0), red);
+        EXPECT_EQ(pixelAt(0, elementInfo.image.size.height - 1), green);
+        EXPECT_EQ(pixelAt(elementInfo.image.size.width - 1, elementInfo.image.size.height - 1), blue);
+
+        finished = true;
+    }];
+
+    TestWebKitAPI::Util::run(&finished);
+}
+
 TEST(WebKit, RequestActivatedElementInfoForBlank)
 {
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/exif-orientation-8-llo.jpg b/Tools/TestWebKitAPI/Tests/WebKitCocoa/exif-orientation-8-llo.jpg
new file mode 100644 (file)
index 0000000..34b895f
Binary files /dev/null and b/Tools/TestWebKitAPI/Tests/WebKitCocoa/exif-orientation-8-llo.jpg differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/img-with-rotated-image.html b/Tools/TestWebKitAPI/Tests/WebKitCocoa/img-with-rotated-image.html
new file mode 100644 (file)
index 0000000..64b9f05
--- /dev/null
@@ -0,0 +1,3 @@
+<body>
+    <img src="exif-orientation-8-llo.jpg">
+</body>