在文本繪制的過(guò)程中,使用textview,textfield,及Text Kit的過(guò)程中,你所能繪制的文本是只能在水平方向及豎直方向排布的,但在實(shí)際的工作中,可能有一類需求是需要你沿著任意一條曲線,可以是弧線,也可以是用戶指定的任意曲線,或者用戶用手指在屏幕上描繪出來(lái)的一條曲線,這個(gè)時(shí)候即是Core Text為你效勞的時(shí)候了
apple給出的官方樣例是Drawing Along a Path Using Core Text with Cocoa,這個(gè)例子其實(shí)是mac開(kāi)發(fā)代碼,但可以很輕松地移植到iOS上來(lái),下面詳細(xì)記錄一下使用這個(gè)樣例的時(shí)候遇到的一些問(wèn)題
編譯相關(guān)
在查看CTLineRef的定義的時(shí)候看到SDK頭文件中它是這樣描述的
typedef const struct CF_BRIDGED_TYPE(id) __CTLine * CTLineRef;
#define CF_BRIDGED_TYPE(T) __attribute__((objc_bridge(T)))
里面的__attribute__指令已經(jīng)不是第一次看到了,隨手查了一下,鏈接在這里,而里面objc_bridge(T)的實(shí)際作用是告訴編譯器,在轉(zhuǎn)換成OC對(duì)象時(shí),只能轉(zhuǎn)換成類型T,如果顯式轉(zhuǎn)換時(shí)會(huì)在Xcode中生成警告。
CTLine涉及到一個(gè)叫做CTRun的概念,概念,它實(shí)際的圖形化闡述是

Core Text相關(guān)
CGAffineTransform:是一種二維坐標(biāo)到二維坐標(biāo)之間的變換,用來(lái)表示二維空間中坐標(biāo)的線性變換,用來(lái)表示某坐標(biāo)進(jìn)行位移,旋轉(zhuǎn),縮放等操作之后所映射到的坐標(biāo)。
textMatrix:這個(gè)矩陣定義的是從文本空間到用戶空間的映射,使用CGAffineTransform來(lái)表示變換的規(guī)則,使用的Core Text API為CGContextSetTextMatrix(context c,CGAffineTransform f); 一個(gè)小細(xì)節(jié)可以反映一點(diǎn)其內(nèi)部操作,即在設(shè)置了tx和ty之后,當(dāng)前textPosition即等于原點(diǎn)的位置加上(tx,ty)了。直觀地理解,可以將CGAffineTransform的tx和ty理解為原點(diǎn)的偏移,而a,b,c,d分量則是進(jìn)行縮放及旋轉(zhuǎn)的因子,即在glyph繪制的textPosition為原點(diǎn),以a,b,c,d為因子進(jìn)行以原點(diǎn)為中心的縮放及旋轉(zhuǎn)。
沿圓弧繪制文本的做法
樣例中沿圓弧繪制文本的原理其實(shí)很簡(jiǎn)單,后一個(gè)字符在繪制的時(shí)候,只要偏移前幾個(gè)字符所占用的角度即可。
備注:
Core Graphics的默認(rèn)坐標(biāo)系是ULO(upper-left-origin)坐標(biāo)系,即以畫(huà)布的左上頂點(diǎn)為原點(diǎn)。
CGContextAddArc的最后一個(gè)參數(shù)clockwise按其SDK的標(biāo)注,1代表順時(shí)針,其實(shí)應(yīng)該是逆時(shí)針,看樣子這文檔有可能原本是給Mac開(kāi)發(fā)用的,忘記在ios上這里其實(shí)是反的,另外角度的增加順序是從x軸正向?yàn)?,順時(shí)針?lè)较蛟鲩L(zhǎng),也就是Y軸負(fù)向方向?yàn)棣?2
CTRunDraw的神奇之處在于,如果只想繪制run中的一部分glyph,則在指定了run及range之后,從繪制起點(diǎn)開(kāi)始,到range中的第一個(gè)字符顯示的位置,是有一段空白的,其實(shí)相當(dāng)于仍給range之前的字符留了位置,只是未將其繪制出來(lái)而已,暫時(shí)還不知道其緣由是什么。