Has anyone already created a PDF document in an iPad app? I see that there are new functions in the UIKit to do this, but I can't find any code example for it.
BOOL UIGraphicsBeginPDFContextToFile (
NSString *path,
CGRect bounds,
NSDictionary *documentInfo
);
void UIGraphicsBeginPDFPage (
void
);
I found an example that is supposed to work on the iPhone, but this gives me errors:
Fri Apr 30 11:55:32 wks104.hs.local PDF[1963] <Error>: CGFont/Freetype: The function `create_subset' is currently unimplemented.
Fri Apr 30 11:55:32 wks104.hs.local PDF[1963] 开发者_运维问答<Error>: invalid Type1 font: unable to stream font.
Fri Apr 30 11:55:32 wks104.hs.local PDF[1963] <Error>: FT_Load_Glyph failed: error 6.
Fri Apr 30 11:55:32 wks104.hs.local PDF[1963] <Error>: FT_Load_Glyph failed: error 6.
Fri Apr 30 11:55:32 wks104.hs.local PDF[1963] <Error>: FT_Load_Glyph failed: error 6.
Fri Apr 30 11:55:32 wks104.hs.local PDF[1963] <Error>: FT_Load_Glyph failed: error 6.
I actually got multi page PDF creation working by modifying the code above, like:
- (void) createPDF:(NSString *)fileName withContent:(NSString *)content forSize:(int)fontSize andFont:(NSString *)font andColor:(UIColor *)color {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *newFilePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:fileName];
CGRect a4Page = CGRectMake(0, 0, DOC_WIDTH, DOC_HEIGHT);
NSDictionary *fileMetaData = [[NSDictionary alloc] init];
if (!UIGraphicsBeginPDFContextToFile(newFilePath, a4Page, fileMetaData )) {
NSLog(@"error creating PDF context");
return;
}
BOOL done = NO;
CGContextRef context = UIGraphicsGetCurrentContext();
CFRange currentRange = CFRangeMake(0, 0);
CGContextSetTextDrawingMode (context, kCGTextFill);
CGContextSelectFont (context, [font cStringUsingEncoding:NSUTF8StringEncoding], fontSize, kCGEncodingMacRoman);
CGContextSetFillColorWithColor(context, [color CGColor]);
// Initialize an attributed string.
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (attrString, currentRange, (CFStringRef)content);
// Create the framesetter with the attributed string.
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
do {
UIGraphicsBeginPDFPage();
CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds = CGRectMake(LEFT_MARGIN,
TOP_MARGIN,
DOC_WIDTH - RIGHT_MARGIN - LEFT_MARGIN,
DOC_HEIGHT - TOP_MARGIN - BOTTOM_MARGIN);
CGPathAddRect(path, NULL, bounds);
// Create the frame and draw it into the graphics context
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, currentRange, path, NULL);
if(frame) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0, bounds.origin.y);
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -(bounds.origin.y + bounds.size.height));
CTFrameDraw(frame, context);
CGContextRestoreGState(context);
// Update the current range based on what was drawn.
currentRange = CTFrameGetVisibleStringRange(frame);
currentRange.location += currentRange.length;
currentRange.length = 0;
CFRelease(frame);
}
// If we're at the end of the text, exit the loop.
if (currentRange.location == CFAttributedStringGetLength((CFAttributedStringRef)attrString))
done = YES;
}
while(!done);
UIGraphicsEndPDFContext();
[fileMetaData release];
CFRelease(attrString);
CFRelease(framesetter);
}
However, as mentioned above, it ignores the font I try to set. I always get something, looking like "Helvetica".
So, there is currently no way to create a PDF file on an iPad/iPhone, that embeds the font used on the device? I can hardly believe that. I would have at least hoped for those "usual suspects" fonts , like: Courier, Times New Roman, etc... to be supported.
If anyone out there has more information or useful tips on workarounds, please feel welcome to share.
Thanks in advance.
Here is a method that will create a new PDF document. It does not do text formatting though.
- (void) createNewPDF: (NSString *) saveFileName withContent: (NSString *) content forSize: (int) fontSize andFont:(NSString *) font andColor: (UIColor *) color
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *newFilePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:saveFileName];
CGRect a4Page = CGRectMake(0, 0, 595, 842);
NSDictionary *fileMetaData = [[NSDictionary alloc] init];
if (!UIGraphicsBeginPDFContextToFile(newFilePath, a4Page, fileMetaData )) {
NSLog(@"error creating PDF context");
return;
}
CGContextRef mpdfContext = UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPage();
CGContextSetTextMatrix(mpdfContext, CGAffineTransformMake(1, 0, 0, -1, 0, 0));
CGContextSetTextDrawingMode (mpdfContext, kCGTextFill);
CGContextSelectFont (mpdfContext, [font cStringUsingEncoding:NSUTF8StringEncoding], fontSize, kCGEncodingMacRoman);
CGContextSetFillColorWithColor(mpdfContext, [color CGColor]);
CGContextShowTextAtPoint (mpdfContext, 20, 20, [content cStringUsingEncoding:NSUTF8StringEncoding], [content length]);
UIGraphicsEndPDFContext();
}
just to let you know that the error message:
invalid Type1 font: unable to stream font
and: FT_Load_Glyph failed: error 6.
disappeared in iOS 4.2
This is a better solution as it uses the correct coordinate transform to get the text to print from the top down.
#define LEFT_MARGIN 25
#define RIGHT_MARGIN 25
#define TOP_MARGIN 35
#define BOTTOM_MARGIN 50
#define BOTTOM_FOOTER_MARGIN 32
#define DOC_WIDTH 595
#define DOC_HEIGHT 842
- (void) createPDF:(NSString *)fileName withContent:(NSString *)content forSize:(int)fontSize andFont:(NSString *)font andColor:(UIColor *)color
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *newFilePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:fileName];
CGRect a4Page = CGRectMake(0, 0, DOC_WIDTH, DOC_HEIGHT);
NSDictionary *fileMetaData = [[NSDictionary alloc] init];
if (!UIGraphicsBeginPDFContextToFile(newFilePath, a4Page, fileMetaData )) {
NSLog(@"error creating PDF context");
return;
}
CGContextRef context = UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPage();
CGContextSetTextDrawingMode (context, kCGTextFill);
CGContextSelectFont (context, [font cStringUsingEncoding:NSUTF8StringEncoding], fontSize, kCGEncodingMacRoman);
CGContextSetFillColorWithColor(context, [color CGColor]);
CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds = CGRectMake(LEFT_MARGIN,
TOP_MARGIN,
DOC_WIDTH - RIGHT_MARGIN - LEFT_MARGIN,
DOC_HEIGHT - TOP_MARGIN - BOTTOM_MARGIN
);
CGPathAddRect(path, NULL, bounds);
// Initialize an attributed string.
CFMutableAttributedStringRef attrString =
CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), (CFStringRef)content);
// Create the framesetter with the attributed string.
CTFramesetterRef framesetter =
CTFramesetterCreateWithAttributedString(attrString);
// Create the frame and draw it into the graphics context
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
CFRange visibleRange = CTFrameGetVisibleStringRange(frame);
if (visibleRange.length < [content length] ) {
NSLog(@"WARNING: Not all displayed on a single page");
}
CFRelease(attrString);
CFRelease(framesetter);
if(frame) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0, bounds.origin.y);
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -(bounds.origin.y + bounds.size.height));
CTFrameDraw(frame, context);
CGContextRestoreGState(context);
CFRelease(frame);
}
UIGraphicsEndPDFContext();
[fileMetaData release];
}
精彩评论