您的位置:首页 > 移动开发 > IOS开发

iOS coretext框架第一章 基础知识

2017-02-11 23:17 381 查看
API接口文档。
https://developer.apple.com/library/mac/#documentation/Carbon/Reference/CoreText_Framework_Ref/_index.html
CoreText 框架中最常用的几个类:

CTFont

CTFontCollection

CTFontDescriptor

CTFrame

CTFramesetter

CTGlyphInfo

CTLine

CTParagraphStyle

CTRun

CTTextTab

CTTypesetter
一、Coretext绘制元素组成:



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

CTLine 可以看做Core Text绘制中的一行的对象 通过它可以获得当前行的line ascent,line descent ,line leading,还可以获得Line下的所有Glyph Runs
CTRun 或者叫做 Glyph Run,是一组共享想相同attributes(属性)的字形的集合体

一个CTFrame有几个CTLine组成,有几行文字就有几行CTLine。一个CTLine有包含多个CTRun,一个CTRun是所有属性都相同的那部分富文本的绘制单元。所以CTRun是CTFrame的
基本绘制单元


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

二、坐标系

首先让我们先来看看 CoreText坐标系 和 UIKit坐标系 的不同

从图中可看出 CoreText坐标系是以左下角为坐标原点 ,而我们常使用的UIKit是以左上角为坐标原点 ,因此在CoreText中的布局完成后需要对其坐标系进行转换,否则直接绘制出现位置反转的镜像情况。在通常情况下我们一般做法是直接获取当前上下文。并将当前上下文的坐标系转换为CoreText坐标系,再将布局好的CoreText绘制到当前上下文中即可。以下是此种方案的实现逻辑

//获取当前上下文
CGContextRef context = UIGraphicsGetCurrentContext();
//翻转坐标系步骤
//设置当前文本矩阵
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
//文本沿y轴移动
CGContextTranslateCTM(context, 0, self.bounds.size.height);
//文本翻转成为CoreText坐标系
CGContextScaleCTM(context, 1, -1);


三、字体的基本知识:

字体(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。由于字些字母形状的原因经常被连写,故排字员已习惯将它们连写。





四、主要函数

1、传入CTFrame,返回一个装有多个CTLine对象的数组。

CFArrayRef CTFrameGetLines(        CTFrameRef frame ) CT_AVAILABLE(10_5, 3_2);

2、获取数组中的元素个数

CFIndex CFArrayGetCount(CFArrayRef theArray);

3、获取数组中第idx个元素

const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx);

4、 获取所有CTLineRef的基础原点,传入CTFrame,CFRange,和一个CGPoint的结构体数组指针,该函数会把每一个CTLine的origin坐标写到数组里。

void CTFrameGetLineOrigins(        CTFrameRef frame,        CFRange range,        CGPoint origins[] ) CT_AVAILABLE(10_5, 3_2);

5、获取CTLine中文字在整段文字中的Range

CFRange CTLineGetStringRange(    CTLineRef line ) CT_AVAILABLE(10_5, 3_2);

6、获取CTLine中的CTRun的数组

CFArrayRef CTLineGetGlyphRuns(    CTLineRef line ) CT_AVAILABLE(10_5, 3_2);

7、获取CTRun在整段文字中的Range

CFRange CTRunGetStringRange(    CTRunRef run ) CT_AVAILABLE(10_5, 3_2);

8、 获取点击处position文字在整段文字中的index

CFIndex CTLineGetStringIndexForPosition(    CTLineRef line,    CGPoint position ) CT_AVAILABLE(10_5, 3_2);

9、获取整段文字中charIndex位置的字符相对line的原点的x值

CGFloat CTLineGetOffsetForStringIndex(    CTLineRef line,    CFIndex charIndex,    CGFloat * __nullable secondaryOffset ) CT_AVAILABLE(10_5, 3_2);

10、获取数组中字形个个数

CFIndex CTLineGetGlyphCount(    CTLineRef line ) CT_AVAILABLE(10_5, 3_2);

11、设置CoreText绘制前的坐标。设置基线位置

CG_EXTERN void CGContextSetTextPosition(CGContextRef __nullable c,    CGFloat x, CGFloat y)    CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

12、绘制CTLine。

void CTLineDraw(    CTLineRef line,    CGContextRef context ) CT_AVAILABLE(10_5, 3_2);

13、获取CTLine的上行高度,下行高度,行距

double CTLineGetTypographicBounds(    CTLineRef line,    CGFloat * __nullable ascent,    CGFloat * __nullable descent,    CGFloat * __nullable leading ) CT_AVAILABLE(10_5, 3_2);

14、设置当前文本矩阵

CG_EXTERN void CGContextSetTextMatrix(CGContextRef __nullable c,    CGAffineTransform t)    CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

15、获取一行文字的范围, 就是指把这一行文字点有的像素矩阵作为一个image图片,来得到整个矩形区域。相对于每一行基线原点的偏移量和宽高(例如:{{1.2, -2.57227}, {208.025, 19.2523}},就是相对于本身的基线原点向右偏移1.2个单位,向下偏移2.57227个单位,后面是宽高)

CGRect CTLineGetImageBounds(    CTLineRef line,    CGContextRef __nullable context ) CT_AVAILABLE(10_5, 3_2);

例如:

//获取frame中CTLineRef数组CFArrayRef Lines = CTFrameGetLines(frame);//获取数组Lines中的个数CFIndex lineCount = CFArrayGetCount(Lines);//获取数组中第一个CTLineRefCTLineRef lineRef = CFArrayGetValueAtIndex(Lines, 0);//获取lineRef中CTRunRef数组CFArrayRef runs = CTLineGetGlyphRuns(lineRef);//获取CTLineRef中字形个数CFIndex
rus = CTLineGetGlyphCount(lineRef);//获取数组runs中的个数CFIndex runCount = CFArrayGetCount(runs);NSLog(@"lines = %ld   runs = %ld rus = %ld",lineCount,runCount,rus);

