0

I am using the following code to convert HTML to PDF (as posted by cwehrung at various places)

UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];

[render addPrintFormatter:webView.viewPrintFormatter startingAtPageAtIndex:0];

CGRect printableRect = CGRectMake(self.pageMargins.left,
                              self.pageMargins.top,
                              self.pageSize.width - self.pageMargins.left - self.pageMargins.right,
                              self.pageSize.height - self.pageMargins.top - self.pageMargins.bottom);

CGRect paperRect = CGRectMake(0, 0, self.pageSize.width, self.pageSize.height);

[render setValue:[NSValue valueWithCGRect:paperRect] forKey:@"paperRect"];
[render setValue:[NSValue valueWithCGRect:printableRect] forKey:@"printableRect"];

NSData *pdfData = [render printToPDF];

[pdfData writeToFile: self.PDFpath  atomically: YES];

created a category on UIPrintPageRenderer to support:

-(NSData*) printToPDF
{
    [self doNotRasterizeSubviews:self.view];

    NSMutableData *pdfData = [NSMutableData data];

    UIGraphicsBeginPDFContextToData( pdfData, self.paperRect, nil );

    [self prepareForDrawingPages: NSMakeRange(0, self.numberOfPages)];

    CGRect bounds = UIGraphicsGetPDFContextBounds();

    for ( int i = 0 ; i < self.numberOfPages ; i++ )
    {
        UIGraphicsBeginPDFPage();

        [self drawPageAtIndex: i inRect: bounds];
    }

    UIGraphicsEndPDFContext();

    return pdfData;
}

The issue I have is with alignment between images and text.

I uploaded the HTML file to here, and it's easy to see the issue in the converted PDF file which I uploaded to here. (see 3rd book and 6th book)

Any help will be greatly appreciated!

Community
  • 1
  • 1
Joshua
  • 1,974
  • 2
  • 23
  • 39
  • Theres isnt much of a difference.... I think it is fine – IronManGill Aug 01 '13 at 06:58
  • You can change frame pdf. – user2545330 Aug 01 '13 at 07:01
  • in UIGraphicsBeginPDFContextToData try to set bounds According to Apple Documents : bound - A rectangle that specifies the default size and location of PDF pages. (This value is used as the default media box for each new page.) The origin of the rectangle should typically be (0, 0). Specifying an empty rectangle (CGRectZero) sets the default page size to 8.5 by 11 inches (612 by 792 points). Try to change the CGRectZero to another Value ..:) – Sahil Mahajan Aug 01 '13 at 07:04
  • user, iPhoneNerd, thanks for your replies but changing the PDF rect will simply move the issue to a different place. I need a way to keep the image and text always in synch regardless of frame size. – Joshua Aug 01 '13 at 07:38
  • How did you solve this problem ? I am stuck at somewhat similar issue – Shailesh Mar 18 '15 at 10:10

1 Answers1

1

We can convert HTML into pdf in another way-

Open html in UIWebview and code is-

-(void)display
{
webViewHeight = [[self.printWebView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"] integerValue];

CGRect screenRect = self.printWebView.frame;

double currentWebViewHeight = webViewHeight;


NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imageCacheDirPath = [documentsDirectory stringByAppendingPathComponent:@"pdfImages"];
if (![[NSFileManager defaultManager] fileExistsAtPath: imageCacheDirPath])
{
    [[NSFileManager defaultManager] createDirectoryAtPath:imageCacheDirPath withIntermediateDirectories:NO attributes:nil error:NULL];
}
else
{
    NSError *error;
    [[NSFileManager defaultManager] removeItemAtPath: imageCacheDirPath error: &error];
    [[NSFileManager defaultManager] createDirectoryAtPath:imageCacheDirPath withIntermediateDirectories:NO attributes:nil error:NULL];
 }

while (currentWebViewHeight > 0)
{
    imageName ++;
     UIGraphicsBeginImageContext(screenRect.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];
    CGContextFillRect(ctx, screenRect);
    [self.printWebView.layer renderInContext:ctx];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    NSString *pngPath = [imageCacheDirPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png",imageName]];
    if(currentWebViewHeight < 440)
    {
        CGRect lastImageRect = CGRectMake(0,440-currentWebViewHeight, self.printWebView.frame.size.width, currentWebViewHeight);
        CGImageRef lastImageRef = CGImageCreateWithImageInRect([newImage CGImage], lastImageRect);
        newImage = [UIImage imageWithCGImage:lastImageRef];
        CGImageRelease(lastImageRef);
    }
    [UIImagePNGRepresentation(newImage) writeToFile:pngPath atomically:YES];
    [self.printWebView stringByEvaluatingJavaScriptFromString:@"window.scrollBy(0,440);"];
    currentWebViewHeight -= 440;
}
[self drawPdf];
}

- (void) drawPdf
{
CGSize pageSize = CGSizeMake(612, webViewHeight);
NSString *fileName = @"Demo.pdf";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imageCacheDirPath = [documentsDirectory stringByAppendingPathComponent:@"pdfImages"];

NSString *pdfFileName = [imageCacheDirPath stringByAppendingPathComponent:fileName];
NSLog(@"file path:%@",pdfFileName);

UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectZero, nil);

// Mark the beginning of a new page.
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, pageSize.width, pageSize.height), nil);

double currentHeight = 0.0;
for (int index = 1; index <= imageName ; index++)
{
    NSString *pngPath = [imageCacheDirPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png", index]];
    UIImage *pngImage = [UIImage imageWithContentsOfFile:pngPath];

    [pngImage drawInRect:CGRectMake(0, currentHeight, pageSize.width, pngImage.size.height)];
    currentHeight += pngImage.size.height;
}
UIGraphicsEndPDFContext();
}
  • Which is fine, unless you actually want the PDF to be something other than a whole heap of images. In which case it is useless. To make a searchable PDF (eg, one that treats the text as text and the images as images) you cannot just render it to images. – Bergasms Aug 01 '13 at 07:02
  • Ok check out http://stackoverflow.com/questions/5817840/print-paper-size-and-content-inset/5988357#5988357 may helps –  Aug 01 '13 at 07:04
  • searchable PDF is probably my way to go, so the code won't do the job for me.. but voted you 1 up for your efforts. – Joshua Aug 01 '13 at 07:18