Core Text 编程指南官方文档笔记 Core Text Programming Guide
关于Core Text
Core Text 是一个高级,底层的布局文字和处理字体的技术。布局文字指通过字符编码和字体数据生成字形,然后在graph runs里控制他们的位置。他让graph runs在line中排列,然后把lines排列进multiline frames(比如一段文字)。Core Text 还提供字形和布局相关的数据,如字形位置和线条和框架的度量。它处理字符属性和段落样式,包括各种类型的标签样式和定位。
Core Text API提供了关于fonts, font collections, font descriptors,便捷的访问font 数据。
Core Text 概览 Core Text Overview
Core Text在高级框架提供的文本布局和字体支持与Quartz提供给所有文本和字体框架的低级功能之间起中介作用。 Quartz框架负责对形及其位置起作用。Core Text了解字符如何映射到字体,在调用Quartz来呈现文本之前,它会考虑有关样式、字体度量和其他属性的信息。 Quartz是在基本级别上绘制字形的唯一方法,并且由于Core Text提供了Quartz可直接使用的所有数据,因此结果就是高性能的文本渲染。
多线程:Core Text 的函数可以被多线程同时调用,前提是客户机不会突然改变任何参数,比如:线程之间共享的属性字符串。
Core Text是基于C语言的,跨平台API Core Text Is a C-based, Platform-Neutral API
虽然OS X版本提供了更丰富的字体管理API,包括可变字体集合,但iOS和OS X上的Core Text API几乎完全相同。但在平台之间移植代码时,必须考虑UIKit和AppKit之间的差异。例如,您必须有一个Quartz 的 graphics context来呈现Core Text生成的字形,并且您在每个平台上获得不同的graphics context。您在iOS中绘制的视图是iOS中的UIView子类,在OS X中是NSView子类。您应该知道,将CGRect对象传递给UIView drawRect:方法,而将drawRect:的OS X版本传递NSRect对象。 (您可以使用OS X中的NSRectToCGRect函数将传入的NSRect对象转换为作为核心文本函数参数所需的CGRect对象。)
由UIView函数UIGraphicsGetCurrentContext返回的graphics context相对于未修改的Quartzgraphics context(也就是UIView返回的上下文的起点位于左上角)翻转,因此您必须重新翻转iOS中的图形上下文但不在OS X中。
核心文本尽可能使用系统数据类型和服务,并且您在OS X和iOS中使用与其他核心框架相同的约定。例如,Core Text为许多输入和输出参数使用Core Foundation对象,因此可以将它们存储在Core Foundation集合类中。由Core Text处理的其他对象(如CGPath对象)由Core Graphics框架提供。
关于Core Text不透明类型 Core Text Opaque Types
Core Text的布局引擎和attributed strings (CFAttributedStringRef)、graphics path(CGPathRef)协同工作。一个attributed string 对象封装了一个代表了显示文字的字符串,还有定义了字符串风格方面的对象——比如font,color。Core Text的排版机制使用attributed string里的信息执行字符—字形转换。
graphics path定义文字frame的形状。path可以不仅仅是矩形。
CFAttributedString 引用类型,CFAttributedStringRef,和NSAttributedString toll-free。意味着Core Foundation 类型在 桥接的 Foundation 对象里是可以互换的。因此,在一个你看见NSAttributedString * 参数的方法里,你可以传入CFAttributedStringRef。同样的,在一个 你看到的CFAttributedStringRef 的方法参数里,你可以传入NSAttributedString 的实例(你可能需要转化一种类型到另一种来解决编译器警告)。这个模式对NSAttributedString的子类也适用。
Attributes 是 kay-value pairs,定了字符串中字符的特征,Attributes被分组在共享相同属性的range内。属性本身被传递给属性字符串,并使用CFDictionary对象从属性中检索。要将样式style应用于graph run(CTRun对象),创建一个CFDictionary对象以保存要应用的属性,然后创建一个属性字符串,并将该字典作为参数传递。 或者,您可以将属性应用于已存在的CFMutableAttributedString对象。 尽管CFDictionaryRef和NSDictionary是toll-free的,但存储在字典中的单个属性对象可能不是。
运行时的Core Text对象形成一个层次结构,如图所示。这个层次结构的顶部是framesetter对象(CTFramesetterRef)。使用attributed strings(CFAttributedStringRef)和graphic path(CGPathRef)作为输入,frame setter会生成一个或多个text frame(CTFrameRef)。每个CTFrame对象都代表一个段落。
为了生成 frames,framessetter 调用一个 typesetter对象(CGTypesetterRef)对象。当这个typesetter 布局文字到一个frame时,framesetter 在上面应用段落风格,包括诸如alignment, tab stops, line spacing, indentation, and line-breaking mode等属性。typesetter 转换attributed strings里的字符为字形,排列这些字形到CFLines,填充一个frame。
每个CTFrame对象都包含段落的行(CTLine)对象。 每一行对象代表一行文本。 一个CTFrame对象可能只包含一个长的CTLine对象,或者它可能包含一组行。 Line 对象是在排版操作过程中由typesetter创建的,并且与frame一样,可以直接将其自身绘制到graphics context中。
每个CTLine对象都包含一个graph runs(CTRun)对象数组。 graph runs是一组具有相同属性和方向的连续字形。typesetter在字符串、属性和字体对象生成line时创建graph runs。 这意味着一个line是由一个或多个graph runs构成的。 如果需要,graph runs可以将自己绘制到graphics context中,但大多数客户端不需要直接与graph runs进行交互。
字体对象Font Objects
字体提供了布局字形的帮助(一个接另一个),并用于在绘制graphics context时创建当前字体。 Core Text font不透明类型CTFont是封装大量信息的特定字体实例。它的引用类型CTFontRef与iOS中的UIFont和OS X中的NSFont桥接在一起。创建CTFont对象时,通常指定(或使用默认)point size和transformation matrix,该matrix为字体实例提供了特定的特征。然后,您可以查询字体对象以获取有关特定点大小字体的各种信息,如字符到字形的映射,编码,字体度量标准数据和字形数据等等。字体指标是诸如ascent, descent, leading, cap height, x-height等参数。字形数据包括bounding rectangles and glyph advances等参数。
Core Text字体对象是不可变的immutable,所以它们可以同时被多个operation,work queue或线程使用。有很多方法可以创建字体对象。首选方法来自使用CTFontCreateWithFontDescriptor的font descriptor。您也可以使用许多转换API,具体取决于您必须从什么开始。例如,可以使用字体的PostScript名称(CTFontCreateWithName)或Core Graphics字体引用(CTFontCreateWithGraphicsFont)。还有CTFontCreateUIFontForLanguage,它为您正在使用的本地化中的应用程序创建用户界面字体的参考。
Core Text font references 提供了一种复杂的,自动的字体替换机制,称为字体级联(font cascading),它可以在考虑字体特征的同时选择合适的字体来替代丢失的字体。字体级联基于级联列表,它是有序font descriptor 的array。系统有默认级联列表(基于用户的语言设置和当前字体呈多态),系统也会在字体创建时指定字体级联列表。使用font descriptor 中的信息,级联机制可以根据样式以及匹配字符匹配字体。 CTFontCreateForString函数使用级联列表来选择合适的字体来编码给定的字符串。要指定和检索字体级联列表,请使用kCTFontCascadeListAttribute属性。
Font descriptors
由CTFontDescriptor不透明类型表示的Font descriptor提供了一种机制,用于完全从attribute字典中描述字体,以及用于构建新字体的易于使用的字体匹配工具。您可以使用Font descriptors创建字体对象,您可以从字体对象获取Font descriptor,然后可以更改Font descriptor并使用它来制作新的字体对象。您可以通过创建Font descriptors来部分描述字体,例如仅使用系列名称或权重,然后可以查找系统中与给定特征匹配的所有字体。 CTFontDescriptorRef类型toll-free到iOS中的UIFontDescriptor和OS X中的NSFontDescriptor。
相对于处理复杂的转换矩阵,你可以创建一个字体属性字典,将字体属性包括PostScript名称,字体系列和样式以及特性(例如,粗体或斜体)作为CTFontDescriptor对象。您可以使用Font descriptor来创建一个CTFont对象。Font descriptor可以被序列化并存储在一个文档中以提供字体的持久性。如图,显示了使用Font descriptor创建特定字体实例的字体系统。
您可以将Font descriptor视为对字体系统的查询。您可以使用不完整的规范创建Font descriptor,即属性字典中只包含一个或几个值,系统将从可用的字体中选择最合适的字体。例如,如果指定Font descriptor为standard faces (normal, bold, italic, bold italic), 使用此Font descriptor进行查询,则不指定任何特征将匹配font family中的所有特性。但如果指定特征字典使用kCTFontTraitBold的kCTFontTraitsAttribute,结果从整个font family进一步缩小到满足bold trait的成员。系统可以通过CTFontDescriptorCreateMatchingFontDescriptors为您提供与您的查询匹配的Font descriptor的完整列表。
在iOS 6.0和更高版本中,应用程序可以根据需要下载可用字体(未使用CTFontDescriptorMatchFontDescriptorsWithProgressHandler函数安装的)。以这种方式下载的字体不会永久安装,并且系统可能会在某些情况下将其删除。可供下载的字体在iOS 6中以““Additional Information”列出。 DownloadFont(在iOS开发者库中)演示了下载技术。在OS X中按需下载字体是不必要的,因为所有可用的字体都随系统一起安装。
Font Collections
字体集合是作为单个对象采用的一组Font descriptors。 字体集合由CTFontCollection不透明类型表示。 字体集合提供了字体枚举,访问全局和自定义字体集合以及访问构成集合的Font descriptors的功能。 例如,您可以通过调用CTFontCollectionCreateFromAvailableFonts创建系统中所有可用字体的字体集合,并且可以使用该集合来获取所有成员字体描述符的数组。