關(guān)于CoreText,自己做一些小紀(jì)錄

? ? 首先我是萌新,ios開發(fā)新手,一些大牛覺得不對(duì),錯(cuò)誤的,請(qǐng)勿噴我怎么吃螃蟹,請(qǐng)告訴我怎么吃就好了,謝謝了。

? ? 之前因?yàn)轫?xiàng)目需求,要給小說閱讀器中內(nèi)容加上下劃線,但是這個(gè)下劃線又跟其他的不一樣,這個(gè)下劃線要在基線的位置再靠上一些,當(dāng)初不明白為什么要這么做,而且效果也很難看,用戶體驗(yàn)也不好,但是老大說這能防止pdf掃描vip章節(jié)內(nèi)容,所以還是得老老實(shí)實(shí)的做,就對(duì)coreText開始了研究。

本次主要用到的點(diǎn)在與CTLineRef.接下來先對(duì)其做一些了解。

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

排版系統(tǒng)中文本顯示的一個(gè)重要的過程就是字符到字形的轉(zhuǎn)換,字符是信息本身的元素,而字形是字符的圖形表征,字符還會(huì)有其它表征比如發(fā)音。 字符在計(jì)算機(jī)中其實(shí)就是一個(gè)編碼,某個(gè)字符集中的編碼,比如Unicode字符集,就囊括了大都數(shù)存在的字符。 而字形則是圖形,一般都存儲(chǔ)在字體文件中,字形也有它的編碼,也就是它在字體中的索引。 一個(gè)字符可以對(duì)應(yīng)多個(gè)字形(不同的字體,或者同種字體的不同樣式:粗體斜體等);多個(gè)字符也可能對(duì)應(yīng)一個(gè)字形,比如字符的連寫( Ligatures)。

下面就來看看字形的各個(gè)參數(shù)也就是所謂的字形度量Glyph Metrics,其實(shí)我認(rèn)為就是一個(gè)小時(shí)侯學(xué)寫字母的時(shí)候的作業(yè)本一樣的各個(gè)線


bounding box(邊界框 bbox),這是一個(gè)假想的框子,它盡可能緊密的裝入字形。

baseline(基線),一條假想的線,一行上的字形都以此線作為上下位置的參考,在這條線的左側(cè)存在一個(gè)點(diǎn)叫做基線的原點(diǎn),

ascent(上行高度)從原點(diǎn)到字體中最高(這里的高深都是以基線為參照線的)的字形的頂部的距離,ascent是一個(gè)正值

descent(下行高度)從原點(diǎn)到字體中最深的字形底部的距離,descent是一個(gè)負(fù)值(比如一個(gè)字體原點(diǎn)到最深的字形的底部的距離為2,那么descent就為-2)

linegap(行距),linegap也可以稱作leading(其實(shí)準(zhǔn)確點(diǎn)講應(yīng)該叫做External leading),行高lineHeight則可以通過 ascent + |descent| + linegap 來計(jì)算。

一些Metrics專業(yè)知識(shí)還可以參考Free Type的文檔 Glyph metrics,其實(shí)iOS就是使用Free Type庫來進(jìn)行字體渲染的。

以上圖片和部分概念來自蘋果文檔 Querying Font Metrics ,Text Layout


2.坐標(biāo)系

蘋果編程中的坐標(biāo)系不明白為什么會(huì)各有不同。 傳統(tǒng)的Mac中的坐標(biāo)系的原點(diǎn)在左下角,比如NSView默認(rèn)的坐標(biāo)系,原點(diǎn)就在左下角。但Mac中有些View為了其實(shí)現(xiàn)的便捷將原點(diǎn)變換到左上角,像NSTableView的坐標(biāo)系坐標(biāo)原點(diǎn)就在左上角。iOS UIKit的UIView的坐標(biāo)系原點(diǎn)在左上角。


看完上邊兒這些,該上代碼勒。


先拿一個(gè)定義好的屬性字符串。

NSMutableAttributedString *attrString = [[NSMutableAttributedString? alloc] initWithString:self.text];//這個(gè)self.text 就是你要用到的字符串

[attrString setAttributes:self.coreTextAttributes range:NSMakeRange(0, attrString.length)];//這里的self.coreTextAttributes就是一個(gè)字典,來配置這個(gè)屬性字符串的,可在他的set方法中隨意設(shè)置,比如顏色,下劃線,刪除線,字型等等


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

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

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

if (_ctFrame != NULL) { ?//這里的_ctFrame 就是一個(gè)裝有字符屬性的集合

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

加上以上這兩句就可以了,就順利的將字畫到了畫布上。


再之后給文字加個(gè)方框

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)};//繪制四邊,位置隨意調(diào)整,位置可以調(diào)整之后也就可以實(shí)現(xiàn)我的下劃線在任何位置了

CGContextAddLines(context, poins, 4);

CGContextClosePath(context);

CGContextStrokePath(context);

}

}


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

第一次寫文章,主要是當(dāng)時(shí)搞這個(gè)東西走了彎路,對(duì)coreText的不了解,也在csdn和cocoachina上問了好多人,都沒解決,防止以后忘記,自己再紀(jì)錄一下。


我目前做的項(xiàng)目是做的小說閱讀器,網(wǎng)上的素材真的是不多,現(xiàn)在也算是寫的差不多了,但是在預(yù)加載,內(nèi)存緩存和磁盤緩存上做的還是不行,希望有做閱讀器這方面有好的方案的,希望可以教教小弟,第一篇小文 也就搞定勒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.iOS中的round、ceil、floor函數(shù)略解 round如果參數(shù)是小數(shù),則求本身的四舍五入.ceil如果...
    K_Gopher閱讀 1,266評(píng)論 1 0
  • 本文所涉及的代碼你可以在這里下載到https://github.com/kejinlu/CTTest,包含兩個(gè)項(xiàng)目...
    eb99d15a673d閱讀 1,336評(píng)論 0 6
  • 目前社交類型的App也是層出不窮,無論是QQ的說說,還是微信的動(dòng)態(tài),微博的帖子。這種類型的App都會(huì)涉及到點(diǎn)贊文本...
    墨香茉香閱讀 721評(píng)論 0 3
  • CoreText是iOS/OSX中文本顯示的一個(gè)底層框架,它是用C語言寫成的,有快速簡單的優(yōu)勢。iOS中的Text...
    小貓仔閱讀 5,124評(píng)論 2 9
  • 最近在網(wǎng)上看了一些大牛的文章,自己也試著寫了一下,感覺圖文混排真的很強(qiáng)大。 廢話不多說,開始整 先上效果圖跟代碼,...
    AllureJM閱讀 1,134評(píng)論 0 1

友情鏈接更多精彩內(nèi)容