Skip to content

Instantly share code, notes, and snippets.

@bcbroom
Created January 27, 2016 12:55
Show Gist options
  • Save bcbroom/8dc68b6c56e7dca72981 to your computer and use it in GitHub Desktop.
Save bcbroom/8dc68b6c56e7dca72981 to your computer and use it in GitHub Desktop.
Generate a paginated PDF based on a NSString. Adds an image and person's name on the last page. Shared under MIT license.
//
// PDFGenerator.h
//
//
// Created by Brian Broom on 12/10/15.
// Copyright © 2015 Brian Broom. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface PDFGenerator : NSObject
- (NSData *)generateWithAgreementText:(NSString *)agreementText signatureImage:(UIImage *)signatureImage fullName:(NSString *)fullName;
@end
//
// PDFGenerator.m
//
//
// Created by Brian Broom on 12/10/15.
// Copyright © 2015 Brian Broom. All rights reserved.
//
@import UIKit;
#import "PDFGenerator.h"
#import "Person.h"
@implementation PDFGenerator
- (NSData *)generateWithAgreementText:(NSString *)agreementText signatureImage:(UIImage *)signatureImage fullName:(NSString *)fullName {
// layout text pages
UIFont *textFont = [UIFont fontWithName:@"Avenir Next" size:12.0];
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.lineHeightMultiple = 1.2;
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
NSDictionary *textAttributes = @{ NSParagraphStyleAttributeName : paragraphStyle, NSFontAttributeName : textFont };
NSAttributedString *styledString = [[NSAttributedString alloc] initWithString:agreementText attributes:textAttributes];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:styledString];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
layoutManager.usesFontLeading = YES;
[textStorage addLayoutManager:layoutManager];
// Create the PDF context using page size of 612 x 792 (8.5x11 at 72dpi).
CGSize pageSize = CGSizeMake(612, 792);
CGRect pageRect = CGRectMake(0, 0, pageSize.width, pageSize.height);
// 0.5" margin top, bottom
CGRect pageRectWithoutMargin = CGRectInset(pageRect, 36, 36);
CGSize pageSizeWithoutMargin = pageRectWithoutMargin.size;
CGPoint textRenderingStartPoint = pageRectWithoutMargin.origin;
while ([self needsMorePagesForLayoutManager:layoutManager]) {
[self addPageToLayoutManager:layoutManager withSize:pageSizeWithoutMargin];
}
// open PDF context
NSMutableData *pdfData = [NSMutableData new];
UIGraphicsBeginPDFContextToData(pdfData, pageRect, nil);
// render pages
for (NSTextContainer *container in layoutManager.textContainers) {
UIGraphicsBeginPDFPage();
NSRange glyphRangeForPage = [layoutManager glyphRangeForTextContainer:container];
[layoutManager drawBackgroundForGlyphRange:glyphRangeForPage atPoint:textRenderingStartPoint];
[layoutManager drawGlyphsForGlyphRange:glyphRangeForPage atPoint:textRenderingStartPoint];
}
// add image on new page
UIGraphicsBeginPDFPage();
[fullName drawAtPoint:CGPointMake(150, 100) withAttributes:textAttributes];
[signatureImage drawInRect:CGRectMake(150, 200, 200, 100)];
// Close the PDF context and write the contents out.
UIGraphicsEndPDFContext();
return pdfData;
}
- (BOOL)needsMorePagesForLayoutManager:(NSLayoutManager *)layoutManager {
if (layoutManager.textContainers.count == 0) {
return YES;
}
NSRange glyphRange = [layoutManager glyphRangeForTextContainer:layoutManager.textContainers.lastObject];
NSUInteger numberOfGlyphs = [layoutManager numberOfGlyphs];
if (glyphRange.location + glyphRange.length < numberOfGlyphs) {
return YES;
}
return NO;
}
- (void)addPageToLayoutManager:(NSLayoutManager *)layoutManager withSize:(CGSize)pageSizeWithoutMargin {
NSTextContainer *container = [[NSTextContainer alloc] initWithSize:pageSizeWithoutMargin];
[layoutManager addTextContainer:container];
}
@end
@swinghu
Copy link

swinghu commented Feb 2, 2016

good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment