2

我知道 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];
  }
4

1 回答 1

3

1)您不能将绘制的UIKit文本与绘制的文本混合CoreText。Apple 文档中提到了这一点(请参阅“核心文本和 UIKit 框架”部分中的 iOS 文本、Web 和编辑编程)。(似乎正在发生的事情是 UIKit 会进行一些舍入并采取一些捷径来提高性能,并且默认情况下也不进行字距调整。)

2)不,你没有错过一些财产。

3) CoreText does not provide a simple means of truncating the text, you would have to write your own code to do it.

于 2012-04-13T21:34:44.350 回答