美文网首页
CoreText应用之代码详细篇

CoreText应用之代码详细篇

作者: LiuffSunny | 来源:发表于2019-08-08 14:34 被阅读0次

    如何使用CoreText

    CoreText是需要自己处理绘制,不像UILabel等最上层的控件 ,所以我们必须在drawRect中绘制,为了更好地使用,我们需要自定义一个UIView。
    CoreText绘图流程:先创建一个framesetter——>创建path——>创建frame(携带framesetter和path等信息)——>生成上下文context——>CTFrameDraw绘制frame——>释放
    转换坐标系

    UIKit的坐标系原点是在右上角,CoreText的坐标原点是在左下角,并且绘制的内容是颠倒的,所以需要进行坐标转换,绘制的内容显示才能正常

    781681-20160107095453075-2053394561.png.jpg
    #pragma mark - drawRect
    - (void)drawRect:(CGRect)rect
    {
        // 1.获取图形上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        // 2.翻转坐标系
        CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformMakeTranslation(0, rect.size.height), 1.f, -1.f);
        CGContextConcatCTM(context, transform);
        
        // 3.获取CTFrameRef
        self.frameRef = [self.attributedString prepareFrameRefWithRect:rect];
        
        // 4.绘制高亮背景颜色
        [self drawHighlightedColor];
        
        // 5.一行一行的绘制文字
        [self frameLineDraw];
        
        // 6.绘制图片
        [self drawImages];
    }
    
    

    一.关于上下文

    由于绘制都是在Context上下文上进行的,所以先补充一些上下文的知识,上下文是什么?为什么要有上下文?上下文是怎么工作的?
    Context上下文
    上下文是什么:
    上下文定义了我们需要绘制的地方。
    为什么要有上下文:
    要盛水,就需要有容器;要画画,就需要画板。上下文就是一个画板,在英语中词根con和com都有很多一起的意思,再看Context,就是很多文本在一起,这就是上下文了。
    上下文是怎么工作的:
    UIKit维护着一个上下文堆栈,UIKit 方法总是绘制到最顶层的上下文中。你可以使用 UIGraphicsGetCurrentContext() 来得到最顶层的上下文。你可以使用 UIGraphicsPushContext()和UIGraphicsPopContext()在 UIKit 的堆栈中推进或取出上下文。最为突出的是,UIKit 使用 UIGraphicsBeginImageContextWithOptions() 和 UIGraphicsEndImageContext()方便的创建类似于 CGBitmapContextCreate()的位图上下文。混合调用 UIKit 和 Core Graphics 非常简单:

    二.主要函数

    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);

    从绘制路径CGMutablePathRef开始

    void CGPathAddRect(CGMutablePathRef path, const CGAffineTransform *m, CGRect rect);
    //*m是一个指向仿射变换矩阵的指针,如果不需要可以设置为NULL,如果指定了矩阵,Core Graphics将转换应用于矩形,然后将其添加到路径中。
    //rect就是需要将该矩阵添加到哪里。
    /**
     * 根据传入的宽高来获取CTFrameRef
     */
    - (CTFrameRef)prepareFrameRefWithRect:(CGRect)rect
                           framesetterRef:(CTFramesetterRef)framesetterRef
    {
    //CGMutablePathRef是一个可变的路径,可通过CGPathCreateMutable()创建,该路径在被创建后,需要加到Context中。
    
    //CGPathAddRect就是将上面的路径添加到上下文中的方法。
        // 创建路径 
        CGMutablePathRef path = CGPathCreateMutable();
        // 添加路径
        CGPathAddRect(path, NULL, rect);
        
        // 获取frameRef
        // CFRangeMake(0,0) 表示绘制全部文字
        CTFrameRef frameRef = CTFramesetterCreateFrame(framesetterRef, CFRangeMake(0, 0), path, NULL);
        
        // 释放内存
        CFRelease(path);
        
        return frameRef;
    }
    
    

    相关文章

      网友评论

          本文标题:CoreText应用之代码详细篇

          本文链接:https://www.haomeiwen.com/subject/nilxjctx.html