将CATextLayer与CGContext一起使用

时间:2012-01-23 07:42:15

标签: iphone ios cgcontext core-text catextlayer

我需要将文本绘制到CGContext中,并希望使用CATextLayer来设置文本。任何人都可以给我一些关于它将如何完成的步骤。我已经为它编写了一些代码,但不知道它的正确性(因为我是iPhone开发的新手)。

一些基本问题: 1.如何获取用于设置CATextLayer帧的文本的位置和大小 2.文本以某种方式反转出来,我已经使用CGAffineTransform修复了它,但它是一个hacky修复,我想知道文本反转出来的实际原因。 3.我还需要设置我正在使用NSAttributedString的文本边框宽度和颜色,但设置文本大小(增加或减少)不会反映在屏幕上。

编辑1:

我已根据您的建议更新了代码,但即使在使用CTFontRef后文本也没有调整大小。此外,在iPhone上,文字从顶部稍微被截断。知道什么设置不正确吗?当我检查我从getTypographicBounds获得的值时,它们都是0(origin.x,origin.y,width和height)。

getTypographicBounds方法:

width = CTLineGetTypographicBounds(m_line, &ascent, &descent, &leading);

// Return text bounds
return CGRectMake(0, 0, width, ascent + descent);

修改后的代码:

CATextLayer*    text      = [[CATextLayer alloc] init];
CGColorSpaceRef rgbColor  = CGColorSpaceCreateDeviceRGB();
CGColorRef rgb            = CGColorCreate(rgbColor, m_fill_color);
text.foregroundColor      = rgb;
text.frame                = CGRectMake([self getTypographicBounds].origin.x, [self getTypographicBounds].origin.y, [self getTypographicBounds].size.width + 2*m_padding, [self getTypographicBounds].size.height + 2*m_padding);
text.wrapped              = YES;

    NSMutableDictionary *stringAttributes = [NSMutableDictionary dictionary];

    CTFontRef aCFFont = CTFontCreateWithName ((CFStringRef)m_font_name, 30.0, NULL);

    // Set a negative width so we get both stroke and fill to show
    [stringAttributes setObject: (NSObject*)aCFFont forKey: (id)kCTFontNameAttribute];
    [stringAttributes setObject: [NSNumber numberWithFloat: -3 ] forKey: (id)kCTStrokeWidthAttributeName];
    [stringAttributes setObject: [UIColor whiteColor] forKey: (id)kCTStrokeColorAttributeName];

    NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:m_text
                                                                       attributes:stringAttributes];

    text.string = (NSString*)stringToDraw;
    [text drawInContext:ctx];

编辑2:wiki示例使用CTLine,我正在使用CATextLayer。 Reason :: CATextLayer允许我在运行时修改文本以显示中文,日文,印地文,俄文和所有具有不同脚本的语言。此外,CATextLayer似乎比CoreText更清晰地呈现。

我现在面临的问题是[text drawInContext:ctx]行显示的文本是从顶部截断的。我检查了框架和文本字体大小。字体大小是16像素,帧高是17.768,所以我不知道为什么它会截断。

// Ensure CTLine is up-to-date
if (m_is_dirty)
    [self recomputeLine];

// Get text metrics
CGFloat width;
CGFloat ascent;
CGFloat descent;
CGFloat leading;

width = CTLineGetTypographicBounds(m_line, &ascent, &descent, &leading);

// Position text so that top of text aligns with top of layer
CGContextSetTextMatrix(ctx, CGAffineTransformIdentity );

// Setup text drawing style
CGContextSetRGBFillColor   (ctx, m_fill_color  [0], m_fill_color  [1], m_fill_color  [2], 1.0);
CGContextSetRGBStrokeColor (ctx, m_stroke_color[0], m_stroke_color[1], m_stroke_color[2], 1.0);
CGContextSetFont           (ctx, m_font        );
CGContextSetFontSize       (ctx, m_font_size   );
CGContextSetLineWidth      (ctx, m_stroke_width);

CATextLayer*    text      = [[CATextLayer alloc] init];
CGColorSpaceRef rgbColor  = CGColorSpaceCreateDeviceRGB();
CGColorRef rgb            = CGColorCreate(rgbColor, m_fill_color);
text.foregroundColor      = rgb;
text.fontSize = m_font_size;
text.font = m_font;
text.frame                = CGRectMake([self getTypographicBounds].origin.x, [self getTypographicBounds].origin.y, [self getTypographicBounds].size.width, [self getTypographicBounds].size.height);
text.wrapped              = YES;

NSMutableDictionary *stringAttributes = [NSMutableDictionary dictionary];


// Set a negative width so we get both stroke and fill to show
[stringAttributes setObject: [UIFont fontWithName:m_font_name size:m_font_size] forKey: (id)kCTFontNameAttribute];
[stringAttributes setObject: [NSNumber numberWithFloat: -3 ] forKey: (id)kCTStrokeWidthAttributeName];
[stringAttributes setObject: [UIColor whiteColor] forKey: (id)kCTStrokeColorAttributeName];

NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:m_text
                                                                       attributes:stringAttributes];

text.string = (NSString*)stringToDraw;        
[text drawInContext:ctx];

提前致谢

尼克

1 个答案:

答案 0 :(得分:1)

这是因为用于CGContexts的翻转坐标空间。有关完整说明(使用图表),请参阅here

编辑: 要在绘制文本之前控制位置翻译您的上下文:

CGContextTranslateCTM(context, x, y);

编辑2:

看起来你需要使用CTFontRef,而不是UIFont。有关示例,请参阅here(请参阅Gordon Apple于2010年6月23日星期五10:40:23发布的帖子)。

编辑3:

除非你特别需要使用NSAttributedString,否则我建议使用更简单的NSString drawInRect:withFont:lineBreakMode:alignment:method。它为您创建了CATextLayer,但使用起来更简单:

    UIFont *font = [UIFont fontWithName:m_font_name size:30.f];
    [m_text drawInRect:text.frame  withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];

编辑4:

尝试像这样设置字典:

    CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)fontName, pointSize,NULL);
    CGColorRef color = textColor.CGColor;

    NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (__bridge id)ctFont, (id)kCTFontAttributeName,
                                    color, (id)kCTForegroundColorAttributeName,nil];