Title: [165872] trunk/Source/WebKit2
Revision
165872
Author
[email protected]
Date
2014-03-18 23:55:29 -0700 (Tue, 18 Mar 2014)

Log Message

[iOS][WebKit2] Provide generic software-snapshotting API
https://bugs.webkit.org/show_bug.cgi?id=130385
<rdar://problem/16005957>

Reviewed by Sam Weinig.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _didCommitLayerTree:WebKit::]):
(-[WKWebView _snapshotRect:intoImageOfWidth:completionHandler:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/API/Cocoa/_WKThumbnailView.mm:
(-[_WKThumbnailView initWithFrame:fromWKView:]):
(-[_WKThumbnailView _requestSnapshotIfNeeded]):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::internalShowContextMenu):
* UIProcess/WebPageProxy.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::takeSnapshot):
(WebKit::WebPage::scaledSnapshotWithOptions):
(WebKit::WebPage::snapshotAtSize):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Rename TakeThumbnailSnapshot message to TakeSnapshot.

Fill the snapshot image with the FrameView's background color, to avoid
half-pixel alpha around the edges.

Factor snapshotAtSize out of scaledSnapshotWithOptions.

Don't apply both the custom and device scale factor to the base CTM,
only the device scale factor. Custom scale factor should only be
applied to the user CTM.

* Shared/ImageOptions.h:
Add a snapshot option, RespectDrawingAreaTransform, that maps
the rect through the drawing area's root layer transform.
Use this in place of the thumbnail-specific code in TakeThumbnailSnapshot.
Add a snapshot option, ExcludeDeviceScaleFactor, which means that
snapshotting will not factor the device scale in (useful for drawing
to a bitmap at an exact requested size).

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (165871 => 165872)


--- trunk/Source/WebKit2/ChangeLog	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/ChangeLog	2014-03-19 06:55:29 UTC (rev 165872)
@@ -1,3 +1,46 @@
+2014-03-18  Tim Horton  <[email protected]>
+
+        [iOS][WebKit2] Provide generic software-snapshotting API
+        https://bugs.webkit.org/show_bug.cgi?id=130385
+        <rdar://problem/16005957>
+
+        Reviewed by Sam Weinig.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _didCommitLayerTree:WebKit::]):
+        (-[WKWebView _snapshotRect:intoImageOfWidth:completionHandler:]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/API/Cocoa/_WKThumbnailView.mm:
+        (-[_WKThumbnailView initWithFrame:fromWKView:]):
+        (-[_WKThumbnailView _requestSnapshotIfNeeded]):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::internalShowContextMenu):
+        * UIProcess/WebPageProxy.h:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::takeSnapshot):
+        (WebKit::WebPage::scaledSnapshotWithOptions):
+        (WebKit::WebPage::snapshotAtSize):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        Rename TakeThumbnailSnapshot message to TakeSnapshot.
+
+        Fill the snapshot image with the FrameView's background color, to avoid
+        half-pixel alpha around the edges.
+
+        Factor snapshotAtSize out of scaledSnapshotWithOptions.
+
+        Don't apply both the custom and device scale factor to the base CTM,
+        only the device scale factor. Custom scale factor should only be
+        applied to the user CTM.
+
+        * Shared/ImageOptions.h:
+        Add a snapshot option, RespectDrawingAreaTransform, that maps
+        the rect through the drawing area's root layer transform.
+        Use this in place of the thumbnail-specific code in TakeThumbnailSnapshot.
+        Add a snapshot option, ExcludeDeviceScaleFactor, which means that
+        snapshotting will not factor the device scale in (useful for drawing
+        to a bitmap at an exact requested size).
+
 2014-03-18  Samuel White  <[email protected]>
 
         AX: Not able to use arrow keys to read text with VoiceOver before selection is set someplace (anyplace).

Modified: trunk/Source/WebKit2/Shared/ImageOptions.h (165871 => 165872)


--- trunk/Source/WebKit2/Shared/ImageOptions.h	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/Shared/ImageOptions.h	2014-03-19 06:55:29 UTC (rev 165872)
@@ -36,7 +36,9 @@
     SnapshotOptionsShareable = 1 << 0,
     SnapshotOptionsExcludeSelectionHighlighting = 1 << 1,
     SnapshotOptionsInViewCoordinates = 1 << 2,
