[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198
ap at apple.com
ap at apple.com
Mon Feb 21 00:02:39 UTC 2011
The following commit has been merged in the webkit-1.3 branch:
commit 286a32a3eb68d46143e1d143a9f522db6e34787f
Author: ap at apple.com <ap at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Thu Jan 27 19:36:10 2011 +0000
Reviewed by Darin Adler.
https://bugs.webkit.org/show_bug.cgi?id=53197
<rdar://problem/8895682> Make WebKit2 printing asynchronous
<rdar://problem/8899988> REGRESSION(WebKit2): Attempting to print WHATWG HTML spec shows
1-page blank preview
<rdar://problem/8900078> WebKit2 printing has a separate message exchange per page when
printing instead of printing all at once
* UIProcess/API/mac/WKPrintingView.h: Store a lot more cached information.
* UIProcess/API/mac/WKPrintingView.mm:
(-[WKPrintingView _adjustPrintingMarginsForHeaderAndFooter]): Use PrintOperation stored in
class. We generally want that now, because current operation will not be set up on other threads.
(-[WKPrintingView _isPrintingPreview]): Added. Preview is different, because it can draw
a placeholder - but actual printing need to wait until UI process has data.
(-[WKPrintingView _updatePreview]): Force AppKit to update print preview when we have real
data to replace placeholder with.
(-[WKPrintingView _hasPageRects]): Return if page rects have already been computed.
(-[WKPrintingView _expectedPreviewCallbackForRect:]): Find an existing request for this rect,
if any.
(pageDidDrawToPDF): Update preview - or if actually printing, release control to printing thread.
(-[WKPrintingView _preparePDFDataForPrintingOnSecondaryThread]): Ask for a PDF document with
pages the user asked to print.
(pageDidComputePageRects): When web process returns page geometry data, we update preview to display
a page count (which indirectly triggers a request for a preview). When actually printing,
request a PDF right away, we'll need it later.
(-[WKPrintingView _askPageToComputePageRects]): Ask web process for page geometry.
(prepareDataForPrintingOnSecondaryThread): This function starts preparing all data necessary
for actual printing on main thread.
(-[WKPrintingView knowsPageRange:]): Changed to be async for preview, and to call main
thread for actual printing.
(-[WKPrintingView _pageForRect:]): Find page number for a given range, assuming that AppKit
always asks for full pages.
(-[WKPrintingView _drawPDFDocument:page:atPoint:]): A helper function to draw a PDF document.
(-[WKPrintingView _drawPreview:]): Draw the whole page for preview.
(-[WKPrintingView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]):
Draw the whole page for actual printing.
(-[WKPrintingView _drawPageBorderWithSizeOnMainThread:]): Call drawPageBorderWithSize: with
correct graphics context and print operation.
(-[WKPrintingView drawPageBorderWithSize:]): Delegate work to main thread when called from a
secondary one.
(-[WKPrintingView _provideTotalScaleFactorForPrintOperation:]): Added an assertion that
our stored NSPrintOperation isn't out of sync with reality.
(-[WKPrintingView rectForPage:]): Handle the case where we don't have the data yet, drawing
a placeholder.
(-[WKPrintingView endDocument]): When page setup changes, we must reset all state.
* UIProcess/API/mac/WKView.mm: (-[WKView printOperationWithPrintInfo:forFrame:]): Tell
NSPrintingView which operation it's serving, so that it knows it even when current operation
isn't set.
* UIProcess/GenericCallback.h:
(WebKit::ComputedPagesCallback::create):
(WebKit::ComputedPagesCallback::~ComputedPagesCallback):
(WebKit::ComputedPagesCallback::performCallbackWithReturnValue):
(WebKit::ComputedPagesCallback::invalidate):
(WebKit::ComputedPagesCallback::callbackID):
(WebKit::ComputedPagesCallback::generateCallbackID):
(WebKit::ComputedPagesCallback::ComputedPagesCallback):
Added ComputedPagesCallback, which returns a vector of IntRects and a double. Hopefully,
it will become a specialization of GenericCallback one day.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::close): Added m_voidCallbacks - it looks like they were omitted
by accident.
(WebKit::WebPageProxy::computedPagesCallback): Added.
(WebKit::WebPageProxy::processDidCrash): Added m_computedPagesCallbacks.
(WebKit::WebPageProxy::computePagesForPrinting): Async now!
(WebKit::WebPageProxy::drawRectToPDF): Ditto.
(WebKit::WebPageProxy::drawPagesToPDF): Added.
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in: Added ComputedPagesCallback.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::beginPriting): Compute page rects right away - we'll need them in
drawPagesToPDF(), which doesn't have a PrintInfo.
(WebKit::WebPage::computePagesForPrinting): Send async response.
(WebKit::WebPage::drawRectToPDF): This function used to draw into original
location at frame coordinates, and now it draws at (0, 0).
(WebKit::WebPage::drawPagesToPDF): Added - make a multi-page PDF.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in: Added DrawPagesToPDF.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76821 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index c13e311..d4fc183 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,15 @@
+2011-01-26 Alexey Proskuryakov <ap at apple.com>
+
+ Reviewed by Darin Adler.
+
+ https://bugs.webkit.org/show_bug.cgi?id=53197
+ <rdar://problem/8895682> Make WebKit2 printing asynchronous
+
+ * WebCore.exp.in: Export more PrintContext methods that we didn't use on Mac before.
+
+ * page/PrintContext.cpp: (WebCore::PrintContext::spoolRect): Changed to make the same
+ transformation as spoolPages does for consistency.
+
2011-01-27 David Grogan <dgrogan at google.com>
Reviewed by Jeremy Orlow.
diff --git a/Source/WebCore/WebCore.exp.in b/Source/WebCore/WebCore.exp.in
index 957c492..44383b3 100644
--- a/Source/WebCore/WebCore.exp.in
+++ b/Source/WebCore/WebCore.exp.in
@@ -1001,6 +1001,8 @@ __ZNK7WebCore12EventHandler20currentKeyboardEventEv
__ZNK7WebCore12IconDatabase12databasePathEv
__ZNK7WebCore12IconDatabase24shouldStopThreadActivityEv
__ZNK7WebCore12IconDatabase9isEnabledEv
+__ZNK7WebCore12PrintContext8pageRectEm
+__ZNK7WebCore12PrintContext9pageCountEv
__ZNK7WebCore12RenderObject14enclosingLayerEv
__ZNK7WebCore12RenderObject15localToAbsoluteENS_10FloatPointEbb
__ZNK7WebCore12RenderObject7childAtEj
diff --git a/Source/WebCore/page/PrintContext.cpp b/Source/WebCore/page/PrintContext.cpp
index 16fd379..760b6af 100644
--- a/Source/WebCore/page/PrintContext.cpp
+++ b/Source/WebCore/page/PrintContext.cpp
@@ -165,8 +165,7 @@ void PrintContext::spoolPage(GraphicsContext& ctx, int pageNumber, float width)
void PrintContext::spoolRect(GraphicsContext& ctx, const IntRect& rect)
{
ctx.save();
- ctx.scale(FloatSize(1, -1));
- ctx.translate(0, -m_frame->view()->contentsHeight());
+ ctx.translate(-rect.x(), -rect.y());
ctx.clip(rect);
m_frame->view()->paintContents(&ctx, rect);
ctx.restore();
diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog
index 3dd6ba6..62b2dd4 100644
--- a/Source/WebKit2/ChangeLog
+++ b/Source/WebKit2/ChangeLog
@@ -1,3 +1,93 @@
+2011-01-26 Alexey Proskuryakov <ap at apple.com>
+
+ Reviewed by Darin Adler.
+
+ https://bugs.webkit.org/show_bug.cgi?id=53197
+ <rdar://problem/8895682> Make WebKit2 printing asynchronous
+
+ <rdar://problem/8899988> REGRESSION(WebKit2): Attempting to print WHATWG HTML spec shows
+ 1-page blank preview
+
+ <rdar://problem/8900078> WebKit2 printing has a separate message exchange per page when
+ printing instead of printing all at once
+
+ * UIProcess/API/mac/WKPrintingView.h: Store a lot more cached information.
+
+ * UIProcess/API/mac/WKPrintingView.mm:
+ (-[WKPrintingView _adjustPrintingMarginsForHeaderAndFooter]): Use PrintOperation stored in
+ class. We generally want that now, because current operation will not be set up on other threads.
+ (-[WKPrintingView _isPrintingPreview]): Added. Preview is different, because it can draw
+ a placeholder - but actual printing need to wait until UI process has data.
+ (-[WKPrintingView _updatePreview]): Force AppKit to update print preview when we have real
+ data to replace placeholder with.
+ (-[WKPrintingView _hasPageRects]): Return if page rects have already been computed.
+ (-[WKPrintingView _expectedPreviewCallbackForRect:]): Find an existing request for this rect,
+ if any.
+ (pageDidDrawToPDF): Update preview - or if actually printing, release control to printing thread.
+ (-[WKPrintingView _preparePDFDataForPrintingOnSecondaryThread]): Ask for a PDF document with
+ pages the user asked to print.
+ (pageDidComputePageRects): When web process returns page geometry data, we update preview to display
+ a page count (which indirectly triggers a request for a preview). When actually printing,
+ request a PDF right away, we'll need it later.
+ (-[WKPrintingView _askPageToComputePageRects]): Ask web process for page geometry.
+ (prepareDataForPrintingOnSecondaryThread): This function starts preparing all data necessary
+ for actual printing on main thread.
+ (-[WKPrintingView knowsPageRange:]): Changed to be async for preview, and to call main
+ thread for actual printing.
+ (-[WKPrintingView _pageForRect:]): Find page number for a given range, assuming that AppKit
+ always asks for full pages.
+ (-[WKPrintingView _drawPDFDocument:page:atPoint:]): A helper function to draw a PDF document.
+ (-[WKPrintingView _drawPreview:]): Draw the whole page for preview.
+ (-[WKPrintingView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]):
+ Draw the whole page for actual printing.
+ (-[WKPrintingView _drawPageBorderWithSizeOnMainThread:]): Call drawPageBorderWithSize: with
+ correct graphics context and print operation.
+ (-[WKPrintingView drawPageBorderWithSize:]): Delegate work to main thread when called from a
+ secondary one.
+ (-[WKPrintingView _provideTotalScaleFactorForPrintOperation:]): Added an assertion that
+ our stored NSPrintOperation isn't out of sync with reality.
+ (-[WKPrintingView rectForPage:]): Handle the case where we don't have the data yet, drawing
+ a placeholder.
+ (-[WKPrintingView endDocument]): When page setup changes, we must reset all state.
+
+ * UIProcess/API/mac/WKView.mm: (-[WKView printOperationWithPrintInfo:forFrame:]): Tell
+ NSPrintingView which operation it's serving, so that it knows it even when current operation
+ isn't set.
+
+ * UIProcess/GenericCallback.h:
+ (WebKit::ComputedPagesCallback::create):
+ (WebKit::ComputedPagesCallback::~ComputedPagesCallback):
+ (WebKit::ComputedPagesCallback::performCallbackWithReturnValue):
+ (WebKit::ComputedPagesCallback::invalidate):
+ (WebKit::ComputedPagesCallback::callbackID):
+ (WebKit::ComputedPagesCallback::generateCallbackID):
+ (WebKit::ComputedPagesCallback::ComputedPagesCallback):
+ Added ComputedPagesCallback, which returns a vector of IntRects and a double. Hopefully,
+ it will become a specialization of GenericCallback one day.
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::close): Added m_voidCallbacks - it looks like they were omitted
+ by accident.
+ (WebKit::WebPageProxy::computedPagesCallback): Added.
+ (WebKit::WebPageProxy::processDidCrash): Added m_computedPagesCallbacks.
+ (WebKit::WebPageProxy::computePagesForPrinting): Async now!
+ (WebKit::WebPageProxy::drawRectToPDF): Ditto.
+ (WebKit::WebPageProxy::drawPagesToPDF): Added.
+ * UIProcess/WebPageProxy.h:
+
+ * UIProcess/WebPageProxy.messages.in: Added ComputedPagesCallback.
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::beginPriting): Compute page rects right away - we'll need them in
+ drawPagesToPDF(), which doesn't have a PrintInfo.
+ (WebKit::WebPage::computePagesForPrinting): Send async response.
+ (WebKit::WebPage::drawRectToPDF): This function used to draw into original
+ location at frame coordinates, and now it draws at (0, 0).
+ (WebKit::WebPage::drawPagesToPDF): Added - make a multi-page PDF.
+ * WebProcess/WebPage/WebPage.h:
+
+ * WebProcess/WebPage/WebPage.messages.in: Added DrawPagesToPDF.
+
2011-01-27 Alejandro G. Castro <alex at igalia.com>
Unreviewed GTK build fix after r76797.
diff --git a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h
index 42e2c30..10c59c4 100644
--- a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h
+++ b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h
@@ -23,8 +23,8 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import <WebCore/IntRect.h>
-#import <wtf/RefPtr.h>
+#import <WebCore/IntRectHash.h>
+#import <wtf/RetainPtr.h>
@class WKPrintingViewData;
@@ -34,9 +34,25 @@ namespace WebKit {
@interface WKPrintingView : NSView {
@public
+ NSPrintOperation *_printOperation; // WKPrintingView is owned by the operation.
+
RefPtr<WebKit::WebFrameProxy> _webFrame;
- Vector<WebCore::IntRect> _webPrintingPageRects;
- double _webTotalScaleFactorForPrinting;
+ Vector<WebCore::IntRect> _printingPageRects;
+ double _totalScaleFactorForPrinting;
+ HashMap<WebCore::IntRect, Vector<uint8_t> > _pagePreviews;
+
+ Vector<uint8_t> _printedPagesData;
+ RetainPtr<CGPDFDocumentRef> _printedPagesPDFDocument;
+
+ uint64_t _expectedComputedPagesCallback;
+ HashMap<uint64_t, WebCore::IntRect> _expectedPreviewCallbacks;
+ uint64_t _latestExpectedPreviewCallback;
+ uint64_t _expectedPrintCallback;
+ BOOL _isForcingPreviewUpdate;
+
+ BOOL _isPrintingFromSecondaryThread;
+ Mutex _printingCallbackMutex;
+ ThreadCondition _printingCallbackCondition;
}
- (id)initWithFrameProxy:(WebKit::WebFrameProxy*)frame;
diff --git a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm
index 99b8610..3508c10 100644
--- a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm
+++ b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm
@@ -27,6 +27,7 @@
#import "Logging.h"
#import "PrintInfo.h"
+#import "WebData.h"
#import "WebPageProxy.h"
@interface NSView (WebNSViewDetails)
@@ -39,6 +40,8 @@ using namespace WebCore;
NSString * const WebKitOriginalTopPrintingMarginKey = @"WebKitOriginalTopMargin";
NSString * const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMargin";
+NSString * const NSPrintInfoDidChangeNotification = @"NSPrintInfoDidChange";
+
@implementation WKPrintingView
- (id)initWithFrameProxy:(WebFrameProxy*)frame
@@ -59,8 +62,7 @@ NSString * const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomM
- (void)_adjustPrintingMarginsForHeaderAndFooter
{
- NSPrintOperation *printOperation = [NSPrintOperation currentOperation];
- NSPrintInfo *info = [printOperation printInfo];
+ NSPrintInfo *info = [_printOperation printInfo];
NSMutableDictionary *infoDictionary = [info dictionary];
// We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
@@ -88,40 +90,236 @@ NSString * const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomM
[info setBottomMargin:originalBottomMargin + _webFrame->page()->footerHeight(_webFrame.get()) * scale];
}
-- (BOOL)knowsPageRange:(NSRangePointer)range
+- (BOOL)_isPrintingPreview
{
- LOG(View, "knowsPageRange:");
- [self _adjustPrintingMarginsForHeaderAndFooter];
+ // <rdar://problem/8901041> Please add an API returning whether the current print operation is for preview.
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+ return [_printOperation preferredRenderingQuality] == NSPrintRenderingQualityResponsive;
+#else
+ // Assuming that if NSPrintOperation is allowed to spawn a thread for printing, it will. Print preview doesn't spawn a thread.
+ return !_isPrintingFromSecondaryThread;
+#endif
+}
+
+- (void)_updatePreview
+{
+ // <rdar://problem/8900923> Please add an API to force print preview update.
+ _isForcingPreviewUpdate = YES;
+ [[NSNotificationCenter defaultCenter] postNotificationName:NSPrintInfoDidChangeNotification object:nil];
+ _isForcingPreviewUpdate = NO;
+}
+
+- (BOOL)_hasPageRects
+{
+ // WebCore always prints at least one page.
+ return !_printingPageRects.isEmpty();
+}
+
+- (uint64_t)_expectedPreviewCallbackForRect:(const IntRect&)rect
+{
+ for (HashMap<uint64_t, WebCore::IntRect>::iterator iter = _expectedPreviewCallbacks.begin(); iter != _expectedPreviewCallbacks.end(); ++iter) {
+ if (iter->second == rect)
+ return iter->first;
+ }
+ return 0;
+}
+
+struct IPCCallbackContext {
+ RetainPtr<WKPrintingView> view;
+ uint64_t callbackID;
+};
+
+static void pageDidDrawToPDF(WKDataRef dataRef, WKErrorRef, void* untypedContext)
+{
+ ASSERT(isMainThread());
+
+ OwnPtr<IPCCallbackContext> context = adoptPtr(static_cast<IPCCallbackContext*>(untypedContext));
+ WKPrintingView *view = context->view.get();
+ WebData* data = toImpl(dataRef);
+
+ if (context->callbackID == view->_expectedPrintCallback) {
+ ASSERT(![view _isPrintingPreview]);
+ ASSERT(view->_printedPagesData.isEmpty());
+ ASSERT(!view->_printedPagesPDFDocument);
+ if (data)
+ view->_printedPagesData.append(data->bytes(), data->size());
+ view->_expectedPrintCallback = 0;
+ view->_printingCallbackCondition.signal();
+ } else {
+ // If the user has already changed print setup, then this response is obsolete. And this callback is not in response to the latest request,
+ // then the user has already moved to another page - we'll cache the response, but won't draw it.
+ HashMap<uint64_t, WebCore::IntRect>::iterator iter = view->_expectedPreviewCallbacks.find(context->callbackID);
+ if (iter != view->_expectedPreviewCallbacks.end()) {
+ ASSERT([view _isPrintingPreview]);
+
+ pair<HashMap<WebCore::IntRect, Vector<uint8_t> >::iterator, bool> entry = view->_pagePreviews.add(iter->second, Vector<uint8_t>());
+ entry.first->second.append(data->bytes(), data->size());
+
+ bool receivedResponseToLatestRequest = view->_latestExpectedPreviewCallback == context->callbackID;
+ view->_latestExpectedPreviewCallback = 0;
+ view->_expectedPreviewCallbacks.remove(context->callbackID);
+ if (receivedResponseToLatestRequest)
+ [view _updatePreview];
+ }
+ }
+}
+
+- (void)_preparePDFDataForPrintingOnSecondaryThread
+{
+ ASSERT(isMainThread());
+
+ if (!_webFrame->page()) {
+ _printingCallbackCondition.signal();
+ return;
+ }
+
+ MutexLocker lock(_printingCallbackMutex);
+
+ ASSERT([self _hasPageRects]);
+ ASSERT(_printedPagesData.isEmpty());
+ ASSERT(!_printedPagesPDFDocument);
+ ASSERT(!_expectedPrintCallback);
+
+ unsigned firstPage = [[[[_printOperation printInfo] dictionary] objectForKey:NSPrintFirstPage] unsignedIntValue];
+ unsigned lastPage = [[[[_printOperation printInfo] dictionary] objectForKey:NSPrintLastPage] unsignedIntValue];
+ if (lastPage > _printingPageRects.size()) // Last page is NSIntegerMax if not set by the user.
+ lastPage = _printingPageRects.size();
- _webFrame->page()->computePagesForPrinting(_webFrame.get(), PrintInfo([[NSPrintOperation currentOperation] printInfo]), _webPrintingPageRects, _webTotalScaleFactorForPrinting);
+ ASSERT(firstPage > 0);
+ ASSERT(firstPage <= lastPage);
+ LOG(View, "WKPrintingView requesting PDF data for pages %u...%u", firstPage, lastPage);
- *range = NSMakeRange(1, _webPrintingPageRects.size());
+ // Return to printing mode if we're already back to screen (e.g. due to window resizing).
+ _webFrame->page()->beginPrinting(_webFrame.get(), PrintInfo([_printOperation printInfo]));
+
+ IPCCallbackContext* context = new IPCCallbackContext;
+ RefPtr<DataCallback> callback = DataCallback::create(context, pageDidDrawToPDF);
+ _expectedPrintCallback = callback->callbackID();
+
+ context->view = self;
+ context->callbackID = callback->callbackID();
+
+ _webFrame->page()->drawPagesToPDF(_webFrame.get(), firstPage - 1, lastPage - firstPage + 1, callback.get());
+}
+
+static void pageDidComputePageRects(const Vector<WebCore::IntRect>& pageRects, double totalScaleFactorForPrinting, WKErrorRef, void* untypedContext)
+{
+ ASSERT(isMainThread());
+
+ OwnPtr<IPCCallbackContext> context = adoptPtr(static_cast<IPCCallbackContext*>(untypedContext));
+ WKPrintingView *view = context->view.get();
+
+ // If the user has already changed print setup, then this response is obsolete.
+ if (context->callbackID == view->_expectedComputedPagesCallback) {
+ ASSERT(isMainThread());
+ ASSERT(view->_expectedPreviewCallbacks.isEmpty());
+ ASSERT(!view->_latestExpectedPreviewCallback);
+ ASSERT(!view->_expectedPrintCallback);
+ ASSERT(view->_pagePreviews.isEmpty());
+ view->_expectedComputedPagesCallback = 0;
+
+ view->_printingPageRects = pageRects;
+ view->_totalScaleFactorForPrinting = totalScaleFactorForPrinting;
+
+ if ([view _isPrintingPreview]) {
+ // Show page count, and ask for an actual image to replace placeholder.
+ [view _updatePreview];
+ } else {
+ // When printing, request everything we'll need beforehand.
+ [view _preparePDFDataForPrintingOnSecondaryThread];
+ }
+ }
+}
+
+- (BOOL)_askPageToComputePageRects
+{
+ ASSERT(isMainThread());
+
+ if (!_webFrame->page())
+ return NO;
+
+ ASSERT(!_expectedComputedPagesCallback);
+
+ IPCCallbackContext* context = new IPCCallbackContext;
+ RefPtr<ComputedPagesCallback> callback = ComputedPagesCallback::create(context, pageDidComputePageRects);
+ _expectedComputedPagesCallback = callback->callbackID();
+ context->view = self;
+ context->callbackID = _expectedComputedPagesCallback;
+
+ _webFrame->page()->computePagesForPrinting(_webFrame.get(), PrintInfo([_printOperation printInfo]), callback.release());
return YES;
}
-// Take over printing. AppKit applies incorrect clipping, and doesn't print pages beyond the first one.
-- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView
+static void prepareDataForPrintingOnSecondaryThread(void* untypedContext)
{
- LOG(View, "Printing rect x:%g, y:%g, width:%g, height:%g", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+ ASSERT(isMainThread());
- ASSERT(self == visibleView);
+ WKPrintingView *view = static_cast<WKPrintingView *>(untypedContext);
+ MutexLocker lock(view->_printingCallbackMutex);
- _webFrame->page()->beginPrinting(_webFrame.get(), PrintInfo([[NSPrintOperation currentOperation] printInfo]));
+ // We may have received page rects while a message to call this function traveled from secondary thread to main one.
+ if ([view _hasPageRects]) {
+ [view _preparePDFDataForPrintingOnSecondaryThread];
+ return;
+ }
- // FIXME: This is optimized for print preview. Get the whole document at once when actually printing.
- Vector<uint8_t> pdfData;
- _webFrame->page()->drawRectToPDF(_webFrame.get(), IntRect(rect), pdfData);
+ // A request for pages has already been made, just wait for it to finish.
+ if (view->_expectedComputedPagesCallback)
+ return;
- RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, pdfData.data(), pdfData.size(), 0));
- RetainPtr<CGPDFDocumentRef> pdfDocument(AdoptCF, CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
+ [view _askPageToComputePageRects];
+}
+
+- (BOOL)knowsPageRange:(NSRangePointer)range
+{
+ LOG(View, "-[WKPrintingView knowsPageRange:], %s, %s", [self _hasPageRects] ? "print data is available" : "print data is not available yet", isMainThread() ? "on main thread" : "on secondary thread");
+ ASSERT(_printOperation == [NSPrintOperation currentOperation]);
+
+ // Assuming that once we switch to printing from a secondary thread, we don't go back.
+ ASSERT(!_isPrintingFromSecondaryThread || !isMainThread());
+ if (!isMainThread())
+ _isPrintingFromSecondaryThread = YES;
+
+ [self _adjustPrintingMarginsForHeaderAndFooter];
+
+ if ([self _hasPageRects])
+ *range = NSMakeRange(1, _printingPageRects.size());
+ else if (!isMainThread()) {
+ ASSERT(![self _isPrintingPreview]);
+ MutexLocker lock(_printingCallbackMutex);
+ callOnMainThread(prepareDataForPrintingOnSecondaryThread, self);
+ _printingCallbackCondition.wait(_printingCallbackMutex);
+ *range = NSMakeRange(1, _printingPageRects.size());
+ } else {
+ ASSERT([self _isPrintingPreview]);
+
+ [self _askPageToComputePageRects];
+
+ *range = NSMakeRange(1, NSIntegerMax);
+ }
+ return YES;
+}
+
+- (unsigned)_pageForRect:(NSRect)rect
+{
+ // Assuming that rect exactly matches one of the pages.
+ for (size_t i = 0; i < _printingPageRects.size(); ++i) {
+ if (rect.origin.y == _printingPageRects[i].y())
+ return i + 1;
+ }
+ return 0; // Invalid page number.
+}
+
+- (void)_drawPDFDocument:(CGPDFDocumentRef)pdfDocument page:(unsigned)page atPoint:(NSPoint)point
+{
if (!pdfDocument) {
- LOG_ERROR("Couldn't create a PDF document with data passed for printing");
+ LOG_ERROR("Couldn't create a PDF document with data passed for preview");
return;
}
- CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument.get(), 1);
+ CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument, page);
if (!pdfPage) {
- LOG_ERROR("Printing data doesn't have page 1");
+ LOG_ERROR("Preview data doesn't have page %d", page);
return;
}
@@ -131,19 +329,120 @@ NSString * const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomM
CGContextSaveGState(context);
// Flip the destination.
CGContextScaleCTM(context, 1, -1);
- CGContextTranslateCTM(context, 0, -CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox).size.height);
+ CGContextTranslateCTM(context, point.x, -point.y -CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox).size.height);
CGContextDrawPDFPage(context, pdfPage);
CGContextRestoreGState(context);
}
+- (void)_drawPreview:(NSRect)nsRect
+{
+ ASSERT(isMainThread());
+
+ IntRect rect(nsRect);
+ HashMap<WebCore::IntRect, Vector<uint8_t> >::iterator pagePreviewIterator = _pagePreviews.find(rect);
+ if (pagePreviewIterator == _pagePreviews.end()) {
+ // It's too early to ask for page preview if we don't even know page size and scale.
+ if ([self _hasPageRects]) {
+ if (uint64_t existingCallback = [self _expectedPreviewCallbackForRect:rect]) {
+ // We've already asked for a preview of this page, and are waiting for response.
+ // There is no need to ask again.
+ _latestExpectedPreviewCallback = existingCallback;
+ } else {
+ // Preview isn't available yet, request it asynchronously.
+ if (!_webFrame->page())
+ return;
+
+ // Return to printing mode if we're already back to screen (e.g. due to window resizing).
+ _webFrame->page()->beginPrinting(_webFrame.get(), PrintInfo([_printOperation printInfo]));
+
+ IPCCallbackContext* context = new IPCCallbackContext;
+ RefPtr<DataCallback> callback = DataCallback::create(context, pageDidDrawToPDF);
+ _latestExpectedPreviewCallback = callback->callbackID();
+ _expectedPreviewCallbacks.add(_latestExpectedPreviewCallback, rect);
+
+ context->view = self;
+ context->callbackID = callback->callbackID();
+
+ _webFrame->page()->drawRectToPDF(_webFrame.get(), rect, callback.get());
+ return;
+ }
+ }
+
+ // FIXME: Draw a placeholder
+ return;
+ }
+
+ const Vector<uint8_t>& pdfData = pagePreviewIterator->second;
+ RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, pdfData.data(), pdfData.size(), 0));
+ RetainPtr<CGPDFDocumentRef> pdfDocument(AdoptCF, CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
+
+ [self _drawPDFDocument:pdfDocument.get() page:1 atPoint:NSMakePoint(nsRect.origin.x, nsRect.origin.y)];
+}
+
+// Take over printing. AppKit applies incorrect clipping, and doesn't print pages beyond the first one.
+- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)nsRect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView
+{
+ LOG(View, "WKPrintingView printing rect x:%g, y:%g, width:%g, height:%g", nsRect.origin.x, nsRect.origin.y, nsRect.size.width, nsRect.size.height);
+
+ ASSERT(_printOperation == [NSPrintOperation currentOperation]);
+ ASSERT(self == visibleView);
+
+ if (!_webFrame->page())
+ return;
+
+ if ([self _isPrintingPreview]) {
+ [self _drawPreview:nsRect];
+ return;
+ }
+
+ ASSERT(!isMainThread());
+ ASSERT(!_printedPagesData.isEmpty()); // Prepared by knowsPageRange:
+
+ if (!_printedPagesPDFDocument) {
+ RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, _printedPagesData.data(), _printedPagesData.size(), 0));
+ _printedPagesPDFDocument.adoptCF(CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
+ }
+
+ [self _drawPDFDocument:_printedPagesPDFDocument.get() page:[self _pageForRect:nsRect] atPoint:NSMakePoint(nsRect.origin.x, nsRect.origin.y)];
+}
+
+- (void)_drawPageBorderWithSizeOnMainThread:(NSSize)borderSize
+{
+ ASSERT(isMainThread());
+
+ // When printing from a secondary thread, the main thread doesn't have graphics context and printing operation set up.
+ NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
+ [NSGraphicsContext setCurrentContext:[_printOperation context]];
+
+ ASSERT(![NSPrintOperation currentOperation]);
+ [NSPrintOperation setCurrentOperation:_printOperation];
+
+ [self drawPageBorderWithSize:borderSize];
+
+ [NSPrintOperation setCurrentOperation:nil];
+ [NSGraphicsContext setCurrentContext:currentContext];
+}
+
- (void)drawPageBorderWithSize:(NSSize)borderSize
{
- ASSERT(NSEqualSizes(borderSize, [[[NSPrintOperation currentOperation] printInfo] paperSize]));
+ ASSERT(NSEqualSizes(borderSize, [[_printOperation printInfo] paperSize]));
+ ASSERT(_printOperation == [NSPrintOperation currentOperation]);
+
+ if (!isMainThread()) {
+ // Don't call the client from a secondary thread.
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[WKPrintingView instanceMethodSignatureForSelector:@selector(_drawPageBorderWithSizeOnMainThread:)]];
+ [invocation setSelector:@selector(_drawPageBorderWithSizeOnMainThread:)];
+ [invocation setArgument:&borderSize atIndex:2];
+ [invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:self waitUntilDone:YES];
+ return;
+ }
+
+ if (!_webFrame->page())
+ return;
// The header and footer rect height scales with the page, but the width is always
// all the way across the printed page (inset by printing margins).
- NSPrintOperation *printOperation = [NSPrintOperation currentOperation];
- NSPrintInfo *printInfo = [printOperation printInfo];
+ NSPrintInfo *printInfo = [_printOperation printInfo];
CGFloat scale = [printInfo scalingFactor];
NSSize paperSize = [printInfo paperSize];
CGFloat headerFooterLeft = [printInfo leftMargin] / scale;
@@ -168,14 +467,43 @@ NSString * const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomM
// if AppKit makes it SPI/API.
- (CGFloat)_provideTotalScaleFactorForPrintOperation:(NSPrintOperation *)printOperation
{
- return _webTotalScaleFactorForPrinting;
+ ASSERT(_printOperation == printOperation);
+ return _totalScaleFactorForPrinting;
}
// Return the drawing rectangle for a particular page number
- (NSRect)rectForPage:(NSInteger)page
{
- LOG(View, "rectForPage:%d -> x %d, y %d, width %d, height %d\n", (int)page, _webPrintingPageRects[page - 1].x(), _webPrintingPageRects[page - 1].y(), _webPrintingPageRects[page - 1].width(), _webPrintingPageRects[page - 1].height());
- return _webPrintingPageRects[page - 1];
+ ASSERT(_printOperation == [NSPrintOperation currentOperation]);
+ if (![self _hasPageRects]) {
+ LOG(View, "-[WKPrintingView rectForPage:%d] - data is not yet available", (int)page);
+ // We must be still calculating the page range.
+ ASSERT(_expectedComputedPagesCallback);
+ return NSMakeRect(0, 0, 1, 1);
+ }
+ LOG(View, "-[WKPrintingView rectForPage:%d] -> x %d, y %d, width %d, height %d", (int)page, _printingPageRects[page - 1].x(), _printingPageRects[page - 1].y(), _printingPageRects[page - 1].width(), _printingPageRects[page - 1].height());
+ return _printingPageRects[page - 1];
}
+- (void)endDocument
+{
+ ASSERT(_printOperation == [NSPrintOperation currentOperation]);
+
+ // Forcing preview update gets us here, but page setup hasn't actually changed.
+ if (_isForcingPreviewUpdate)
+ return;
+
+ LOG(View, "-[WKPrintingView endDocument] - clearing cached data");
+
+ // Both existing data and pending responses are now obsolete.
+ _printingPageRects.clear();
+ _totalScaleFactorForPrinting = 1;
+ _pagePreviews.clear();
+ _printedPagesData.clear();
+ _printedPagesPDFDocument = nullptr;
+ _expectedComputedPagesCallback = 0;
+ _expectedPreviewCallbacks.clear();
+ _latestExpectedPreviewCallback = 0;
+ _expectedPrintCallback = 0;
+}
@end
diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm
index 9432e33..fb06fd3 100644
--- a/Source/WebKit2/UIProcess/API/mac/WKView.mm
+++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm
@@ -1391,7 +1391,10 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I
} else {
RetainPtr<WKPrintingView> printingView(AdoptNS, [[WKPrintingView alloc] initWithFrameProxy:toImpl(frameRef)]);
// NSPrintOperation takes ownership of the view.
- return [NSPrintOperation printOperationWithView:printingView.get()];
+ NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:printingView.get()];
+ [printOperation setCanSpawnSeparateThread:YES];
+ printingView->_printOperation = printOperation;
+ return printOperation;
}
}
diff --git a/Source/WebKit2/UIProcess/GenericCallback.h b/Source/WebKit2/UIProcess/GenericCallback.h
index 010ce04..c34414a 100644
--- a/Source/WebKit2/UIProcess/GenericCallback.h
+++ b/Source/WebKit2/UIProcess/GenericCallback.h
@@ -89,6 +89,61 @@ private:
uint64_t m_callbackID;
};
+// FIXME: Make a version of GenericCallback with two arguments, and define ComputedPagesCallback as a specialization.
+class ComputedPagesCallback : public RefCounted<ComputedPagesCallback> {
+public:
+ typedef void (*CallbackFunction)(const Vector<WebCore::IntRect>&, double, WKErrorRef, void*);
+
+ static PassRefPtr<ComputedPagesCallback> create(void* context, CallbackFunction callback)
+ {
+ return adoptRef(new ComputedPagesCallback(context, callback));
+ }
+
+ ~ComputedPagesCallback()
+ {
+ ASSERT(!m_callback);
+ }
+
+ void performCallbackWithReturnValue(const Vector<WebCore::IntRect>& returnValue1, double returnValue2)
+ {
+ ASSERT(m_callback);
+
+ m_callback(returnValue1, returnValue2, 0, m_context);
+
+ m_callback = 0;
+ }
+
+ void invalidate()
+ {
+ ASSERT(m_callback);
+
+ RefPtr<WebError> error = WebError::create();
+ m_callback(Vector<WebCore::IntRect>(), 0, toAPI(error.get()), m_context);
+
+ m_callback = 0;
+ }
+
+ uint64_t callbackID() const { return m_callbackID; }
+
+private:
+ static uint64_t generateCallbackID()
+ {
+ static uint64_t uniqueCallbackID = 1;
+ return uniqueCallbackID++;
+ }
+
+ ComputedPagesCallback(void* context, CallbackFunction callback)
+ : m_context(context)
+ , m_callback(callback)
+ , m_callbackID(generateCallbackID())
+ {
+ }
+
+ void* m_context;
+ CallbackFunction m_callback;
+ uint64_t m_callbackID;
+};
+
template<typename APIReturnValueType, typename InternalReturnValueType = typename APITypeInfo<APIReturnValueType>::ImplType>
class GenericCallback : public RefCounted<GenericCallback<APIReturnValueType, InternalReturnValueType> > {
public:
diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp
index 02e598a..f24905d 100644
--- a/Source/WebKit2/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp
@@ -275,8 +275,10 @@ void WebPageProxy::close()
m_toolTip = String();
+ invalidateCallbackMap(m_voidCallbacks);
invalidateCallbackMap(m_dataCallbacks);
invalidateCallbackMap(m_stringCallbacks);
+ invalidateCallbackMap(m_computedPagesCallbacks);
Vector<WebEditCommandProxy*> editCommandVector;
copyToVector(m_editCommandSet, editCommandVector);
@@ -2208,6 +2210,17 @@ void WebPageProxy::stringCallback(const String& resultString, uint64_t callbackI
callback->performCallbackWithReturnValue(resultString.impl());
}
+void WebPageProxy::computedPagesCallback(const Vector<WebCore::IntRect>& pageRects, double totalScaleFactorForPrinting, uint64_t callbackID)
+{
+ RefPtr<ComputedPagesCallback> callback = m_computedPagesCallbacks.take(callbackID);
+ if (!callback) {
+ // FIXME: Log error or assert.
+ return;
+ }
+
+ callback->performCallbackWithReturnValue(pageRects, totalScaleFactorForPrinting);
+}
+
#if PLATFORM(MAC)
void WebPageProxy::sendAccessibilityPresenterToken(const CoreIPC::DataReference& token)
{
@@ -2298,6 +2311,7 @@ void WebPageProxy::processDidCrash()
invalidateCallbackMap(m_voidCallbacks);
invalidateCallbackMap(m_dataCallbacks);
invalidateCallbackMap(m_stringCallbacks);
+ invalidateCallbackMap(m_computedPagesCallbacks);
Vector<WebEditCommandProxy*> editCommandVector;
copyToVector(m_editCommandSet, editCommandVector);
@@ -2464,17 +2478,27 @@ void WebPageProxy::endPrinting()
process()->send(Messages::WebPage::EndPrinting(), m_pageID);
}
-void WebPageProxy::computePagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, Vector<WebCore::IntRect>& resultPageRects, double& resultTotalScaleFactorForPrinting)
+void WebPageProxy::computePagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, PassRefPtr<ComputedPagesCallback> callback)
{
- // Layout for printing can take a long time, but we need to have the answer.
- process()->sendSync(Messages::WebPage::ComputePagesForPrinting(frame->frameID(), printInfo), Messages::WebPage::ComputePagesForPrinting::Reply(resultPageRects, resultTotalScaleFactorForPrinting), m_pageID);
+ uint64_t callbackID = callback->callbackID();
+ m_computedPagesCallbacks.set(callbackID, callback.get());
+ m_isInPrintingMode = true;
+ process()->send(Messages::WebPage::ComputePagesForPrinting(frame->frameID(), printInfo, callbackID), m_pageID);
}
#if PLATFORM(MAC)
-void WebPageProxy::drawRectToPDF(WebFrameProxy* frame, const IntRect& rect, Vector<uint8_t>& pdfData)
+void WebPageProxy::drawRectToPDF(WebFrameProxy* frame, const IntRect& rect, PassRefPtr<DataCallback> callback)
{
- // Printing can take a long time, but we need to have the answer.
- process()->sendSync(Messages::WebPage::DrawRectToPDF(frame->frameID(), rect), Messages::WebPage::DrawRectToPDF::Reply(pdfData), m_pageID);
+ uint64_t callbackID = callback->callbackID();
+ m_dataCallbacks.set(callbackID, callback.get());
+ process()->send(Messages::WebPage::DrawRectToPDF(frame->frameID(), rect, callbackID), m_pageID);
+}
+
+void WebPageProxy::drawPagesToPDF(WebFrameProxy* frame, uint32_t first, uint32_t count, PassRefPtr<DataCallback> callback)
+{
+ uint64_t callbackID = callback->callbackID();
+ m_dataCallbacks.set(callbackID, callback.get());
+ process()->send(Messages::WebPage::DrawPagesToPDF(frame->frameID(), first, count, callbackID), m_pageID);
}
#endif
diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h
index 4228024..7caf9d9 100644
--- a/Source/WebKit2/UIProcess/WebPageProxy.h
+++ b/Source/WebKit2/UIProcess/WebPageProxy.h
@@ -366,9 +366,10 @@ public:
void beginPrinting(WebFrameProxy*, const PrintInfo&);
void endPrinting();
- void computePagesForPrinting(WebFrameProxy*, const PrintInfo&, Vector<WebCore::IntRect>& resultPageRects, double& resultTotalScaleFactorForPrinting);
+ void computePagesForPrinting(WebFrameProxy*, const PrintInfo&, PassRefPtr<ComputedPagesCallback>);
#if PLATFORM(MAC)
- void drawRectToPDF(WebFrameProxy*, const WebCore::IntRect&, Vector<uint8_t>& pdfData);
+ void drawRectToPDF(WebFrameProxy*, const WebCore::IntRect&, PassRefPtr<DataCallback>);
+ void drawPagesToPDF(WebFrameProxy*, uint32_t first, uint32_t count, PassRefPtr<DataCallback>);
#endif
private:
@@ -523,6 +524,7 @@ private:
void voidCallback(uint64_t);
void dataCallback(const CoreIPC::DataReference&, uint64_t);
void stringCallback(const String&, uint64_t);
+ void computedPagesCallback(const Vector<WebCore::IntRect>&, double totalScaleFactorForPrinting, uint64_t);
void focusedFrameChanged(uint64_t frameID);
void frameSetLargestFrameChanged(uint64_t frameID);
@@ -570,6 +572,7 @@ private:
HashMap<uint64_t, RefPtr<VoidCallback> > m_voidCallbacks;
HashMap<uint64_t, RefPtr<DataCallback> > m_dataCallbacks;
HashMap<uint64_t, RefPtr<StringCallback> > m_stringCallbacks;
+ HashMap<uint64_t, RefPtr<ComputedPagesCallback> > m_computedPagesCallbacks;
HashSet<WebEditCommandProxy*> m_editCommandSet;
diff --git a/Source/WebKit2/UIProcess/WebPageProxy.messages.in b/Source/WebKit2/UIProcess/WebPageProxy.messages.in
index ea16cc4..a48ca8f 100644
--- a/Source/WebKit2/UIProcess/WebPageProxy.messages.in
+++ b/Source/WebKit2/UIProcess/WebPageProxy.messages.in
@@ -116,6 +116,7 @@ messages -> WebPageProxy {
VoidCallback(uint64_t callbackID)
DataCallback(CoreIPC::DataReference resultData, uint64_t callbackID)
StringCallback(WTF::String resultString, uint64_t callbackID)
+ ComputedPagesCallback(Vector<WebCore::IntRect> pageRects, double totalScaleFactorForPrinting, uint64_t callbackID)
DidReceiveAccessibilityPageToken(CoreIPC::DataReference data)
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
index 686195b..b4df4df 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
@@ -1784,6 +1784,9 @@ void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo)
m_printContext = adoptPtr(new PrintContext(coreFrame));
m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight);
+
+ float fullPageHeight;
+ m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
}
void WebPage::endPrinting()
@@ -1791,57 +1794,90 @@ void WebPage::endPrinting()
m_printContext = nullptr;
}
-void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, Vector<IntRect>& resultPageRects, double& resultTotalScaleFactorForPrinting)
+void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
{
- beginPrinting(frameID, printInfo);
+ Vector<IntRect> resultPageRects;
+ double resultTotalScaleFactorForPrinting = 1;
- WebFrame* frame = WebProcess::shared().webFrame(frameID);
- if (!frame)
- return;
-
- float fullPageHeight;
- m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
+ beginPrinting(frameID, printInfo);
- resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(printInfo.availablePaperWidth) * printInfo.pageSetupScaleFactor;
- resultPageRects = m_printContext->pageRects();
+ if (m_printContext) {
+ resultPageRects = m_printContext->pageRects();
+ resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(printInfo.availablePaperWidth) * printInfo.pageSetupScaleFactor;
+ }
// If we're asked to print, we should actually print at least a blank page.
if (resultPageRects.isEmpty())
resultPageRects.append(IntRect(0, 0, 1, 1));
+
+ send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID));
}
#if PLATFORM(MAC)
// FIXME: Find a better place for Mac specific code.
-void WebPage::drawRectToPDF(uint64_t frameID, const WebCore::IntRect& rect, Vector<uint8_t>& pdfData)
+void WebPage::drawRectToPDF(uint64_t frameID, const WebCore::IntRect& rect, uint64_t callbackID)
{
WebFrame* frame = WebProcess::shared().webFrame(frameID);
- if (!frame)
- return;
+ Frame* coreFrame = frame ? frame->coreFrame() : 0;
- Frame* coreFrame = frame->coreFrame();
- if (!coreFrame)
- return;
+ RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
+
+ if (coreFrame) {
+ ASSERT(coreFrame->document()->printing());
+
+ // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
+ RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
+
+ CGRect mediaBox = CGRectMake(0, 0, rect.width(), rect.height());
+ RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
+ RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ CGPDFContextBeginPage(context.get(), pageInfo.get());
+
+ GraphicsContext ctx(context.get());
+ ctx.scale(FloatSize(1, -1));
+ ctx.translate(0, -rect.height());
+ m_printContext->spoolRect(ctx, rect);
+
+ CGPDFContextEndPage(context.get());
+ CGPDFContextClose(context.get());
+ }
- ASSERT(coreFrame->document()->printing());
+ send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
+}
+
+void WebPage::drawPagesToPDF(uint64_t frameID, uint32_t first, uint32_t count, uint64_t callbackID)
+{
+ WebFrame* frame = WebProcess::shared().webFrame(frameID);
+ Frame* coreFrame = frame ? frame->coreFrame() : 0;
RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
- // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
- RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
+ if (coreFrame) {
+ ASSERT(coreFrame->document()->printing());
- CGRect mediaBox = CGRectMake(0, 0, frame->size().width(), frame->size().height());
- RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
- RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
- CGPDFContextBeginPage(context.get(), pageInfo.get());
+ // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
+ RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
- GraphicsContext ctx(context.get());
- m_printContext->spoolRect(ctx, rect);
+ CGRect mediaBox = m_printContext->pageRect(0);
+ RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
+ for (uint32_t page = first; page < first + count; ++page) {
+ if (page > m_printContext->pageCount())
+ break;
- CGPDFContextEndPage(context.get());
- CGPDFContextClose(context.get());
+ RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ CGPDFContextBeginPage(context.get(), pageInfo.get());
+
+ GraphicsContext ctx(context.get());
+ ctx.scale(FloatSize(1, -1));
+ ctx.translate(0, -m_printContext->pageRect(page).height());
+ m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width());
+
+ CGPDFContextEndPage(context.get());
+ }
+ CGPDFContextClose(context.get());
+ }
- pdfData.resize(CFDataGetLength(pdfPageData.get()));
- CFDataGetBytes(pdfPageData.get(), CFRangeMake(0, pdfData.size()), pdfData.data());
+ send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
}
#endif
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.h b/Source/WebKit2/WebProcess/WebPage/WebPage.h
index a465327..3dae655 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.h
@@ -309,9 +309,10 @@ public:
void beginPrinting(uint64_t frameID, const PrintInfo&);
void endPrinting();
- void computePagesForPrinting(uint64_t frameID, const PrintInfo&, Vector<WebCore::IntRect>& resultPageRects, double& resultTotalScaleFactorForPrinting);
+ void computePagesForPrinting(uint64_t frameID, const PrintInfo&, uint64_t callbackID);
#if PLATFORM(MAC)
- void drawRectToPDF(uint64_t frameID, const WebCore::IntRect&, Vector<uint8_t>& pdfData);
+ void drawRectToPDF(uint64_t frameID, const WebCore::IntRect&, uint64_t callbackID);
+ void drawPagesToPDF(uint64_t frameID, uint32_t first, uint32_t count, uint64_t callbackID);
#endif
bool mainFrameHasCustomRepresentation() const;
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
index 5d02d31..afd4c72 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
@@ -139,11 +139,12 @@ messages -> WebPage {
SetWindowResizerSize(WebCore::IntSize intersectsView)
# Printing.
- BeginPrinting(uint64_t frameID, WebKit::PrintInfo printInfo);
+ BeginPrinting(uint64_t frameID, WebKit::PrintInfo printInfo)
EndPrinting();
- ComputePagesForPrinting(uint64_t frameID, WebKit::PrintInfo printInfo) -> (Vector<WebCore::IntRect> pageRects, double totalScaleFactorForPrinting)
+ ComputePagesForPrinting(uint64_t frameID, WebKit::PrintInfo printInfo, uint64_t callbackID)
#if PLATFORM(MAC)
- DrawRectToPDF(uint64_t frameID, WebCore::IntRect rect) -> (Vector<uint8_t> pdfData)
+ DrawRectToPDF(uint64_t frameID, WebCore::IntRect rect, uint64_t callbackID)
+ DrawPagesToPDF(uint64_t frameID, uint32_t first, uint32_t count, uint64_t callbackID)
#endif
// FIXME: This a dummy message, to avoid breaking the build for platforms that don't require
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list