CoreText學習(一)Base Objects of Core Text

最近要作一個讀入Word,PDF格式等的文件而且加以編輯的程序,原本覺得使用Text Kit結合Text View來打開doc文件是徹底沒問題的,結果用了各類方法打開要麼是數據是nil,要麼打開的文字中不少亂碼。對於Word,PDF這種格式或許必需要用底層的Core Text來作了(若是用WebView來作的話,很難對內容進行操做)。框架

因此接下來又要從Core Text從頭學起了。首先看了Core Text Programming Guide,理解的並不算深刻,可是寫個博客來作個筆記吧。ide


Core Text是一個iOS中一個比較底層的框架,借用iOS7 Text Kit介紹視頻中的一個圖:佈局


其中Core Text在Core Graphics之上,Text Kit在Core Text之上構建(UIWebView不在Text Kit之上,不少Text Kit中很棒的特性UIWebView沒法使用)。學習

在文檔中,Core Text被描述爲一個高級的、底層的框架,主要用來對文本進行排版佈局和字體處理。字體

Core Text有一個很強大的功能就是進行Character-to-glyph轉換,其實以前看Text Kit的時候glyph這個詞就是一個高頻出現的詞,我的以爲必需要分清楚character,glyph,font這些概念之間的分別。ui

按照我的的理解(語文很差,說錯了請指出):spa

(1)character:字符,指一個符號,數字或者文字等。.net

(2)glyph:字形,對於同一套字符有不一樣的寫法,形態或者說是樣式。字形是字符的一族形態,例如Helvetica, New Romancode

(3)font:字體,在字形的基礎上進行的加工修飾便構成了字體,如加粗,傾斜,加顏色,改變磅數等。例如orm

9pt Helvetica Bold是一個字體。

回到文檔來看看Character-to-glyph conversion:


對應同一個字符A,有着各類不一樣的形態,對應不一樣的字形glyph,固然同一種風格的寫法便構成了一種字形。


一樣地,對於f加l兩個字符連起來寫便又變成了一種新的寫法,對應另一種字形。

經過Core Text能夠快速高效地進行字符到字形之間的轉換。

使用Core Text能夠直接使用Core Foundation的對象,這些對象是toll-free bridging的(一種容許某些OC類與其對應的CoreFoundation類之間能夠互換使用的機制),因此無需進行特殊的對象類型轉換。另外Core Text構建於Core Graphics框架之上,因此能夠經過Core Graphics的方法進行高效高質量的文字描畫。


接下來是Core Text的一些Base Objects。

1.Layout Objects:Framesetters, Frames, Typesetters, Lines and Glyph runs

仍是先上個圖吧:


其中framesetter經過attributed string對象持有文本的內容,並調用typesetter來建立line對象從而填滿由CGPath所描述的區域。輸出的結果是包含了一系列行對象的一個frame。

其中每個line中對於相同屬性內的一段文字使用同一個的CTRun對象去描畫該段文字:


下面這張圖(來自raywenderlich)更加容易理解:


其中CTRun對象會由Core Text自動生成,不須要也不該該由開發者本身去建立,因此整個程序跑起來有不少細節是開發者不用考慮的。


2.Font Objects:Fonts, Font Descriptors, Font Collections

Font Descriptor用來描述字體的特性,是Font的核心部分,Font Collections是許多個Font Descriptors的集合。


說完一大堆Core Text的基本對象後,仍是寫個Demo看看(主要參考了http://blog.csdn.net/andypan1314/article/details/7614469)

首先要使用Core Text框架的話,第一步是要導入CoreText.framework,而後在要使用的頭文件中導入:

 

#import <CoreText/CoreText.h>

 

 

在使用Core Text來draw文字的時候,關鍵是要使用UIView中的drawRect:方法,因此先新建一個ViewController,而後新建一個UIView的子類,並將兩者在視圖上關聯起來。

而後重寫View中的drawRect:方法:

 

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    
    // 1.建立一個字符串用來保存文本內容  CFAttributedString
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"First Core Text Demo"];
    
    
    // 2.建立一個framesetter用來管理描畫文字的frame  CTFramesetter
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString);
    
    
    // 3.建立一個用來描畫文字的路徑,其區域爲當前視圖的bounds  CGPath
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rectForPath = CGRectMake(0.0, 0.0, self.bounds.size.width, self.bounds.size.height - 20.0);
    CGPathAddRect(path, NULL, rectForPath);
    
    
    // 4.建立由framesetter管理的frame,是描畫文字的一個視圖範圍  CTFrame
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, attrString.length), path, NULL);
    
    
    // 5.獲取當前視圖的上下文環境
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    
    // 6.經過context在frame中描畫文字內容
    CTFrameDraw(frame, context);
    
    
    // 7.全部建立的對象必須被release
    CFRelease(frame);
    CFRelease(path);
    CFRelease(frameSetter);
}


 

以上代碼中各個對象的建立順序基本與Figure 1.3相同。

其中首先對NSAttributedString強制類型轉換獲得CFAtttributedString對象用來保存文本內容,而後建立一個CTFramesetter對象用來保存文本內容、在所管理的Frame中對文字進行佈局、輸出文字等,接着建立CGPath對象和CTFrame對象,兩者定義了一個輸出文字內容的區域。注意CTTypesetter在CTFramesetter建立時隨之而生成了,不須要再手動去建立。

在基本對象建立好後,獲取當前視圖上下文並設置好一些仿射變換後,直接在Frame中draw就完成了文字的輸出:


注意最後全部建立的Core Foundation對象都必須被釋放。


還有一個大問題,draw出來的文字是倒過來的,必需要將它們倒回來。

這就涉及到仿射變換的內容了,有篇文章挺好理解的:http://hi.baidu.com/cqhg1981/item/1a527bf4bda2fb0fc6dc45aa

主要的仿射變換有下面幾種:



其中translation是平移,flip是翻轉,rotation是旋轉,scaling是縮放,shear是錯切,identity是保持不變。


再看看基本的仿射變換代碼:

 

// 平移仿射變換:tx爲x正方向上的位移量,ty爲y正方向上的位移量
CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)

// 縮放仿射變換:在原點的基礎上進行縮放,sx爲x正方向上的縮放倍數,sy爲y正方向上的縮放倍數。若是縮放倍數爲負數則爲反向縮放
CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy);

// 旋轉仿射變換:angle爲旋轉角度,逆時針爲正,順時針爲負
CGContextRotateCTM(CGContextRef c, CGFloat angle);


 

CGContextRef context =UIGraphicsGetCurrentContext();下面加上如下代碼。

首先設置好初始的仿射變換矩陣(原封不動):

 

CGContextSetTextMatrix(context, CGAffineTransformIdentity);

 


而後將整個視圖向右移動10.0,向下方移動整個視圖的高度:

 

CGContextTranslateCTM(context, 10.0, self.bounds.size.height);


最後倒過來(方向放大):

 

 

CGContextScaleCTM(context, 1.0, -1.0);


Run一下:

 


完成了。


Core Text還有不少內容,隨着我學習的深刻會繼續更新博客的。

相關文章
相關標籤/搜索