-    SnapshotOptionsPaintSelectionRectangle = 1 << 3
+    SnapshotOptionsPaintSelectionRectangle = 1 << 3,
+    SnapshotOptionsRespectDrawingAreaTransform = 1 << 4,
+    SnapshotOptionsExcludeDeviceScaleFactor = 1 << 5,
 };
 typedef uint32_t SnapshotOptions;
 

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (165871 => 165872)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2014-03-19 06:55:29 UTC (rev 165872)
@@ -415,7 +415,7 @@
         [_scrollView setContentOffset:CGPointMake(-inset.left, -inset.top)];
         _isWaitingForNewLayerTreeAfterDidCommitLoad = NO;
     }
-    
+
 }
 
 - (RetainPtr<CGImageRef>)_takeViewSnapshot
@@ -1058,6 +1058,35 @@
     [self _updateVisibleContentRects];
 }
 
+- (void)_snapshotRect:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler
+{
+    CGRect snapshotRectInContentCoordinates = [self convertRect:rectInViewCoordinates toView:_contentView.get()];
+    CGFloat imageHeight = imageWidth / snapshotRectInContentCoordinates.size.width * snapshotRectInContentCoordinates.size.height;
+    CGSize imageSize = CGSizeMake(imageWidth, imageHeight);
+
+    void(^copiedCompletionHandler)(CGImageRef) = [completionHandler copy];
+    _page->takeSnapshot(WebCore::enclosingIntRect(snapshotRectInContentCoordinates), WebCore::expandedIntSize(WebCore::FloatSize(imageSize)), WebKit::SnapshotOptionsExcludeDeviceScaleFactor, [copiedCompletionHandler](bool, const WebKit::ShareableBitmap::Handle& imageHandle) {
+        if (imageHandle.isNull()) {
+            copiedCompletionHandler(nullptr);
+            [copiedCompletionHandler release];
+            return;
+        }
+
+        RefPtr<WebKit::ShareableBitmap> bitmap = WebKit::ShareableBitmap::create(imageHandle, WebKit::SharedMemory::ReadOnly);
+
+        if (!bitmap) {
+            copiedCompletionHandler(nullptr);
+            [copiedCompletionHandler release];
+            return;
+        }
+
+        RetainPtr<CGImageRef> cgImage;
+        cgImage = bitmap->makeCGImage();
+        copiedCompletionHandler(cgImage.get());
+        [copiedCompletionHandler release];
+    });
+}
+
 #else
 
 #pragma mark - OS X-specific methods

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h (165871 => 165872)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h	2014-03-19 06:55:29 UTC (rev 165872)
@@ -89,6 +89,8 @@
 
 - (void)_beginInteractiveObscuredInsetsChange;
 - (void)_endInteractiveObscuredInsetsChange;
+
+- (void)_snapshotRect:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler;
 #else
 @property (readonly) NSColor *_pageExtendedBackgroundColor;
 @property (nonatomic, setter=_setDrawsTransparentBackground:) BOOL _drawsTransparentBackground;

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKThumbnailView.mm (165871 => 165872)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKThumbnailView.mm	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKThumbnailView.mm	2014-03-19 06:55:29 UTC (rev 165872)
@@ -30,6 +30,7 @@
 
 #if PLATFORM(MAC)
 
+#import "ImageOptions.h"
 #import "WKAPICast.h"
 #import "WKView.h"
 #import "WKViewInternal.h"
@@ -69,6 +70,9 @@
     _originalSourceViewIsInWindow = !![_wkView window];
 
     _shouldApplyThumbnailScale = !_originalSourceViewIsInWindow;
+
+    self.usesSnapshot = YES;
+
     return self;
 }
 
@@ -107,7 +111,11 @@
     _waitingForSnapshot = YES;
 
     RetainPtr<_WKThumbnailView> thumbnailView = self;
