关于CoreText,自己做一些小纪录

    首先我是萌新,ios开发新手,一些大牛觉得不对,错误的,请勿喷我怎么吃螃蟹,请告诉我怎么吃就好了,谢谢了。

    之前因为项目需求,要给小说阅读器中内容加上下划线,但是这个下划线又跟其他的不一样,这个下划线要在基线的位置再靠上一些,当初不明白为什么要这么做,而且效果也很难看,用户体验也不好,但是老大说这能防止pdf扫描vip章节内容,所以还是得老老实实的做,就对coreText开始了研究。

本次主要用到的点在与CTLineRef.接下来先对其做一些了解。

1.字符(Character)和字形(Glyphs)

排版系统中文本显示的一个重要的过程就是字符到字形的转换,字符是信息本身的元素,而字形是字符的图形表征,字符还会有其它表征比如发音。 字符在计算机中其实就是一个编码,某个字符集中的编码,比如Unicode字符集,就囊括了大都数存在的字符。 而字形则是图形,一般都存储在字体文件中,字形也有它的编码,也就是它在字体中的索引。 一个字符可以对应多个字形(不同的字体,或者同种字体的不同样式:粗体斜体等);多个字符也可能对应一个字形,比如字符的连写( Ligatures)。

下面就来看看字形的各个参数也就是所谓的字形度量Glyph Metrics,其实我认为就是一个小时侯学写字母的时候的作业本一样的各个线


bounding box(边界框 bbox),这是一个假想的框子,它尽可能紧密的装入字形。

baseline(基线),一条假想的线,一行上的字形都以此线作为上下位置的参考,在这条线的左侧存在一个点叫做基线的原点,

ascent(上行高度)从原点到字体中最高(这里的高深都是以基线为参照线的)的字形的顶部的距离,ascent是一个正值

descent(下行高度)从原点到字体中最深的字形底部的距离,descent是一个负值(比如一个字体原点到最深的字形的底部的距离为2,那么descent就为-2)

linegap(行距),linegap也可以称作leading(其实准确点讲应该叫做External leading),行高lineHeight则可以通过 ascent + |descent| + linegap 来计算。

一些Metrics专业知识还可以参考Free Type的文档 Glyph metrics,其实iOS就是使用Free Type库来进行字体渲染的。

以上图片和部分概念来自苹果文档 Querying Font Metrics ,Text Layout


2.坐标系

苹果编程中的坐标系不明白为什么会各有不同。 传统的Mac中的坐标系的原点在左下角,比如NSView默认的坐标系,原点就在左下角。但Mac中有些View为了其实现的便捷将原点变换到左上角,像NSTableView的坐标系坐标原点就在左上角。iOS UIKit的UIView的坐标系原点在左上角。


看完上边儿这些,该上代码勒。


先拿一个定义好的属性字符串。

NSMutableAttributedString *attrString = [[NSMutableAttributedString  alloc] initWithString:self.text];//这个self.text 就是你要用到的字符串

[attrString setAttributes:self.coreTextAttributes range:NSMakeRange(0, attrString.length)];//这里的self.coreTextAttributes就是一个字典,来配置这个属性字符串的,可在他的set方法中随意设置,比如颜色,下划线,删除线,字型等等


然后把属性字符串放到frame中

CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef) attrString);

CGPathRef path = CGPathCreateWithRect(self.bounds, NULL);

if (_ctFrame != NULL) {  //这里的_ctFrame 就是一个装有字符属性的集合

CFRelease(_ctFrame), _ctFrame = NULL;

}

_ctFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);

CFRelease(path);

CFRelease(frameSetter);


做完了上面这些,就该开始画字了。

在- (void)drawRect:(CGRect)rect方法中

if (!_ctFrame) return;

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSetTextMatrix(context, CGAffineTransformIdentity);

CTFrameDraw(_ctFrame, context);

这样写的效果如图


是镜像过来的,要再翻过来

CGAffineTransform transform = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);

CGContextConcatCTM(context, transform);

加上以上这两句就可以了,就顺利的将字画到了画布上。


再之后给文字加个方框

CGMutablePathRef path = CGPathCreateMutable();


CGPathAddRect(path, NULL, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));

CFArrayRef lines = CTFrameGetLines(_ctFrame);

CFIndex linecount = CFArrayGetCount(lines);

CGPoint origins[linecount];

CTFrameGetLineOrigins(_ctFrame, CFRangeMake(0, 0), origins);

NSInteger lineIndex = 0;

for (id oneLine in (__bridge NSArray *)lines) {

CGRect lineBounds = CTLineGetImageBounds((CTLineRef)oneLine, context);

lineBounds.origin.x += origins[lineIndex].x;

lineBounds.origin.y += origins[lineIndex].y;

lineIndex ++;

CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);

CGContextSetLineWidth(context, 1.0);

CGPoint poins[] = {CGPointMake(lineBounds.origin.x, lineBounds.origin.y),CGPointMake(lineBounds.origin.x+lineBounds.size.width, lineBounds.origin.y),CGPointMake(lineBounds.origin.x+lineBounds.size.width, lineBounds.origin.y+lineBounds.size.height),CGPointMake(lineBounds.origin.x, lineBounds.origin.y+lineBounds.size.height)};//绘制四边,位置随意调整,位置可以调整之后也就可以实现我的下划线在任何位置了

CGContextAddLines(context, poins, 4);

CGContextClosePath(context);

CGContextStrokePath(context);

}

}


其中主要是取CTFrameRef集合中的CTLines ,在其中他包含了字符的各种属性,rang等

第一次写文章,主要是当时搞这个东西走了弯路,对coreText的不了解,也在csdn和cocoachina上问了好多人,都没解决,防止以后忘记,自己再纪录一下。


我目前做的项目是做的小说阅读器,网上的素材真的是不多,现在也算是写的差不多了,但是在预加载,内存缓存和磁盘缓存上做的还是不行,希望有做阅读器这方面有好的方案的,希望可以教教小弟,第一篇小文 也就搞定勒。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.iOS中的round、ceil、floor函数略解 round如果参数是小数,则求本身的四舍五入.ceil如果...
    K_Gopher阅读 1,201评论 1 0
  • 本文所涉及的代码你可以在这里下载到https://github.com/kejinlu/CTTest,包含两个项目...
    eb99d15a673d阅读 1,281评论 0 6
  • 目前社交类型的App也是层出不穷,无论是QQ的说说,还是微信的动态,微博的帖子。这种类型的App都会涉及到点赞文本...
    墨香茉香阅读 687评论 0 3
  • CoreText是iOS/OSX中文本显示的一个底层框架,它是用C语言写成的,有快速简单的优势。iOS中的Text...
    小猫仔阅读 5,026评论 2 9
  • 最近在网上看了一些大牛的文章,自己也试着写了一下,感觉图文混排真的很强大。 废话不多说,开始整 先上效果图跟代码,...
    AllureJM阅读 1,012评论 0 1