| 1 | import CoreText |
| 2 | import Foundation |
| 3 | #if os(macOS) |
| 4 | import AppKit |
| 5 | typealias DocsPlatformFont = NSFont |
| 6 | #else |
| 7 | import UIKit |
| 8 | typealias DocsPlatformFont = UIFont |
| 9 | #endif |
| 10 | |
| 11 | @MainActor enum DocsFonts { |
| 12 | private static let registered: Void = { |
| 13 | for family in ["Sans", "Serif", "Mono"] { |
| 14 | for face in ["Regular", "Bold", "Italic", "BoldItalic"] { |
| 15 | let name = "Liberation\(family)-\(face)" |
| 16 | if let url = DocsResources.bundle.url(forResource: name, withExtension: "ttf") { |
| 17 | CTFontManagerRegisterFontsForURL(url as CFURL, .process, nil) |
| 18 | } |
| 19 | } |
| 20 | } |
| 21 | }() |
| 22 | static func font(marks: [String: JSONValue], size baseSize: CGFloat, heading: Bool) -> DocsPlatformFont { |
| 23 | _ = registered |
| 24 | var size = baseSize |
| 25 | for key in marks.keys.sorted() where key.hasPrefix("size_") { |
| 26 | if let value = Double(key.dropFirst(5)), [8, 9, 10, 11, 12, 14, 18, 24, 36, 48, 72].contains(value) { size = value } |
| 27 | else if key == "size_sm" { size = 10 } |
| 28 | else if key == "size_lg" { size = 14 } |
| 29 | else if key == "size_xl" { size = 18 } |
| 30 | } |
| 31 | if marks["code"] != nil { size *= 0.85 } |
| 32 | let family = marks["font_mono"] != nil || marks["code"] != nil ? "Mono" : marks["font_serif"] != nil ? "Serif" : "Sans" |
| 33 | let bold = marks["strong"] != nil || heading |
| 34 | let italic = marks["em"] != nil |
| 35 | let face = bold ? (italic ? "BoldItalic" : "Bold") : (italic ? "Italic" : "Regular") |
| 36 | let postScriptName = "Liberation\(family)" + (face == "Regular" ? "" : "-\(face)") |
| 37 | return DocsPlatformFont(name: postScriptName, size: size) ?? DocsPlatformFont.systemFont(ofSize: size) |
| 38 | } |
| 39 | } |
| 40 | |