[iOS]CoreText 学习笔记(1)

感谢唐巧大神的文章,总结一下学习笔记.

完善的排版引擎,所有的代码(颜色、frame等)按照不同的功能分成不同的类。


按照以上原则,将CTDisplayView中的部分内容拆开,由 4 个类构成:

  1. CTFrameParserConfig类,用于配置绘制的参数,例如:文字颜色,大小,行间距等。
  2. CTFrameParser类,用于生成最后绘制界面需要的CTFrameRef实例。
  3. CoreTextData类,用于保存由CTFrameParser类生成的CTFrameRef实例以及CTFrameRef实际绘制需要的高度。
  4. CTDisplayView类,持有CoreTextData类的实例,负责将CTFrameRef绘制到界面上。
  1. CTFrameParser通过CTFrameParserConfig实例来生成CoreTextData实例。
  2. CTDisplayView通过持有CoreTextData实例来获得绘制所需要的所有信息。
  3. ViewController类通过配置CTFrameParserConfig实例,进而获得生成的CoreTextData实例,最后将其赋值给他的CTDisplayView成员,达到将指定内容显示在界面上的效果。

图:UML 示意图

API接口文档。

https://developer.apple.com/library/mac/#documentation/Carbon/Reference/CoreText_Framework_Ref/_index.html

CoreText 框架中最常用的几个类:

  1. CTFont
  2. CTFontCollection
  3. CTFontDescriptor
  4. CTFrame
  5. CTFramesetter
  6. CTGlyphInfo
  7. CTLine
  8. CTParagraphStyle
  9. CTRun
  10. CTTextTab
  11. CTTypesetter

先来了解一下该框架的整体视窗组合图:

CTFrame 作为一个整体的画布(Canvas),其中由行(CTLine)组成,而每行可以分为一个或多个小方块(CTRun)。

注意: 你不需要自己创建CTRun,Core Text将根据NSAttributedString的属性来自动创建CTRun。每个CTRun对象对应不同的属性,正因此,你可以自由的控制字体、颜色、字间距等等信息。

通常处理步聚:

1.使用core text就是先有一个要显示的string,然后定义这个string每个部分的样式->attributedString -> 生成 CTFramesetter -> 得到CTFrame -> 绘制(CTFrameDraw) 
其中可以更详细的设置换行方式,对齐方式,绘制区域的大小等。 
2.绘制只是显示,点击事件就需要一个判断了。 
CTFrame 包含了多个CTLine,并且可以得到各个line的其实位置与大小。判断点击处在不在某个line上。CTLine 又可以判断这个点(相对于ctline的坐标)处的文字范围。然后遍历这个string的所有NSTextCheckingResult,根据result的rang判断点击处在不在这个rang上,从而得到点击的链接与位置。

字体的基本知识:

字体(Font):是一系列字号、样式和磅值相同的字符(例如:10磅黑体Palatino)。现多被视为字样的同义词

字面(Face):是所有字号的磅值和格式的综合

字体集(Font family):是一组相关字体(例如:Franklin family包括Franklin Gothic、Fran-klinHeavy和Franklin Compressed)

磅值(Weight):用于描述字体粗度。典型的磅值,从最粗到最细,有极细、细、book、中等、半粗、粗、较粗、极粗

样式(Style):字形有三种形式:Roman type是直体;oblique type是斜体;utakuc type是斜体兼曲线(比Roman type更像书法体)。

x高度(X height):指小写字母的平均高度(以x为基准)。磅值相同的两字母,x高度越大的字母看起来比x高度小的字母要大

Cap高度(Cap height):与x高度相似。指大写字母的平均高度(以C为基准)

下行字母(Descender):例如在字母q中,基线以下的字母部分叫下伸部分

上行字母(Ascender):x高度以上的部分(比如字母b)叫做上伸部分

基线(Baseline):通常在x、v、b、m下的那条线

描边(Stroke):组成字符的线或曲线。可以加粗或改变字符形状

衬线(Serif):用来使字符更可视的一条水平线。如字母左上角和下部的水平线。

无衬线(Sans Serif):可以让排字员不使用衬线装饰。

方形字(Block):这种字体的笔画使字符看起来比无衬线字更显眼,但还不到常见的衬线字的程度。例如Lubalin Graph就是方形字,这种字看起来好像是木头块刻的一样

手写体脚本(Calligraphic script):是一种仿效手写体的字体。例如Murray Hill或者Fraktur字体

艺术字(Decorative):像绘画般的字体

Pi符号(Pisymbol):非标准的字母数字字符的特殊符号。例如Wingdings和Mathematical Pi

连写(Ligature):是一系列连写字母如fi、fl、ffi或ffl。由于字些字母形状的原因经常被连写,故排字员已习惯将它们连写。

字符属性名称:

