Changeset 201888 in webkit


Ignore:
Timestamp:
Jun 9, 2016 3:05:04 PM (8 years ago)
Author:
aestes@apple.com
Message:

WKWebView does not render PDF pages in AirPrint
https://bugs.webkit.org/show_bug.cgi?id=151386
rdar://problem/22499157

Reviewed by Tim Horton.

_WKWebViewPrintFormatter originally attempted to handle PDFs, but the code path was never
properly tested since Safari prints PDFs by setting a printingItem on the
UIPrintInteractionController instead of going through a print formatter. The existing code
almost worked, if it weren't for CGContextScaleCTM() scaling each page into oblivion due to
_totalScaleFactor equaling 0.

This patch properly implements -[_WKWebViewPrintFormatter drawInRect:forPageAtIndex:] to
handle drawing both PDFs generated by WebKit and PDFs loaded in the main frame. It also
takes the opportunity to clean up a number of issues in the existing code:

  • Handling of -[_WKWebViewPrintFormatter startPage] is now correct. I had previously assumed this property represented the first page of output to print, but it actually represents the first page in the overall print job that the print formatter renders. In other words, regardless of -startPage, the print formatter should always print all its pages.
  • Code specific to webpage and PDF printing was factored out into WKContentView and WKPDFView, respectively. Each conforms to @protocol(_WKWebViewPrintProvider), and _WKWebViewPrintFormatter accesses the provider via -[WKWebView _printProvider].
  • Instead of piping the printed PDF data from WebPageProxy to WKWebView via PageClient, use the GenericCallback mechanism to have WebPageProxy call a lambda specified by WKContentView when the printed PDF is available.
  • Removed _totalScaleFactor and used CGPDFPageGetDrawingTransform() to transform both webpages and PDFs. For webpages, _totalScaleFactor will always equal the ratio of the paper width to the PDF page width, so CGPDFPageGetDrawingTransform() will apply the same scaling as CGContextScaleCTM(_totalScaleFactor, _totalScaleFactor) would.
  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _printProvider]): Added. Returns _currentContentView if it conforms to
@protocol(_WKWebViewPrintProvider).
(-[WKWebView _computePageCountAndStartDrawingToPDFForFrame:printInfo:firstPage:computedTotalScaleFactor:]):
Moved code to _wk_pageCountForPrintFormatter in WKContentView and WKPDFView.
(-[WKWebView _endPrinting]): Deleted.
(-[WKWebView _printedDocument]): Deleted.
(-[WKWebView _setPrintedDocument:]): Deleted.

  • UIProcess/API/Cocoa/WKWebViewInternal.h: Declared the _printProvider property.
  • UIProcess/PageClient.h: Removed didFinishDrawingPagesToPDF().
  • UIProcess/WebPageProxy.h: Declared computePagesForPrintingAndDrawToPDF() and

drawToPDFCallback().

  • UIProcess/WebPageProxy.messages.in: Renamed DidFinishDrawingPagesToPDF to

DrawToPDFCallback.

  • UIProcess/_WKWebViewPrintFormatter.mm: Backed the frameToPrint property with a RetainPtr

ivar so that it doesn't need to be released manually in -dealloc; removed _totalScaleFactor
and _printInfo ivars and added a _printedDocument ivar; removed the property declaration for
webView.
(-[_WKWebViewPrintFormatter frameToPrint]): Added a custom getter for the frameToPrint
property.
(-[_WKWebViewPrintFormatter setFrameToPrint:]): Added a custom setter for the frameToPrint
property.
(-[_WKWebViewPrintFormatter _webView]): Renamed from webView; added an underscore since this
is a private method.
(-[_WKWebViewPrintFormatter _recalcPageCount]): Retrieved the page count from the print
provider and clamped its value to NSIntegerMax.
(-[_WKWebViewPrintFormatter drawInRect:forPageAtIndex:]): Retrieved the printed document
from the print provider if needed; modified the CTM transformations to work for both
webpages and PDFs.
(-[_WKWebViewPrintFormatter dealloc]): Deleted.
(-[_WKWebViewPrintFormatter webView]): Renamed to _webView.
(-[_WKWebViewPrintFormatter rectForPageAtIndex:]): Deleted.

  • UIProcess/_WKWebViewPrintFormatterInternal.h: Added. Moved a UIPrintFormatter internal

method declaration to here and defined the _WKWebViewPrintProvider protocol.

  • UIProcess/ios/PageClientImplIOS.h: Removed didFinishDrawingPagesToPDF().
  • UIProcess/ios/PageClientImplIOS.mm: Ditto.

(WebKit::PageClientImpl::didFinishDrawingPagesToPDF): Deleted.

  • UIProcess/ios/WKContentView.mm: Conformed to @protocol(_WKWebViewPrintProvider).

(-[WKContentView _wk_pageCountForPrintFormatter:]): Moved the code to compute page count
from WKWebView to here.
(-[WKContentView _wk_printedDocument]): Moved the code to get the printed document from
WKWebView to here.

  • UIProcess/ios/WKPDFView.mm:

