CoreText

作者: Code_人生 | 来源:发表于2019-10-08 16:43 被阅读0次

    一、绘制流程

    二、文本

    - (void)drawRect:(CGRect)rect {
        CGContextRef context = UIGraphicsGetCurrentContext();
        //坐标转换
        CGAffineTransform transform = CGContextGetTextMatrix(context);
        transform = CGAffineTransformIdentity;
        CGContextTranslateCTM(context, 0, self.bounds.size.height);
        CGContextScaleCTM(context, 1.0f, -1.0f);
        
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddRect(path, nil, self.bounds);
    
        NSAttributedString *attributeString = [[NSAttributedString alloc] initWithString:@"Hello World"];
    
        CTFramesetterRef frameSetterRef = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributeString);
    
        CTFrameRef frameRef = CTFramesetterCreateFrame(frameSetterRef, CFRangeMake(0, attributeString.length), path, nil);
    
        CTFrameDraw(frameRef, context);
    }
    

    三、图片

    //Core Text 不支持直接绘制图片,留出空白区域,填充上图片
    -(void)drawRect:(CGRect)rect
    {
        [super drawRect:rect];
        CGContextRef context = UIGraphicsGetCurrentContext();
        NSLog(@"当前context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));
        //坐标系转换
        CGContextSetTextMatrix(context, CGAffineTransformIdentity);
        CGContextTranslateCTM(context, 0, self.bounds.size.height + 20);
        CGContextScaleCTM(context, 1.0, -1.0);
        NSLog(@"变换后context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));
    //\n终身学习,\n
        NSMutableAttributedString * attributeStr = [[NSMutableAttributedString alloc] initWithString:@"人人为师"];
    
        CTRunDelegateCallbacks callBacks;
        memset(&callBacks,0,sizeof(CTRunDelegateCallbacks));
        callBacks.version = kCTRunDelegateVersion1;
        callBacks.getAscent = ascentCallBacks;
        callBacks.getDescent = descentCallBacks;
        callBacks.getWidth = widthCallBacks;
    
        NSDictionary * dicPic = @{@"ascent":@200,@"descent":@100,@"width":@200};
        CTRunDelegateRef delegate = CTRunDelegateCreate(&callBacks, (__bridge void *)dicPic);
    
        NSString * placeHolderStr = @" ";
        NSMutableAttributedString * placeHolderAttrStr = [[NSMutableAttributedString alloc] initWithString:placeHolderStr];
        CFAttributedStringSetAttribute((CFMutableAttributedStringRef)placeHolderAttrStr, CFRangeMake(0, 1), kCTRunDelegateAttributeName, delegate);
        CFRelease(delegate);
        [attributeStr insertAttributedString:placeHolderAttrStr atIndex:0];
    
        CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributeStr);
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddRect(path, NULL, self.bounds);
        NSInteger length = attributeStr.length;
        CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, length), path, NULL);
        CTFrameDraw(frame, context);
    
        //图片!!!网络加载~
        UIImage * image = [UIImage imageNamed:@"1.png"];
        //坐标!。
        CGRect imgFrm = [self calculateImageRectWithFrame:frame];
        CGContextDrawImage(context,imgFrm, image.CGImage);
        CFRelease(frame);
        CFRelease(path);
        CFRelease(frameSetter);
    }
    
    //Ascent + descent = Height
    static CGFloat ascentCallBacks(void * ref)
    {
        return [(NSNumber *)[(__bridge NSDictionary *)ref valueForKey:@"ascent"] floatValue];
    }
    static CGFloat descentCallBacks(void * ref)
    {
        return 100;
    }
    
    static CGFloat widthCallBacks(void * ref)
    {
        return [(NSNumber *)[(__bridge NSDictionary *)ref valueForKey:@"width"] floatValue];
    }
    
    -(CGRect)calculateImageRectWithFrame:(CTFrameRef)frame
    {
        NSArray * arrLines = (NSArray *)CTFrameGetLines(frame);
        NSInteger count = [arrLines count];
        CGPoint points[count];
        //拿到所有CTLine 的原点坐标
        CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), points);
        for (int i = 0; i < count; i ++) {
            CTLineRef line = (__bridge CTLineRef)arrLines[i];
            NSArray * arrGlyphRun = (NSArray *)CTLineGetGlyphRuns(line);
            for (int j = 0; j < arrGlyphRun.count; j ++) {
                CTRunRef run = (__bridge CTRunRef)arrGlyphRun[j];
                NSDictionary * attributes = (NSDictionary *)CTRunGetAttributes(run);
                //取出代理
                CTRunDelegateRef delegate = (__bridge CTRunDelegateRef)[attributes valueForKey:(id)kCTRunDelegateAttributeName];
                if (delegate == nil) {
                    continue;
                }
                NSDictionary * dic = CTRunDelegateGetRefCon(delegate);
                if (![dic isKindOfClass:[NSDictionary class]]) {
                    continue;
                }
                //修正 UIImage 的坐标!!!
                CGPoint point = points[i];
                CGFloat ascent;
                CGFloat descent;
                CGRect boundsRun;
                boundsRun.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, NULL);
                boundsRun.size.height = ascent + descent;
                CGFloat xOffset = CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL);
                boundsRun.origin.x = point.x + xOffset;
                boundsRun.origin.y = point.y - descent;
                CGPathRef path = CTFrameGetPath(frame);
                CGRect colRect = CGPathGetBoundingBox(path);
                CGRect imageBounds = CGRectOffset(boundsRun, colRect.origin.x, colRect.origin.y);
                NSLog(@"%@",NSStringFromCGRect(imageBounds));
                return imageBounds;
            }
        }
        return CGRectZero;
    }
    

    相关文章

      网友评论

          本文标题:CoreText

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