Contex Drawing + Pagination
IphoneIosPdfQuartz 2dCgcontextIphone 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.
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.
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);
}