【问题标题】:Use CATextLayer with CGContext将 CATextLayer 与 CGContext 一起使用
【发布时间】:2012-01-23 07:42:14
【问题描述】:

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

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

编辑 1:

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

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。原因 :: CATextLayer 允许我在运行时修改文本以显示中文、日文、印地文、俄文和所有具有不同脚本的语言。此外,CATextLayer 的渲染似乎比 CoreText 更清晰。

我现在面临的问题是 [text drawInContext:ctx] 行显示的文本从顶部截断。我检查了框架和文本字体大小。字体大小为 16 px,帧高为 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];

提前致谢

尼克

【问题讨论】:

    标签: iphone ios cgcontext core-text catextlayer


    【解决方案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: 方法。它为您创建了一个 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];
    

    【讨论】:

    • 酷。现在坐标空间是完美的。但仍然无法根据 NSAttributedString 中设置的属性或为 CATextLayer 设置 .fontSize 属性来调整 CATextLayer 的大小。
    • 我编辑显示如何控制位置。至于大小,我不明白有什么问题。字体是否正确?它的尺寸是多少,您要制作多大的尺寸?
    • 是正确的字体还是字体也被忽略了?由于我提供的那个 URL 似乎有效,我会尝试按照它的方式实现它。
    • 字体被忽略。不知道怎么样。 :( 代码行 :: CTFontRef aCFFont = CTFontCreateWithName (CFSTR("Baskerville"),30, NULL);
    • 我需要 NSAttributedString,因为我正在设置文本的边框宽度和颜色,例如这里 :: stackoverflow.com/questions/8702740/… 我正在使用此代码逐字逐句地绘制整个段落text 无法在除英文(如中文、日文、印地文等)之外的脚本中绘制文本,因此使用 CATextLayer 而不是 CTLine。
    猜你喜欢
    • 2010-12-26
    • 1970-01-01
    • 2011-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    相关资源
    最近更新 更多