zoukankan      html  css  js  c++  java
  • Core Text

    文档版本

    • 2015-02-16 - 创建文档

    本文结构

    摘要:本文讲述Core Text基础概念,然后实现一个显示文本的样例程序,并指出代码中容易出现问题地方。

    ** 关键字:iOS8 Xcode6 Core Text 入门教程 排版概念 仿射**

    背景

    我们有一个不上架的阅读项目,同事用UIWebView展示HTML,最近我想使用Core Text重新实现。之前没接触Core Text,只能边学边用。学习过程中参考了不少资料,多数资料写于2013年,相同的代码在Xcode 6.1.1、iOS 8.1中无法得出原作者一致的效果。几经折腾,现在分享学习成果,故有了本系列博客。

    编程环境:OS X Yosemite 10.10.2,Xcode 6.1.1
    运行环境:iOS 8.1.3

    Core Text的框架位置

    Core Text的框架位置

    从图片可知,Core Text位于UIKit和Core Graphics/Quartz之间:

    • 使用UIKit可简单拖拽将文本显示在UILabel上,但无法单独控制文本中每个字的颜色。GitHub有个代替UILabel的项目:TTTAttributedLabel,可支持链接植入等功能。
    • 使用Core Graphics/Quartz,可做到系统能够做到的一切,但需要计算文本每个字符绘制在屏幕上的坐标。
    • Core Text恰巧位于二者之间,可完全控制文字的位置、布局以及颜色大小等属性,同时Core Text简化了一些工作——例如从文本换行到字体的渲染。

    排版基础

    Core Text主要用来对文本进行排版布局和字体处理,故需了解字符(Character)、字形(Glyph)和字体(Font)等概念。

    • 字体(Character):一个符号,数字或者文字等。
    • 字形(Glyph):对于同一套字符有不同的写法,形态或样式。字形是字符的一族形态,例如Helvetica,New Roman。
    • 字体(Font):在字形的基础上进行的加工修饰便构成了字体,如加粗,倾斜,加颜色,改变磅数等。例如
      9pt Helvetica Bold是一个字体。

    Core Text基础数据类型

    Core Text的编码流程完全按照Text Layout数据流进行,因此熟悉Text Layout数据流非常重要。

    Text Layout数据流

    • CFAttributedString:属性字符串或称特性字符串,即是格式化的字符串,可包含字体、前景色、下划线、段落等排版信息。
    • CTFramesetter(CTFramesetterRef):通过CFAttributedString进行初始化,它作为CTFrame对象的生产工厂,负责根据path生产对应的CTFrame。
    • CTTypesetter:自动生成,无需处理。
    • CGPath:用于指示绘制区域
    • CTFrame(CTFrameRef):通过CTFrameDraw函数直接绘制到context上,可在绘制前,操作CTFrame中的CTLine进行微调。
    • CTLine(CTLineRef)为Core Text绘制中的一行的对象,通过它可以获得当前行的line ascent,line descent,line leading,还可以获得Line下的所有Glyph Runs。
    • CTRun或称Glyph Run,是一组共享相同特性(attributes)的字形集合

    有关字体、段落信息,后续博客再作讲解,一次全交代略显复杂,分步走平缓学习曲线。

    例子:显示普通文本

    现在,根据Text Layout数据流编写一个简单的程序。此程序通过重载UIView的 -drawRect: 方法在屏幕上显示一串不带格式的文本,带格式及段落样式和图文混排的做法会在后续博客讲解。先从基础开始。

    1 创建一个Single View Application应用。
    2 由于Core Text需要使用CGContext,故添加一个UIView的子类,命名为SimpleCoreTextView。
    3 在Storyboard中指定默认UIViewController的UIView的Class为SimpleCoreTextView。
    4 重载SimpleCoreTextView的 -drawRect: 方法,加入如下代码,外加引入头文件 #import <CoreText/CoreText.h>

    // 1 带属性的字符串,由此开始Core Text后续操作
    NSAttributedString *contentString = [[NSAttributedString alloc] initWithString:@"你好,Core Text!"];
    // 2 由1创建CTFramesetter,在Core Text中用CTFramesetterRef类型表示
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge void*)contentString);
    // 3 创建用于Core Text绘制的图形上下文可变路径并添加整个屏幕范围作为其绘制区域,由CGMutablePathRef类型表示
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, self.bounds);
    // 4 获取图形上下文,由CGContextRef类型表示
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 5 添加路径到图形上下文中
    CGContextAddPath(ctx, path);
    // 6 由CTFramesetter创建CTFrame,由CTFrameRef类型表示
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, contentString.length), path, NULL);
    // 7 设置每个字形(Glyph)不参与当前变换矩阵(Current Transformation Matrix)
    CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
    // 8 将Core Text绘图原点从左下角上升至左上角,与UIView一致,即是把y轴平移一个屏幕高度,因为当前绘制的区域为整个屏幕。多余的40点使文字超出屏幕顶部40点,在下一步倒转y轴朝向后将在(0,40)位置显示文本内容。
    CGContextTranslateCTM(ctx, 0, self.bounds.size.height + 40);
    // 9 沿x轴翻转y轴,使之向下增长,与UIView坐标轴朝向一致,1.0表示不变,-1.0表示反方向
    CGContextScaleCTM(ctx, 1.0, -1.0);
    // 10 绘制内容
    CTFrameDraw(frame, ctx);
    // 11 释放资源
    CFRelease(framesetter);
    CFRelease(frame);
    CFRelease(path);
    

    如果不添加7~9行,则绘制了的文本将出现在屏幕左下角,这是由于Core Text坐标系与UIView的坐标系不同所致,故需转换。

    由于使用Core Foundation的数据结构,所有后缀为Ref的数据类型,若通过Create或Copy结尾的函数获得,则必须在使用结束时进行释放,否则造成内存泄露。

    运行结果
    运行结果
    示例代码托管在GitHub

    参考

    1. CoreText学习(一)Base Objects of Core Text
    2. how-to-create-a-simple-magazine-app-with-core-text
    3. Core Text入门
  • 相关阅读:
    设计模式之六大设计原则学习笔记
    java多线程学习笔记
    mac上安装mongodb数据库教程
    在mac下使用终端命令通过ssh协议连接远程linux系统,代替windows的putty
    从request对象中获取请求json格式的参数
    @Conditional注释
    lambda 根据实体类的拼音排序
    PHP一行代码获取时间戳
    PHP导出生成Excel文件
    Mysql merge引擎介绍
  • 原文地址:https://www.cnblogs.com/michaellfx/p/2015-2-16-Core-Text.html
Copyright © 2011-2022 走看看