Core Text 学习笔记-基础
前言
最近在学习YYKit框架,看到关于CoreText相关的知识的时候感到非常吃力,于是乎就恶补了一下Core Text相关的基础知识。
Glyphs(字形)
- 字符的图形形式, 则是文字中字母 (character) 的视觉表现。
- (字形)Glyphs = 字符(Character)+ 字体(font)字符通过字体(map)找到字形
OC中的表现形式: 字形 CGGlyph 字体 UIFont/CTFont 字符 unichar
字形描述集(Glyphs Metris):即字形的各个参数。如下面的两张图:
边框(Bounding Box):一个假想的边框,尽可能地容纳整个字形。
基线(Baseline):一条假想的参照线,以此为基础进行字形的渲染。一般来说是一条横线。
基础原点(Origin):基线上最左侧的点。
行间距(Leading):行与行之间的间距。
字间距(Kerning):字与字之间的距离,为了排版的美观,并不是所有的字形之间的距离都是一致的,但是这个基本步影响到我们的文字排版。
上行高度(Ascent)和下行高度(Decent):一个字形最高点和最低点到基线的距离,前者为正数,而后者为负数。当同一行内有不同字体的文字时,就取最大值作为相应的值。如下图,
红框高度既为当前行的行高,绿线为baseline,绿色到红框上部分为当前行的最大Ascent,绿线到黄线为当前行的最大Desent,而黄框的高即为行间距。由此可以得出:lineHeight = Ascent + |Decent| + Leading。 更加详细的内容可以参考苹果的这篇文档: 《Cocoa Text Architecture Guide》 。当然如果要做到更完善的排版,还需要掌握段落排版(Paragragh Style)相关的知识,但是如果只是完成聊天框内的文字排版,以上的基础知识已经够用了。详细的段落样式相关知识可以参考: 《Ruler and Paragraph Style Programming Topics》
Core Text简介
CoreText 是用于处理文字和字体的底层技术。它直接和 Core Graphics(又被称为 Quartz)打交道。Quartz 是一个 2D 图形渲染引擎,能够处理 OSX 和 iOS 中的图形显示。
注意:这个是 iOS7 之后的架构图,在 iOS7 以前,并没有图中的 Text Kit 类,不过 CoreText 仍然是处在最底层直接和 Core Graphics 打交道的模块。
图上可以看出CoreText处于非常底层的位置上层的UILabel,UITextfield等都是通过CoreText来实现的。
Quartz 这个框架能够直接通过字形(glyphs)和位置(positions)将文字渲染在视图上面。
UIWebView 也是处理复杂的文字排版的备选方案。对于排版,基于 CoreText 和基于 UIWebView 相比,前者有以下好处:
- CoreText 占用的内存更少,渲染速度快,UIWebView 占用的内存更多,渲染速度慢。
- CoreText 在渲染界面前就可以精确地获得显示内容的高度(只要有了 CTFrame 即可),而 UIWebView 只有渲染出内容后,才能获得内容的高度(而且还需要用 javascript 代码来获取)
- CoreText 的 CTFrame 可以在后台线程渲染,UIWebView 的内容只能在主线程(UI 线程)渲染。
基于 CoreText 可以做更好的原生交互效果,交互效果可以更细腻。而 UIWebView 的交互效果都是用 javascript 来实现的,在交互效果上会有一些卡顿存在。例如,在 UIWebView 下,一个简单的按钮按下效果,都无法做到原生按钮的即时和细腻的按下效果。
当然,基于 CoreText 的排版方案也有一些劣势:
- CoreText 渲染出来的内容不能像 UIWebView 那样方便地支持内容的复制。
- 基于 CoreText 来排版需要自己处理很多复杂逻辑,例如需要自己处理图片与文字混排相关的逻辑,也需要自己实现链接点击操作的支持。
Core Text关键类
NSAttributedString
富文本,使用NSAttributedString(CFAttributedStringRef)可以创建CTFramesetter。
- (instancetype)initWithString:(NSString *)str attributes:(nullable NSDictionary<NSString *, id> *)attrs
第二个参数attributes:包含了详细的文字排版信息。详细的信息可以在<CoreText/CTStringAttributes.h>
或者#<Foundation/NSAttributedString.h>
文件中看到。
CTFramesetter
通过CFAttributedString(NSAttributedString)创建,作用相当于一个生产CTFrame的工厂。
CTFrame
每个CTFrame可以看做一个段落 每个CTFrame由多个CTLine组成。可以使用它进行绘制
CTLine
代表一个line 一行文字中可能有多个CTLine组成,单每一个CTLine一定在同一行内。 一个CTLine有多个CTRun组成。也可以使用它进行绘制。
CTRun
一个连续的有着相同的attributes和direction的字形(glyph)的集合,是最小的字形绘制单元。
CTTypesetter
通过CFAttributedString(NSAttributedString)创建,相当于一个生产CTLine的工厂。
代码
自定义一个view继承UIView,重写drawRect: 方法
使用Core Text简单的绘制一个段落
- (void)drawRect:(CGRect)rect {// Drawing code// 1.获取绘制上下文CGContextRef context = UIGraphicsGetCurrentContext();// 2.翻转坐标系// 对于底层绘制引擎来说左下角是(0,0),对于上层UIKit来说左上是(0,0)点CGContextTranslateCTM(context, 0, self.bounds.size.height);CGContextScaleCTM(context, 1.0, -1.0);CGContextSetTextMatrix(context, CGAffineTransformIdentity);// 3.创建矩形的路径 指定文字的绘制范围CGMutablePathRef path = CGPathCreateMutable();CGPathAddRect(path, NULL, self.bounds);// 4.创建富文本NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"Hello, World! I know nothing in the world that has as much power as a word. Sometimes I write one, and I look at it, until it begins to shine." attributes:nil];// 5.根据attrStr初始化CTFramesetterRefCTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrStr);// 6.使用framesetter根据刚才创建的绘制路径和字符串范围初始化CTFrameRefCTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);// 7.在指定的上下文中绘制指定的内容CTFrameDraw(frame, context);// 8. 释放内存CFRelease(frame);CFRelease(framesetter);CFRelease(path);}
Reference:
Core Text Programming Guide
iOS文字排版(CoreText)那些事
基于 CoreText 的排版引擎:基础
CoreText入门
作者:樂亦leeyii
链接:http://www.jianshu.com/p/611f61cd99da
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关文章:

虚拟机下CentOS 6.5配置IP地址的三种方法
实验软件环境:虚拟机Vmware Workstation10.0 、CentOS 6.5 32位 1、自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分配IP地址。 dhclient 自动获取ip地址命令 ifconfig 查询系统里网卡信息&…

GIS 相关知识扫盲
1、什么是GIS GIS:地理信息系统,它是一种特定的十分重要的空间信息系统。它是在计算机硬、软件系统支持下,对整个或部分地球表层(包括大气层)空间中的有关地理分布数据进行采集、储存、管理、运算、分析、显示和描述的技术系统。2…

Linux操作系统(二:shell脚本)
练习一:编写shell脚本,计算1-100的和; 练习二:将一目录下所有的文件的扩展名改为bak 练习三:写一个脚本,统计。/etc/ 目录下共有多少个目录文件 练习四:写一个脚本,依次向/etc/passw…

用OpenGLES实现yuv420p视频播放界面
背景 例子TFLive这个项目里,是我按着ijkPlayer写的直播播放器,要运行需要编译ffmpeg的库,网盘里存了一份, 提取码:vjce。OpenGL ES播放相关的在在OpenGLES的文件夹里。 learnOpenGL学到会使用纹理就可以了。 播放视频,就是把画面一…

C++类的静态成员详细讲解
在C中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。 静态成员的定义或声明要…

jenkins2 multibranch
通过multibranch类型的pipeline job使得对于多个branch的支持更加简单。只需要创建一个multibranch job,jenkins将自动地为所有的branch创建job。 文章来自:http://www.ciandcd.com文中的代码来自可以从github下载: https://github.com/ciand…

Nagios的安装和基本配置(一:知识点总结及环境准备)
实验目的及要求 掌握Nagios监控的基本使用;掌握Nagios监控服务的搭建和配置; 实验环境: 1、满足实验要求的PC端; Host-name OS IP sofaware Nagios-server Centos7 192.168.1.119 Apache,php,Nagios,Nagios-plguins Nag…

浅谈Android四大组件之Service
一:Service简介 Android开发中,当需要创建在后台运行的程序的时候,就要使用到Service。 1:Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切…

使用 fastlane 实现 iOS 持续集成(二)
本文接上篇文章主要说下怎样使用 fastlane 上传到fir和蒲公英,下面先介绍下 plugin 命令。 plugin命令介绍: 列出所有可用插件 fastlane search_plugins 搜索指定名称的插件: fastlane search_plugins [query] 添加插件: fastlane add_plugin [name] 安装插件: fast…

Nagios的安装和基本配置(二:Nagios-Server的安装)
任务二、Nagios-server的安装 2.1、创建Nagios用户和组 注: #useradd Nagios -s /bin/nologin #groundadd nagcmd #usermod -a -G nagcmd Nagios #usermod -a G nagcmd apache 2.2、安装Nagios 2.2.1、上传软件包至操作系统中; 2.2.2、解压软件并…

shell编程-正则表达式
1.正则表达式是什么 它主要用于字符串的模式分割,匹配,查找及替换操作。 2、正则表达式与通配符 正则表达式用来在文件中匹配符合条件的字符串,正则包含匹配。grep,awk,sed等命令可以支持正则表达式。 通配符用来匹配符合条件的文件名&#x…
使用 CocoaPods 给微信集成 SDK 打印收发消息
推荐序 本文介绍的是一套逆向工具,可以在非越狱手机上给任意应用增加插件。在文末的示例中,作者拿微信举例,展示出在微信中打印收发消息的功能。 这套工具可以加快逆向开发的速度,其重签名思想也可以用于二次分发别人的应用。 其实…

数据库之子查询四(多重,表复制)
一、多重子查询 select teaID,teaName,age,sex,dept,professionfrom tteacherwhere dept(select dept from teaIDt103265)and profession(select professionfrom tteacherwhere teaIDt103265)这里的子查询就是为了从表中提取出有效信息参与外部查询二、create table 语句中子查…

Nagios的安装和基本配置(三:Nagios-Client的安装)
任务三、Nagios-Client的安装 3.1、关闭防火墙和selinux 注: #systemctl stop firewalld.service #systemctl disable firewalld.service #vi /etc/selinux/config 3.2、配置环境 #yum install gcc glibc-common -y #yum install gd gd-devel openssl openssl…

事件(待完成)
内容窗口 事件绑定 给整个浏览器 内容窗口区的事件绑定。 通过 document.documentElement或者document.body?似乎都可以。但最好是直接通过document document.addEventListener(mousemove,function () { });// 整个浏览器内容范围都将触发。拖动实现必用 转载…
iOS 模仿支付宝支付到账推送,播报钱数
最近申请了支付宝的二维码收钱码,其中支付宝有这么一个功能,就是,别人扫描你的二维码给你转账之后,收到钱会有一条语音推送,”支付宝到账 1000万“之类的推送消息,不管你的支付宝app有没有被杀死。 只要你的…

hdu - 4707 - Pet
题意:一棵N个结点(编号从0开始)的树,根结点为0,求到根结点的距离大于D的结点个数(0 < 测试组数T < 10, 0<N<100000, 0<D<N)。 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid4707…

Nagios的安装和基本配置(四:调试验证 错误总结)
任务四、调试验证 4.1、验证连通性 在/usr/local/Nagios/etc/nrpe.cfg文件中server的ip地址 #vi /usr/local/Nagios/etc/nrpe.cfg #重启nrpe #pkill nrpe #netstat -Intp #/usr/local/Nagios/bin/nrpe -d -c /usr/local/Nagios/etc/nrpe.cfg #在server主机做验证 #cd /…
hitTest和pointInside方法
hittest方法 就是用来寻找最合适的view当一个事件传递给一个控件,就会调用这个控件的hitTest方法点击了白色的view: 触摸事件 -> UIApplication -> UIWindow 调用 [UIWindow hitTest] -> 白色view [WhteView hitTest] 实验1: 定义 BaseView&…

Github上的PHP资源汇总大全
依赖管理 ——用于依赖管理的包和框架 Composer/Packagist : 一个包和依赖管理器 Composer Installers: 一个多框架Composer库安装器 Pickle: 可以在任意平台上安装PHP扩展包 依赖管理的附加部分 ——其它依赖管理的相关工具 Satis : 静态的Composer库生成器 Composition: 一个…

UIButton长按事件
添加长按事件1 - (void)viewDidLoad2 {3 [super viewDidLoad];4 //Do any additional setup after loading the view, typically from a nib.5 6 UIButton *aBtn[UIButton buttonWithType:UIButtonTypeRoundedRect];7 [aBtn setFrame:CGRectMake(0, 10, 60, 60…

Hadoop集群搭建(一:集群安装及网络环境配置)
实验目的及要求 完成VMware workstations安装,会应用相关操作;完成虚拟机中Linux CentOS 7操作系统安装;完成静态网络地址的配置,所有主机的网络能够正常使用,相互之间能够正常连接;完成主机名配置&#x…

QQ音乐API分析记录
我一直是QQ音乐的用户,最近想做一个应用,想用QQ音乐的API,搜索了很久无果,于是就自己分析QQ音乐的API。 前不久发现QQ音乐出了网页版的,是Flash的,但是,我用iPhone打开这个链接的时候࿰…
Vision 圖像識別框架的使用
阅读 137收藏 102017-10-18原文链接:www.itread01.comGoogle无人车之父、MIT/斯坦福/耶鲁专家带你进入无人驾驶之域 http://cn.udacity.com/course/intro-to-self-driving-cars--nd113 本文為CocoaChina網友 品位生活 投稿 北京時間2017.6.6日淩晨1點,新…

Jmeter性能测试 入门
Jmeter性能测试 入门 原文:Jmeter性能测试 入门Jmeter是一款优秀的开源测试工具, 是每个资深测试工程师,必须掌握的测试工具,熟练使用Jmeter能大大提高工作效率。 熟练使用Jmeter后, 能用Jmeter搞定的事情,你就不会使用…

Hadoop集群搭建(二:集群主机间免密登录配置)
实验目的及要求: 静态网络地址配置;主机名的配置;防火墙的配置,使平台相关软件的常用端口能够远程正常访问;主机地址映射的配置,使所有主机能够通过主机名相互正常访问;免密码登录的配置&#…
你真的会用 CocoaPods 吗?
CocoaPods 可以说是 iOS 开发应用最广泛的包管理工具,本篇文章主要介绍 CocoaPods 的第三方库是怎样从网络集成到我们本地的项目当中,也是制作私有库、开源库和 iOS 项目组件化的一个知识铺垫。 让我们从一张图片开始: CocoaPods 工作流程 …

【spring 5】AOP:spring中对于AOP的的实现
在前两篇博客中,介绍了AOP实现的基础:静态代理和动态代理,这篇博客介绍spring中AOP的实现。 一、采用Annotation方式 首先引入jar包:aspectjrt.jar && aspectweaver.jar applicationContext配置文件: <span…

通过BeanShell获取UUID并将参数传递给Jmeter
有些HTTPS请求报文的报文体中包含由客户端生成的UUID,在用Jmeter做接口自动化测试的时候,因为越过了客户端,直接向服务器端发送报文,所以,需要在Jmeter中通过beanshell获取UUID,并能将参数传递给Jmeter&…

Hadoop集群搭建(四:Zookeeper环境安装)
实验 目的 要求 目的: 1、掌握在完全分布模式的整合平台中Zookeeper的完全分布模式的安装 要求: 完成Zookeeper的完全分布农事的安装;Zookeeper服务能够正常启动和连接;Zookeeper控制台能够正常进入;Zookeeper控制台命…