打印:

lines = 7   runs = 5 rus = 37

  

五、举例说明:

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




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




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




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



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




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




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


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

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




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


无明显效果。

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



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



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

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



最后是draw了。

-(void)characterAttribute  
{  
    NSString *str = @"This is a test of characterAttribute. 中文字符";  
    NSMutableAttributedString *mabstring = [[NSMutableAttributedString alloc]initWithString:str];  
      
    [mabstring beginEditing];  
    /* 
    long number = 1; 
    CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number); 
    [mabstring addAttribute:(id)kCTCharacterShapeAttributeName value:(id)num range:NSMakeRange(0, 4)]; 
    */  
    /* 
    //设置字体属性 
    CTFontRef font = CTFontCreateWithName(CFSTR("Georgia"), 40, NULL); 
    [mabstring addAttribute:(id)kCTFontAttributeName value:(id)font range:NSMakeRange(0, 4)]; 
    */  
    /* 
    //设置字体简隔 eg:test  
    long number = 10; 
    CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number); 
    [mabstring addAttribute:(id)kCTKernAttributeName value:(id)num range:NSMakeRange(10, 4)]; 
    */  
  
    /* 
    long number = 1; 
    CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number); 
    [mabstring addAttribute:(id)kCTLigatureAttributeName value:(id)num range:NSMakeRange(0, [str length])]; 
     */  
    /* 
    //设置字体颜色 
    [mabstring addAttribute:(id)kCTForegroundColorAttributeName value:(id)[UIColor redColor].CGColor range:NSMakeRange(0, 9)]; 
     */  
    /* 
    //设置字体颜色为前影色 
    CFBooleanRef flag = kCFBooleanTrue; 
    [mabstring addAttribute:(id)kCTForegroundColorFromContextAttributeName value:(id)flag range:NSMakeRange(5, 10)]; 
     */  
      
    /* 
    //设置空心字 
    long number = 2; 
    CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number); 
    [mabstring addAttribute:(id)kCTStrokeWidthAttributeName value:(id)num range:NSMakeRange(0, [str length])]; 
      
    //设置空心字颜色 
    [mabstring addAttribute:(id)kCTStrokeColorAttributeName value:(id)[UIColor greenColor].CGColor range:NSMakeRange(0, [str length])]; 
     */  
      
    /* 
    long number = 1; 
    CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number); 
    [mabstring addAttribute:(id)kCTSuperscriptAttributeName value:(id)num range:NSMakeRange(3, 1)]; 
    */  
      
    /* 
    //设置斜体字 
    CTFontRef font = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 14, NULL); 
    [mabstring addAttribute:(id)kCTFontAttributeName value:(id)font range:NSMakeRange(0, 4)]; 
    */   
      
    /* 
    //下划线 
    [mabstring addAttribute:(id)kCTUnderlineStyleAttributeName value:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble] range:NSMakeRange(0, 4)];  
    //下划线颜色 
    [mabstring addAttribute:(id)kCTUnderlineColorAttributeName value:(id)[UIColor redColor].CGColor range:NSMakeRange(0, 4)]; 
     */  
      
      
      
    //对同一段字体进行多属性设置      
    //红色  
    NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(id)[UIColor redColor].CGColor forKey:(id)kCTForegroundColorAttributeName];  
    //斜体  
    CTFontRef font = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 40, NULL);  
    [attributes setObject:(id)font forKey:(id)kCTFontAttributeName];  
    //下划线  
    [attributes setObject:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble] forKey:(id)kCTUnderlineStyleAttributeName];  
      
    [mabstring addAttributes:attributes range:NSMakeRange(0, 4)];  
       
  
      
    NSRange kk = NSMakeRange(0, 4);  
      
    NSDictionary * dc = [mabstring attributesAtIndex:0 effectiveRange:&kk];  
      
    [mabstring endEditing];  
      
    NSLog(@"value = %@",dc);  
      
  
      
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)mabstring);  
      
    CGMutablePathRef Path = CGPathCreateMutable();  
      
    CGPathAddRect(Path, NULL ,CGRectMake(10 , 0 ,self.bounds.size.width-10 , self.bounds.size.height-10));  
      
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL);      
      
    //获取当前(View)上下文以便于之后的绘画,这个是一个离屏。  
    CGContextRef context = UIGraphicsGetCurrentContext();  
      
    CGContextSetTextMatrix(context , CGAffineTransformIdentity);  
      
    //压栈,压入图形状态栈中.每个图形上下文维护一个图形状态栈,并不是所有的当前绘画环境的图形状态的元素都被保存。图形状态中不考虑当前路径,所以不保存  
    //保存现在得上下文图形状态。不管后续对context上绘制什么都不会影响真正得屏幕。  
    CGContextSaveGState(context);  
      
    //x,y轴方向移动  
    CGContextTranslateCTM(context , 0 ,self.bounds.size.height);  
      
    //缩放x,y轴方向缩放,-1.0为反向1.0倍,坐标系转换,沿x轴翻转180度  
    CGContextScaleCTM(context, 1.0 ,-1.0);  
      
    CTFrameDraw(frame,context);  
      
    CGPathRelease(Path);  
    CFRelease(framesetter);  
}  

- (void)drawRect:(CGRect)rect  
{  
    [self characterAttribute];  
}  

CORETEXT框架图



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




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: