8
8
9
9
import Cairo
10
10
import CCairo
11
- import CFontConfig
11
+ import FontConfig
12
12
import Foundation
13
13
#if os(macOS)
14
14
import struct CoreGraphics. CGAffineTransform
@@ -34,7 +34,7 @@ public struct CGFont {
34
34
35
35
// MARK: - Initialization
36
36
37
- public init ? ( name: String ) {
37
+ public init ? ( name: String , configuration : FontConfiguration = . current ) {
38
38
39
39
if let cachedFont = CGFont . cache [ name] {
40
40
@@ -43,10 +43,11 @@ public struct CGFont {
43
43
} else {
44
44
45
45
// create new font
46
- guard let ( fontConfigPattern, family) = FcPattern ( name: name)
46
+ guard let pattern = FontConfig . Pattern ( cgFont: name, configuration: configuration) ,
47
+ let family = pattern. family
47
48
else { return nil }
48
49
49
- let face = FontFace ( fontConfigPattern : fontConfigPattern )
50
+ let face = FontFace ( pattern : pattern )
50
51
51
52
let options = FontOptions ( )
52
53
options. hintMetrics = . off
@@ -147,93 +148,59 @@ public extension CGFont {
147
148
}
148
149
}
149
150
150
- // MARK: - Private
151
+ // MARK: - Font Config Pattern
151
152
152
- /// Initialize a pointer to a `FcPattern` object created from the specified PostScript font name.
153
- internal func FcPattern( name: String ) -> ( pointer: OpaquePointer , family: String ) ? {
153
+ internal extension FontConfig . Pattern {
154
154
155
- guard let pattern = FcPatternCreate ( )
156
- else { return nil }
157
-
158
- /// hacky way to cleanup, `defer` will copy initial value of `Bool` so this is needed.
159
- /// ARC will cleanup for us
160
- final class ErrorCleanup {
155
+ convenience init ? ( cgFont name: String , configuration: FontConfiguration = . current) {
156
+ self . init ( )
161
157
162
- var shouldCleanup = true
158
+ let separator : Character = " - "
163
159
164
- let cleanup : ( ) -> ( )
160
+ let traits : String ?
165
161
166
- deinit { if shouldCleanup { cleanup ( ) } }
162
+ let family : String
167
163
168
- init ( cleanup: @escaping ( ) -> ( ) ) {
169
-
170
- self . cleanup = cleanup
171
- }
172
- }
173
-
174
- let cleanup = ErrorCleanup ( cleanup: { FcPatternDestroy ( pattern) } )
175
-
176
- let separator : Character = " - "
177
-
178
- let traits : String ?
179
-
180
- let family : String
181
-
182
- let components = name. split ( separator: separator, maxSplits: 2 , omittingEmptySubsequences: true )
183
-
184
- if components. count == 2 {
185
- family = String ( components [ 0 ] )
186
- traits = String ( components [ 1 ] )
187
- } else {
188
- family = name
189
- traits = nil
190
- }
191
-
192
- guard FcPatternAddString ( pattern, FC_FAMILY, family) != 0
193
- else { return nil }
194
-
195
- // FontConfig assumes Medium Roman Regular, add / replace additional traits
196
- if let traits = traits {
164
+ let components = name. split ( separator: separator, maxSplits: 2 , omittingEmptySubsequences: true )
197
165
198
- if traits. contains ( " Bold " ) {
199
-
200
- guard FcPatternAddInteger ( pattern, FC_WEIGHT, FC_WEIGHT_BOLD) != 0
201
- else { return nil }
166
+ if components. count == 2 {
167
+ family = String ( components [ 0 ] )
168
+ traits = String ( components [ 1 ] )
169
+ } else {
170
+ family = name
171
+ traits = nil
202
172
}
203
173
204
- if traits. contains ( " Italic " ) {
205
-
206
- guard FcPatternAddInteger ( pattern, FC_SLANT, FC_SLANT_ITALIC) != 0
207
- else { return nil }
208
- }
174
+ self . family = family
175
+ assert ( self . family == family)
209
176
210
- if traits. contains ( " Oblique " ) {
177
+ // FontConfig assumes Medium Roman Regular, add / replace additional traits
178
+ if let traits = traits {
211
179
212
- guard FcPatternAddInteger ( pattern, FC_SLANT, FC_SLANT_OBLIQUE) != 0
213
- else { return nil }
214
- }
215
-
216
- if traits. contains ( " Condensed " ) {
180
+ if traits. contains ( " Bold " ) {
181
+ self . weight = . bold
182
+ }
217
183
218
- guard FcPatternAddInteger ( pattern, FC_WIDTH, FC_WIDTH_CONDENSED) != 0
219
- else { return nil }
184
+ if traits. contains ( " Italic " ) {
185
+ self . slant = . italic
186
+ }
187
+
188
+ if traits. contains ( " Oblique " ) {
189
+ self . slant = . oblique
190
+ }
191
+
192
+ if traits. contains ( " Condensed " ) {
193
+ self . width = . condensed
194
+ }
220
195
}
196
+
197
+ guard configuration. substitute ( pattern: self , kind: FcMatchPattern)
198
+ else { return nil }
199
+
200
+ self . defaultSubstitutions ( )
201
+
202
+ guard configuration. match ( self ) != nil
203
+ else { return nil }
204
+
221
205
}
222
-
223
- let matchPattern = FcMatchKind ( rawValue: 0 ) // FcMatchPattern
224
-
225
- guard FcConfigSubstitute ( nil , pattern, matchPattern) != 0
226
- else { return nil }
227
-
228
- FcDefaultSubstitute ( pattern)
229
-
230
- var result = FcResult ( 0 )
231
-
232
- guard FcFontMatch ( nil , pattern, & result) != nil
233
- else { return nil }
234
-
235
- // success
236
- cleanup. shouldCleanup = false
237
-
238
- return ( pattern, family)
239
206
}
0 commit comments