const CFStringRef kCTCharacterShapeAttributeName;              
//字体形状属性  必须是CFNumberRef对象默认为0,非0则对应相应的字符形状定义,如1表示传统字符形状
const CFStringRef kCTFontAttributeName;                        
//字体属性   必须是CTFont对象
const CFStringRef kCTKernAttributeName;                        
//字符间隔属性 必须是CFNumberRef对象
const CFStringRef kCTLigatureAttributeName;                 
//设置是否使用连字属性,设置为0,表示不使用连字属性。标准的英文连字有FI,FL.默认值为1,既是使用标准连字。也就是当搜索到f时候,会把fl当成一个文字。必须是CFNumberRef 默认为1,可取0,1,2
const CFStringRef kCTForegroundColorAttributeName;             
//字体颜色属性  必须是CGColor对象,默认为black
const CFStringRef kCTForegroundColorFromContextAttributeName; 
//上下文的字体颜色属性 必须为CFBooleanRef 默认为False,
const CFStringRef kCTParagraphStyleAttributeName;              
//段落样式属性 必须是CTParagraphStyle对象 默认为NIL
const CFStringRef kCTStrokeWidthAttributeName;              
//笔画线条宽度 必须是CFNumberRef对象,默为0.0f,标准为3.0f
const CFStringRef kCTStrokeColorAttributeName;              
//笔画的颜色属性 必须是CGColorRef 对象,默认为前景色
const CFStringRef kCTSuperscriptAttributeName;              
//设置字体的上下标属性 必须是CFNumberRef对象 默认为0,可为-1为下标,1为上标,需要字体支持才行。如排列组合的样式Cn1
const CFStringRef kCTUnderlineColorAttributeName;           
//字体下划线颜色属性 必须是CGColorRef对象,默认为前景色
const CFStringRef kCTUnderlineStyleAttributeName;           
//字体下划线样式属性 必须是CFNumberRef对象,默为kCTUnderlineStyleNone 可以通过CTUnderlineStypleModifiers 进行修改下划线风格
const CFStringRef kCTVerticalFormsAttributeName;
//文字的字形方向属性 必须是CFBooleanRef 默认为falsefalse表示水平方向,true表示竖直方向
const CFStringRef kCTGlyphInfoAttributeName;
//字体信息属性 必须是CTGlyphInfo对象
const CFStringRef kCTRunDelegateAttributeName
//CTRun 委托属性 必须是CTRunDelegate对象

举例说明:

[cpp]   view plain copy

  1. NSMutableAttributedString *mabstring = [[NSMutableAttributedString alloc]initWithString:@ "This is a test of characterAttribute. 中文字符" ];  


[cpp]   view plain copy

  1. //设置字体属性   
  2.   CTFontRef font = CTFontCreateWithName(CFSTR( "Georgia" ), 40, NULL);  
  3.   [mabstring addAttribute:(id)kCTFontAttributeName value:(id)font range:NSMakeRange(0, 4)];   

[cpp]   view plain copy

  1. //设置斜体字   
  2.     CTFontRef font = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 14, NULL);  
  3.     [mabstring addAttribute:(id)kCTFontAttributeName value:(id)font range:NSMakeRange(0, 4)];  

[cpp]   view plain copy

  1. //下划线   
  2.     [mabstring addAttribute:(id)kCTUnderlineStyleAttributeName value:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble] range:NSMakeRange(0, 4)];   

[cpp]   view plain copy

  1. //下划线颜色   
  2.     [mabstring addAttribute:(id)kCTUnderlineColorAttributeName value:(id)[UIColor redColor].CGColor range:NSMakeRange(0, 4)];  

[cpp]   view plain copy

  1. //设置字体简隔 eg:test    
  2.      long  number = 10;  
  3.     CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number);  
  4.     [mabstring addAttribute:(id)kCTKernAttributeName value:(id)num range:NSMakeRange(10, 4)];  

[cpp]   view plain copy

  1. //设置连字   
  2. long  number = 1;  
  3.     CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number);  
  4.     [mabstring addAttribute:(id)kCTLigatureAttributeName value:(id)num range:NSMakeRange(0, [str length])];  

连字还不会使用,未看到效果。

[cpp]   view plain copy

  1. //设置字体颜色   
  2.     [mabstring addAttribute:(id)kCTForegroundColorAttributeName value:(id)[UIColor redColor].CGColor range:NSMakeRange(0, 9)];  

[cpp]   view plain copy

  1. //设置字体颜色为前影色   
  2.     CFBooleanRef flag = kCFBooleanTrue;  
  3.     [mabstring addAttribute:(id)kCTForegroundColorFromContextAttributeName value:(id)flag range:NSMakeRange(5, 10)];  

无明显效果。

[cpp]   view plain copy

  1. //设置空心字   
  2.      long  number = 2;  
  3.     CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number);  
  4.     [mabstring addAttribute:(id)kCTStrokeWidthAttributeName value:(id)num range:NSMakeRange(0, [str length])];  

