OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
3 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> | 3 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * | 8 * |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #import "config.h" | 30 #import "config.h" |
31 #import "platform/fonts/mac/FontFamilyMatcherMac.h" | 31 #import "platform/fonts/mac/FontFamilyMatcherMac.h" |
32 | 32 |
33 #import <AppKit/AppKit.h> | 33 #import <AppKit/AppKit.h> |
34 #import <Foundation/Foundation.h> | 34 #import <Foundation/Foundation.h> |
35 #import <math.h> | 35 #import <math.h> |
36 #import <wtf/HashSet.h> | 36 #import <wtf/HashSet.h> |
37 #import <wtf/text/AtomicStringHash.h> | 37 #import <wtf/text/AtomicStringHash.h> |
38 | 38 |
39 #include "platform/fonts/FontTraits.h" | |
40 #include "platform/LayoutTestSupport.h" | |
41 #include "platform/mac/VersionUtilMac.h" | |
42 | |
43 @interface NSFont (YosemiteAdditions) | |
44 + (NSFont*)systemFontOfSize:(CGFloat)size weight:(CGFloat)weight; | |
45 @end | |
46 | |
47 namespace { | |
48 | |
49 static CGFloat toYosemiteFontWeight(blink::FontWeight fontWeight) | |
50 { | |
51 static uint64_t nsFontWeights[] = { | |
52 0xbfe99999a0000000, // NSFontWeightUltraLight | |
53 0xbfe3333340000000, // NSFontWeightThin | |
54 0xbfd99999a0000000, // NSFontWeightLight | |
55 0x0000000000000000, // NSFontWeightRegular | |
56 0x3fcd70a3e0000000, // NSFontWeightMedium | |
57 0x3fd3333340000000, // NSFontWeightSemibold | |
58 0x3fd99999a0000000, // NSFontWeightBold | |
59 0x3fe1eb8520000000, // NSFontWeightHeavy | |
60 0x3fe3d70a40000000, // NSFontWeightBlack | |
61 }; | |
62 ASSERT(fontWeight >= 0 && fontWeight <= 8); | |
63 CGFloat* weight = reinterpret_cast<CGFloat*>(&nsFontWeights[fontWeight]); | |
64 return *weight; | |
65 } | |
66 } | |
67 | |
68 namespace blink { | 39 namespace blink { |
69 | 40 |
70 const NSFontTraitMask SYNTHESIZED_FONT_TRAITS = (NSBoldFontMask | NSItalicFontMa
sk); | 41 const NSFontTraitMask SYNTHESIZED_FONT_TRAITS = (NSBoldFontMask | NSItalicFontMa
sk); |
71 | 42 |
72 const NSFontTraitMask IMPORTANT_FONT_TRAITS = (NSCompressedFontMask | 43 const NSFontTraitMask IMPORTANT_FONT_TRAITS = (NSCompressedFontMask |
73 | NSCondensedFontMask | 44 | NSCondensedFontMask |
74 | NSExpandedFontMask | 45 | NSExpandedFontMask |
75 | NSItalicFontMask | 46 | NSItalicFontMask |
76 | NSNarrowFontMask | 47 | NSNarrowFontMask |
77 | NSPosterFontMask | 48 | NSPosterFontMask |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 if (chosenWeightDeltaMagnitude == candidateWeightDeltaMagnitude) | 94 if (chosenWeightDeltaMagnitude == candidateWeightDeltaMagnitude) |
124 return abs(candidateWeight - 6) > abs(chosenWeight - 6); | 95 return abs(candidateWeight - 6) > abs(chosenWeight - 6); |
125 | 96 |
126 // Otherwise, prefer the one closer to the desired weight. | 97 // Otherwise, prefer the one closer to the desired weight. |
127 return candidateWeightDeltaMagnitude < chosenWeightDeltaMagnitude; | 98 return candidateWeightDeltaMagnitude < chosenWeightDeltaMagnitude; |
128 } | 99 } |
129 | 100 |
130 // Family name is somewhat of a misnomer here. We first attempt to find an exac
t match | 101 // Family name is somewhat of a misnomer here. We first attempt to find an exac
t match |
131 // comparing the desiredFamily to the PostScript name of the installed fonts. I
f that fails | 102 // comparing the desiredFamily to the PostScript name of the installed fonts. I
f that fails |
132 // we then do a search based on the family names of the installed fonts. | 103 // we then do a search based on the family names of the installed fonts. |
133 NSFont* MatchNSFontFamily(NSString* desiredFamily, NSFontTraitMask desiredTraits
, FontWeight desiredWeight, float size) | 104 NSFont* MatchNSFontFamily(NSString* desiredFamily, NSFontTraitMask desiredTraits
, int desiredWeight, float size) |
134 { | 105 { |
135 if ([desiredFamily isEqualToString:@"BlinkMacSystemFont"]) { | |
136 // On OSX 10.9, the default system font depends on the SDK version. When | |
137 // compiled against the OSX 10.10 SDK, the font is .LucidaGrandeUI. When | |
138 // compiled against the OSX 10.6 SDK, the font is Lucida Grande. Layout | |
139 // tests don't support different expectations based on the SDK version, | |
140 // so force layout tests to use "Lucida Grande". Once the 10.10 SDK | |
141 // switch is made, this should be changed to return .LucidaGrandeUI and | |
142 // the Layout Expectations should be updated. http://crbug.com/515836. | |
143 if (LayoutTestSupport::isRunningLayoutTest() && IsOSMavericks()) { | |
144 if (desiredWeight >= blink::FontWeightBold) | |
145 return [NSFont fontWithName:@"Lucida Grande Bold" size:size]; | |
146 else | |
147 return [NSFont fontWithName:@"Lucida Grande" size:size]; | |
148 } | |
149 | |
150 NSFont* font = nil; | |
151 if (IsOSMavericksOrEarlier()) { | |
152 // On older OSX versions, only bold and regular are available. | |
153 if (desiredWeight >= blink::FontWeightBold) | |
154 font = [NSFont boldSystemFontOfSize:size]; | |
155 else | |
156 font = [NSFont systemFontOfSize:size]; | |
157 } | |
158 else { | |
159 // On OSX 10.10+, the default system font has more weights. | |
160 font = [NSFont systemFontOfSize:size weight:toYosemiteFontWeight(des
iredWeight)]; | |
161 } | |
162 | |
163 if (desiredTraits & IMPORTANT_FONT_TRAITS) | |
164 font = [[NSFontManager sharedFontManager] convertFont:font toHaveTra
it:desiredTraits]; | |
165 return font; | |
166 } | |
167 | |
168 NSFontManager *fontManager = [NSFontManager sharedFontManager]; | 106 NSFontManager *fontManager = [NSFontManager sharedFontManager]; |
169 | 107 |
170 // Do a simple case insensitive search for a matching font family. | 108 // Do a simple case insensitive search for a matching font family. |
171 // NSFontManager requires exact name matches. | 109 // NSFontManager requires exact name matches. |
172 // This addresses the problem of matching arial to Arial, etc., but perhaps
not all the issues. | 110 // This addresses the problem of matching arial to Arial, etc., but perhaps
not all the issues. |
173 NSEnumerator *e = [[fontManager availableFontFamilies] objectEnumerator]; | 111 NSEnumerator *e = [[fontManager availableFontFamilies] objectEnumerator]; |
174 NSString *availableFamily; | 112 NSString *availableFamily; |
175 while ((availableFamily = [e nextObject])) { | 113 while ((availableFamily = [e nextObject])) { |
176 if ([desiredFamily caseInsensitiveCompare:availableFamily] == NSOrderedS
ame) | 114 if ([desiredFamily caseInsensitiveCompare:availableFamily] == NSOrderedS
ame) |
177 break; | 115 break; |
178 } | 116 } |
179 | 117 |
180 int appKitFontWeight = toAppKitFontWeight(desiredWeight); | |
181 if (!availableFamily) { | 118 if (!availableFamily) { |
182 // Match by PostScript name. | 119 // Match by PostScript name. |
183 NSEnumerator *availableFonts = [[fontManager availableFonts] objectEnume
rator]; | 120 NSEnumerator *availableFonts = [[fontManager availableFonts] objectEnume
rator]; |
184 NSString *availableFont; | 121 NSString *availableFont; |
185 NSFont *nameMatchedFont = nil; | 122 NSFont *nameMatchedFont = nil; |
186 NSFontTraitMask desiredTraitsForNameMatch = desiredTraits | (appKitFontW
eight >= 7 ? NSBoldFontMask : 0); | 123 NSFontTraitMask desiredTraitsForNameMatch = desiredTraits | (desiredWeig
ht >= 7 ? NSBoldFontMask : 0); |
187 while ((availableFont = [availableFonts nextObject])) { | 124 while ((availableFont = [availableFonts nextObject])) { |
188 if ([desiredFamily caseInsensitiveCompare:availableFont] == NSOrdere
dSame) { | 125 if ([desiredFamily caseInsensitiveCompare:availableFont] == NSOrdere
dSame) { |
189 nameMatchedFont = [NSFont fontWithName:availableFont size:size]; | 126 nameMatchedFont = [NSFont fontWithName:availableFont size:size]; |
190 | 127 |
191 // Special case Osaka-Mono. According to <rdar://problem/399946
7>, we need to | 128 // Special case Osaka-Mono. According to <rdar://problem/399946
7>, we need to |
192 // treat Osaka-Mono as fixed pitch. | 129 // treat Osaka-Mono as fixed pitch. |
193 if ([desiredFamily caseInsensitiveCompare:@"Osaka-Mono"] == NSOr
deredSame && desiredTraitsForNameMatch == 0) | 130 if ([desiredFamily caseInsensitiveCompare:@"Osaka-Mono"] == NSOr
deredSame && desiredTraitsForNameMatch == 0) |
194 return nameMatchedFont; | 131 return nameMatchedFont; |
195 | 132 |
196 NSFontTraitMask traits = [fontManager traitsOfFont:nameMatchedFo
nt]; | 133 NSFontTraitMask traits = [fontManager traitsOfFont:nameMatchedFo
nt]; |
(...skipping 21 matching lines...) Expand all Loading... |
218 // Array indices must be hard coded because of lame AppKit API. | 155 // Array indices must be hard coded because of lame AppKit API. |
219 NSString *fontFullName = [fontInfo objectAtIndex:0]; | 156 NSString *fontFullName = [fontInfo objectAtIndex:0]; |
220 NSInteger fontWeight = [[fontInfo objectAtIndex:2] intValue]; | 157 NSInteger fontWeight = [[fontInfo objectAtIndex:2] intValue]; |
221 | 158 |
222 NSFontTraitMask fontTraits = [[fontInfo objectAtIndex:3] unsignedIntValu
e]; | 159 NSFontTraitMask fontTraits = [[fontInfo objectAtIndex:3] unsignedIntValu
e]; |
223 | 160 |
224 BOOL newWinner; | 161 BOOL newWinner; |
225 if (!choseFont) | 162 if (!choseFont) |
226 newWinner = acceptableChoice(desiredTraits, fontTraits); | 163 newWinner = acceptableChoice(desiredTraits, fontTraits); |
227 else | 164 else |
228 newWinner = betterChoice(desiredTraits, appKitFontWeight, chosenTrai
ts, chosenWeight, fontTraits, fontWeight); | 165 newWinner = betterChoice(desiredTraits, desiredWeight, chosenTraits,
chosenWeight, fontTraits, fontWeight); |
229 | 166 |
230 if (newWinner) { | 167 if (newWinner) { |
231 choseFont = YES; | 168 choseFont = YES; |
232 chosenWeight = fontWeight; | 169 chosenWeight = fontWeight; |
233 chosenTraits = fontTraits; | 170 chosenTraits = fontTraits; |
234 chosenFullName = fontFullName; | 171 chosenFullName = fontFullName; |
235 | 172 |
236 if (chosenWeight == appKitFontWeight && (chosenTraits & IMPORTANT_FO
NT_TRAITS) == (desiredTraits & IMPORTANT_FONT_TRAITS)) | 173 if (chosenWeight == desiredWeight && (chosenTraits & IMPORTANT_FONT_
TRAITS) == (desiredTraits & IMPORTANT_FONT_TRAITS)) |
237 break; | 174 break; |
238 } | 175 } |
239 } | 176 } |
240 | 177 |
241 if (!choseFont) | 178 if (!choseFont) |
242 return nil; | 179 return nil; |
243 | 180 |
244 NSFont *font = [NSFont fontWithName:chosenFullName size:size]; | 181 NSFont *font = [NSFont fontWithName:chosenFullName size:size]; |
245 | 182 |
246 if (!font) | 183 if (!font) |
247 return nil; | 184 return nil; |
248 | 185 |
249 NSFontTraitMask actualTraits = 0; | 186 NSFontTraitMask actualTraits = 0; |
250 if (desiredTraits & NSFontItalicTrait) | 187 if (desiredTraits & NSFontItalicTrait) |
251 actualTraits = [fontManager traitsOfFont:font]; | 188 actualTraits = [fontManager traitsOfFont:font]; |
252 int actualWeight = [fontManager weightOfFont:font]; | 189 int actualWeight = [fontManager weightOfFont:font]; |
253 | 190 |
254 bool syntheticBold = appKitFontWeight >= 7 && actualWeight < 7; | 191 bool syntheticBold = desiredWeight >= 7 && actualWeight < 7; |
255 bool syntheticItalic = (desiredTraits & NSFontItalicTrait) && !(actualTraits
& NSFontItalicTrait); | 192 bool syntheticItalic = (desiredTraits & NSFontItalicTrait) && !(actualTraits
& NSFontItalicTrait); |
256 | 193 |
257 // There are some malformed fonts that will be correctly returned by -fontWi
thFamily:traits:weight:size: as a match for a particular trait, | 194 // There are some malformed fonts that will be correctly returned by -fontWi
thFamily:traits:weight:size: as a match for a particular trait, |
258 // though -[NSFontManager traitsOfFont:] incorrectly claims the font does no
t have the specified trait. This could result in applying | 195 // though -[NSFontManager traitsOfFont:] incorrectly claims the font does no
t have the specified trait. This could result in applying |
259 // synthetic bold on top of an already-bold font, as reported in <http://bug
s.webkit.org/show_bug.cgi?id=6146>. To work around this | 196 // synthetic bold on top of an already-bold font, as reported in <http://bug
s.webkit.org/show_bug.cgi?id=6146>. To work around this |
260 // problem, if we got an apparent exact match, but the requested traits aren
't present in the matched font, we'll try to get a font from | 197 // problem, if we got an apparent exact match, but the requested traits aren
't present in the matched font, we'll try to get a font from |
261 // the same family without those traits (to apply the synthetic traits to la
ter). | 198 // the same family without those traits (to apply the synthetic traits to la
ter). |
262 NSFontTraitMask nonSyntheticTraits = desiredTraits; | 199 NSFontTraitMask nonSyntheticTraits = desiredTraits; |
263 | 200 |
264 if (syntheticBold) | 201 if (syntheticBold) |
265 nonSyntheticTraits &= ~NSBoldFontMask; | 202 nonSyntheticTraits &= ~NSBoldFontMask; |
266 | 203 |
267 if (syntheticItalic) | 204 if (syntheticItalic) |
268 nonSyntheticTraits &= ~NSItalicFontMask; | 205 nonSyntheticTraits &= ~NSItalicFontMask; |
269 | 206 |
270 if (nonSyntheticTraits != desiredTraits) { | 207 if (nonSyntheticTraits != desiredTraits) { |
271 NSFont *fontWithoutSyntheticTraits = [fontManager fontWithFamily:availab
leFamily traits:nonSyntheticTraits weight:chosenWeight size:size]; | 208 NSFont *fontWithoutSyntheticTraits = [fontManager fontWithFamily:availab
leFamily traits:nonSyntheticTraits weight:chosenWeight size:size]; |
272 if (fontWithoutSyntheticTraits) | 209 if (fontWithoutSyntheticTraits) |
273 font = fontWithoutSyntheticTraits; | 210 font = fontWithoutSyntheticTraits; |
274 } | 211 } |
275 | 212 |
276 return font; | 213 return font; |
277 } | 214 } |
278 | 215 |
279 int toAppKitFontWeight(FontWeight fontWeight) | |
280 { | |
281 static int appKitFontWeights[] = { | |
282 2, // FontWeight100 | |
283 3, // FontWeight200 | |
284 4, // FontWeight300 | |
285 5, // FontWeight400 | |
286 6, // FontWeight500 | |
287 8, // FontWeight600 | |
288 9, // FontWeight700 | |
289 10, // FontWeight800 | |
290 12, // FontWeight900 | |
291 }; | |
292 return appKitFontWeights[fontWeight]; | |
293 } | |
294 | |
295 } // namespace blink | 216 } // namespace blink |
OLD | NEW |