| 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 |