[cpp]   view plain copy

  1. //设置空心字   
  2.      long  number = 2;  
  3.     CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number);  
  4.     [mabstring addAttribute:(id)kCTStrokeWidthAttributeName value:(id)num range:NSMakeRange(0, [str length])];  
  5.        
  6.      //设置空心字颜色   
  7.     [mabstring addAttribute:(id)kCTStrokeColorAttributeName value:(id)[UIColor greenColor].CGColor range:NSMakeRange(0, [str length])];  


在设置空心字颜色时,必须先将字体高为空心,否则设置颜色是没有效果的。 

[cpp]   view plain copy

  1. //对同一段字体进行多属性设置       
  2.      //红色   
  3.     NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(id)[UIColor redColor].CGColor forKey:(id)kCTForegroundColorAttributeName];  
  4.      //斜体   
  5.     CTFontRef font = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 40, NULL);  
  6.     [attributes setObject:(id)font forKey:(id)kCTFontAttributeName];  
  7.      //下划线   
  8.     [attributes setObject:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble] forKey:(id)kCTUnderlineStyleAttributeName];  
  9.       
  10.     [mabstring addAttributes:attributes range:NSMakeRange(0, 4)];  

最后是draw了。

[cpp]   view plain copy

  1. -( void )characterAttribute  
  2. {  
  3.     NSString *str = @ "This is a test of characterAttribute. 中文字符" ;  
  4.     NSMutableAttributedString *mabstring = [[NSMutableAttributedString alloc]initWithString:str];  
  5.       
  6.     [mabstring beginEditing];  
  7.      /*  
  8.     long number = 1;  
  9.     */   
  10.      /*  
  11.     //设置字体属性  
  12.  
  13.     */   
  14.      /*  
  15.     //设置字体简隔 eg:test   
  16.     long number = 10;  
  17.     */   
  18.   
  19.      /*  
  20.     long number = 1;  
  21.      */   
  22.      /*  
  23.     //设置字体颜色  
  24.      */   
  25.      /*  
  26.     //设置字体颜色为前影色  
  27.     CFBooleanRef flag = kCFBooleanTrue;  
  28.      */   
  29.       
  30.      /*  
  31.     //设置空心字  
  32.     long number = 2;  
  33.        
  34.     //设置空心字颜色  
  35.      */   
  36.       
  37.      /*  
  38.     long number = 1;  
  39.     */   
  40.       
  41.      /*  
  42.     //设置斜体字  
  43.     */    
  44.       
  45.      /*  
  46.     //下划线  
  47.     //下划线颜色  
  48.      */   
  49.       
  50.       
  51.       
  52.      //对同一段字体进行多属性设置       
  53.      //红色   
  54.     NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(id)[UIColor redColor].CGColor forKey:(id)kCTForegroundColorAttributeName];  
  55.      //斜体   
  56.     CTFontRef font = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 40, NULL);  
  57.     [attributes setObject:(id)font forKey:(id)kCTFontAttributeName];  
  58.      //下划线   
  59.     [attributes setObject:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble] forKey:(id)kCTUnderlineStyleAttributeName];  
  60.       
  61.     [mabstring addAttributes:attributes range:NSMakeRange(0, 4)];  
  62.        
  63.   
  64.       
  65.     NSRange kk = NSMakeRange(0, 4);  
  66.       
  67.     NSDictionary * dc = [mabstring attributesAtIndex:0 effectiveRange:&kk];  
  68.       
  69.     [mabstring endEditing];  
  70.       
  71.     NSLog(@ "value = %@" ,dc);  
  72.       
  73.   
  74.       
  75.     CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)mabstring);  
  76.       
  77.     CGMutablePathRef Path = CGPathCreateMutable();  
  78.       
  79.     CGPathAddRect(Path, NULL ,CGRectMake(10 , 0 ,self.bounds.size.width-10 , self.bounds.size.height-10));  
  80.       
  81.     CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL);      
  82.       
  83.      //获取当前(View)上下文以便于之后的绘画,这个是一个离屏。   
  84.     CGContextRef context = UIGraphicsGetCurrentContext();  
  85.       
  86.     CGContextSetTextMatrix(context , CGAffineTransformIdentity);  
  87.       
  88.        
  89.        
  90.     CGContextSaveGState(context);  
  91.       
  92.      //x,y轴方向移动   
  93.     CGContextTranslateCTM(context , 0 ,self.bounds.size.height);  
  94.       
  95.      //缩放x,y轴方向缩放,-1.0为反向1.0倍,坐标系转换,沿x轴翻转180度   
  96.     CGContextScaleCTM(context, 1.0 ,-1.0);  
  97.       
  98.     CTFrameDraw(frame,context);  
  99.       
  100.     CGPathRelease(Path);  
  101.     CFRelease(framesetter);  
  102. }  

[cpp]   view plain copy

  1. - ( void )drawRect:(CGRect)rect  
  2. {  
  3.     [self characterAttribute];  
  4. }  

CORETEXT框架图

另对于Context的了解可以参考:http://www.padovo.com/blog/2013/01/31/study-coretext/



猜你喜欢

转载自blog.csdn.net/w250130255/article/details/47776285