我知道 UIFont 和 CTFont 是不同的东西,但我能够让它发挥作用。
我正在尝试生成 PDF 并使用 UIView 作为模板,但是要绘制可编辑的 PDF,我需要让 CTFontRef 在某个帧中呈现自身。下面是我在 PDF 上下文中绘制 UILabel 的方法。该方法使用 UILabel 作为字体名称、字体大小和位置的模板,而 CTFontRef 将字符呈现为 PDF。
该方法有效,但有怪癖。
我注意到下面的代码可能无法在一个大到足以容纳使用 UIFont 编写的文本的框架中呈现。例如,我有一个适合某种字体的 80x21 UILabel。如果我尝试使用 CTFontRef 渲染该字体,我会得到一个空格,除非我将标签的高度增加到 80x30。简单地说,CTFontRef 不会渲染没有水平或垂直剪辑框架的文本。
另外,我注意到有些字体有不同的宽度,所以一个 80x21 的标签适合 UIFont 的 20 个字符可能只适合 CTFontRef 的 15 个字符。我的猜测是这是因为 CTFontRef 不会截断文本,并且根本不会渲染从框架中任一方向伸出的单词。
几个问题: 什么可能导致我的字体大小错位?我需要复制一些其他属性吗?有没有办法让 CTFontRef 截断标签末尾的长词?
//xOriginOffset, yOriginOffset is the X of the origin of the container view that holds the label.
+(void)drawTextLabel:(UILabel*)label WithXOriginOffset:(int)xOriginOffset YOffset:(int)yOriginOffset
{
NSString* textToDraw = label.text;
CFStringRef stringRef = (__bridge CFStringRef)textToDraw;
UIFont* uiFont = label.font;
// Prepare font
CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)uiFont.fontName, uiFont.pointSize, NULL);
// Create an attributed string
CFStringRef keys[] = { kCTFontAttributeName,kCTForegroundColorAttributeName };
CFTypeRef values[] = { font,[[UIColor redColor]CGColor] };
CFDictionaryRef attr = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values,
sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// Prepare the text using a Core Text Framesetter
CFAttributedStringRef currentText = CFAttributedStringCreate(NULL, stringRef, attr);
NSAssert(currentText!=nil,@"current text is nil!");
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
//account for the view's superview
CGRect frameRect = CGRectMake(xOriginOffset+label.frame.origin.x,
yOriginOffset+label.frame.origin.y,
label.frame.size.width,
label.frame.size.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);
// Get the graphics context.
CGContextRef currentContext = UIGraphicsGetCurrentContext();
NSAssert(currentContext!=nil,@"currentContext is nil!");
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
CFRelease(frameRef);
CFRelease(stringRef);
CFRelease(framesetter);
}
更新:
我重构了代码,现在正在使用这种方法来生成功能齐全的 PDF 文本。
+(void)drawTextLabel:(UILabel*)label WithXOriginOffset:(int)xOriginOffset YOffset:(int)yOriginOffset
{
NSString* textToDraw = label.text;
UIFont* uiFont = label.font;
// Prepare font
CGRect frameRect = CGRectMake(xOriginOffset+label.frame.origin.x,
yOriginOffset+label.frame.origin.y,
label.frame.size.width,
label.frame.size.height);
[textToDraw drawInRect:frameRect withFont:uiFont lineBreakMode:UILineBreakModeTailTruncation];
}