Contex Drawing + Pagination

IphoneIosPdfQuartz 2dCgcontext

Iphone Problem Overview


I am trying to draw contents of scrollview into a PDF context & I am facing problem with pagination.

Following Code I have used:

- (void)renderTheView:(UIView *)view inPDFContext:(CGContextRef)pdfContext
{
    // Creating frame.
    CGFloat heightOfPdf = [[[self attributes] objectForKey:SRCPdfHeight] floatValue];
    CGFloat widthOfPdf  = [[[self attributes] objectForKey:SRCPdfWidth] floatValue];
    CGRect pdfFrame = CGRectMake(0, 0, widthOfPdf, heightOfPdf);   
    CGRect viewFrame = [view frame];

    if ([view isKindOfClass:[UIScrollView class]])
    {
        viewFrame.size.height = ((UIScrollView *)view).contentSize.height;
        [view setFrame:viewFrame];
    }
    // Calculates number of pages.
    NSUInteger totalNumberOfPages = ceil(viewFrame.size.height/heightOfPdf);
        
    // Start rendering.
    for (NSUInteger pageNumber = 0; pageNumber<totalNumberOfPages; pageNumber++)
    {
       // Starts our first page.
       CGContextBeginPage (pdfContext, &pdfFrame);	
       // Turn PDF upsidedown
       CGAffineTransform transform = CGAffineTransformIdentity;
       transform = CGAffineTransformMakeTranslation(0,view.bounds.size.height);
       transform = CGAffineTransformScale(transform, 1.0, -1.0);
       CGContextConcatCTM(pdfContext, transform);

       // Calculate amount of y to be displace.
       CGFloat ty = (heightOfPdf*(pageNumber));
            
       CGContextTranslateCTM(pdfContext,0,-ty);
       [view.layer renderInContext:pdfContext];
    		
       // We are done drawing to this page, let's end it.
       CGContextEndPage (pdfContext);
   }	
}

It creates required number of pages but places the content wrongly. Following figure explains it.enter image description here

Is there anything wrong in my code?

Iphone Solutions


Solution 1 - Iphone

I don't think you need the code which flips the PDF upside down. I've done this before (manual pagination, but without a scroll view) and never had to flip the context vertically. My main concern is that you are doing it on every iteration - if you have a valid reason for flipping it, you probably don't need it in the loop, but just once before the loop begins. Also the code CGContextTranslateCTM(pdfContext,0,-ty); might need to be replaced with CGContextTranslateCTM(pdfContext,0,heightOfPdf);

If that doesn't work, try UIGraphicsBeginPDFPage(); instead of CGContextBeginPage(), that's the only major difference between your code and mine.

Solution 2 - Iphone

Found this link to render a PDF, it says about multiple pages but haven't shown an implementation. It doesnt straight away answer to your question but it tells a simpler method to render a pdf with much less translation and transforms.

Render PDF

Generate Multipage PDF -anoop

Solution 3 - Iphone

The portions you need to add to pdf pages put in seperate views inside the scroll and render tht view to the pdf context

OR

Just find the correct dimensions and draw using the CG method:

        UIImage *Logo=[UIImage imageNamed:@"small-logo-left-top130_133.png"];
    CGPoint drawingLogoOrgin = CGPointMake(5,5);
   
    UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, nil);
    UIGraphicsBeginPDFPageWithInfo(pageFrame, nil);
    CGContextRef pdfContext = UIGraphicsGetCurrentContext();
    [Logo drawAtPoint:drawingLogoOrgin];

There are a lot of drawing methods to draw pdf. You can use that to draw all the contents.

Solution 4 - Iphone

This github project can definitely help you.

- (void) renderPageAtIndex:(NSUInteger)index inContext:(CGContextRef)ctx {
CGPDFPageRef page = CGPDFDocumentGetPage(pdf, index + 1);
CGAffineTransform transform = aspectFit(CGPDFPageGetBoxRect(page, kCGPDFMediaBox),
										CGContextGetClipBoundingBox(ctx));
CGContextConcatCTM(ctx, transform);
CGContextDrawPDFPage(ctx, page);

}

Solution 5 - Iphone

You could consider using a UIScrollView to layout your separate PDF pages. The following method loads each PDF page in a view (PDFView) and adds it to the scroll view content in a centered fashion:

- (void) loadPDFAtPath:(NSString *)path
{
    NSURL *pdfUrl = [NSURL fileURLWithPath:path];
    CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((__bridge CFURLRef)pdfUrl);

    float height = 0.0;

    for(int i = 0; i < CGPDFDocumentGetNumberOfPages(document); i++) {
        CGPDFPageRef page = CGPDFDocumentGetPage(document, i + 1);
        PDFView *pdfView = [[PDFView alloc] initPdfViewWithPageRef:page];

        CGRect pageSize = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
        pv.frame = CGRectMake((self.frame.size.width / 2.0) - pageSize.size.width / 2.0, height, pageSize.size.width, pageSize.size.height);
        height += pageSize.size.height + SOME_SPACE_IN_BETWEEN_PAGES;
    
        // self is a subclass of UIScrollView
        [self addSubview:pdfView];
        [pdfView setNeedsDisplay];
    }

    CGPDFDocumentRelease(document);
    [self setContentSize:CGSizeMake(self.frame.size.width, height)];
}

In this case, PDFView is responsible for rendering a single CGPDFPageRef in its drawRect or drawLayer implementation.

Solution 6 - Iphone

this might help you.

- (void) renderPageAtIndex:(NSUInteger)index inContext:(CGContextRef)ctx 
{
CGPDFPageRef page = CGPDFDocumentGetPage(pdf, index + 1);
CGAffineTransform transform = aspectFit(CGPDFPageGetBoxRect(page, kCGPDFMediaBox),
                                    CGContextGetClipBoundingBox(ctx));
CGContextConcatCTM(ctx, transform);
CGContextDrawPDFPage(ctx, page);
} 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSamView Question on Stackoverflow
Solution 1 - IphonezeroimplView Answer on Stackoverflow
Solution 2 - Iphoneanoop4realView Answer on Stackoverflow
Solution 3 - IphoneLithu T.VView Answer on Stackoverflow
Solution 4 - IphoneYogiARView Answer on Stackoverflow
Solution 5 - IphonejverrijtView Answer on Stackoverflow
Solution 6 - IphoneiCodeView Answer on Stackoverflow