(-[WKPDFView _wk_pageCountForPrintFormatter:]): Moved the code to compute the page count
from WKWebView to here; added a call to CGPDFDocumentAllowsPrinting(), returning 0 if
printing is not allowed.
(-[WKPDFView _wk_printedDocument]): Moved the code to get the printed document from
WKWebView to here.

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::computePagesForPrintingAndDrawToPDF): Registered the callback with
m_callbacks and sent Messages::WebPage::ComputePagesForPrintingAndDrawToPDF; returned the
synchronously-returned page count.
(WebKit::WebPageProxy::drawToPDFCallback): Added to perform the callback when drawing to PDF
is complete.
(WebKit::WebPageProxy::didFinishDrawingPagesToPDF): Deleted.

  • WebKit2.xcodeproj/project.pbxproj: Added _WKWebViewPrintFormatterInternal.h.
  • WebProcess/WebPage/WebPage.h: Renamed computePagesForPrintingAndStartDrawingToPDF() to

computePagesForPrintingAndDrawToPDF().

  • WebProcess/WebPage/WebPage.messages.in: Renamed

ComputePagesForPrintingAndStartDrawingToPDF to ComputePagesForPrintingAndDrawToPDF. Removed
the startPage parameter and added a callbackID.

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::computePagesForPrintingAndDrawToPDF): Renamed from
computePagesForPrintingAndStartDrawingToPDF(). Added a call to endPrinting() after sending
Messages::WebPageProxy::DrawToPDFCallback.
(WebKit::WebPage::computePagesForPrintingAndStartDrawingToPDF): Renamed to
computePagesForPrintingAndDrawToPDF.

