若是您是一位 WEB 開發者,相信您對 CSS 的 font-family 屬性必定不會陌生。一般咱們會爲 font-family 屬性設置一長串的字體(家族)列表,就像這樣的:css
.text { font-family: Menlo, Monaco, Consolas, "Courier New", monospace, Arial, "Microsoft YaHei", "黑體", "宋體", sans-serif; }
複製代碼
有人確定會問,爲何要這麼設置啊?若是你足夠細心,你必定會發現當你瀏覽該網頁時英文字體和中文字體並非同一種字體,若是你在不一樣的操做系統甚至不一樣的電腦上看到網頁所呈現的字體也不同。這又是爲何呢?git
此外,在您使用 Microsoft Word 進行段落排版的時候,你會發現 Word 能夠自動對中文樣式應用中文字體,對英文樣式應用英文字體。這又是如何作到的呢?github
在實際的排版需求中,爲了好看,咱們一般會須要針對不一樣語言的文字 (script) 進行不一樣的字體設定,以達到最佳的視覺效果。固然,對於咱們來講,最多見的仍是中英文混排。一般設計人員給出的設計稿很是漂亮,但是中英文使用了不一樣的字體,咱們開發人員該如何高保真地還原設計稿的原始設計呢?swift
很顯然,對於 WEB 開發者來講,已經有了很好的解決方案,而對於其餘客戶端的同窗來講,這估計應該就有點犯難了,咱們一般會告訴設計人員:「系統不支持」 抑或 「作不了」 之類的話。那事實上,到底能不能作到呢?答案是確定的。app
要實現這個,咱們先來了解一個概念:fallback 機制。字體
這種機制一般是首先規定拉丁字母、西裏爾字母、希臘字母等西文的字體,而後以必定的順序分別規定阿拉伯字母、天城文(例如印度文)、日文、韓文、簡體中文、繁體中文等文字的字體。文本引擎會盡可能用優先的字體來顯示當前遇到的字符,若是 fallback 列表中最靠前的字體不支持此字符,就向後找(這就是所謂 fallback)。CSS 的 font-family 屬性基本也是這樣工做的。動畫
Windows 其實也是相似這樣的。目前 Windows 7 的西文字體是 Segoe UI,簡體中文字體是微軟雅黑,繁體中文字體是微軟正黑,日文字體是 Meiryo,天城文字體是 Mangal…… 因此你根本不須要這樣的軟件,你的操做系統已是這樣了。ui
由於中日韓漢字共享 Unicode code point,因此當一個字(好比「直」這個字)同時受到簡體中文、繁體中文、日文、韓文字體的支持,操做系統會根據當前的 locale 以及系統語言列表的順序選擇最優先的書寫系統的字體。spa
然而,不多談及移動操做系統上的字體 fallback 機制,更別說實現了,還好我通過不斷查找,找到一些蛛絲馬跡。因爲本人是一名 iOS 開發者,因此咱們以 iOS 爲例,來看看它的實現方式。操作系統
一般,咱們使用以下的方式建立一個字體:
let systemFont = UIFont.systemFont(ofSize: fontSize)
複製代碼
顯然,若是您還這樣建立,確定沒法實現咱們的目標。那應該怎麼作呢?咱們須要使用到 UIFontDescriptor,代碼以下:
public extension UIFont {
convenience init(names: [String], size: CGFloat) {
if names.first != nil {
let mainFontName = names.first!
let descriptors = names.map { UIFontDescriptor(fontAttributes: [.name: $0]) }
let attributes: [UIFontDescriptor.AttributeName: Any] = [
UIFontDescriptor.AttributeName.cascadeList: descriptors,
UIFontDescriptor.AttributeName.name: mainFontName,
UIFontDescriptor.AttributeName.size: size,
]
let customFontDescriptor: UIFontDescriptor = UIFontDescriptor(fontAttributes: attributes)
self.init(descriptor: customFontDescriptor, size: size)
}
else{
let systemFont = UIFont.systemFont(ofSize: size)
let systemFontDescriptor: UIFontDescriptor = systemFont.fontDescriptor
self.init(descriptor: systemFontDescriptor, size: size)
}
}
convenience init(families: [String], size: CGFloat, weight: UIFont.Weight = .regular) {
if families.first != nil {
let mainFontFamily = families.first!
let descriptors = families.map { UIFontDescriptor(fontAttributes: [.family: $0]) }
let traits = [UIFontDescriptor.TraitKey.weight: weight]
let attributes: [UIFontDescriptor.AttributeName: Any] = [
UIFontDescriptor.AttributeName.cascadeList: descriptors,
UIFontDescriptor.AttributeName.family: mainFontFamily,
UIFontDescriptor.AttributeName.size: size,
UIFontDescriptor.AttributeName.traits: traits
]
let customFontDescriptor: UIFontDescriptor = UIFontDescriptor(fontAttributes: attributes)
self.init(descriptor: customFontDescriptor, size: size)
}
else{
let systemFont = UIFont.systemFont(ofSize: size, weight: weight)
let systemFontDescriptor: UIFontDescriptor = systemFont.fontDescriptor
self.init(descriptor: systemFontDescriptor, size: size)
}
}
}
複製代碼
調用示例:
let text = "これは日本語文章と Roman Text の混植文章です。美しいヒラギノと San Francisco で日本語とローマ字を書きます。System Font のフォントメトリクスには獨自の調整が入っています。\n\nあのイーハトーヴォの\nすきとおった風、\n夏でも底に冷たさをもつ青いそら、\nうつくしい森で飾られたモーリオ市、\n郊外のぎらぎらひかる草の波。\n祇辻飴葛蛸鯖鰯噌庖箸\n底辺直卿蝕薩化\nABCDEFGHIJKLM\nabcdefghijklm\n1234567890iClockᴹᴵᴺᴵClockªMINI"
let font = UIFont(families: ["Lucida Grande", "Baskerville", "Apple SD Gothic Neo"], size: 20, weight: .medium)
//let font = UIFont(names: ["LucidaGrande", "Baskerville", "AppleSDGothicNeo-Thin"], size: 20)
label.font = font
label.text = text
複製代碼
其中 family 和 font name 這兩個別搞混了,不知道怎麼在 iOS 上看字體的 family 和 font name 的能夠下載這個 App:字體預覽(itunes.apple.com/cn/app/字體預覽…)
若是是自定義字體,也能夠在同一個wifi的局域網中將字體上傳到 App 裏查看。
演示動畫:
Github源碼: github.com/pcjbird/fbC…
參考連接:
是否有一種軟件可以對不一樣語言的文字指定不一樣的字體?
Fallback to pure Japanese font. No more Chinese font in Japanese text on iOS apps.