Sunday, April 19, 2009

HTML to PDF using WebKit

Creating a PDF with the contents of any NSView is extremely easy. All you have to do is use NSViews:


- (NSData *)dataWithPDFInsideRect:(NSRect)aRect


When trying to create a PDF from HTML the natural way to go is using the method mentioned above from an instance of WebView. Unfortunately, it turns out there is a small inconvenience. When called from an instance of WebView this method WILL NOT draw everything to PDF. It's very easy to test this without writing any code. Try printing a few pages to PDF in Safari. This is how my blog gets rendered:




It's also interesting that google.pl renders without the google logo, while google.us renders properly:




Anyhow, this issue is very easy to solve in code. Let's say you load your PDF as follows:


//get a pointer to the document view so that we render the entire web page, not just the visible portion.
NSView *docView = [[[webview mainFrame] frameView] documentView];

[docView lockFocus];

//create the PDF
NSData *data = [docView dataWithPDFInsideRect:[docView bounds]];

[docView unlockFocus];

//create an instance of a PDFDocument to display in a PDFView.
PDFDocument *doc = [[PDFDocument alloc] initWithData:data];

//display the PDF document in a PDFView
[pdfview setDocument:doc];

[pdfWindow orderFront:nil];


This will produce the standard results. In order to render everything to PDF you have to set WebViews preferences appropriately. WebView has a method - (void)setPreferences:(WebPreferences*)preferences. If you look at the documentation for WebPreferences you will notice it has a method called - (void)setShouldPrintBackgrounds:(BOOL)pb. Setting this to YES solves the minor inconvenience mentioned in this post.


WebPreferences *preferences = [[[WebPreferences alloc] initWithIdentifier:@"testing"] autorelease];
[preferences setShouldPrintBackgrounds:YES];
[webview setPreferences:preferences];


After setting WebViews preferences to print the backgrounds, my blog and all other pages print just fine to PDF.



UPDATE:

Check out my next post where I mention two important things:
1) How to print to a PDF with paging.
2) How to make sure the WebView loaded all it's content before printing (if you're getting a blank page when printing this is what you need!).

No comments:

Post a Comment