Location:
trunk/Source/WebKit2
Files:
1 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r201880 r201888  
     12016-06-09  Andy Estes  <aestes@apple.com>
     2
     3        WKWebView does not render PDF pages in AirPrint
     4        https://bugs.webkit.org/show_bug.cgi?id=151386
     5        rdar://problem/22499157
     6
     7        Reviewed by Tim Horton.
     8
     9        _WKWebViewPrintFormatter originally attempted to handle PDFs, but the code path was never
     10        properly tested since Safari prints PDFs by setting a printingItem on the
     11        UIPrintInteractionController instead of going through a print formatter. The existing code
     12        almost worked, if it weren't for CGContextScaleCTM() scaling each page into oblivion due to
     13        _totalScaleFactor equaling 0.
     14
     15        This patch properly implements -[_WKWebViewPrintFormatter drawInRect:forPageAtIndex:] to
     16        handle drawing both PDFs generated by WebKit and PDFs loaded in the main frame. It also
     17        takes the opportunity to clean up a number of issues in the existing code:
     18
     19        - Handling of -[_WKWebViewPrintFormatter startPage] is now correct. I had previously assumed
     20          this property represented the first page of output to print, but it actually represents
     21          the first page in the overall print job that the print formatter renders. In other words,
     22          regardless of -startPage, the print formatter should always print all its pages.
     23        - Code specific to webpage and PDF printing was factored out into WKContentView and
     24          WKPDFView, respectively. Each conforms to @protocol(_WKWebViewPrintProvider), and
     25          _WKWebViewPrintFormatter accesses the provider via -[WKWebView _printProvider].
     26        - Instead of piping the printed PDF data from WebPageProxy to WKWebView via PageClient, use
     27          the GenericCallback mechanism to have WebPageProxy call a lambda specified by
     28          WKContentView when the printed PDF is available.
     29        - Removed _totalScaleFactor and used CGPDFPageGetDrawingTransform() to transform both
     30          webpages and PDFs. For webpages, _totalScaleFactor will always equal the ratio of the
     31          paper width to the PDF page width, so CGPDFPageGetDrawingTransform() will apply the same
     32          scaling as CGContextScaleCTM(_totalScaleFactor, _totalScaleFactor) would.
     33
     34        * UIProcess/API/Cocoa/WKWebView.mm:
     35        (-[WKWebView _printProvider]): Added. Returns _currentContentView if it conforms to
     36        @protocol(_WKWebViewPrintProvider).
     37        (-[WKWebView _computePageCountAndStartDrawingToPDFForFrame:printInfo:firstPage:computedTotalScaleFactor:]):
     38        Moved code to _wk_pageCountForPrintFormatter in WKContentView and WKPDFView.
     39        (-[WKWebView _endPrinting]): Deleted.
     40        (-[WKWebView _printedDocument]): Deleted.
     41        (-[WKWebView _setPrintedDocument:]): Deleted.
     42        * UIProcess/API/Cocoa/WKWebViewInternal.h: Declared the _printProvider property.
     43        * UIProcess/PageClient.h: Removed didFinishDrawingPagesToPDF().
     44        * UIProcess/WebPageProxy.h: Declared computePagesForPrintingAndDrawToPDF() and
     45        drawToPDFCallback().
     46        * UIProcess/WebPageProxy.messages.in: Renamed DidFinishDrawingPagesToPDF to
     47        DrawToPDFCallback.
     48        * UIProcess/_WKWebViewPrintFormatter.mm: Backed the frameToPrint property with a RetainPtr
     49        ivar so that it doesn't need to be released manually in -dealloc; removed _totalScaleFactor
     50        and _printInfo ivars and added a _printedDocument ivar; removed the property declaration for
     51        webView.
     52        (-[_WKWebViewPrintFormatter frameToPrint]): Added a custom getter for the frameToPrint
     53        property.
     54        (-[_WKWebViewPrintFormatter setFrameToPrint:]): Added a custom setter for the frameToPrint
     55        property.
     56        (-[_WKWebViewPrintFormatter _webView]): Renamed from webView; added an underscore since this
     57        is a private method.
     58        (-[_WKWebViewPrintFormatter _recalcPageCount]): Retrieved the page count from the print
     59        provider and clamped its value to NSIntegerMax.
     60        (-[_WKWebViewPrintFormatter drawInRect:forPageAtIndex:]): Retrieved the printed document
     61        from the print provider if needed; modified the CTM transformations to work for both
     62        webpages and PDFs.
     63        (-[_WKWebViewPrintFormatter dealloc]): Deleted.
     64        (-[_WKWebViewPrintFormatter webView]): Renamed to _webView.
     65        (-[_WKWebViewPrintFormatter rectForPageAtIndex:]): Deleted.
     66        * UIProcess/_WKWebViewPrintFormatterInternal.h: Added. Moved a UIPrintFormatter internal
     67        method declaration to here and defined the _WKWebViewPrintProvider protocol.
     68        * UIProcess/ios/PageClientImplIOS.h: Removed didFinishDrawingPagesToPDF().
     69        * UIProcess/ios/PageClientImplIOS.mm: Ditto.
     70        (WebKit::PageClientImpl::didFinishDrawingPagesToPDF): Deleted.
     71        * UIProcess/ios/WKContentView.mm: Conformed to @protocol(_WKWebViewPrintProvider).
     72        (-[WKContentView _wk_pageCountForPrintFormatter:]): Moved the code to compute page count
     73        from WKWebView to here.
     74        (-[WKContentView _wk_printedDocument]): Moved the code to get the printed document from
     75        WKWebView to here.
     76        * UIProcess/ios/WKPDFView.mm:
     77        (-[WKPDFView _wk_pageCountForPrintFormatter:]): Moved the code to compute the page count
     78        from WKWebView to here; added a call to CGPDFDocumentAllowsPrinting(), returning 0 if
     79        printing is not allowed.
     80        (-[WKPDFView _wk_printedDocument]): Moved the code to get the printed document from
     81        WKWebView to here.
     82        * UIProcess/ios/WebPageProxyIOS.mm:
     83        (WebKit::WebPageProxy::computePagesForPrintingAndDrawToPDF): Registered the callback with
     84        m_callbacks and sent Messages::WebPage::ComputePagesForPrintingAndDrawToPDF; returned the
     85        synchronously-returned page count.
     86        (WebKit::WebPageProxy::drawToPDFCallback): Added to perform the callback when drawing to PDF
     87        is complete.
     88        (WebKit::WebPageProxy::didFinishDrawingPagesToPDF): Deleted.
     89        * WebKit2.xcodeproj/project.pbxproj: Added _WKWebViewPrintFormatterInternal.h.
     90        * WebProcess/WebPage/WebPage.h: Renamed computePagesForPrintingAndStartDrawingToPDF() to
     91        computePagesForPrintingAndDrawToPDF().
     92        * WebProcess/WebPage/WebPage.messages.in: Renamed
     93        ComputePagesForPrintingAndStartDrawingToPDF to ComputePagesForPrintingAndDrawToPDF. Removed
     94        the startPage parameter and added a callbackID.
     95        * WebProcess/WebPage/ios/WebPageIOS.mm:
     96        (WebKit::WebPage::computePagesForPrintingAndDrawToPDF): Renamed from
     97        computePagesForPrintingAndStartDrawingToPDF(). Added a call to endPrinting() after sending
     98        Messages::WebPageProxy::DrawToPDFCallback.
     99        (WebKit::WebPage::computePagesForPrintingAndStartDrawingToPDF): Renamed to
     100        computePagesForPrintingAndDrawToPDF.
     101
    11022016-06-09  Alex Christensen  <achristensen@webkit.org>
    2103
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r201592 r201888  
    100100#if PLATFORM(IOS)
    101101#import "_WKWebViewPrintFormatter.h"
    102 #import "PrintInfo.h"
    103102#import "ProcessThrottler.h"
    104103#import "RemoteLayerTreeDrawingAreaProxy.h"
     
    109108#import "WKScrollView.h"
    110109#import "WKWebViewContentProviderRegistry.h"
    111 #import "WebPageMessages.h"
    112110#import "WebVideoFullscreenManagerProxy.h"
    113111#import <UIKit/UIApplication.h>
     
    261259    BOOL _hadDelayedUpdateVisibleContentRects;
    262260
    263     BOOL _pageIsPrintingToPDF;
    264     RetainPtr<CGPDFDocumentRef> _printedDocument;
    265261    Vector<std::function<void ()>> _snapshotsDeferredDuringResize;
    266262#endif
     
    45344530}
    45354531
    4536 - (NSInteger)_computePageCountAndStartDrawingToPDFForFrame:(_WKFrameHandle *)frame printInfo:(const WebKit::PrintInfo&)printInfo firstPage:(uint32_t)firstPage computedTotalScaleFactor:(double&)totalScaleFactor
    4537 {
    4538     if ([self _isDisplayingPDF])
    4539         return CGPDFDocumentGetNumberOfPages([(WKPDFView *)_customContentView pdfDocument]);
    4540 
    4541     _pageIsPrintingToPDF = YES;
    4542     Vector<WebCore::IntRect> pageRects;
    4543     uint64_t frameID = frame ? frame._frameID : _page->mainFrame()->frameID();
    4544     if (!_page->sendSync(Messages::WebPage::ComputePagesForPrintingAndStartDrawingToPDF(frameID, printInfo, firstPage), Messages::WebPage::ComputePagesForPrintingAndStartDrawingToPDF::Reply(pageRects, totalScaleFactor)))
    4545         return 0;
    4546     return pageRects.size();
    4547 }
    4548 
    4549 - (void)_endPrinting
    4550 {
    4551     _pageIsPrintingToPDF = NO;
    4552     _printedDocument = nullptr;
    4553     _page->send(Messages::WebPage::EndPrinting());
    4554 }
    4555 
    4556 - (CGPDFDocumentRef)_printedDocument
    4557 {
    4558     if ([self _isDisplayingPDF]) {
    4559         ASSERT(!_pageIsPrintingToPDF);
    4560         return [(WKPDFView *)_customContentView pdfDocument];
    4561     }
    4562 
    4563     if (_pageIsPrintingToPDF) {
    4564         if (!_page->process().connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DidFinishDrawingPagesToPDF>(_page->pageID(), std::chrono::milliseconds::max())) {
    4565             ASSERT_NOT_REACHED();
    4566             return nullptr;
    4567         }
    4568         ASSERT(!_pageIsPrintingToPDF);
    4569     }
    4570     return _printedDocument.get();
    4571 }
    4572 
    4573 - (void)_setPrintedDocument:(CGPDFDocumentRef)printedDocument
    4574 {
    4575     if (!_pageIsPrintingToPDF)
    4576         return;
    4577     ASSERT(![self _isDisplayingPDF]);
    4578     _printedDocument = printedDocument;
    4579     _pageIsPrintingToPDF = NO;
     4532- (id <_WKWebViewPrintProvider>)_printProvider
     4533{
     4534    id contentView = self._currentContentView;
     4535    if ([contentView conformsToProtocol:@protocol(_WKWebViewPrintProvider)])
     4536        return contentView;
     4537    return nil;
    45804538}
    45814539
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h

    r200470 r201888  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5858@class WKWebViewContentProviderRegistry;
    5959@class _WKFrameHandle;
     60@protocol _WKWebViewPrintProvider;
    6061
    6162@interface WKWebView () WK_WEB_VIEW_PROTOCOLS {
     
    135136#if PLATFORM(IOS)
    136137@interface WKWebView (_WKWebViewPrintFormatter)
    137 - (NSInteger)_computePageCountAndStartDrawingToPDFForFrame:(_WKFrameHandle *)frame printInfo:(const WebKit::PrintInfo&)printInfo firstPage:(uint32_t)firstPage computedTotalScaleFactor:(double&)totalScaleFactor;
    138 - (void)_endPrinting;
    139 @property (nonatomic, setter=_setPrintedDocument:) CGPDFDocumentRef _printedDocument;
     138@property (nonatomic, readonly) id <_WKWebViewPrintProvider> _printProvider;
    140139@end
    141140#endif
  • trunk/Source/WebKit2/UIProcess/PageClient.h

    r199810 r201888  
    11/*
    2  * Copyright (C) 2010, 2011, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    306306    virtual void overflowScrollWillStartScroll() = 0;
    307307    virtual void overflowScrollDidEndScroll() = 0;
    308     virtual void didFinishDrawingPagesToPDF(const IPC::DataReference&) = 0;
    309308    virtual Vector<String> mimeTypesWithCustomContentProviders() = 0;
    310309
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r201441 r201888  
    11/*
    2  * Copyright (C) 2010, 2011, 2014-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    257257    RefPtr<API::Object> m_userData;
    258258};
     259
     260using DrawToPDFCallback = GenericCallback<const IPC::DataReference&>;
    259261#endif
    260262
     
    516518    void didNotHandleTapAsClick(const WebCore::IntPoint&);
    517519    void disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID);
    518     void didFinishDrawingPagesToPDF(const IPC::DataReference&);
    519520    void contentSizeCategoryDidChange(const String& contentSizeCategory);
    520521    void getSelectionContext(std::function<void(const String&, const String&, const String&, CallbackBase::Error)>);
     
    906907    void drawRectToImage(WebFrameProxy*, const PrintInfo&, const WebCore::IntRect&, const WebCore::IntSize&, PassRefPtr<ImageCallback>);
    907908    void drawPagesToPDF(WebFrameProxy*, const PrintInfo&, uint32_t first, uint32_t count, PassRefPtr<DataCallback>);
     909#if PLATFORM(IOS)
     910    uint32_t computePagesForPrintingAndDrawToPDF(uint64_t frameID, const PrintInfo&, DrawToPDFCallback::CallbackFunction&&);
     911    void drawToPDFCallback(const IPC::DataReference& pdfData, uint64_t callbackID);
     912#endif
    908913#elif PLATFORM(GTK)
    909914    void drawPagesForPrinting(WebFrameProxy*, const PrintInfo&, PassRefPtr<PrintFinishedCallback>);
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in

    r201298 r201888  
    1 # Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
     1# Copyright (C) 2010-2016 Apple Inc. All rights reserved.
    22#
    33# Redistribution and use in source and binary forms, with or without
     
    187187    DidNotHandleTapAsClick(WebCore::IntPoint point)
    188188    DisableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
    189     DidFinishDrawingPagesToPDF(IPC::DataReference pdfData)
     189    DrawToPDFCallback(IPC::DataReference pdfData, uint64_t callbackID)
    190190#endif
    191191#if ENABLE(DATA_DETECTION)
  • trunk/Source/WebKit2/UIProcess/_WKWebViewPrintFormatter.mm

    r199960 r201888  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2525
    2626#import "config.h"
    27 #import "_WKWebViewPrintFormatter.h"
     27#import "_WKWebViewPrintFormatterInternal.h"
    2828
    2929#if PLATFORM(IOS)
    3030
    31 #import "PrintInfo.h"
    3231#import "WKWebViewInternal.h"
     32#import "_WKFrameHandle.h"
    3333#import <wtf/RetainPtr.h>
    3434
    35 @interface UIPrintFormatter ()
    36 - (CGRect)_pageContentRect:(BOOL)firstPage;
    37 - (void)_recalcIfNecessary;
    38 @end
    39 
    40 @interface _WKWebViewPrintFormatter ()
    41 @property (nonatomic, readonly) WKWebView *webView;
    42 @end
    43 
    4435@implementation _WKWebViewPrintFormatter {
    45     double _totalScaleFactor;
    46     WebKit::PrintInfo _printInfo;
     36    RetainPtr<_WKFrameHandle> _frameToPrint;
     37    RetainPtr<CGPDFDocumentRef> _printedDocument;
    4738}
    4839
    49 - (void)dealloc
     40- (_WKFrameHandle *)frameToPrint
    5041{
    51     [self.webView _endPrinting];
    52     [_frameToPrint release];
    53     [super dealloc];
     42    return _frameToPrint.get();
    5443}
    5544
    56 - (WKWebView *)webView
     45- (void)setFrameToPrint:(_WKFrameHandle *)frameToPrint
    5746{
    58     ASSERT([self.view isKindOfClass:[WKWebView class]]);
    59     return static_cast<WKWebView *>(self.view);
     47    _frameToPrint = frameToPrint;
     48}
     49
     50- (WKWebView *)_webView
     51{
     52    UIView *view = self.view;
     53    ASSERT([view isKindOfClass:[WKWebView class]]);
     54    return static_cast<WKWebView *>(view);
    6055}
    6156
    6257- (NSInteger)_recalcPageCount
    6358{
    64     ASSERT([self respondsToSelector:@selector(_pageContentRect:)]);
    65 
    66     CGRect firstRect = [self _pageContentRect:YES];
    67     CGRect nextRect = [self _pageContentRect:NO];
    68     if (CGRectIsEmpty(firstRect) || CGRectIsEmpty(nextRect))
    69         return 0;
    70 
    71     // The first page can have a smaller content rect than subsequent pages if a top content inset is specified. Since
    72     // WebKit requires a uniform content rect for each page during layout, use the first page rect for all pages if it's
    73     // smaller. This is what UIWebView's print formatter does.
    74     ASSERT(firstRect.size.width == nextRect.size.width);
    75     ASSERT(firstRect.origin.y >= nextRect.origin.y);
    76     _printInfo.pageSetupScaleFactor = 1;
    77     _printInfo.availablePaperWidth = nextRect.size.width;
    78     _printInfo.availablePaperHeight = nextRect.size.height - (firstRect.origin.y - nextRect.origin.y);
    79 
    80     return [self.webView _computePageCountAndStartDrawingToPDFForFrame:_frameToPrint printInfo:_printInfo firstPage:self.startPage computedTotalScaleFactor:_totalScaleFactor];
     59    _printedDocument = nullptr;
     60    NSUInteger pageCount = [self._webView._printProvider _wk_pageCountForPrintFormatter:self];
     61    return std::min<NSUInteger>(pageCount, NSIntegerMax);
    8162}
    8263
    8364- (CGRect)rectForPageAtIndex:(NSInteger)pageIndex
    8465{
    85     ASSERT([self respondsToSelector:@selector(_recalcIfNecessary)]);
    86     [self _recalcIfNecessary];
    8766    return [self _pageContentRect:pageIndex == self.startPage];
    8867}
     
    9069- (void)drawInRect:(CGRect)rect forPageAtIndex:(NSInteger)pageIndex
    9170{
    92     // CGPDFDocuments use 1-based page indexing.
    93     CGPDFPageRef pdfPage = CGPDFDocumentGetPage(self.webView._printedDocument, pageIndex - self.startPage + 1);
     71    if (!_printedDocument)
     72        _printedDocument = self._webView._printProvider._wk_printedDocument;
     73
     74    NSInteger offsetFromStartPage = pageIndex - self.startPage;
     75    if (offsetFromStartPage < 0)
     76        return;
     77
     78    CGPDFPageRef page = CGPDFDocumentGetPage(_printedDocument.get(), offsetFromStartPage + 1);
     79    if (!page)
     80        return;
    9481
    9582    CGContextRef context = UIGraphicsGetCurrentContext();
    9683    CGContextSaveGState(context);
    9784
    98     CGContextTranslateCTM(context, rect.origin.x, rect.origin.y);
    99     CGContextScaleCTM(context, _totalScaleFactor, -_totalScaleFactor);
    100     CGContextTranslateCTM(context, 0, -CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox).size.height);
    101     CGContextDrawPDFPage(context, pdfPage);
     85    CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMaxY(rect));
     86    CGContextScaleCTM(context, 1, -1);
     87    CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)), 0, true));
     88    CGContextClipToRect(context, CGPDFPageGetBoxRect(page, kCGPDFCropBox));
     89    CGContextDrawPDFPage(context, page);
    10290
    10391    CGContextRestoreGState(context);
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h

    r199695 r201888  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    153153    void overflowScrollDidEndScroll() override;
    154154
    155     void didFinishDrawingPagesToPDF(const IPC::DataReference&) override;
    156 
    157155    // Auxiliary Client Creation
    158156#if ENABLE(FULLSCREEN_API)
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm

    r199695 r201888  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    664664}
    665665
    666 void PageClientImpl::didFinishDrawingPagesToPDF(const IPC::DataReference& pdfData)
    667 {
    668     RetainPtr<CFDataRef> data = adoptCF(CFDataCreate(kCFAllocatorDefault, pdfData.data(), pdfData.size()));
    669     RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateWithCFData(data.get()));
    670     m_webView._printedDocument = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get())).get();
    671 }
    672 
    673666Vector<String> PageClientImpl::mimeTypesWithCustomContentProviders()
    674667{
  • trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm

    r200470 r201888  
    11/*
    2  * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333#import "ApplicationStateTracker.h"
    3434#import "PageClientImplIOS.h"
     35#import "PrintInfo.h"
    3536#import "RemoteLayerTreeDrawingAreaProxy.h"
    3637#import "RemoteScrollingCoordinatorProxy.h"
     
    4950#import "WebProcessPool.h"
    5051#import "WebSystemInterface.h"
     52#import "_WKFrameHandleInternal.h"
     53#import "_WKWebViewPrintFormatterInternal.h"
    5154#import <CoreGraphics/CoreGraphics.h>
    5255#import <WebCore/FloatQuad.h>
     
    182185
    183186    std::unique_ptr<ApplicationStateTracker> _applicationStateTracker;
     187
     188    BOOL _isPrintingToPDF;
     189    RetainPtr<CGPDFDocumentRef> _printedDocument;
    184190}
    185191
     
    611617@end
    612618
     619#pragma mark Printing
     620
     621@interface WKContentView (_WKWebViewPrintFormatter) <_WKWebViewPrintProvider>
     622@end
     623
     624@implementation WKContentView (_WKWebViewPrintFormatter)
     625
     626- (NSUInteger)_wk_pageCountForPrintFormatter:(_WKWebViewPrintFormatter *)printFormatter
     627{
     628    if (_isPrintingToPDF)
     629        return 0;
     630
     631    uint64_t frameID;
     632    if (_WKFrameHandle *handle = printFormatter.frameToPrint)
     633        frameID = handle._frameID;
     634    else if (auto mainFrame = _page->mainFrame())
     635        frameID = mainFrame->frameID();
     636    else
     637        return 0;
     638
     639    // The first page can have a smaller content rect than subsequent pages if a top content inset
     640    // is specified. Since WebKit requires a uniform content rect for each page during layout, use
     641    // the intersection of the first and non-first page rects.
     642    // FIXME: Teach WebCore::PrintContext to accept an initial content offset when paginating.
     643    CGRect printingRect = CGRectIntersection([printFormatter _pageContentRect:YES], [printFormatter _pageContentRect:NO]);
     644    if (CGRectIsEmpty(printingRect))
     645        return 0;
     646
     647    PrintInfo printInfo;
     648    printInfo.pageSetupScaleFactor = 1;
     649    printInfo.availablePaperWidth = CGRectGetWidth(printingRect);
     650    printInfo.availablePaperHeight = CGRectGetHeight(printingRect);
     651
     652    _isPrintingToPDF = YES;
     653    auto retainedSelf = retainPtr(self);
     654    return _page->computePagesForPrintingAndDrawToPDF(frameID, printInfo, [retainedSelf](const IPC::DataReference& pdfData, CallbackBase::Error error) {
     655        retainedSelf->_isPrintingToPDF = NO;
     656        if (error != CallbackBase::Error::None)
     657            return;
     658
     659        auto data = adoptCF(CFDataCreate(kCFAllocatorDefault, pdfData.data(), pdfData.size()));
     660        auto dataProvider = adoptCF(CGDataProviderCreateWithCFData(data.get()));
     661        retainedSelf->_printedDocument = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get()));
     662    });
     663}
     664
     665- (CGPDFDocumentRef)_wk_printedDocument
     666{
     667    if (_isPrintingToPDF) {
     668        if (!_page->process().connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DrawToPDFCallback>(_page->pageID(), std::chrono::milliseconds::max())) {
     669            ASSERT_NOT_REACHED();
     670            return nullptr;
     671        }
     672        ASSERT(!_isPrintingToPDF);
     673    }
     674
     675    return _printedDocument.autorelease();
     676}
     677
     678@end
     679
    613680#endif // PLATFORM(IOS)
  • trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm

    r195982 r201888  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4040#import "WebPageProxy.h"
    4141#import "_WKFindDelegate.h"
     42#import "_WKWebViewPrintFormatterInternal.h"
    4243#import <MobileCoreServices/UTCoreTypes.h>
    4344#import <WebCore/FloatRect.h>
     
    891892@end
    892893
     894#pragma mark Printing
     895
     896@interface WKPDFView (_WKWebViewPrintFormatter) <_WKWebViewPrintProvider>
     897@end
     898
     899@implementation WKPDFView (_WKWebViewPrintFormatter)
     900
     901- (NSUInteger)_wk_pageCountForPrintFormatter:(_WKWebViewPrintFormatter *)printFormatter
     902{
     903    CGPDFDocumentRef document = _cgPDFDocument.get();
     904    if (CGPDFDocumentAllowsPrinting(document))
     905        return CGPDFDocumentGetNumberOfPages(document);
     906    return 0;
     907}
     908
     909- (CGPDFDocumentRef)_wk_printedDocument
     910{
     911    return _cgPDFDocument.get();
     912}
     913
     914@end
     915
    893916#endif /* PLATFORM(IOS) */
  • trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm

    r200660 r201888  
    11/*
    2  * Copyright (C) 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535#import "NativeWebKeyboardEvent.h"
    3636#import "PageClient.h"
     37#import "PrintInfo.h"
    3738#import "RemoteLayerTreeDrawingAreaProxy.h"
    3839#import "RemoteLayerTreeDrawingAreaProxyMessages.h"
     
    963964}
    964965
    965 void WebPageProxy::didFinishDrawingPagesToPDF(const IPC::DataReference& pdfData)
    966 {
    967     m_pageClient.didFinishDrawingPagesToPDF(pdfData);
     966uint32_t WebPageProxy::computePagesForPrintingAndDrawToPDF(uint64_t frameID, const PrintInfo& printInfo, DrawToPDFCallback::CallbackFunction&& callback)
     967{
     968    if (!isValid()) {
     969        callback(IPC::DataReference(), CallbackBase::Error::OwnerWasInvalidated);
     970        return 0;
     971    }
     972
     973    uint32_t pageCount = 0;
     974    uint64_t callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
     975    using Message = Messages::WebPage::ComputePagesForPrintingAndDrawToPDF;
     976    process().sendSync(Message(frameID, printInfo, callbackID), Message::Reply(pageCount), m_pageID);
     977    return pageCount;
     978}
     979
     980void WebPageProxy::drawToPDFCallback(const IPC::DataReference& pdfData, uint64_t callbackID)
     981{
     982    auto callback = m_callbacks.take<DrawToPDFCallback>(callbackID);
     983    RELEASE_ASSERT(callback);
     984    callback->performCallbackWithReturnValue(pdfData);
    968985}
    969986
  • trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj

    r201504 r201888  
    12621262                A182D5B41BE6BD250087A7CC /* AccessibilityIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = A182D5B21BE6BD250087A7CC /* AccessibilityIOS.mm */; };
    12631263                A182D5B51BE6BD250087A7CC /* AccessibilityIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = A182D5B31BE6BD250087A7CC /* AccessibilityIOS.h */; };
     1264                A19DD3C01D07D16800AC823B /* _WKWebViewPrintFormatterInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A19DD3BF1D07D16800AC823B /* _WKWebViewPrintFormatterInternal.h */; };
    12641265                A1A4FE5A18DCE9FA00B5EA8A /* _WKDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = A1A4FE5718DCE9FA00B5EA8A /* _WKDownload.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12651266                A1A4FE5B18DCE9FA00B5EA8A /* _WKDownload.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A4FE5818DCE9FA00B5EA8A /* _WKDownload.mm */; };
     
    33133314                A182D5B21BE6BD250087A7CC /* AccessibilityIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AccessibilityIOS.mm; sourceTree = "<group>"; };
    33143315                A182D5B31BE6BD250087A7CC /* AccessibilityIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityIOS.h; sourceTree = "<group>"; };
     3316                A19DD3BF1D07D16800AC823B /* _WKWebViewPrintFormatterInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKWebViewPrintFormatterInternal.h; sourceTree = "<group>"; };
    33153317                A1A4FE5718DCE9FA00B5EA8A /* _WKDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKDownload.h; sourceTree = "<group>"; };
    33163318                A1A4FE5818DCE9FA00B5EA8A /* _WKDownload.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKDownload.mm; sourceTree = "<group>"; };
     
    48654867                                C54256AE18BEC16100DE4179 /* forms */,
    48664868                                A115DC6E191D82AB00DA8072 /* _WKWebViewPrintFormatter.h */,
     4869                                A19DD3BF1D07D16800AC823B /* _WKWebViewPrintFormatterInternal.h */,
    48674870                                A115DC6D191D82AB00DA8072 /* _WKWebViewPrintFormatter.mm */,
    48684871                                1AD4C1911B39F33200ABC28E /* ApplicationStateTracker.h */,
     
    80698072                                37608823150414F700FC82C7 /* WKRenderObject.h in Headers */,
    80708073                                3336763B130C99DC006C9DE2 /* WKResourceCacheManager.h in Headers */,
     8074                                A19DD3C01D07D16800AC823B /* _WKWebViewPrintFormatterInternal.h in Headers */,
    80718075                                BC8A501511765F5600757573 /* WKRetainPtr.h in Headers */,
    80728076                                1A7E377918E4A4FE003D0FFF /* WKScriptMessage.h in Headers */,
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h

    r201519 r201888  
    11/*
    2  * Copyright (C) 2010, 2011, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    744744    void drawPagesToPDFImpl(uint64_t frameID, const PrintInfo&, uint32_t first, uint32_t count, RetainPtr<CFMutableDataRef>& pdfPageData);
    745745#if PLATFORM(IOS)
    746     void computePagesForPrintingAndStartDrawingToPDF(uint64_t frameID, const PrintInfo&, uint32_t firstPage, PassRefPtr<Messages::WebPage::ComputePagesForPrintingAndStartDrawingToPDF::DelayedReply>);
     746    void computePagesForPrintingAndDrawToPDF(uint64_t frameID, const PrintInfo&, uint64_t callbackID, PassRefPtr<Messages::WebPage::ComputePagesForPrintingAndDrawToPDF::DelayedReply>);
    747747#endif
    748748#elif PLATFORM(GTK)
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in

    r199399 r201888  
    1 # Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
     1# Copyright (C) 2010-2016 Apple Inc. All rights reserved.
    22#
    33# Redistribution and use in source and binary forms, with or without
     
    302302    DrawPagesToPDF(uint64_t frameID, struct WebKit::PrintInfo printInfo, uint32_t first, uint32_t count, uint64_t callbackID)
    303303#if PLATFORM(IOS)
    304     ComputePagesForPrintingAndStartDrawingToPDF(uint64_t frameID, struct WebKit::PrintInfo printInfo, uint32_t firstPage) -> (Vector<WebCore::IntRect> pageRects, double totalScaleFactor) Delayed
     304    ComputePagesForPrintingAndDrawToPDF(uint64_t frameID, struct WebKit::PrintInfo printInfo, uint64_t callbackID) -> (uint32_t pageCount) Delayed
    305305#endif
    306306#endif
  • trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

    r201588 r201888  
    11/*
    2  * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    31293129#endif
    31303130
    3131 void WebPage::computePagesForPrintingAndStartDrawingToPDF(uint64_t frameID, const PrintInfo& printInfo, uint32_t firstPage, PassRefPtr<Messages::WebPage::ComputePagesForPrintingAndStartDrawingToPDF::DelayedReply> reply)
     3131void WebPage::computePagesForPrintingAndDrawToPDF(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID, PassRefPtr<Messages::WebPage::ComputePagesForPrintingAndDrawToPDF::DelayedReply> reply)
    31323132{
    31333133    Vector<WebCore::IntRect> pageRects;
    3134     double totalScaleFactor = 1;
     3134    double totalScaleFactor;
    31353135    computePagesForPrintingImpl(frameID, printInfo, pageRects, totalScaleFactor);
     3136
    31363137    std::size_t pageCount = pageRects.size();
    3137     reply->send(WTFMove(pageRects), totalScaleFactor);
     3138    ASSERT(pageCount <= std::numeric_limits<uint32_t>::max());
     3139    reply->send(pageCount);
    31383140
    31393141    RetainPtr<CFMutableDataRef> pdfPageData;
    3140     drawPagesToPDFImpl(frameID, printInfo, firstPage, pageCount - firstPage, pdfPageData);
    3141     send(Messages::WebPageProxy::DidFinishDrawingPagesToPDF(IPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get()))));
     3142    drawPagesToPDFImpl(frameID, printInfo, 0, pageCount, pdfPageData);
     3143    send(Messages::WebPageProxy::DrawToPDFCallback(IPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
     3144
     3145    endPrinting();
    31423146}
    31433147
Note: See TracChangeset for help on using the changeset viewer.