CTLine

准备知识

字符(Character)和字形(Glyphs):排版过程中一个重要的步骤就是从字符到字形的转换,字符表示信息本身,而字形是它的图形表现形式。字符一般就是指某种编码,如Unicode编码,而字形则是这些编码对应的图片。但是他们之间不是一一对应关系,同个字符的不同字体族,不同字体大小,不同字体样式都对应了不同的字形。而由于连写(Ligatures)的存在,多个字符也会存在对应一个字形的情况。

正文

图一.png

CTLine里边可能有一个或者多个CTRun,那么CTRun是怎么划分的?

刚开始学些 Core Text 看到这张图,就单纯的以为:一个CTFrame对象对应一个自然段,一个CTLine对应一行,一个CTRun对应一个字。 错的理所当然。CTRun不是一个字,CTFrame也不是一个一篇文章中的自然段。

先看Core Text Programming Guide对于CTRun的解释:

Each CTLine object contains an array of glyph run (CTRun) objects. A glyph run 
is a set of consecutive glyphs that share the same attributes and direction. The 
typesetter creates glyph runs as it produces lines from character strings, 
attributes, and font objects. This means that a line is constructed of one or more 
glyphs runs. Glyph runs can draw themselves into a graphic context, if desired, 
although most clients have no need to interact directly with glyph runs.

中文:

每个 CTLine 对象包含一个 glyph run(CTRun) objects的数组。一个 glyph run(CTRun)对象 是一系列共享相同
 attributes 和 direction 的连贯的字形集合。当排版从字符、attributes、font objects 里生成 lines 时,
同时生成glyph runs(CTRun)。意思是一个line由一个或者更多glyphs runs(CTRun)组成。Glyph runs可以把它们自己绘制到 graphic context
上,如果你想着么做的话,然而大部分客户端不需要直接和glyph runs交互。

由上可知:每个CTLine对象包含了一个CTRun的数组,每个CTRun又包含了一个字形集合(set)
CTLine -> [CTRun]
CTRun -> [字形]
(字形的表示类在Core Graphics中定义:CGGlyph
可以通过CTRun.h里定义的方法获取CTRun对象中的字形集合:

/*!
    @function   CTRunGetGlyphs
    @abstract   Copies a range of glyphs into user-provided buffer.

    @param      run
                The run whose glyphs you wish to copy.

    @param      range
                The range of glyphs to be copied, with the entire range having a
                location of 0 and a length of CTRunGetGlyphCount. If the length
                of the range is set to 0, then the operation will continue from
                the range's start index to the end of the run.

    @param      buffer
                The buffer where the glyphs will be copied to. The buffer must be
                allocated to at least the value specified by the range's length.
*/

void CTRunGetGlyphs(
    CTRunRef run,
    CFRange range,
    CGGlyph buffer[_Nonnull] ) CT_AVAILABLE(macos(10.5), ios(3.2), watchos(2.0), tvos(9.0));

此时这个字形(CGGlyph)才能对应一个字(字符)

那么如何将一个CTLine表示的字符串划分为一个或者多个CTRun呢?

CTRun的划分

上文文档重点: the same attributes and direction

Cote Text的工作流程是:
通过 CFAttributedStringRef(NSAttributedString) 对象生成CTFramesetterRef 对象,通过CTFramesetterRef 对象生成CTFrameRef对象,CTFrameRef对象包含了CTLineRef对象,CTLineRef对象包含了CTRunRef对象

CFAttributedStringRef(NSAttributedString) 对象是数据源,可以理解为是带有字号,颜色等属性信息的字符串,NSAttributedString的可变类型NSMutableAttributedString,我们可以添加删除替换属性信息。在一个 range 范围内的子字符串的属性内容相同并且被包含在一个CTLine内,则就会划分到同一个CTRun对象中。

NSAttributedString属性被包含在一个字典中NSDictionary<NSAttributedStringKey, id>,当设置属性的时候可以指定range范围,例如设置前两个字符的颜色为红色:

[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 2)];

观察如下代码:

        NSMutableAttributedString *one = [[NSMutableAttributedString alloc] initWithString:@"Shadow"];
        NSLog(@"%@",one);
        [one addAttribute:@"123" value:@"123" range:NSMakeRange(0, 2)];
        [one addAttribute:@"456" value:@"456" range:NSMakeRange(2, 2)];
        NSLog(@"%@",one);

打印结果:

2018-10-27 18:27:34.947284+0800 TextDemo[13804:363305] Shadow{
}
2018-10-27 18:27:34.947526+0800 TextDemo[13804:363305] Sh{
    123 = 123;
}ad{
    456 = 456;
}ow{
}

可以看到不同范围内有不同的属性,在数据源NSAttributedString中要展示的字符串就会被分割成多个不同的区间,这些区间就会对应生成不同的CTRun对象。如果一个NSAttributedString对象所有字符都有相同的属性并且能在一行内展示完,那么这个NSAttributedString对象会对应生成一个CTLine对象,并且这个CTLine对象中只包含一个CTRun对象。

那么这个CTRun对象里边包含几个字形(CGGlyph)对象呢?这个就不好说了,这取决于字符串包含的字符数、字体、字号等信息。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,565评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,021评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,003评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,015评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,020评论 5 370
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,856评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,178评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,824评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,264评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,788评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,913评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,535评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,130评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,102评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,334评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,298评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,622评论 2 343

推荐阅读更多精彩内容