在 pdf 上书写文本 ios
Writing text on pdf ios
你好我已经关注了这个guide to write text on pdf file. This guide maybe old but follows the same approach as in apple docs
到目前为止我做了什么:
PdfCreator.m
const int A4_WIDTH = 612;
const int A4_HEIGHT = 792;
@interface PdfCreator()
@property (nonatomic, assign) double currentHeight;
@end
@implementation PdfCreator
- (void) createPdfWithName:(NSString*)name{
// Create the PDF context using the default page size of 612 x 792.
UIGraphicsBeginPDFContextToFile(name, CGRectZero, nil);
// Mark the beginning of a new page.
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, A4_WIDTH, A4_HEIGHT), nil);
self.currentHeight = 0;
}
- (void) printTrip:(Trip*) trip{
// Get the graphics context.
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
NSString* textToDraw = @"Hello World";
CFStringRef stringRef = (__bridge CFStringRef)textToDraw;
// Prepare the text using a Core Text Framesetter
CFAttributedStringRef currentText = CFAttributedStringCreate(NULL, stringRef, NULL);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
//
CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(
framesetter, /* Framesetter */
CFRangeMake(0, textToDraw.length), /* String range (entire string) */
NULL, /* Frame attributes */
CGSizeMake(A4_WIDTH, CGFLOAT_MAX), /* Constraints (CGFLOAT_MAX indicates unconstrained) */
NULL /* Gives the range of string that fits into the constraints, doesn't matter in your situation */
);
CGRect frameRect = CGRectMake(0, 0, suggestedSize.width, suggestedSize.height);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
// Get the frame that will do the rendering.
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGPathRelease(framePath);
// Core Text draws from the bottom-left corner up, so flip
// the current transform prior to drawing.
CGContextTranslateCTM(currentContext, 0, 100);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
CFRelease(frameRef);
CFRelease(stringRef);
CFRelease(framesetter);
}
- (void) endFile{
UIGraphicsEndPDFContext();
}
@end
现在我在另一个模型文件中这样使用它:
PdfCreator *pdf = [[PdfCreator alloc] init];
[pdf createPdfWithName:documentDirectoryFilename];
for (Trip *t in self.trips) {
[pdf printTrip:t];
}
[pdf endFile];
NSURL *URL = [NSURL fileURLWithPath:documentDirectoryFilename];
if (URL) {
// Initialize Document Interaction Controller
self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:URL];
// Configure Document Interaction Controller
[self.documentInteractionController setDelegate:self];
// Preview PDF
[self.documentInteractionController presentPreviewAnimated:YES];
}
问题是它打印了这个:
我注意到,如果我只调用一次 printTrip:
方法,则只会打印一个 HelloWorld 标签并位于正确的位置。连续调用在顶部打印镜像文本。这很奇怪,因为这一行
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
应该重置比例因子。任何帮助将不胜感激。
答案可在教程的 part 2 中找到。上下文应该在绘制文本后重置。
CGContextTranslateCTM(currentContext, 0, 100);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
/*NEW!*/
CGContextScaleCTM(currentContext, 1.0, -1.0);
在此处查看 Apple 关于 CGContextSaveGState
和 CGContextRestoreGState
的文档:
https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGContext/#//apple_ref/c/func/CGContextSaveGState
这两个函数常用于 PDF 文件中以将对当前图形状态的修改括起来(包括从颜色设置到裁剪和 CTM 或当前变换矩阵的所有内容)。
使用您的代码:
CGContextSaveGState(currentContext); /// A
CGContextTranslateCTM(currentContext, 0, 100);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
CGContextRestoreGState(currentContext); /// B
在 B 点,您现在回到了 A 点的确切位置。
您可以嵌套这些,它是作为堆栈实现的。不过,您必须小心保持它们的平衡。从编写 PDF 解析器软件的人的角度来看,您还希望将保存/恢复对的数量保持在您实际需要的数量。不要不必要地使用它们:)
你好我已经关注了这个guide to write text on pdf file. This guide maybe old but follows the same approach as in apple docs
到目前为止我做了什么:
PdfCreator.m
const int A4_WIDTH = 612;
const int A4_HEIGHT = 792;
@interface PdfCreator()
@property (nonatomic, assign) double currentHeight;
@end
@implementation PdfCreator
- (void) createPdfWithName:(NSString*)name{
// Create the PDF context using the default page size of 612 x 792.
UIGraphicsBeginPDFContextToFile(name, CGRectZero, nil);
// Mark the beginning of a new page.
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, A4_WIDTH, A4_HEIGHT), nil);
self.currentHeight = 0;
}
- (void) printTrip:(Trip*) trip{
// Get the graphics context.
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
NSString* textToDraw = @"Hello World";
CFStringRef stringRef = (__bridge CFStringRef)textToDraw;
// Prepare the text using a Core Text Framesetter
CFAttributedStringRef currentText = CFAttributedStringCreate(NULL, stringRef, NULL);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
//
CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(
framesetter, /* Framesetter */
CFRangeMake(0, textToDraw.length), /* String range (entire string) */
NULL, /* Frame attributes */
CGSizeMake(A4_WIDTH, CGFLOAT_MAX), /* Constraints (CGFLOAT_MAX indicates unconstrained) */
NULL /* Gives the range of string that fits into the constraints, doesn't matter in your situation */
);
CGRect frameRect = CGRectMake(0, 0, suggestedSize.width, suggestedSize.height);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
// Get the frame that will do the rendering.
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGPathRelease(framePath);
// Core Text draws from the bottom-left corner up, so flip
// the current transform prior to drawing.
CGContextTranslateCTM(currentContext, 0, 100);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
CFRelease(frameRef);
CFRelease(stringRef);
CFRelease(framesetter);
}
- (void) endFile{
UIGraphicsEndPDFContext();
}
@end
现在我在另一个模型文件中这样使用它:
PdfCreator *pdf = [[PdfCreator alloc] init];
[pdf createPdfWithName:documentDirectoryFilename];
for (Trip *t in self.trips) {
[pdf printTrip:t];
}
[pdf endFile];
NSURL *URL = [NSURL fileURLWithPath:documentDirectoryFilename];
if (URL) {
// Initialize Document Interaction Controller
self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:URL];
// Configure Document Interaction Controller
[self.documentInteractionController setDelegate:self];
// Preview PDF
[self.documentInteractionController presentPreviewAnimated:YES];
}
问题是它打印了这个:
我注意到,如果我只调用一次 printTrip:
方法,则只会打印一个 HelloWorld 标签并位于正确的位置。连续调用在顶部打印镜像文本。这很奇怪,因为这一行
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
应该重置比例因子。任何帮助将不胜感激。
答案可在教程的 part 2 中找到。上下文应该在绘制文本后重置。
CGContextTranslateCTM(currentContext, 0, 100);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
/*NEW!*/
CGContextScaleCTM(currentContext, 1.0, -1.0);
在此处查看 Apple 关于 CGContextSaveGState
和 CGContextRestoreGState
的文档:
https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGContext/#//apple_ref/c/func/CGContextSaveGState
这两个函数常用于 PDF 文件中以将对当前图形状态的修改括起来(包括从颜色设置到裁剪和 CTM 或当前变换矩阵的所有内容)。
使用您的代码:
CGContextSaveGState(currentContext); /// A
CGContextTranslateCTM(currentContext, 0, 100);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
CGContextRestoreGState(currentContext); /// B
在 B 点,您现在回到了 A 点的确切位置。
您可以嵌套这些,它是作为堆栈实现的。不过,您必须小心保持它们的平衡。从编写 PDF 解析器软件的人的角度来看,您还希望将保存/恢复对的数量保持在您实际需要的数量。不要不必要地使用它们:)