IOS CoreText --- 行 CTLineRef
2015-05-29 09:04
435 查看
前面两篇文章介绍了文字的样式,段落样式。本文章主要介绍行模式。CTLineRef
知识了解:
排版系统中文本显示的一个重要的过程就是字符到字形的转换,字符是信息本身的元素,而字形是字符的图形表征,字符还会有其它表征比如发音。 字符在计算机中其实就是一个编码,某个字符集中的编码,比如Unicode字符集,就囊括了大都数存在的字符。 而字形则是图形,一般都存储在字体文件中,字形也有它的编码,也就是它在字体中的索引。 一个字符可以对应多个字形(不同的字体,或者同种字体的不同样式:粗体斜体等);多个字符也可能对应一个字形,比如字符的连写( Ligatures)。
![](http://ww1.sinaimg.cn/large/65cc0af7gw1e2u5ypr899g.gif)
Roman Ligatures
下面就来详情看看字形的各个参数也就是所谓的字形度量Glyph Metrics
![](http://img.my.csdn.net/uploads/201303/21/1363857127_4241.gif)
![](http://img.my.csdn.net/uploads/201303/21/1363857155_5097.gif)
bounding box(边界框 bbox),这是一个假想的框子,它尽可能紧密的装入字形。
baseline(基线),一条假想的线,一行上的字形都以此线作为上下位置的参考,在这条线的左侧存在一个点叫做基线的原点,
ascent(上行高度)从原点到字体中最高(这里的高深都是以基线为参照线的)的字形的顶部的距离,ascent是一个正值
descent(下行高度)从原点到字体中最深的字形底部的距离,descent是一个负值(比如一个字体原点到最深的字形的底部的距离为2,那么descent就为-2)
linegap(行距),linegap也可以称作leading(其实准确点讲应该叫做External leading),行高lineHeight则可以通过 ascent + |descent| + linegap 来计算。
一些Metrics专业知识还可以参考Free Type的文档 Glyph metrics,其实iOS就是使用Free
Type库来进行字体渲染的。
以上图片和部分概念来自苹果文档 Querying
Font Metrics ,Text
Layout
首先不得不说 苹果编程中的坐标系花样百出,经常让开发者措手不及。 传统的Mac中的坐标系的原点在左下角,比如NSView默认的坐标系,原点就在左下角。但Mac中有些View为了其实现的便捷将原点变换到左上角,像NSTableView的坐标系坐标原点就在左上角。iOS UIKit的UIView的坐标系原点在左上角。
往底层看,Core Graphics的context使用的坐标系的原点是在左下角。而在iOS中的底层界面绘制就是通过Core Graphics进行的,那么坐标系列是如何变换的呢? 在UIView的drawRect方法中我们可以通过UIGraphicsGetCurrentContext()来获得当前的Graphics Context。drawRect方法在被调用前,这个Graphics Context被创建和配置好,你只管使用便是。如果你细心,通过CGContextGetCTM(CGContextRef c)可以看到其返回的值并不是CGAffineTransformIdentity,通过打印出来看到值为
这是非retina分辨率下的结果,如果是如果是retina上面的a,d,ty的值将会乘2,如果是iPhone 5,ty的值会再大些。 但是作用都是一样的就是将上下文空间坐标系进行了flip,使得原本左下角原点变到左上角,y轴正方向也变换成向下。
还是老样子,拿一个事先定义好的属性字串进行开讲。
[cpp] view
plaincopy
NSString *src = [NSString stringWithString:@"其实流程是这样的: 1、生成要绘制的NSAttributedString对象。 "];
NSMutableAttributedString * mabstring = [[NSMutableAttributedString alloc]initWithString:src];
long slen = [mabstring length];
将属性字串放到frame当中。
[cpp] view
plaincopy
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)mabstring);
CGMutablePathRef Path = CGPathCreateMutable();
//坐标点在左下角
CGPathAddRect(Path, NULL ,CGRectMake(10 , 10 ,self.bounds.size.width-20 , self.bounds.size.height-20));
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL);
显示效果:
![](http://img.my.csdn.net/uploads/201303/21/1363859072_6076.jpg)
得到属性字串在frame中被自动分成了多少个行。每行中有多少个CTRun
[cpp] view
plaincopy
//得到frame中的行数组
CFArrayRef rows = CTFrameGetLines(frame);
int rowcount = CFArrayGetCount(rows);
NSLog(@"rowcount = %i",rowcount);
CTLineRef line = CFArrayGetValueAtIndex(rows, 0);
//从一行中得到CTRun数组
CFArrayRef runs = CTLineGetGlyphRuns(line);
int runcount = CFArrayGetCount(runs);
NSLog(@"runcount = %i",runcount);
结果:
[cpp] view
plaincopy
2013-03-20 23:07:38.835 CTextDemo[5612:207] rowcount = 2
2013-03-20 23:07:38.838 CTextDemo[5612:207] runcount = 17
将第一行设置为使用省略号模式
[cpp] view
plaincopy
NSAttributedString *truncatedString = [[NSAttributedString alloc]initWithString:@"\u2026"];
CTLineRef token = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)truncatedString);
CTLineTruncationType ltt = kCTLineTruncationStart;//kCTLineTruncationEnd;
CTLineRef newline = CTLineCreateTruncatedLine(line, self.bounds.size.width-200, ltt, token);
CGContextSetTextPosition(context,20, 20);
CTLineDraw(newline, context);
效果:
![](http://img.my.csdn.net/uploads/201303/22/1363945405_1018.jpg)
CTLineTruncationType 为kCTLineTrunceationEnd;
![](http://img.my.csdn.net/uploads/201303/22/1363945625_1917.jpg)
省略号在中间
知识了解:
1.字符(Character)和字形(Glyphs)
排版系统中文本显示的一个重要的过程就是字符到字形的转换,字符是信息本身的元素,而字形是字符的图形表征,字符还会有其它表征比如发音。 字符在计算机中其实就是一个编码,某个字符集中的编码,比如Unicode字符集,就囊括了大都数存在的字符。 而字形则是图形,一般都存储在字体文件中,字形也有它的编码,也就是它在字体中的索引。 一个字符可以对应多个字形(不同的字体,或者同种字体的不同样式:粗体斜体等);多个字符也可能对应一个字形,比如字符的连写( Ligatures)。 ![](http://ww1.sinaimg.cn/large/65cc0af7gw1e2u5ypr899g.gif)
Roman Ligatures
下面就来详情看看字形的各个参数也就是所谓的字形度量Glyph Metrics
![](http://img.my.csdn.net/uploads/201303/21/1363857127_4241.gif)
![](http://img.my.csdn.net/uploads/201303/21/1363857155_5097.gif)
bounding box(边界框 bbox),这是一个假想的框子,它尽可能紧密的装入字形。
baseline(基线),一条假想的线,一行上的字形都以此线作为上下位置的参考,在这条线的左侧存在一个点叫做基线的原点,
ascent(上行高度)从原点到字体中最高(这里的高深都是以基线为参照线的)的字形的顶部的距离,ascent是一个正值
descent(下行高度)从原点到字体中最深的字形底部的距离,descent是一个负值(比如一个字体原点到最深的字形的底部的距离为2,那么descent就为-2)
linegap(行距),linegap也可以称作leading(其实准确点讲应该叫做External leading),行高lineHeight则可以通过 ascent + |descent| + linegap 来计算。
一些Metrics专业知识还可以参考Free Type的文档 Glyph metrics,其实iOS就是使用Free
Type库来进行字体渲染的。
以上图片和部分概念来自苹果文档 Querying
Font Metrics ,Text
Layout
2.坐标系
首先不得不说 苹果编程中的坐标系花样百出,经常让开发者措手不及。 传统的Mac中的坐标系的原点在左下角,比如NSView默认的坐标系,原点就在左下角。但Mac中有些View为了其实现的便捷将原点变换到左上角,像NSTableView的坐标系坐标原点就在左上角。iOS UIKit的UIView的坐标系原点在左上角。 往底层看,Core Graphics的context使用的坐标系的原点是在左下角。而在iOS中的底层界面绘制就是通过Core Graphics进行的,那么坐标系列是如何变换的呢? 在UIView的drawRect方法中我们可以通过UIGraphicsGetCurrentContext()来获得当前的Graphics Context。drawRect方法在被调用前,这个Graphics Context被创建和配置好,你只管使用便是。如果你细心,通过CGContextGetCTM(CGContextRef c)可以看到其返回的值并不是CGAffineTransformIdentity,通过打印出来看到值为
Printing description of contextCTM: (CGAffineTransform) contextCTM = { a = 1 b = 0 c = 0 d = -1 tx = 0 ty = 460 }
这是非retina分辨率下的结果,如果是如果是retina上面的a,d,ty的值将会乘2,如果是iPhone 5,ty的值会再大些。 但是作用都是一样的就是将上下文空间坐标系进行了flip,使得原本左下角原点变到左上角,y轴正方向也变换成向下。
还是老样子,拿一个事先定义好的属性字串进行开讲。
[cpp] view
plaincopy
NSString *src = [NSString stringWithString:@"其实流程是这样的: 1、生成要绘制的NSAttributedString对象。 "];
NSMutableAttributedString * mabstring = [[NSMutableAttributedString alloc]initWithString:src];
long slen = [mabstring length];
将属性字串放到frame当中。
[cpp] view
plaincopy
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)mabstring);
CGMutablePathRef Path = CGPathCreateMutable();
//坐标点在左下角
CGPathAddRect(Path, NULL ,CGRectMake(10 , 10 ,self.bounds.size.width-20 , self.bounds.size.height-20));
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL);
显示效果:
![](http://img.my.csdn.net/uploads/201303/21/1363859072_6076.jpg)
得到属性字串在frame中被自动分成了多少个行。每行中有多少个CTRun
[cpp] view
plaincopy
//得到frame中的行数组
CFArrayRef rows = CTFrameGetLines(frame);
int rowcount = CFArrayGetCount(rows);
NSLog(@"rowcount = %i",rowcount);
CTLineRef line = CFArrayGetValueAtIndex(rows, 0);
//从一行中得到CTRun数组
CFArrayRef runs = CTLineGetGlyphRuns(line);
int runcount = CFArrayGetCount(runs);
NSLog(@"runcount = %i",runcount);
结果:
[cpp] view
plaincopy
2013-03-20 23:07:38.835 CTextDemo[5612:207] rowcount = 2
2013-03-20 23:07:38.838 CTextDemo[5612:207] runcount = 17
将第一行设置为使用省略号模式
[cpp] view
plaincopy
NSAttributedString *truncatedString = [[NSAttributedString alloc]initWithString:@"\u2026"];
CTLineRef token = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)truncatedString);
CTLineTruncationType ltt = kCTLineTruncationStart;//kCTLineTruncationEnd;
CTLineRef newline = CTLineCreateTruncatedLine(line, self.bounds.size.width-200, ltt, token);
CGContextSetTextPosition(context,20, 20);
CTLineDraw(newline, context);
效果:
![](http://img.my.csdn.net/uploads/201303/22/1363945405_1018.jpg)
CTLineTruncationType 为kCTLineTrunceationEnd;
![](http://img.my.csdn.net/uploads/201303/22/1363945625_1917.jpg)
省略号在中间
![](http://img.my.csdn.net/uploads/201303/22/1363945730_4798.jpg)
相关文章推荐
- IOS CoreText --- 基本用法
- ios 手势
- IOS 开发学习28 NSArray 基本用法
- iOS 逆向之ARM汇编
- iOS开发笔记18--SEL (@selector) 原理及使用总结(二)
- iOS开发笔记17-SEL (@selector) 原理及使用总结(一)
- iOS开发笔记16--第三方登陆
- 解决Xcode package manager无法使用
- ios开发-日期处理(类似朋友圈,微博等的发送时间)
- ios与js交互,获取webview完整url,title,获取元素并赋值跳转
- ios时间与日期的处理
- 浅谈iOS面向对象之类与对象
- ios动画学习(一)
- iOS将汉字转化成oc字符串
- iOS开发-retain/assign/strong/weak/copy/mutablecopy/autorelease区别
- iOS - 中三种定时器的用法NSTimer、CADisplayLink、GCD
- IOS 6 自动布局 入门-1
- 控制器View的生命周期图解
- ios8.3 编译 arm64版 openssl-1.0.2a
- IOS框架图