CoreText学习(一)Base Objects of Core Text
最近要做一个读入Word,PDF格式等的文件并且加以编辑的程序,本来以为使用Text Kit结合Text View来打开doc文件是完全没问题的,结果用了各种方法打开要么是数据是nil,要么打开的文字中很多乱码。对于Word,PDF这种格式或许必须要用底层的Core Text来做了(如果用WebView来做的话,很难对内容进行操作)。
所以接下来又要从Core Text从头学起了。首先看了Core Text Programming Guide,理解的并不算深入,但是写个博客来做个笔记吧。
Core Text是一个iOS中一个比较底层的框架,借用iOS7 Text Kit介绍视频中的一个图:
其中Core Text在Core Graphics之上,Text Kit在Core Text之上构建(UIWebView不在Text Kit之上,很多Text Kit中很棒的特性UIWebView无法使用)。
在文档中,Core Text被描述为一个高级的、底层的框架,主要用来对文本进行排版布局和字体处理。
Core Text有一个很强大的功能就是进行Character-to-glyph转换,其实之前看Text Kit的时候glyph这个词就是一个高频出现的词,个人觉得必须要分清楚character,glyph,font这些概念之间的分别。
按照个人的理解(语文不好,说错了请指出):
(1)character:字符,指一个符号,数字或者文字等。
(2)glyph:字形,对于同一套字符有不同的写法,形态或者说是样式。字形是字符的一族形态,例如Helvetica, New Roman
(3)font:字体,在字形的基础上进行的加工修饰便构成了字体,如加粗,倾斜,加颜色,改变磅数等。例如
9pt Helvetica Bold是一个字体。
回到文档来看看Character-to-glyph conversion:
对应同一个字符A,有着各种不同的形态,对应不同的字形glyph,当然同一种风格的写法便构成了一种字形。
同样地,对于f加l两个字符连起来写便又变成了一种新的写法,对应另外一种字形。
通过Core Text可以快速高效地进行字符到字形之间的转换。
使用Core Text可以直接使用Core Foundation的对象,这些对象是toll-free bridging的(一种允许某些OC类与其对应的CoreFoundation类之间可以互换使用的机制),所以无需进行特殊的对象类型转换。另外Core Text构建于Core Graphics框架之上,所以可以通过Core Graphics的方法进行高效高质量的文字描画。
接下来是Core Text的一些Base Objects。
1.Layout Objects:Framesetters, Frames, Typesetters, Lines and Glyph runs
还是先上个图吧:
其中framesetter通过attributed string对象持有文本的内容,并调用typesetter来创建line对象从而填满由CGPath所描述的区域。输出的结果是包含了一系列行对象的一个frame。
其中每一个line中对于相同属性内的一段文字使用同一个的CTRun对象去描画该段文字:
下面这张图(来自raywenderlich)更加容易理解:
其中CTRun对象会由Core Text自动生成,不需要也不应该由开发者自己去创建,所以整个程序跑起来有很多细节是开发者不用考虑的。
2.Font Objects:Fonts, Font Descriptors, Font Collections
Font Descriptor用来描述字体的特性,是Font的核心部分,Font Collections是许多个Font Descriptors的集合。
说完一大堆Core Text的基本对象后,还是写个Demo看看(主要参考了http://blog.csdn.net/andypan1314/article/details/7614469)
首先要使用Core Text框架的话,第一步是要导入CoreText.framework,然后在要使用的头文件中导入:
#import <CoreText/CoreText.h>
在使用Core Text来draw文字的时候,关键是要使用UIView中的drawRect:方法,所以先新建一个ViewController,然后新建一个UIView的子类,并将二者在视图上关联起来。
然后重写View中的drawRect:方法:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect]; // 1.创建一个字符串用来保存文本内容 CFAttributedString
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"First Core Text Demo"]; // 2.创建一个framesetter用来管理描画文字的frame CTFramesetter
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString); // 3.创建一个用来描画文字的路径,其区域为当前视图的bounds CGPath
CGMutablePathRef path = CGPathCreateMutable();
CGRect rectForPath = CGRectMake(0.0, 0.0, self.bounds.size.width, self.bounds.size.height - 20.0);
CGPathAddRect(path, NULL, rectForPath); // 4.创建由framesetter管理的frame,是描画文字的一个视图范围 CTFrame
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, attrString.length), path, NULL); // 5.获取当前视图的上下文环境
CGContextRef context = UIGraphicsGetCurrentContext(); // 6.通过context在frame中描画文字内容
CTFrameDraw(frame, context); // 7.所有创建的对象必须被release
CFRelease(frame);
CFRelease(path);
CFRelease(frameSetter);
}
以上代码中各个对象的创建顺序基本与Figure 1.3相同。
其中首先对NSAttributedString强制类型转换得到CFAtttributedString对象用来保存文本内容,然后创建一个CTFramesetter对象用来保存文本内容、在所管理的Frame中对文字进行布局、输出文字等,接着创建CGPath对象和CTFrame对象,二者定义了一个输出文字内容的区域。注意CTTypesetter在CTFramesetter创建时随之而生成了,不需要再手动去创建。
在基本对象创建好后,获取当前视图上下文并设置好一些仿射变换后,直接在Frame中draw就完成了文字的输出:
注意最后所有创建的Core Foundation对象都必须被释放。
还有一个大问题,draw出来的文字是倒过来的,必须要将它们倒回来。
这就涉及到仿射变换的内容了,有篇文章挺好理解的:http://hi.baidu.com/cqhg1981/item/1a527bf4bda2fb0fc6dc45aa
主要的仿射变换有下面几种:
其中translation是平移,flip是翻转,rotation是旋转,scaling是缩放,shear是错切,identity是保持不变。
再看看基本的仿射变换代码:
// 平移仿射变换:tx为x正方向上的位移量,ty为y正方向上的位移量
CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty) // 缩放仿射变换:在原点的基础上进行缩放,sx为x正方向上的缩放倍数,sy为y正方向上的缩放倍数。如果缩放倍数为负数则为反向缩放
CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy); // 旋转仿射变换:angle为旋转角度,逆时针为正,顺时针为负
CGContextRotateCTM(CGContextRef c, CGFloat angle);
在CGContextRef context =UIGraphicsGetCurrentContext();下面加上以下代码。
首先设置好初始的仿射变换矩阵(原封不动):
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
然后将整个视图向右移动10.0,向下方移动整个视图的高度:
CGContextTranslateCTM(context, 10.0, self.bounds.size.height);
最后倒过来(方向放大):
CGContextScaleCTM(context, 1.0, -1.0);
Run一下:
完成了。
Core Text还有很多内容,随着我学习的深入会继续更新博客的。
CoreText学习(一)Base Objects of Core Text的更多相关文章
- 基于Core Text实现的TXT电子书阅读器
本篇文章的项目地址基于Core Text实现的TXT电子书阅读器. 最近花了一点时间学习了iOS的底层文字处理的框架Core Text.在网上也参考很多资料,具体的资料在文章最后列了出来,有兴趣的可参 ...
- CoreText学习(二)之Hello world
最后更新:2017-08-10 部分内容丢失,后续补上 相关配置: Xcode 8.3.3 Swift 3.0 macOS Sierra 一.CoreText 简介 CoreText 是用于处理文字和 ...
- IOS利用Core Text对文字进行排版 - 转
原贴地址:http://hi.baidu.com/jwq359699768/blog/item/5df305c893413d0a7e3e6f7b.html core text 这个包默认是没有的,要自 ...
- Core Text 入门
本文所涉及的代码你可以在这里下载到 https://github.com/kejinlu/CTTest,包含两个项目,一个Mac的NSTextView的测试项目,一个iOS的Core Text的测试项 ...
- Core Text概述
本文是我翻译的苹果官方文档<Core Text Overview> Core Text框架是高级的底层文字布局和处理字体的技术.它在Mac OS X v10.5 and iOS 3.2开始 ...
- Core Text
Core Text 本文所涉及的代码你可以在这里下载到 https://github.com/kejinlu/CTTest,包含两个项目,一个Mac的NSTextView的测试项目,一个iOS的Cor ...
- [翻译] Core Text Objective-C Wrapper
Core Text Objective-C Wrapper https://github.com/akosma/CoreTextWrapper Introduction(介绍) One of the ...
- 学习笔记之C# / .NET Core 2.0
C# 教程 | 菜鸟教程 http://www.runoob.com/csharp/csharp-tutorial.html .NET API Browser | Microsoft Docs htt ...
- Docker学习笔记之-部署.Net Core 3.1项目到Docker容器,并使用Nginx反向代理(CentOS7)(一)
上一节演示如何安装Docker,链接:Docker学习笔记之-在CentOS中安装Docker 本节演示 将.net core 3.1 部署到docker容器当中,并使用 Nginx反向代理,部署平台 ...
随机推荐
- Windows下用C语言获取进程cpu使用率,内存使用,IO情况
#ifndef PROCESS_STAT_H #define PROCESS_STAT_H #ifdef __cplusplus extern “C” { #endif typedef l ...
- [转] 深入剖析 linux GCC 4.4 的 STL string
本文通过研究STL源码来剖析C++中标准模板块库std::string运行机理,重点研究了其中的引用计数和Copy-On-Write技术. 平台:x86_64-redhat-linux gcc ver ...
- 查看linux系统版本
1.查看内核版本 #cat /proc/version Linux version 2.6.18-164.el5 (mockbuild@x86-003.build.bos.redhat.com) (g ...
- 阿里云ECS安全改造:改用AWS EC2私钥方式登录
阿里云ECS有多烂,用过AWS的人都知道,ECS有什么问题呢,简单总结一下: 1)ubuntu居然root直接访问 2)端口全开 3)WEB控制台无法定义安全组及关闭端口 4)云盾黑洞 的确用起来很糟 ...
- Android Studio 简介
Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,Google的更新速度也很快,明显能感觉到这是Android开发 ...
- vs连接mysql
1.打开vs2012在aspx中添加一个Grid view 控件,,. 2,选择新建数据源. 3,选择数据库. 4,选择新建连接. 5,更改成mysql连接. 6,这里的Server name 是你自 ...
- Examples_07_06 无法下载android的sdk
在hosts里面配置. 74.125.237.1 dl-ssl.google.com 在AndroidManifest.xml中添加 <uses-feature android:name=&qu ...
- 使用三层交换机的ACL实现不同vlan间的隔离
使用三层交换机的ACL实现不同vlan间的隔离 建立三个vlan vlan10 vlan20 vlan30 www.2cto.com PC1 PC3属于vlan10 PC2 PC4属于v ...
- STL 之 空间配置器(allocator)
一.SGI 标准的空间配置器,std::allocator SGI也定义了一个符合部分标准,名为allocator的配置器,但是它自己不使用,也不建议我们使用,主要原因是效率不佳. 它只是把C++的操 ...
- 利用 Makefile 写的小程序
1.建立一个工程 2.写一个进度条的程序(原理就是在同一位置重复打印某一个字符(变化),达到动态显示的效果) 所以说我们这里只用回车'\r',覆盖这一行以前的输出,重新向缓冲区写数据刷新缓冲区,就能达 ...