iPhone sdk:NSMutableAttributedString使用CTFramesetterCreateFrame时的错误行为

时间:2012-01-25 13:42:08

标签: iphone objective-c core-text

我正在尝试用不同颜色的部分内容绘制文字

首先发布使用以下代码:

NSMutableAttributedString *test1 = [[NSMutableAttributedString alloc] initWithString:@"fi"];

// Should color only the first character "f"
[test1 addAttribute:(id)kCTForegroundColorAttributeName value:(id)[[UIColor redColor] CGColor] range:NSMakeRange(0, 1)];

CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)test1);

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height));

CTFrameRef textFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, test1.string.length), path, NULL);

然后绘制框架:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);

CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);

// Flip the coordinate system
CGContextScaleCTM(context, 1.0, -1.0);

CTFrameDraw(textFrame, context);

CGContextRestoreGState(context);

由于某种原因,它显示“f”和“i”都用红色着色。当我将文本更改为“f1”,“f!”或其他任何其他工作正常。即使我使用“afi”和范围为(1,1),它也会将“f”和“i”都颜色,就好像它将它视为单个字符一样。

第二个问题,当绘制宽度小于文本宽度的框架内时:

NSMutableAttributedString *test2 = [[NSMutableAttributedString alloc] initWithString:@"aaaaaaaaaaaaaaaaaaaa"];

CTLineBreakMode lineBreakMode;
lineBreakMode = kCTLineBreakByTruncatingTail;

// Apply selected truncation
CTParagraphStyleSetting paragraphStyleSetting = {kCTParagraphStyleSpecifierLineBreakMode, sizeof(CTLineBreakMode), &lineBreakMode};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(&paragraphStyleSetting, 1);
[test1 addAttribute:(NSString *)kCTParagraphStyleAttributeName value:(__bridge id)paragraphStyle range:NSMakeRange(0, test2.string.length)];
[test1 addAttribute:(id)kCTForegroundColorAttributeName value:(id)[[UIColor redColor] CGColor] range:NSMakeRange(7, 16)];

CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)test2);

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height));

CTFrameRef textFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, test1.string.length), path, NULL);

共有20个字符, 索引7到16的那些看起来是红色的颜色(因为它们应该),CoreText根据我的要求添加了一个截断标记,但问题是它也是红色的,我希望它保持黑色(因为剩下的截断字符颜色是黑色)。

我做了一些研究,似乎在通过命令中的某些(随机/字体特定?)值增加帧大小时:

CGPathAddRect(path, NULL, CGRectMake(0, 0, self.frame.size.width + 10.0f, self.frame.size.height));

它使截断标记保持黑色,但由于额外的空间,有时会截断标记

2 个答案:

答案 0 :(得分:2)

NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:@"firstsecondthird"];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,5)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(5,6)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(11,5)];

答案 1 :(得分:0)

这听起来像ligatures的问题。对于某些看起来比单个字符更好的字符组合,好的字体有特殊字符。例如,在许多字体To中,如果单独渲染,则效果不佳,因为T的垂直条与o的开头之间有很多空格。因此提供了具有更吸引人的间距的连字。有时字符甚至可以连接,您的fi就是一个很好的例子:某些字体提供了一个连字,使f的顶部加倍为i的点。

因此,您可能需要关闭连字,但将属性kCTLigatureAttributeName设置为0。