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 |
39 namespace blink { | 68 namespace blink { |
40 | 69 |
41 const NSFontTraitMask SYNTHESIZED_FONT_TRAITS = (NSBoldFontMask | NSItalicFontMa
sk); | 70 const NSFontTraitMask SYNTHESIZED_FONT_TRAITS = (NSBoldFontMask | NSItalicFontMa
sk); |
42 | 71 |
43 const NSFontTraitMask IMPORTANT_FONT_TRAITS = (NSCompressedFontMask | 72 const NSFontTraitMask IMPORTANT_FONT_TRAITS = (NSCompressedFontMask |
44 | NSCondensedFontMask | 73 | NSCondensedFontMask |
45 | NSExpandedFontMask | 74 | NSExpandedFontMask |
46 | NSItalicFontMask | 75 | NSItalicFontMask |
47 | NSNarrowFontMask | 76 | NSNarrowFontMask |
48 | NSPosterFontMask | 77 | NSPosterFontMask |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 if (chosenWeightDeltaMagnitude == candidateWeightDeltaMagnitude) | 123 if (chosenWeightDeltaMagnitude == candidateWeightDeltaMagnitude) |
95 return abs(candidateWeight - 6) > abs(chosenWeight - 6); | 124 return abs(candidateWeight - 6) > abs(chosenWeight - 6); |
96 | 125 |
97 // Otherwise, prefer the one closer to the desired weight. | 126 // Otherwise, prefer the one closer to the desired weight. |
98 return candidateWeightDeltaMagnitude < chosenWeightDeltaMagnitude; | 127 return candidateWeightDeltaMagnitude < chosenWeightDeltaMagnitude; |
99 } | 128 } |
100 | 129 |
101 // Family name is somewhat of a misnomer here. We first attempt to find an exac
t match | 130 // Family name is somewhat of a misnomer here. We first attempt to find an exac
t match |
102 // comparing the desiredFamily to the PostScript name of the installed fonts. I
f that fails | 131 // comparing the desiredFamily to the PostScript name of the installed fonts. I
f that fails |
103 // we then do a search based on the family names of the installed fonts. | 132 // we then do a search based on the family names of the installed fonts. |
104 NSFont* MatchNSFontFamily(NSString* desiredFamily, NSFontTraitMask desiredTraits
, int desiredWeight, float size) | 133 NSFont* MatchNSFontFamily(NSString* desiredFamily, NSFontTraitMask desiredTraits
, FontWeight desiredWeight, float size) |
105 { | 134 { |
| 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 |
106 NSFontManager *fontManager = [NSFontManager sharedFontManager]; | 168 NSFontManager *fontManager = [NSFontManager sharedFontManager]; |
107 | 169 |
108 // Do a simple case insensitive search for a matching font family. | 170 // Do a simple case insensitive search for a matching font family. |
109 // NSFontManager requires exact name matches. | 171 // NSFontManager requires exact name matches. |
110 // This addresses the problem of matching arial to Arial, etc., but perhaps
not all the issues. | 172 // This addresses the problem of matching arial to Arial, etc., but perhaps
not all the issues. |
111 NSEnumerator *e = [[fontManager availableFontFamilies] objectEnumerator]; | 173 NSEnumerator *e = [[fontManager availableFontFamilies] objectEnumerator]; |
112 NSString *availableFamily; | 174 NSString *availableFamily; |
113 while ((availableFamily = [e nextObject])) { | 175 while ((availableFamily = [e nextObject])) { |
114 if ([desiredFamily caseInsensitiveCompare:availableFamily] == NSOrderedS
ame) | 176 if ([desiredFamily caseInsensitiveCompare:availableFamily] == NSOrderedS
ame) |
115 break; | 177 break; |
116 } | 178 } |
117 | 179 |
| 180 int appKitFontWeight = toAppKitFontWeight(desiredWeight); |
118 if (!availableFamily) { | 181 if (!availableFamily) { |
119 // Match by PostScript name. | 182 // Match by PostScript name. |
120 NSEnumerator *availableFonts = [[fontManager availableFonts] objectEnume
rator]; | 183 NSEnumerator *availableFonts = [[fontManager availableFonts] objectEnume
rator]; |
121 NSString *availableFont; | 184 NSString *availableFont; |
122 NSFont *nameMatchedFont = nil; | 185 NSFont *nameMatchedFont = nil; |
123 NSFontTraitMask desiredTraitsForNameMatch = desiredTraits | (desiredWeig
ht >= 7 ? NSBoldFontMask : 0); | 186 NSFontTraitMask desiredTraitsForNameMatch = desiredTraits | (appKitFontW
eight >= 7 ? NSBoldFontMask : 0); |
124 while ((availableFont = [availableFonts nextObject])) { | 187 while ((availableFont = [availableFonts nextObject])) { |
125 if ([desiredFamily caseInsensitiveCompare:availableFont] == NSOrdere
dSame) { | 188 if ([desiredFamily caseInsensitiveCompare:availableFont] == NSOrdere
dSame) { |
126 nameMatchedFont = [NSFont fontWithName:availableFont size:size]; | 189 nameMatchedFont = [NSFont fontWithName:availableFont size:size]; |
127 | 190 |
128 // Special case Osaka-Mono. According to <rdar://problem/399946
7>, we need to | 191 // Special case Osaka-Mono. According to <rdar://problem/399946
7>, we need to |
129 // treat Osaka-Mono as fixed pitch. | 192 // treat Osaka-Mono as fixed pitch. |
130 if ([desiredFamily caseInsensitiveCompare:@"Osaka-Mono"] == NSOr
deredSame && desiredTraitsForNameMatch == 0) | 193 if ([desiredFamily caseInsensitiveCompare:@"Osaka-Mono"] == NSOr
deredSame && desiredTraitsForNameMatch == 0) |
131 return nameMatchedFont; | 194 return nameMatchedFont; |
132 | 195 |
133 NSFontTraitMask traits = [fontManager traitsOfFont:nameMatchedFo
nt]; | 196 NSFontTraitMask traits = [fontManager traitsOfFont:nameMatchedFo
nt]; |
(...skipping 21 matching lines...) Expand all Loading... |
155 // Array indices must be hard coded because of lame AppKit API. | 218 // Array indices must be hard coded because of lame AppKit API. |
156 NSString *fontFullName = [fontInfo objectAtIndex:0]; | 219 NSString *fontFullName = [fontInfo objectAtIndex:0]; |
157 NSInteger fontWeight = [[fontInfo objectAtIndex:2] intValue]; | 220 NSInteger fontWeight = [[fontInfo objectAtIndex:2] intValue]; |
158 | 221 |
159 NSFontTraitMask fontTraits = [[fontInfo objectAtIndex:3] unsignedIntValu
e]; | 222 NSFontTraitMask fontTraits = [[fontInfo objectAtIndex:3] unsignedIntValu
e]; |
160 | 223 |
161 BOOL newWinner; | 224 BOOL newWinner; |
162 if (!choseFont) | 225 if (!choseFont) |
163 newWinner = acceptableChoice(desiredTraits, fontTraits); | 226 newWinner = acceptableChoice(desiredTraits, fontTraits); |
164 else | 227 else |
165 newWinner = betterChoice(desiredTraits, desiredWeight, chosenTraits,
chosenWeight, fontTraits, fontWeight); | 228 newWinner = betterChoice(desiredTraits, appKitFontWeight, chosenTrai
ts, chosenWeight, fontTraits, fontWeight); |
166 | 229 |
167 if (newWinner) { | 230 if (newWinner) { |
168 choseFont = YES; | 231 choseFont = YES; |
169 chosenWeight = fontWeight; | 232 chosenWeight = fontWeight; |
170 chosenTraits = fontTraits; | 233 chosenTraits = fontTraits; |
171 chosenFullName = fontFullName; | 234 chosenFullName = fontFullName; |
172 | 235 |
173 if (chosenWeight == desiredWeight && (chosenTraits & IMPORTANT_FONT_
TRAITS) == (desiredTraits & IMPORTANT_FONT_TRAITS)) | 236 if (chosenWeight == appKitFontWeight && (chosenTraits & IMPORTANT_FO
NT_TRAITS) == (desiredTraits & IMPORTANT_FONT_TRAITS)) |
174 break; | 237 break; |
175 } | 238 } |
176 } | 239 } |
177 | 240 |
178 if (!choseFont) | 241 if (!choseFont) |
179 return nil; | 242 return nil; |
180 | 243 |
181 NSFont *font = [NSFont fontWithName:chosenFullName size:size]; | 244 NSFont *font = [NSFont fontWithName:chosenFullName size:size]; |
182 | 245 |
183 if (!font) | 246 if (!font) |
184 return nil; | 247 return nil; |
185 | 248 |
186 NSFontTraitMask actualTraits = 0; | 249 NSFontTraitMask actualTraits = 0; |
187 if (desiredTraits & NSFontItalicTrait) | 250 if (desiredTraits & NSFontItalicTrait) |
188 actualTraits = [fontManager traitsOfFont:font]; | 251 actualTraits = [fontManager traitsOfFont:font]; |
189 int actualWeight = [fontManager weightOfFont:font]; | 252 int actualWeight = [fontManager weightOfFont:font]; |
190 | 253 |
191 bool syntheticBold = desiredWeight >= 7 && actualWeight < 7; | 254 bool syntheticBold = appKitFontWeight >= 7 && actualWeight < 7; |
192 bool syntheticItalic = (desiredTraits & NSFontItalicTrait) && !(actualTraits
& NSFontItalicTrait); | 255 bool syntheticItalic = (desiredTraits & NSFontItalicTrait) && !(actualTraits
& NSFontItalicTrait); |
193 | 256 |
194 // There are some malformed fonts that will be correctly returned by -fontWi
thFamily:traits:weight:size: as a match for a particular trait, | 257 // There are some malformed fonts that will be correctly returned by -fontWi
thFamily:traits:weight:size: as a match for a particular trait, |
195 // though -[NSFontManager traitsOfFont:] incorrectly claims the font does no
t have the specified trait. This could result in applying | 258 // though -[NSFontManager traitsOfFont:] incorrectly claims the font does no
t have the specified trait. This could result in applying |
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 | 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 |
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 | 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 |
198 // the same family without those traits (to apply the synthetic traits to la
ter). | 261 // the same family without those traits (to apply the synthetic traits to la
ter). |
199 NSFontTraitMask nonSyntheticTraits = desiredTraits; | 262 NSFontTraitMask nonSyntheticTraits = desiredTraits; |
200 | 263 |
201 if (syntheticBold) | 264 if (syntheticBold) |
202 nonSyntheticTraits &= ~NSBoldFontMask; | 265 nonSyntheticTraits &= ~NSBoldFontMask; |
203 | 266 |
204 if (syntheticItalic) | 267 if (syntheticItalic) |
205 nonSyntheticTraits &= ~NSItalicFontMask; | 268 nonSyntheticTraits &= ~NSItalicFontMask; |
206 | 269 |
207 if (nonSyntheticTraits != desiredTraits) { | 270 if (nonSyntheticTraits != desiredTraits) { |
208 NSFont *fontWithoutSyntheticTraits = [fontManager fontWithFamily:availab
leFamily traits:nonSyntheticTraits weight:chosenWeight size:size]; | 271 NSFont *fontWithoutSyntheticTraits = [fontManager fontWithFamily:availab
leFamily traits:nonSyntheticTraits weight:chosenWeight size:size]; |
209 if (fontWithoutSyntheticTraits) | 272 if (fontWithoutSyntheticTraits) |
210 font = fontWithoutSyntheticTraits; | 273 font = fontWithoutSyntheticTraits; |
211 } | 274 } |
212 | 275 |
213 return font; | 276 return font; |
214 } | 277 } |
215 | 278 |
| 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 |
216 } // namespace blink | 295 } // namespace blink |
OLD | NEW |