-    _webPageProxy->takeThumbnailSnapshot([thumbnailView](bool, const ShareableBitmap::Handle& imageHandle) {
+    IntRect snapshotRect(IntPoint(), _webPageProxy->viewSize());
+    SnapshotOptions options = SnapshotOptionsRespectDrawingAreaTransform | SnapshotOptionsInViewCoordinates;
+    IntSize bitmapSize = snapshotRect.size();
+    bitmapSize.scale(_webPageProxy->deviceScaleFactor());
+    _webPageProxy->takeSnapshot(snapshotRect, bitmapSize, options, [thumbnailView](bool, const ShareableBitmap::Handle& imageHandle) {
         RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(imageHandle, SharedMemory::ReadOnly);
         RetainPtr<CGImageRef> cgImage = bitmap->makeCGImage();
         [thumbnailView _didTakeSnapshot:cgImage.get()];

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (165871 => 165872)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2014-03-19 06:55:29 UTC (rev 165872)
@@ -4595,17 +4595,19 @@
     m_process->send(Messages::WebPage::AddMIMETypeWithCustomContentProvider(mimeType), m_pageID);
 }
 
-void WebPageProxy::takeThumbnailSnapshot(ImageCallback::CallbackFunction callbackFunction)
+void WebPageProxy::takeSnapshot(IntRect rect, IntSize bitmapSize, SnapshotOptions options, ImageCallback::CallbackFunction callbackFunction)
 {
-    if (!isValid())
+    RefPtr<ImageCallback> callback = ImageCallback::create(callbackFunction);
+
+    if (!isValid()) {
+        callback->invalidate();
         return;
+    }
 
-    RefPtr<ImageCallback> callback = ImageCallback::create(callbackFunction);
-
     uint64_t callbackID = callback->callbackID();
     m_imageCallbacks.set(callbackID, callback.get());
 
-    m_process->send(Messages::WebPage::TakeThumbnailSnapshot(callbackID), m_pageID);
+    m_process->send(Messages::WebPage::TakeSnapshot(rect, bitmapSize, options, callbackID), m_pageID);
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (165871 => 165872)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2014-03-19 06:55:29 UTC (rev 165872)
@@ -923,7 +923,7 @@
 
     void setThumbnailScale(double);
 
-    void takeThumbnailSnapshot(ImageCallback::CallbackFunction);
+    void takeSnapshot(WebCore::IntRect, WebCore::IntSize bitmapSize, SnapshotOptions, ImageCallback::CallbackFunction);
 
 #if ENABLE(IMAGE_CONTROLS)
     void replaceControlledImage(PassRefPtr<ShareableBitmap>);

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (165871 => 165872)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp	2014-03-19 06:55:29 UTC (rev 165872)
@@ -1514,12 +1514,12 @@
 }
 #endif // !PLATFORM(IOS)
 
-void WebPage::takeThumbnailSnapshot(uint64_t callbackID)
+void WebPage::takeSnapshot(IntRect snapshotRect, IntSize bitmapSize, uint32_t options, uint64_t callbackID)
 {
-    IntRect snapshotRect(IntPoint(), m_viewSize);
-    snapshotRect = m_drawingArea->rootLayerTransform().inverse().mapRect(snapshotRect);
+    SnapshotOptions snapshotOptions = static_cast<SnapshotOptions>(options);
+    snapshotOptions |= SnapshotOptionsShareable;
 
-    RefPtr<WebImage> image = scaledSnapshotWithOptions(snapshotRect, 1, SnapshotOptionsShareable | SnapshotOptionsInViewCoordinates);
+    RefPtr<WebImage> image = snapshotAtSize(snapshotRect, bitmapSize, snapshotOptions);
 
     ShareableBitmap::Handle handle;
     if (image)
@@ -1530,6 +1530,18 @@
 
 PassRefPtr<WebImage> WebPage::scaledSnapshotWithOptions(const IntRect& rect, double scaleFactor, SnapshotOptions options)
 {
+    IntRect snapshotRect = rect;
+    if (options & SnapshotOptionsRespectDrawingAreaTransform)
+        snapshotRect = m_drawingArea->rootLayerTransform().inverse().mapRect(snapshotRect);
+
+    IntSize bitmapSize = snapshotRect.size();
+    bitmapSize.scale(scaleFactor * corePage()->deviceScaleFactor());
+
+    return snapshotAtSize(rect, bitmapSize, options);
+}
+
+PassRefPtr<WebImage> WebPage::snapshotAtSize(const IntRect& rect, const IntSize& bitmapSize, SnapshotOptions options)
+{
     Frame* coreFrame = m_mainFrame->coreFrame();
     if (!coreFrame)
         return nullptr;
@@ -1538,21 +1550,28 @@
     if (!frameView)
         return nullptr;
 
-    IntSize bitmapSize = rect.size();
-    float combinedScaleFactor = scaleFactor * corePage()->deviceScaleFactor();
-    bitmapSize.scale(combinedScaleFactor);
+    IntRect snapshotRect = rect;
+    if (options & SnapshotOptionsRespectDrawingAreaTransform)
+        snapshotRect = m_drawingArea->rootLayerTransform().inverse().mapRect(snapshotRect);
 
+    float horizontalScaleFactor = static_cast<float>(bitmapSize.width()) / rect.width();
+    float verticalScaleFactor = static_cast<float>(bitmapSize.height()) / rect.height();
+    float scaleFactor = std::min(horizontalScaleFactor, verticalScaleFactor);
+
     RefPtr<WebImage> snapshot = WebImage::create(bitmapSize, snapshotOptionsToImageOptions(options));
     if (!snapshot->bitmap())
         return nullptr;
 
     auto graphicsContext = snapshot->bitmap()->createGraphicsContext();
 
-    graphicsContext->clearRect(IntRect(IntPoint(), bitmapSize));
+    graphicsContext->fillRect(IntRect(IntPoint(), bitmapSize), frameView->baseBackgroundColor(), ColorSpaceDeviceRGB);
 
-    graphicsContext->applyDeviceScaleFactor(combinedScaleFactor);
-    graphicsContext->translate(-rect.x(), -rect.y());
+    if (!(options & SnapshotOptionsExcludeDeviceScaleFactor))
+        graphicsContext->applyDeviceScaleFactor(corePage()->deviceScaleFactor());
 
+    graphicsContext->scale(FloatSize(scaleFactor, scaleFactor));
+    graphicsContext->translate(-snapshotRect.x(), -snapshotRect.y());
+
     FrameView::SelectionInSnapshot shouldPaintSelection = FrameView::IncludeSelection;
     if (options & SnapshotOptionsExcludeSelectionHighlighting)
         shouldPaintSelection = FrameView::ExcludeSelection;
@@ -1561,14 +1580,14 @@
     if (options & SnapshotOptionsInViewCoordinates)
         coordinateSpace = FrameView::ViewCoordinates;
 
-    frameView->paintContentsForSnapshot(graphicsContext.get(), rect, shouldPaintSelection, coordinateSpace);
+    frameView->paintContentsForSnapshot(graphicsContext.get(), snapshotRect, shouldPaintSelection, coordinateSpace);
 
     if (options & SnapshotOptionsPaintSelectionRectangle) {
         FloatRect selectionRectangle = m_mainFrame->coreFrame()->selection().selectionBounds();
         graphicsContext->setStrokeColor(Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
         graphicsContext->strokeRect(selectionRectangle, 1);
     }
-
+    
     return snapshot.release();
 }
 

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (165871 => 165872)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h	2014-03-19 06:55:29 UTC (rev 165872)
@@ -422,6 +422,7 @@
     WebCore::IntRect rootViewToScreen(const WebCore::IntRect&);
 
     PassRefPtr<WebImage> scaledSnapshotWithOptions(const WebCore::IntRect&, double scaleFactor, SnapshotOptions);
+    PassRefPtr<WebImage> snapshotAtSize(const WebCore::IntRect&, const WebCore::IntSize& bitmapSize, SnapshotOptions);
 
     static const WebEvent* currentEvent();
 
@@ -855,7 +856,7 @@
     void getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID);
     void runJavaScriptInMainFrame(const String&, uint64_t callbackID);
     void forceRepaint(uint64_t callbackID);
-    void takeThumbnailSnapshot(uint64_t callbackID);
+    void takeSnapshot(WebCore::IntRect snapshotRect, WebCore::IntSize bitmapSize, uint32_t options, uint64_t callbackID);
 
     void preferencesDidChange(const WebPreferencesStore&);
     void platformPreferencesDidChange(const WebPreferencesStore&);

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in (165871 => 165872)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in	2014-03-19 06:22:46 UTC (rev 165871)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in	2014-03-19 06:55:29 UTC (rev 165872)
@@ -341,7 +341,7 @@
 
     GetBytecodeProfile(uint64_t callbackID)
     
-    TakeThumbnailSnapshot(uint64_t callbackID)
+    TakeSnapshot(WebCore::IntRect snapshotRect, WebCore::IntSize bitmapSize, uint32_t options, uint64_t callbackID)
 
 #if ENABLE(IMAGE_CONTROLS)
     ReplaceControlledImage(WebKit::ShareableBitmap::Handle newBitmapHandle)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to