jow*_*wie 11 objective-c subscript nsattributedstring ipad core-text
我正在使用a NSMutableAttribtuedString来构建带有格式的字符串,然后我将其传递给Core Text以渲染到框架中.问题是,我需要使用上标和下标.除非这些字符在字体中可用(大多数字体不支持它),否则设置属性kCTSuperscriptAttributeName什么都不做.
所以我想我只留下了唯一的选择,即通过改变字体大小和移动基线来伪造它.我可以做字体大小位,但不知道改变基线的代码.有人可以帮忙吗?
谢谢!
编辑:我正在考虑,考虑到我可以用来解决这个问题的时间,编辑一个字体,以便给它一个下标"2"......或者找到一个内置的iPad字体.有没有人知道任何带有下标"2"的衬线字体我可以使用?
Tom*_*mmy 14
CTParagraphStyleSpecifiers或定义的字符串属性名称常量中没有基线设置.因此,我认为结论CoreText本身不支持文本的基线调整属性是安全的.在CTTypesetter中有一个对基线位置的引用,但我无法将其与任何能够在iPad的CoreText中的一行中改变基线的能力联系起来.
因此,您可能需要自己干预渲染过程.例如:
CTFramesetterCreateWithAttributedStringCTFramesetterCreateFrameCTFrameGetLineOrigins和CTFrameGetLines获取CTLines数组以及它们应该被绘制的位置(即,具有适当段落/换行符的文本以及所有其他字距调整/前导/其他定位文本属性应用)CTLineDraw并忘记它CTLineGetGlyphRuns获取描述线上各种字形的CTRun对象数组CTRunGetStringIndices确定运行中的源字符; 如果你想要上标或下标都不包括在内,那就用CTRunDraw它画画CTRunGetGlyphs打破单个字形的运行,并CTRunGetPositions找出它们在正常运行中的绘制位置CGContextShowGlyphsAtPoint适当地使用,在上标或下标中调整你想要的文本矩阵我还没有找到一种方法来查询字体是否具有自动上标/下标生成的相关提示,这使得事情有点棘手.如果你是绝望的并且没有解决方案,那么根本不使用CoreText的东西可能更容易 - 在这种情况下你应该定义你自己的属性(这就是为什么[NS/CF] AttributedString允许任意属性应用,由字符串名称标识)并使用常规的NSString搜索方法来识别需要在上标或下标中打印的区域.
出于性能原因,二进制搜索可能是继续搜索所有行,一行中的运行以及运行中的字形以供您感兴趣的方式.假设您有一个自定义UIView子类来绘制CoreText内容,它可能是更聪明地提前做,而不是每个drawRect :(或等效的方法,如果你使用CATiledLayer).
此外,CTRun方法的变体请求指向C数组的指针,该数组包含您要求复制的内容,可能会保存复制操作但不一定成功.查看文档.我刚刚确定我正在草拟一个可行的解决方案,而不是通过CoreText API绘制绝对最佳的路线.
这是一些基于Tommy概述的代码,可以很好地完成工作(尽管仅在单行上进行了测试)。使用设置属性字符串的基线@"MDBaselineAdjust",此代码将线绘制到offseta CGPoint。要获得上标,还可以将字体大小降低一个缺口。可能的预览:http : //cloud.mochidev.com/IfPF(读为“ [Xe] 4f 14 ...”的行)
希望这可以帮助 :)
NSAttributedString *string = ...;
CGPoint origin = ...;
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);
CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, string.length), NULL, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX), NULL);
CGPathRef path = CGPathCreateWithRect(CGRectMake(origin.x, origin.y, suggestedSize.width, suggestedSize.height), NULL);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, string.length), path, NULL);
NSArray *lines = (NSArray *)CTFrameGetLines(frame);
if (lines.count) {
CGPoint *lineOrigins = malloc(lines.count * sizeof(CGPoint));
CTFrameGetLineOrigins(frame, CFRangeMake(0, lines.count), lineOrigins);
int i = 0;
for (id aLine in lines) {
NSArray *glyphRuns = (NSArray *)CTLineGetGlyphRuns((CTLineRef)aLine);
CGFloat width = origin.x+lineOrigins[i].x-lineOrigins[0].x;
for (id run in glyphRuns) {
CFRange range = CTRunGetStringRange((CTRunRef)run);
NSDictionary *dict = [string attributesAtIndex:range.location effectiveRange:NULL];
CGFloat baselineAdjust = [[dict objectForKey:@"MDBaselineAdjust"] doubleValue];
CGContextSetTextPosition(context, width, origin.y+baselineAdjust);
CTRunDraw((CTRunRef)run, context, CFRangeMake(0, 0));
}
i++;
}
free(lineOrigins);
}
CFRelease(frame);
CGPathRelease(path);
CFRelease(framesetter);
Run Code Online (Sandbox Code Playgroud)
`
| 归档时间: |
|
| 查看次数: |
4457 次 |
| 最近记录: |