Changeset 104377 in webkit


Ignore:
Timestamp:
Jan 6, 2012 10:57:32 PM (12 years ago)
Author:
mrowe@apple.com
Message:

REGRESSION (WebKit2): Save as PDF no longer generates links to URLs
<http://webkit.org/b/65076> / <rdar://problem/9606246>

WebKit2 printing works by having the web process render the page content to a PDF. The PDF
data is then shipped to the UI process which will render it in to the printing graphics context.
Links were being lost because the API used to do the rendering of the PDF in to the printing
graphics context, CGContextDrawPDFPage, did not preserve the links that were present in the
PDF content received from the web process.

To fix this we switch to using PDFKit for drawing the PDF in to the printing graphics context.
PDFKit provides the ability for us to iterate over the links in the PDF content ourselves and
add links in to the printing graphics context.

Reviewed by Alexey Proskuryakov.

  • UIProcess/API/mac/WKPrintingView.h:
  • UIProcess/API/mac/WKPrintingView.mm:

(pdfAnnotationLinkClass): Look up the PDFAnnotationLink class from PDFKit as WebKit2 loads PDFKit lazily.
(pdfDocumentClass): Ditto.
(-[WKPrintingView _drawPDFDocument:page:atPoint:]): Switch to using the PDFKit equivalents of several types.
Iterate over the annotations present in the PDFPage, calling CGPDFContextSetURLForRect for each PDFAnnotationLink
that we find.
(-[WKPrintingView _drawPreview:]): Create an NSData to feed to PDFDocument.
(-[WKPrintingView drawRect:]): Ditto.

  • WebKit2Prefix.h: Add the usual workaround to make Objective-C exceptions compile when C++ exception handling is disabled.
