[Cocoa] Add an optional width parameter to -[WKWebProcessPlugInNodeHandle renderedIma...
authoraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 May 2017 14:41:03 +0000 (14:41 +0000)
committeraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 May 2017 14:41:03 +0000 (14:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171646
<rdar://problem/30306321>

Reviewed by Tim Horton.

Source/WebKit2:

* WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInNodeHandle.h:
* WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInNodeHandle.mm:
(-[WKWebProcessPlugInNodeHandle renderedImageWithOptions:]): Called
-renderedImageWithOptions:width: with a nil width.
(-[WKWebProcessPlugInNodeHandle renderedImageWithOptions:width:]): Passed an optional width
to InjectedBundleNodeHandle::renderedImage().
* WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.cpp:
(WebKit::imageForRect): If a width is specified, create an image graphics context at that
width, preserving the aspect ratio of paintingRect.
(WebKit::InjectedBundleNodeHandle::renderedImage):
* WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.h:

Tools:

* TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptions.mm:
(runTestWithWidth):
(TEST):
(-[RenderedImageWithOptionsObject didRenderImageWithSize:]): Deleted.
* TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptionsPlugIn.mm:
(-[RenderedImageWithOptionsPlugIn webProcessPlugIn:didCreateBrowserContextController:]):
(-[RenderedImageWithOptionsPlugIn webProcessPlugInBrowserContextController:didFinishLoadForFrame:]):
(-[RenderedImageWithOptionsPlugIn renderImageWithWidth:completionHandler:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptionsProtocol.h:

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

Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInNodeHandle.h
Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInNodeHandle.mm
Source/WebKit2/WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.cpp
Source/WebKit2/WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.h
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptions.mm
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptionsPlugIn.mm
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptionsProtocol.h

index 63c2784..60b620d 100644 (file)
@@ -1,3 +1,23 @@
+2017-05-04  Andy Estes  <aestes@apple.com>
+
+        [Cocoa] Add an optional width parameter to -[WKWebProcessPlugInNodeHandle renderedImageWithOptions:]
+        https://bugs.webkit.org/show_bug.cgi?id=171646
+        <rdar://problem/30306321>
+
+        Reviewed by Tim Horton.
+
+        * WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInNodeHandle.h:
+        * WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInNodeHandle.mm:
+        (-[WKWebProcessPlugInNodeHandle renderedImageWithOptions:]): Called
+        -renderedImageWithOptions:width: with a nil width.
+        (-[WKWebProcessPlugInNodeHandle renderedImageWithOptions:width:]): Passed an optional width
+        to InjectedBundleNodeHandle::renderedImage().
+        * WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.cpp:
+        (WebKit::imageForRect): If a width is specified, create an image graphics context at that
+        width, preserving the aspect ratio of paintingRect.
+        (WebKit::InjectedBundleNodeHandle::renderedImage):
+        * WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.h:
+
 2017-05-04  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r216172.
index 99b9dfb..bc5c8ed 100644 (file)
@@ -45,8 +45,10 @@ WK_CLASS_AVAILABLE(macosx(10.10), ios(8.0))
 
 #if TARGET_OS_IPHONE
 - (UIImage *)renderedImageWithOptions:(WKSnapshotOptions)options WK_API_AVAILABLE(macosx(10.11), ios(9.0));
+- (UIImage *)renderedImageWithOptions:(WKSnapshotOptions)options width:(NSNumber *)width WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 #else
 - (NSImage *)renderedImageWithOptions:(WKSnapshotOptions)options WK_API_AVAILABLE(macosx(10.11), ios(9.0));
+- (NSImage *)renderedImageWithOptions:(WKSnapshotOptions)options width:(NSNumber *)width WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 #endif
 
 @property (nonatomic, readonly) CGRect elementBounds;
index 534fdf8..2ec937c 100644 (file)
@@ -68,7 +68,16 @@ using namespace WebKit;
 #if PLATFORM(IOS)
 - (UIImage *)renderedImageWithOptions:(WKSnapshotOptions)options
 {
-    RefPtr<WebImage> image = _nodeHandle->renderedImage(toSnapshotOptions(options), options & kWKSnapshotOptionsExcludeOverflow);
+    return [self renderedImageWithOptions:options width:nil];
+}
+
+- (UIImage *)renderedImageWithOptions:(WKSnapshotOptions)options width:(NSNumber *)width
+{
+    std::optional<float> optionalWidth;
+    if (width)
+        optionalWidth = width.floatValue;
+
+    RefPtr<WebImage> image = _nodeHandle->renderedImage(toSnapshotOptions(options), options & kWKSnapshotOptionsExcludeOverflow, optionalWidth);
     if (!image)
         return nil;
 
@@ -79,7 +88,16 @@ using namespace WebKit;
 #if PLATFORM(MAC)
 - (NSImage *)renderedImageWithOptions:(WKSnapshotOptions)options
 {
-    RefPtr<WebImage> image = _nodeHandle->renderedImage(toSnapshotOptions(options), options & kWKSnapshotOptionsExcludeOverflow);
+    return [self renderedImageWithOptions:options width:nil];
+}
+
+- (NSImage *)renderedImageWithOptions:(WKSnapshotOptions)options width:(NSNumber *)width
+{
+    std::optional<float> optionalWidth;
+    if (width)
+        optionalWidth = width.floatValue;
+
+    RefPtr<WebImage> image = _nodeHandle->renderedImage(toSnapshotOptions(options), options & kWKSnapshotOptionsExcludeOverflow, optionalWidth);
     if (!image)
         return nil;
 
index 825a88d..3471d2d 100644 (file)
@@ -134,18 +134,36 @@ IntRect InjectedBundleNodeHandle::renderRect(bool* isReplaced)
     return m_node->pixelSnappedRenderRect(isReplaced);
 }
 
-static RefPtr<WebImage> imageForRect(FrameView* frameView, const IntRect& rect, SnapshotOptions options)
+static RefPtr<WebImage> imageForRect(FrameView* frameView, const IntRect& paintingRect, const std::optional<float>& bitmapWidth, SnapshotOptions options)
 {
-    IntSize bitmapSize = rect.size();
-    float scaleFactor = frameView->frame().page()->deviceScaleFactor();
-    bitmapSize.scale(scaleFactor);
+    if (paintingRect.isEmpty())
+        return nullptr;
+
+    float bitmapScaleFactor;
+    IntSize bitmapSize;
+    if (bitmapWidth) {
+        bitmapScaleFactor = bitmapWidth.value() / paintingRect.width();
+        bitmapSize = roundedIntSize(FloatSize(bitmapWidth.value(), paintingRect.height() * bitmapScaleFactor));
+    } else {
+        bitmapScaleFactor = 1;
+        bitmapSize = paintingRect.size();
+    }
+
+    float deviceScaleFactor = frameView->frame().page()->deviceScaleFactor();
+    bitmapSize.scale(deviceScaleFactor);
+
+    if (bitmapSize.isEmpty())
+        return nullptr;
 
     auto snapshot = WebImage::create(bitmapSize, snapshotOptionsToImageOptions(options));
+    if (!snapshot)
+        return nullptr;
 
     auto graphicsContext = snapshot->bitmap().createGraphicsContext();
     graphicsContext->clearRect(IntRect(IntPoint(), bitmapSize));
-    graphicsContext->applyDeviceScaleFactor(scaleFactor);
-    graphicsContext->translate(-rect.x(), -rect.y());
+    graphicsContext->applyDeviceScaleFactor(deviceScaleFactor);
+    graphicsContext->scale(bitmapScaleFactor);
+    graphicsContext->translate(-paintingRect.x(), -paintingRect.y());
 
     FrameView::SelectionInSnapshot shouldPaintSelection = FrameView::IncludeSelection;
     if (options & SnapshotOptionsExcludeSelectionHighlighting)
@@ -159,13 +177,13 @@ static RefPtr<WebImage> imageForRect(FrameView* frameView, const IntRect& rect,
 
     PaintBehavior oldPaintBehavior = frameView->paintBehavior();
     frameView->setPaintBehavior(paintBehavior);
-    frameView->paintContentsForSnapshot(*graphicsContext.get(), rect, shouldPaintSelection, FrameView::DocumentCoordinates);
+    frameView->paintContentsForSnapshot(*graphicsContext.get(), paintingRect, shouldPaintSelection, FrameView::DocumentCoordinates);
     frameView->setPaintBehavior(oldPaintBehavior);
 
     return snapshot;
 }
 
-RefPtr<WebImage> InjectedBundleNodeHandle::renderedImage(SnapshotOptions options, bool shouldExcludeOverflow)
+RefPtr<WebImage> InjectedBundleNodeHandle::renderedImage(SnapshotOptions options, bool shouldExcludeOverflow, const std::optional<float>& bitmapWidth)
 {
     Frame* frame = m_node->document().frame();
     if (!frame)
@@ -190,7 +208,7 @@ RefPtr<WebImage> InjectedBundleNodeHandle::renderedImage(SnapshotOptions options
     }
 
     frameView->setNodeToDraw(m_node.ptr());
-    auto image = imageForRect(frameView, paintingRect, options);
+    auto image = imageForRect(frameView, paintingRect, bitmapWidth, options);
     frameView->setNodeToDraw(0);
 
     return image;
index 42ee95f..0b4c542 100644 (file)
@@ -29,6 +29,7 @@
 #include "ImageOptions.h"
 #include <JavaScriptCore/JSBase.h>
 #include <wtf/Forward.h>
+#include <wtf/Optional.h>
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -61,7 +62,7 @@ public:
     // Note: These should only be operations that are not exposed to JavaScript.
     WebCore::IntRect elementBounds();
     WebCore::IntRect renderRect(bool*);
-    RefPtr<WebImage> renderedImage(SnapshotOptions, bool shouldExcludeOverflow);
+    RefPtr<WebImage> renderedImage(SnapshotOptions, bool shouldExcludeOverflow, const std::optional<float>& bitmapWidth = std::nullopt);
     RefPtr<InjectedBundleRangeHandle> visibleRange();
     void setHTMLInputElementValueForUser(const String&);
     void setHTMLInputElementSpellcheckEnabled(bool);
index 470480d..952457e 100644 (file)
@@ -1,3 +1,21 @@
+2017-05-04  Andy Estes  <aestes@apple.com>
+
+        [Cocoa] Add an optional width parameter to -[WKWebProcessPlugInNodeHandle renderedImageWithOptions:]
+        https://bugs.webkit.org/show_bug.cgi?id=171646
+        <rdar://problem/30306321>
+
+        Reviewed by Tim Horton.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptions.mm:
+        (runTestWithWidth):
+        (TEST):
+        (-[RenderedImageWithOptionsObject didRenderImageWithSize:]): Deleted.
+        * TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptionsPlugIn.mm:
+        (-[RenderedImageWithOptionsPlugIn webProcessPlugIn:didCreateBrowserContextController:]):
+        (-[RenderedImageWithOptionsPlugIn webProcessPlugInBrowserContextController:didFinishLoadForFrame:]):
+        (-[RenderedImageWithOptionsPlugIn renderImageWithWidth:completionHandler:]):
+        * TestWebKitAPI/Tests/WebKit2Cocoa/RenderedImageWithOptionsProtocol.h:
+
 2017-05-04  Adrian Perez de Castro  <aperez@igalia.com>
 
         [GTK] Fontconfig 2.11.2 in JHBuild does not build with glibc 2.25+ or gperf 3.1+
index 4cb1003..4a3a2b3 100644 (file)
@@ -28,6 +28,7 @@
 #if WK_API_ENABLED
 
 #import "RenderedImageWithOptionsProtocol.h"
+#import "TestNavigationDelegate.h"
 #import "Utilities.h"
 #import "WKWebViewConfigurationExtras.h"
 #import <WebKit/WKWebViewPrivate.h>
 
 using namespace TestWebKitAPI;
 
-static bool testFinished;
+static void runTestWithWidth(NSNumber *width, CGSize expectedSize)
+{
+    WKWebViewConfiguration *configuration = [WKWebViewConfiguration testwebkitapi_configurationWithTestPlugInClassName:@"RenderedImageWithOptionsPlugIn"];
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration]);
 
-@interface RenderedImageWithOptionsObject : NSObject <RenderedImageWithOptionsProtocol>
-@end
+    _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(RenderedImageWithOptionsProtocol)];
+    auto remoteObject = retainPtr([[webView _remoteObjectRegistry] remoteObjectProxyWithInterface:interface]);
 
-@implementation RenderedImageWithOptionsObject
+    [webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"rendered-image-excluding-overflow" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
+    [webView _test_waitForDidFinishNavigation];
 
-- (void)didRenderImageWithSize:(CGSize)size
-{
+    __block bool testFinished = false;
+    [remoteObject renderImageWithWidth:width completionHandler:^(CGSize imageSize) {
 #if PLATFORM(IOS)
-    CGFloat scale = [UIScreen mainScreen].scale;
+        CGFloat scale = [UIScreen mainScreen].scale;
 #elif PLATFORM(MAC)
-    CGFloat scale = [NSScreen mainScreen].backingScaleFactor;
+        CGFloat scale = [NSScreen mainScreen].backingScaleFactor;
 #endif
-    EXPECT_EQ(720, size.width / scale);
-    EXPECT_EQ(540, size.height / scale);
-    testFinished = true;
-}
+        EXPECT_EQ(expectedSize.width, imageSize.width / scale);
+        EXPECT_EQ(expectedSize.height, imageSize.height / scale);
+        testFinished = true;
+    }];
 
-@end
+    Util::run(&testFinished);
+}
 
-TEST(WebKit2, RenderedImageExcludingOverflow)
+TEST(WebKit2, NodeHandleRenderedImageExcludingOverflow)
 {
-    WKWebViewConfiguration *configuration = [WKWebViewConfiguration testwebkitapi_configurationWithTestPlugInClassName:@"RenderedImageWithOptionsPlugIn"];
-    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration]);
-
-    auto object = adoptNS([[RenderedImageWithOptionsObject alloc] init]);
-    _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(RenderedImageWithOptionsProtocol)];
-    [[webView _remoteObjectRegistry] registerExportedObject:object.get() interface:interface];
-
-    [webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"rendered-image-excluding-overflow" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
+    runTestWithWidth(nil, { 720, 540 });
+}
 
-    Util::run(&testFinished);
+TEST(WebKit2, NodeHandleRenderedImageWithWidth)
+{
+    runTestWithWidth(@(-1), { 0, 0 });
+    runTestWithWidth(@0, { 0, 0 });
+    runTestWithWidth(@1, { 1, 1 });
+    runTestWithWidth(@360, { 360, 270 });
+    runTestWithWidth(@719, { 719, 539 });
+    runTestWithWidth(@720, { 720, 540 });
+    runTestWithWidth(@721, { 721, 541 });
 }
 
 #endif // WK_API_ENABLED
index d860300..62a0d76 100644 (file)
 #import <WebKit/_WKRemoteObjectRegistry.h>
 #import <wtf/RetainPtr.h>
 
-@interface RenderedImageWithOptionsPlugIn : NSObject <WKWebProcessPlugIn, WKWebProcessPlugInLoadDelegate>
+@interface RenderedImageWithOptionsPlugIn : NSObject <WKWebProcessPlugIn, WKWebProcessPlugInLoadDelegate, RenderedImageWithOptionsProtocol>
 @end
 
 @implementation RenderedImageWithOptionsPlugIn {
-    RetainPtr<id <RenderedImageWithOptionsProtocol>> _remoteObject;
+    RetainPtr<WKWebProcessPlugInFrame> _frame;
 }
 
 - (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
     browserContextController.loadDelegate = self;
 
     _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(RenderedImageWithOptionsProtocol)];
-    _remoteObject = [browserContextController._remoteObjectRegistry remoteObjectProxyWithInterface:interface];
+    [browserContextController._remoteObjectRegistry registerExportedObject:self interface:interface];
 }
 
 - (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller didFinishLoadForFrame:(WKWebProcessPlugInFrame *)frame
 {
-    JSContext *context = [frame jsContextForWorld:[WKWebProcessPlugInScriptWorld normalWorld]];
+    _frame = frame;
+}
+
+- (void)renderImageWithWidth:(NSNumber *)width completionHandler:(void (^)(CGSize))completionHandler
+{
+    JSContext *context = [_frame jsContextForWorld:[WKWebProcessPlugInScriptWorld normalWorld]];
     JSValue *containerValue = [context evaluateScript:@"document.querySelector('.container')"];
     WKWebProcessPlugInNodeHandle *containerNode = [WKWebProcessPlugInNodeHandle nodeHandleWithJSValue:containerValue inContext:context];
 #if PLATFORM(IOS)
-    UIImage *image = [containerNode renderedImageWithOptions:kWKSnapshotOptionsExcludeOverflow];
+    UIImage *image = [containerNode renderedImageWithOptions:kWKSnapshotOptionsExcludeOverflow width:width];
 #elif PLATFORM(MAC)
-    NSImage *image = [containerNode renderedImageWithOptions:kWKSnapshotOptionsExcludeOverflow];
+    NSImage *image = [containerNode renderedImageWithOptions:kWKSnapshotOptionsExcludeOverflow width:width];
 #endif
-    [_remoteObject didRenderImageWithSize:image.size];
+    completionHandler(image.size);
 }
 
 @end
index 35583bf..20a23be 100644 (file)
@@ -24,5 +24,5 @@
  */
 
 @protocol RenderedImageWithOptionsProtocol
-- (void)didRenderImageWithSize:(CGSize)size;
+- (void)renderImageWithWidth:(NSNumber *)width completionHandler:(void (^)(CGSize imageSize))completionHandler;
 @end