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)