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