iOS 定製應用程式字型

來源:互聯網
上載者:User

使用Quartz Core繪製文字非常簡單,蘋果的Quartz 2D參考中示範了如何使用CGContextShowTextAtPoint函數繪製文本。不幸的是,這個函數不支援Unicode字元的繪製(這個函數只支援MacRoman一種編碼)。如果你使用中文、日文等亞洲字型,那麼就不得不悲催了。

許多童鞋肯定會被文檔中的這句話所吸引:

“如果想使用MacRoman以外的文本編碼,⋯⋯調用CGContextShowGlyphsAtPoint替代CGContextShowTextAtPoint。”

如果你採用這種辦法,那麼另一種悲劇就產生了。

一、CGContextShowGlyphsAtPoint的挑戰

 

CGContextShowGlyphsAtPoint 函數的第4個參數要使用到CGGlyph數組。意思是你需要自己把unichar字元自已映射成字型檔中的Glyph(字元圖形,有稱字模、字元點陣)索引。如果你不使用私人架構,那麼這是一個幾乎不可能完成的任務。

實際上,大部分程式員會建議你用UIKit架構或者[NSString drawAtPoint:]方法而不是NSStringCGContextShowGlyphsAtPoint來繪製unicode字元。

如果你真是只是想在UIView上繪製幾句文本,那麼drawAtPoint能夠滿足你的需要,下面的內容你也不必要看了。

 

但是,CGContextShowGlyphsAtPoint就真的沒有任何用處了嗎?

實際上,蘋果最初設計這個API的目的,是為了提供給Application使用定製字型的能力。基本上iOS提供的系統字型非常少,我們在一些app中為了實現一些效果(比如讓字型更加清晰)不得不使用自己的字型檔,這個時候這些API就顯得非常必要。

然而,關於使用自定字型,蘋果的文檔描述得非常少。我們知道的僅僅是CGContextSetFont和CGContextSetFontSize、CGContextShowGlyphsAtPoint等3個Quartz函數。所有的google文檔都語焉不詳。顯然,真正要想使用自定字型,根本沒有這麼簡單。

那麼真正的挑戰在哪裡?

StackOverFlow上有人發了一個文章,文章問到如何用繪製日文字元(中文也是一樣)。其中 Brad Larson 的回複描述得很精確:

You may also be able to print custom characters withCGContextShowGlyphsAtPoint(), but the challenge is generating the glyphs on theiPhone. This post has an example: gogo-robot.com/devblog/?p=5 – Brad Larson

真正的挑戰是unicharàglyph,也就是 CGContextShowGlyphsAtPoint的第4個參數如何獲得。Brad提到的例子實際上描述了一種不可能的情況,他假設字型檔中的glyph編碼是在unicode編碼的基礎上加一個固定的位移量(他稱之為Magic Number)構成。實際上對於某個.ttf/.otf字型檔,我們無法獲得這個MagicNumber,我們不能靠猜測來編寫程式碼。

那麼我們只有自己解析字型檔的資料結構了。萬幸的是,Zynga Game Networks的 Kevin Ballard實現了一個unichar到glyph的映射。項目地址:https://github.com/zynga/FontLabel。

我們可以利用這個實現來解析cmap為format4和format12的字型檔。

關於cmap的內容,請參考True Type 字型檔相關文檔(微軟和蘋果的網站)。

二、實現過程

1、在程式中載入ttf檔案

首先要解決的問題,是在程式中載入.ttf/otf檔案。我們在樣本程式的資源束中加入了一個“方正大黑簡體.ttf”的檔案。這個檔案是我從Mac系統中搜尋到的,應該是MicrosoftOffice中提供的字型檔。我們用以下代碼來載入它:

NSString *fontPath = [[NSBundlemainBundle] pathForResource:@"方正大黑簡體" ofType:@"ttf"];

    CGDataProviderReffontDataProvider = CGDataProviderCreateWithFilename([fontPath UTF8String]);

    font_ref =CGFontCreateWithDataProvider(fontDataProvider);

    currentTable=readFontTableFromCGFont(font_ref);

    CGDataProviderRelease(fontDataProvider);

提示:在iOS3.2以後,還可以在plist檔案中添加 UIAppFonts鍵的方式添加自定字型。見蘋果文檔“Custom Font Support”主題。

2、從字型檔中擷取Glyph

這部分的實現來自Ballard的FontLabel,非常感謝!整個實現主要包含2個函數定義:

staticfontTable*readFontTableFromCGFont(CGFontRef font);

 

staticvoidmapCharactersToGlyphsInFont(constfontTable *table, unichar characters[], size_t charLen, CGGlyph outGlyphs[], size_t *outGlyphLen) ;

第一個函數用於從CGFont中讀取cmap表,第二個函數用於將unichar數組映射為Glyphs數組(實現cmap format4和format12子表)。

3、繪製字元

Quartz繪圖是在UIView的drawRect方法中進行,字元也不例外。下面是字元繪製代碼:

CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextClearRect(context, rect);

    CGContextSetFont(context, font_ref);

    CGContextSetTextDrawingMode(context, kCGTextFillStroke);

    CGContextSetFillColorWithColor(context, fontColor.CGColor);

    UIColor * strokeColor = [UIColorblackColor];

    CGContextSetStrokeColorWithColor(context, strokeColor.CGColor);

    CGContextSetFontSize(context, 24.0f);

   

    CGGlyph glyphs[[self.textlength]];

    size_t glyphCount;

    unichar textChars[[textlength]];

    [textgetCharacters:textChars range:NSMakeRange(0, text.length)];

    mapCharactersToGlyphsInFont(currentTable, textChars, text.length, glyphs, &glyphCount);

    CGAffineTransform textTransform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0,0.0, 0.0);

    CGContextSetTextMatrix(context,textTransform);

    CGContextShowGlyphsAtPoint(context, 20, 30, glyphs, [self.textlength]);

代碼中先使用Ballard實現的mapCharactersToGlyphsInFont函數將unicode字元轉換為Glyphs數組,然後用CGContextShowGlyphsAtPoint進行繪製。

注意:由於Quartz空間和使用者空間的座標系統不同(Quartz空間座標原點位於螢幕左下角,使用者空間座標原點位於螢幕左上方,二者座標轉換隻需y座標取反即可),所以我們使用了一個漸層反射來進行座標轉換並應用於文字矩陣。

4、運行效果

圖片

5、原始碼下載

整個樣本工程見資源下載:http://download.csdn.net/detail/kmyhy/4359481

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.