Location:
trunk/Source/WebKit2
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r104370 r104377  
     12012-01-06  Mark Rowe  <mrowe@apple.com>
     2
     3        REGRESSION (WebKit2): Save as PDF no longer generates links to URLs
     4        <http://webkit.org/b/65076> / <rdar://problem/9606246>
     5
     6        WebKit2 printing works by having the web process render the page content to a PDF. The PDF
     7        data is then shipped to the UI process which will render it in to the printing graphics context.
     8        Links were being lost because the API used to do the rendering of the PDF in to the printing
     9        graphics context, CGContextDrawPDFPage, did not preserve the links that were present in the
     10        PDF content received from the web process.
     11
     12        To fix this we switch to using PDFKit for drawing the PDF in to the printing graphics context.
     13        PDFKit provides the ability for us to iterate over the links in the PDF content ourselves and
     14        add links in to the printing graphics context.
     15
     16        Reviewed by Alexey Proskuryakov.
     17
     18        * UIProcess/API/mac/WKPrintingView.h:
     19        * UIProcess/API/mac/WKPrintingView.mm:
     20        (pdfAnnotationLinkClass): Look up the PDFAnnotationLink class from PDFKit as WebKit2 loads PDFKit lazily.
     21        (pdfDocumentClass): Ditto.
     22        (-[WKPrintingView _drawPDFDocument:page:atPoint:]): Switch to using the PDFKit equivalents of several types.
     23        Iterate over the annotations present in the PDFPage, calling CGPDFContextSetURLForRect for each PDFAnnotationLink
     24        that we find.
     25        (-[WKPrintingView _drawPreview:]): Create an NSData to feed to PDFDocument.
     26        (-[WKPrintingView drawRect:]): Ditto.
     27        * WebKit2Prefix.h: Add the usual workaround to make Objective-C exceptions compile when C++ exception handling is disabled.
     28
    1292012-01-06  Viatcheslav Ostapenko  <ostapenko.viatcheslav@nokia.com>
    230
  • trunk/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h

    r95901 r104377  
    2828
    2929@class WKPrintingViewData;
     30@class PDFDocument;
    3031
    3132namespace WebKit {
     
    4445
    4546    Vector<uint8_t> _printedPagesData;
    46     RetainPtr<CGPDFDocumentRef> _printedPagesPDFDocument;
     47    RetainPtr<PDFDocument> _printedPagesPDFDocument;
    4748
    4849    uint64_t _expectedComputedPagesCallback;
  • trunk/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm

    r104334 r104377  
    3131#import "WebData.h"
    3232#import "WebPageProxy.h"
     33#import <PDFKit/PDFKit.h>
    3334#import <WebCore/WebCoreObjCExtras.h>
    3435#import <wtf/MainThread.h>
     
    411412}
    412413
    413 - (void)_drawPDFDocument:(CGPDFDocumentRef)pdfDocument page:(unsigned)page atPoint:(NSPoint)point
     414static Class pdfAnnotationLinkClass()
     415{
     416    static Class pdfAnnotationLinkClass = NSClassFromString(@"PDFAnnotationLink");
     417    return pdfAnnotationLinkClass;
     418}
     419
     420static Class pdfDocumentClass()
     421{
     422    static Class pdfDocumentClass = NSClassFromString(@"PDFDocument");
     423    return pdfDocumentClass;
     424}
     425
     426- (void)_drawPDFDocument:(PDFDocument *)pdfDocument page:(unsigned)page atPoint:(NSPoint)point
    414427{
    415428    if (!pdfDocument) {
     
    418431    }
    419432
    420     CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument, page);
    421     if (!pdfPage) {
    422         LOG_ERROR("Preview data doesn't have page %d", page);
     433    PDFPage *pdfPage;
     434    @try {
     435        pdfPage = [pdfDocument pageAtIndex:page];
     436    } @catch (id exception) {
     437        LOG_ERROR("Preview data doesn't have page %d: %@", page, exception);
    423438        return;
    424439    }
     
    430445    CGContextTranslateCTM(context, point.x, point.y);
    431446    CGContextScaleCTM(context, _totalScaleFactorForPrinting, -_totalScaleFactorForPrinting);
    432     CGContextTranslateCTM(context, 0, -CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox).size.height);
    433     CGContextDrawPDFPage(context, pdfPage);
     447    CGContextTranslateCTM(context, 0, -[pdfPage boundsForBox:kPDFDisplayBoxMediaBox].size.height);
     448    [pdfPage drawWithBox:kPDFDisplayBoxMediaBox];
     449
     450    CGAffineTransform transform = CGContextGetCTM(context);
     451
     452    for (PDFAnnotation *annotation in [pdfPage annotations]) {
     453        if (![annotation isKindOfClass:pdfAnnotationLinkClass()])
     454            continue;
     455
     456        PDFAnnotationLink *linkAnnotation = (PDFAnnotationLink *)annotation;
     457        NSURL *url = [linkAnnotation URL];
     458        if (!url)
     459            continue;
     460
     461        CGRect urlRect = NSRectToCGRect([linkAnnotation bounds]);
     462        CGRect transformedRect = CGRectApplyAffineTransform(urlRect, transform);
     463        CGPDFContextSetURLForRect(context, (CFURLRef)url, transformedRect);
     464    }
     465
    434466    CGContextRestoreGState(context);
    435467}
     
    474506    }
    475507
    476     const Vector<uint8_t>& pdfData = pagePreviewIterator->second;
    477     RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, pdfData.data(), pdfData.size(), 0));
    478     RetainPtr<CGPDFDocumentRef> pdfDocument(AdoptCF, CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
    479 
    480     [self _drawPDFDocument:pdfDocument.get() page:1 atPoint:NSMakePoint(nsRect.origin.x, nsRect.origin.y)];
     508    const Vector<uint8_t>& pdfDataBytes = pagePreviewIterator->second;
     509    RetainPtr<NSData> pdfData(AdoptNS, [[NSData alloc] initWithBytes:pdfDataBytes.data() length:pdfDataBytes.size()]);
     510    RetainPtr<PDFDocument> pdfDocument(AdoptNS, [[pdfDocumentClass() alloc] initWithData:pdfData.get()]);
     511
     512    [self _drawPDFDocument:pdfDocument.get() page:0 atPoint:NSMakePoint(nsRect.origin.x, nsRect.origin.y)];
    481513}
    482514
     
    499531
    500532    if (!_printedPagesPDFDocument) {
    501         RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, _printedPagesData.data(), _printedPagesData.size(), 0));
    502         _printedPagesPDFDocument.adoptCF(CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
    503     }
    504 
    505     unsigned printedPageNumber = [self _pageForRect:nsRect] - [self _firstPrintedPageNumber] + 1;
     533        RetainPtr<NSData> pdfData(AdoptNS, [[NSData alloc] initWithBytes:_printedPagesData.data() length:_printedPagesData.size()]);
     534        _printedPagesPDFDocument.adoptNS([[pdfDocumentClass() alloc] initWithData:pdfData.get()]);
     535    }
     536
     537    unsigned printedPageNumber = [self _pageForRect:nsRect] - [self _firstPrintedPageNumber];
    506538    [self _drawPDFDocument:_printedPagesPDFDocument.get() page:printedPageNumber atPoint:NSMakePoint(nsRect.origin.x, nsRect.origin.y)];
    507539}
  • trunk/Source/WebKit2/WebKit2Prefix.h

    r95901 r104377  
    2929#endif
    3030
     31/* When C++ exceptions are disabled, the C++ library defines |try| and |catch|
     32* to allow C++ code that expects exceptions to build. These definitions
     33* interfere with Objective-C++ uses of Objective-C exception handlers, which
     34* use |@try| and |@catch|. As a workaround, undefine these macros. */
     35
     36#ifdef __cplusplus
     37#include <algorithm> // needed for exception_defines.h
     38#endif
     39
     40#ifdef __OBJC__
     41#undef try
     42#undef catch
     43#endif
     44
    3145#ifdef __cplusplus
    3246#define new ("if you use new/delete make sure to include config.h at the top of the file"())
Note: See TracChangeset for help on using the changeset viewer.