CoreText入门
发布日期:2022-03-18 08:27:42 浏览次数:40 分类:技术文章

本文共 3694 字,大约阅读时间需要 12 分钟。

CoreText入门

文档内容

CoreText文档

Core Text布局引擎通常与属性字符串(CFAttributedStringRef)和图形路径(CGPathRef)打交道

  • 属性字符串封装了一个支持显示文本的字符串,并包含定义字符串中字符的属性(例如字体和颜色)。Core Text中的排版机制使用属性字符串中的信息来执行字符到字形转换
  • 图形路径定义文本框的形状。在OS X v10.7和iOS 3.2及更高版本中,路径可以是非矩形的

CFAttributedString的引用类型CFAttributedStringRef,是与NSAttributedString桥接的。所以有NSAttributedString参数的地方,你可以传递CFAttributedStringRef,有CFAttributedStringRef参数的地方,你也可以传递NSAttributedString

要将样式应用于一个glyph run(CTRun对象),要创建一个CFDictionary对象来保存要应用的属性,然后创建一个属性字符串,把这个CFDictionary对象作为参数。

Core Text运行时的层次结构如下:

这里写图片描述

层次结构的顶部是framesetter对象(CTFramesetterRef),它使用属性字符串(attributed string)和图形路径(graphics path)作为输入,framesetter生成一个或多个文本框(CTFrameRef)。每个CTFrame对象都代表一个段落(paragraph)

字体对象

CTFont的引用类型CTFontRefUIFont是完全桥接的

CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", fontSize, NULL);

简介

CoreText是用于处理文字和字体的底层技术。它直接和Core Graphics(又被称为Quartz)打交道。Quartz是一个2D图形渲染引擎,能够处理OSX和iOS中的图形显示问题。

UIWebView也常用于处理复杂的排版,对应排版他们之间的优劣如下(摘自 《iOS开发进阶》—— 唐巧):

  • CoreText占用的内容更少,渲染速度更快。UIWebView占用的内存多,渲染速度慢。
  • CoreText在渲染界面的前就可以精确地获得显示内容的高度(只要有了CTFrame即可),而WebView只有渲染出内容后,才能获得内容的高度(而且还需要用JavaScript代码来获取)。
  • CoreText的CTFrame可以在后台线程渲染,UIWebView的内容只能在主线程(UI线程)渲染。
  • 基于CoreText可以做更好的原生交互效果,交互效果可以更加细腻。而UIWebView的交互效果都是用JavaScript来实现的,在交互效果上会有一些卡顿的情况存在。例如,在UIWebView下,一个简单的按钮按下的操作,都无法做出原生按钮的即时和细腻的按下效果。

CoreText排版的劣势:

  • CoreText渲染出来的内容不能像UIWebView那样方便地支持内容的复制。
  • 基于CoreText来排版需要自己处理很多复制的逻辑,例如需要自己处理图片与文字混排相关的逻辑,也需要自己实现连接点击操作的支持。

Core Text对象模型

这里写图片描述

这里写图片描述

  • framesetter framesetter对应的类型是 CTFramesetter,通过CFAttributedString进行初始化,它作为CTFrame对象的生产工厂,负责根据path生产对应的CTFrame
  • CTFrame CTFrame是可以通过CTFrameDraw函数直接绘制到context上的,当然你可以在绘制之前,操作CTFrame中的CTLine,进行一些参数的微调
  • CTLine 可以看做Core Text绘制中的一行的对象 通过它可以获得当前行的line ascent,line descent ,line leading,还可以获得Line下的所有Glyph Runs
  • CTRun 或者叫做 Glyph Run,是一组共享想相同attributes(属性)的字形的集合体

上面说了这么多对也没一个东西和图片绘制有关系,其实吧,Core Text本身并不支持图片绘制,图片的绘制你还得通过Core Graphics来进行。只是Core Text可以通过CTRun的设置为你的图片在文本绘制的过程中留出适当的空间。这个设置就使用到CTRunDelegate了,看这个名字大概就可以知道什么意思了,CTRunDelegate作为CTRun相关属性或操作扩展的一个入口,使得我们可以对CTRun做一些自定义的行为。为图片留位置的方法就是加入一个空白的CTRun,自定义其ascent,descent,width等参数,使得绘制文本的时候留下空白位置给相应的图片。然后图片在相应的空白位置上使用Core Graphics接口进行绘制。

使用CTRunDelegateCreate可以创建一个CTRunDelegate,它接收两个参数,一个是callbacks结构体,一个是所有callback调用的时候需要传入的对象。 callbacks的结构体为CTRunDelegateCallbacks,主要是包含一些回调函数,比如有返回当前run的ascent,descent,width这些值的回调函数,至于函数中如何鉴别当前是哪个run,可以在CTRunDelegateCreate的第二个参数来达到目的,因为CTRunDelegateCreate的第二个参数会作为每一个回调调用时的入参。

例子

- (void)drawRect:(CGRect)rect{    [super drawRect:rect];    //得到当前绘制画布的上下文,用于后续将内容绘制在画布上    CGContextRef context = UIGraphicsGetCurrentContext();    //将坐标系上下翻转    CGContextSetTextMatrix(context, CGAffineTransformIdentity);    CGContextTranslateCTM(context, 0, self.bounds.size.height);    CGContextScaleCTM(context, 1.0, -1.0);    //创建绘制区域    CGMutablePathRef path = CGPathCreateMutable();    CGPathAddRect(path, NULL, self.bounds);    NSAttributedString *attString = [[NSAttributedString alloc] initWithString:@"Hello World!"];    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString);    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attString length]), path, NULL);    CTFrameDraw(frame, context);    CFRelease(frame);    CFRelease(path);    CFRelease(framesetter);}

这里写图片描述

改变创建区域的代码如下:

CGMutablePathRef path = CGPathCreateMutable();    CGPathAddEllipseInRect(path, NULL, self.bounds);    NSAttributedString *attString = [[NSAttributedString alloc] initWithString:@"Hello World! Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!"];

这里写图片描述

参考文档

转载地址:https://windzen.blog.csdn.net/article/details/53610050 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Text Kit进阶——Intermediate Text Kit
下一篇:AVFoundation编程指南-使用 Assets

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月08日 08时22分28秒