1 /* 2 * Copyright (C) 2006, 2007 Apple Computer, Inc. 3 * Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "config.h" 33 #include "FontCache.h" 34 35 #include "ChromiumBridge.h" 36 #include "Font.h" 37 #include "FontUtilsChromiumWin.h" 38 #include "HashMap.h" 39 #include "HashSet.h" 40 #include "SimpleFontData.h" 41 #include "StringHash.h" 42 #include <unicode/uniset.h> 43 44 #include <windows.h> 45 #include <objidl.h> 46 #include <mlang.h> 47 48 using std::min; 49 50 namespace WebCore 51 { 52 53 void FontCache::platformInit() 54 { 55 // Not needed on Windows. 56 } 57 58 // FIXME: consider adding to WebKit String class 59 static bool charactersAreAllASCII(const String& s) 60 { 61 return charactersAreAllASCII(s.characters(), s.length()); 62 } 63 64 // When asked for a CJK font with a native name under a non-CJK locale or 65 // asked for a CJK font with a Romanized name under a CJK locale, 66 // |GetTextFace| (after |CreateFont*|) returns a 'bogus' value (e.g. Arial). 67 // This is not consistent with what MSDN says !! 68 // Therefore, before we call |CreateFont*|, we have to map a Romanized name to 69 // the corresponding native name under a CJK locale and vice versa 70 // under a non-CJK locale. 71 // See the corresponding gecko bugs at 72 // https://bugzilla.mozilla.org/show_bug.cgi?id=373952 73 // https://bugzilla.mozilla.org/show_bug.cgi?id=231426 74 static bool LookupAltName(const String& name, String& altName) 75 { 76 struct FontCodepage { 77 WCHAR* name; 78 int codePage; 79 }; 80 81 struct NamePair { 82 WCHAR* name; 83 FontCodepage altNameCodepage; 84 }; 85 86 const int japaneseCodepage = 932; 87 const int simplifiedChineseCodepage = 936; 88 const int koreanCodepage = 949; 89 const int traditionalChineseCodepage = 950; 90 91 // FIXME(jungshik) : This list probably covers 99% of cases. 92 // To cover the remaining 1% and cut down the file size, 93 // consider accessing 'NAME' table of a truetype font 94 // using |GetFontData| and caching the mapping. 95 // In the table below, the ASCII keys are all lower-cased for 96 // case-insensitive matching. 97 static const NamePair namePairs[] = { 98 // , MS PGothic 99 {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", {L"MS PGothic", japaneseCodepage}}, 100 {L"ms pgothic", {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", japaneseCodepage}}, 101 // , MS PMincho 102 {L"\xFF2D\xFF33 \xFF30\x660E\x671D", {L"MS PMincho", japaneseCodepage}}, 103 {L"ms pmincho", {L"\xFF2D\xFF33 \xFF30\x660E\x671D", japaneseCodepage}}, 104 // , MS Gothic 105 {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", {L"MS Gothic", japaneseCodepage}}, 106 {L"ms gothic", {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", japaneseCodepage}}, 107 // , MS Mincho 108 {L"\xFF2D\xFF33 \x660E\x671D", {L"MS Mincho", japaneseCodepage}}, 109 {L"ms mincho", {L"\xFF2D\xFF33 \x660E\x671D", japaneseCodepage}}, 110 // , Meiryo 111 {L"\x30E1\x30A4\x30EA\x30AA", {L"Meiryo", japaneseCodepage}}, 112 {L"meiryo", {L"\x30E1\x30A4\x30EA\x30AA", japaneseCodepage}}, 113 // , Batang 114 {L"\xBC14\xD0D5", {L"Batang", koreanCodepage}}, 115 {L"batang", {L"\xBC14\xD0D5", koreanCodepage}}, 116 // , Batangche 117 {L"\xBC14\xD0D5\xCCB4", {L"Batangche", koreanCodepage}}, 118 {L"batangche", {L"\xBC14\xD0D5\xCCB4", koreanCodepage}}, 119 // , Gulim 120 {L"\xAD74\xB9BC", {L"Gulim", koreanCodepage}}, 121 {L"gulim", {L"\xAD74\xB9BC", koreanCodepage}}, 122 // , Gulimche 123 {L"\xAD74\xB9BC\xCCB4", {L"Gulimche", koreanCodepage}}, 124 {L"gulimche", {L"\xAD74\xB9BC\xCCB4", koreanCodepage}}, 125 // , Dotum 126 {L"\xB3CB\xC6C0", {L"Dotum", koreanCodepage}}, 127 {L"dotum", {L"\xB3CB\xC6C0", koreanCodepage}}, 128 // , Dotumche 129 {L"\xB3CB\xC6C0\xCCB4", {L"Dotumche", koreanCodepage}}, 130 {L"dotumche", {L"\xB3CB\xC6C0\xCCB4", koreanCodepage}}, 131 // , Gungsuh 132 {L"\xAD81\xC11C", {L"Gungsuh", koreanCodepage}}, 133 {L"gungsuh", {L"\xAD81\xC11C", koreanCodepage}}, 134 // , Gungsuhche 135 {L"\xAD81\xC11C\xCCB4", {L"Gungsuhche", koreanCodepage}}, 136 {L"gungsuhche", {L"\xAD81\xC11C\xCCB4", koreanCodepage}}, 137 // , Malgun Gothic 138 {L"\xB9D1\xC740 \xACE0\xB515", {L"Malgun Gothic", koreanCodepage}}, 139 {L"malgun gothic", {L"\xB9D1\xC740 \xACE0\xB515", koreanCodepage}}, 140 // , SimSun 141 {L"\x5B8B\x4F53", {L"SimSun", simplifiedChineseCodepage}}, 142 {L"simsun", {L"\x5B8B\x4F53", simplifiedChineseCodepage}}, 143 // , SimHei 144 {L"\x9ED1\x4F53", {L"SimHei", simplifiedChineseCodepage}}, 145 {L"simhei", {L"\x9ED1\x4F53", simplifiedChineseCodepage}}, 146 // , NSimSun 147 {L"\x65B0\x5B8B\x4F53", {L"NSimSun", simplifiedChineseCodepage}}, 148 {L"nsimsun", {L"\x65B0\x5B8B\x4F53", simplifiedChineseCodepage}}, 149 // , Microsoft Yahei 150 {L"\x5FAE\x8F6F\x96C5\x9ED1", {L"Microsoft Yahei", simplifiedChineseCodepage}}, 151 {L"microsoft yahei", {L"\x5FAE\x8F6F\x96C5\x9ED1", simplifiedChineseCodepage}}, 152 // , FangSong 153 {L"\x4EFF\x5B8B", {L"FangSong", simplifiedChineseCodepage}}, 154 {L"fangsong", {L"\x4EFF\x5B8B", simplifiedChineseCodepage}}, 155 // , KaiTi 156 {L"\x6977\x4F53", {L"KaiTi", simplifiedChineseCodepage}}, 157 {L"kaiti", {L"\x6977\x4F53", simplifiedChineseCodepage}}, 158 // _GB2312, FangSong_GB2312 159 {L"\x4EFF\x5B8B_GB2312", {L"FangSong_GB2312", simplifiedChineseCodepage}}, 160 {L"fangsong_gb2312", {L"\x4EFF\x5B8B_gb2312", simplifiedChineseCodepage}}, 161 // _GB2312, KaiTi_GB2312 162 {L"\x6977\x4F53", {L"KaiTi_GB2312", simplifiedChineseCodepage}}, 163 {L"kaiti_gb2312", {L"\x6977\x4F53_gb2312", simplifiedChineseCodepage}}, 164 // , PMingLiu 165 {L"\x65B0\x7D30\x660E\x9AD4", {L"PMingLiu", traditionalChineseCodepage}}, 166 {L"pmingliu", {L"\x65B0\x7D30\x660E\x9AD4", traditionalChineseCodepage}}, 167 // , MingLiu 168 {L"\x7D30\x660E\x9AD4", {L"MingLiu", traditionalChineseCodepage}}, 169 {L"mingliu", {L"\x7D30\x660E\x9AD4", traditionalChineseCodepage}}, 170 // , Microsoft JhengHei 171 {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", {L"Microsoft JhengHei", traditionalChineseCodepage}}, 172 {L"microsoft jhengHei", {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", traditionalChineseCodepage}}, 173 // , DFKai-SB 174 {L"\x6A19\x6977\x9AD4", {L"DFKai-SB", traditionalChineseCodepage}}, 175 {L"dfkai-sb", {L"\x6A19\x6977\x9AD4", traditionalChineseCodepage}}, 176 // WenQuanYi Zen Hei 177 {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", {L"WenQuanYi Zen Hei", traditionalChineseCodepage}}, 178 {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", traditionalChineseCodepage}}, 179 // WenQuanYi Zen Hei 180 {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", {L"WenQuanYi Zen Hei", simplifiedChineseCodepage}}, 181 {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", simplifiedChineseCodepage}}, 182 // AR PL ShanHeiSun Uni, 183 {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", 184 {L"AR PL ShanHeiSun Uni", traditionalChineseCodepage}}, 185 {L"ar pl shanheisun uni", 186 {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", traditionalChineseCodepage}}, 187 // AR PL ShanHeiSun Uni, 188 {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", 189 {L"AR PL ShanHeiSun Uni", simplifiedChineseCodepage}}, 190 {L"ar pl shanheisun uni", 191 {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", simplifiedChineseCodepage}}, 192 // AR PL ZenKai Uni 193 // Traditional Chinese and Simplified Chinese names are 194 // identical. 195 {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", traditionalChineseCodepage}}, 196 {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", traditionalChineseCodepage}}, 197 {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", simplifiedChineseCodepage}}, 198 {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", simplifiedChineseCodepage}}, 199 }; 200 201 typedef HashMap<String, const FontCodepage*> NameMap; 202 static NameMap* fontNameMap = 0; 203 204 if (!fontNameMap) { 205 size_t numElements = sizeof(namePairs) / sizeof(NamePair); 206 fontNameMap = new NameMap; 207 for (size_t i = 0; i < numElements; ++i) 208 fontNameMap->set(String(namePairs[i].name), &(namePairs[i].altNameCodepage)); 209 } 210 211 bool isAscii = false; 212 String n; 213 // use |lower| only for ASCII names 214 // For non-ASCII names, we don't want to invoke an expensive 215 // and unnecessary |lower|. 216 if (charactersAreAllASCII(name)) { 217 isAscii = true; 218 n = name.lower(); 219 } else 220 n = name; 221 222 NameMap::iterator iter = fontNameMap->find(n); 223 if (iter == fontNameMap->end()) 224 return false; 225 226 static int systemCp = ::GetACP(); 227 int fontCp = iter->second->codePage; 228 229 if ((isAscii && systemCp == fontCp) || (!isAscii && systemCp != fontCp)) { 230 altName = String(iter->second->name); 231 return true; 232 } 233 234 return false; 235 } 236 237 static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winfont, String* winName) 238 { 239 int len = min(static_cast<int>(family.length()), LF_FACESIZE - 1); 240 memcpy(winfont->lfFaceName, family.characters(), len * sizeof(WORD)); 241 winfont->lfFaceName[len] = '\0'; 242 243 HFONT hfont = CreateFontIndirect(winfont); 244 if (!hfont) 245 return 0; 246 247 HDC dc = GetDC(0); 248 HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont)); 249 WCHAR name[LF_FACESIZE]; 250 unsigned resultLength = GetTextFace(dc, LF_FACESIZE, name); 251 if (resultLength > 0) 252 resultLength--; // ignore the null terminator 253 254 SelectObject(dc, oldFont); 255 ReleaseDC(0, dc); 256 *winName = String(name, resultLength); 257 return hfont; 258 } 259 260 // This maps font family names to their repertoires of supported Unicode 261 // characters. Because it's family names rather than font faces we use 262 // as keys, there might be edge cases where one face of a font family 263 // has a different repertoire from another face of the same family. 264 typedef HashMap<const wchar_t*, icu::UnicodeSet*> FontCmapCache; 265 266 static bool fontContainsCharacter(const FontPlatformData* fontData, 267 const wchar_t* family, UChar32 character) 268 { 269 // FIXME: For non-BMP characters, GetFontUnicodeRanges is of 270 // no use. We have to read directly from the cmap table of a font. 271 // Return true for now. 272 if (character > 0xFFFF) 273 return true; 274 275 // This cache is just leaked on shutdown. 276 static FontCmapCache* fontCmapCache = 0; 277 if (!fontCmapCache) 278 fontCmapCache = new FontCmapCache; 279 280 HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family); 281 if (it != fontCmapCache->end()) 282 return it->second->contains(character); 283 284 HFONT hfont = fontData->hfont(); 285 HDC hdc = GetDC(0); 286 HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont)); 287 int count = GetFontUnicodeRanges(hdc, 0); 288 if (count == 0 && ChromiumBridge::ensureFontLoaded(hfont)) 289 count = GetFontUnicodeRanges(hdc, 0); 290 if (count == 0) { 291 LOG_ERROR("Unable to get the font unicode range after second attempt"); 292 SelectObject(hdc, oldFont); 293 ReleaseDC(0, hdc); 294 return true; 295 } 296 297 static Vector<char, 512> glyphsetBuffer; 298 glyphsetBuffer.resize(GetFontUnicodeRanges(hdc, 0)); 299 GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(glyphsetBuffer.data()); 300 // In addition, refering to the OS/2 table and converting the codepage list 301 // to the coverage map might be faster. 302 count = GetFontUnicodeRanges(hdc, glyphset); 303 ASSERT(count > 0); 304 SelectObject(hdc, oldFont); 305 ReleaseDC(0, hdc); 306 307 // FIXME: consider doing either of the following two: 308 // 1) port back ICU 4.0's faster look-up code for UnicodeSet 309 // 2) port Mozilla's CompressedCharMap or gfxSparseBitset 310 unsigned i = 0; 311 icu::UnicodeSet* cmap = new icu::UnicodeSet; 312 while (i < glyphset->cRanges) { 313 WCHAR start = glyphset->ranges[i].wcLow; 314 cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1); 315 i++; 316 } 317 cmap->freeze(); 318 // We don't lowercase |family| because all of them are under our control 319 // and they're already lowercased. 320 fontCmapCache->set(family, cmap); 321 return cmap->contains(character); 322 } 323 324 // Given the desired base font, this will create a SimpleFontData for a specific 325 // font that can be used to render the given range of characters. 326 const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) 327 { 328 // FIXME: Consider passing fontDescription.dominantScript() 329 // to GetFallbackFamily here. 330 FontDescription fontDescription = font.fontDescription(); 331 UChar32 c; 332 UScriptCode script; 333 const wchar_t* family = getFallbackFamily(characters, length, 334 fontDescription.genericFamily(), &c, &script); 335 FontPlatformData* data = 0; 336 if (family) 337 data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family)), false); 338 339 // Last resort font list : PanUnicode. CJK fonts have a pretty 340 // large repertoire. Eventually, we need to scan all the fonts 341 // on the system to have a Firefox-like coverage. 342 // Make sure that all of them are lowercased. 343 const static wchar_t* const cjkFonts[] = { 344 L"arial unicode ms", 345 L"ms pgothic", 346 L"simsun", 347 L"gulim", 348 L"pmingliu", 349 L"wenquanyi zen hei", // partial CJK Ext. A coverage but more 350 // widely known to Chinese users. 351 L"ar pl shanheisun uni", 352 L"ar pl zenkai uni", 353 L"han nom a", // Complete CJK Ext. A coverage 354 L"code2000", // Complete CJK Ext. A coverage 355 // CJK Ext. B fonts are not listed here because it's of no use 356 // with our current non-BMP character handling because we use 357 // Uniscribe for it and that code path does not go through here. 358 }; 359 360 const static wchar_t* const commonFonts[] = { 361 L"tahoma", 362 L"arial unicode ms", 363 L"lucida sans unicode", 364 L"microsoft sans serif", 365 L"palatino linotype", 366 // Four fonts below (and code2000 at the end) are not from MS, but 367 // once installed, cover a very wide range of characters. 368 L"freeserif", 369 L"freesans", 370 L"gentium", 371 L"gentiumalt", 372 L"ms pgothic", 373 L"simsun", 374 L"gulim", 375 L"pmingliu", 376 L"code2000", 377 }; 378 379 const wchar_t* const* panUniFonts = 0; 380 int numFonts = 0; 381 if (script == USCRIPT_HAN) { 382 panUniFonts = cjkFonts; 383 numFonts = ARRAYSIZE(cjkFonts); 384 } else { 385 panUniFonts = commonFonts; 386 numFonts = ARRAYSIZE(commonFonts); 387 } 388 // Font returned from GetFallbackFamily may not cover |characters| 389 // because it's based on script to font mapping. This problem is 390 // critical enough for non-Latin scripts (especially Han) to 391 // warrant an additional (real coverage) check with fontCotainsCharacter. 392 int i; 393 for (i = 0; (!data || !fontContainsCharacter(data, family, c)) && i < numFonts; ++i) { 394 family = panUniFonts[i]; 395 data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family))); 396 } 397 // When i-th font (0-base) in |panUniFonts| contains a character and 398 // we get out of the loop, |i| will be |i + 1|. That is, if only the 399 // last font in the array covers the character, |i| will be numFonts. 400 // So, we have to use '<=" rather than '<' to see if we found a font 401 // covering the character. 402 if (i <= numFonts) 403 return getCachedFontData(data); 404 405 return 0; 406 407 } 408 409 SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) 410 { 411 return 0; 412 } 413 414 SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description) 415 { 416 FontDescription::GenericFamilyType generic = description.genericFamily(); 417 418 // FIXME: Would be even better to somehow get the user's default font here. 419 // For now we'll pick the default that the user would get without changing 420 // any prefs. 421 static AtomicString timesStr("Times New Roman"); 422 static AtomicString courierStr("Courier New"); 423 static AtomicString arialStr("Arial"); 424 425 AtomicString& fontStr = timesStr; 426 if (generic == FontDescription::SansSerifFamily) 427 fontStr = arialStr; 428 else if (generic == FontDescription::MonospaceFamily) 429 fontStr = courierStr; 430 431 return getCachedFontData(description, fontStr); 432 } 433 434 static LONG toGDIFontWeight(FontWeight fontWeight) 435 { 436 static LONG gdiFontWeights[] = { 437 FW_THIN, // FontWeight100 438 FW_EXTRALIGHT, // FontWeight200 439 FW_LIGHT, // FontWeight300 440 FW_NORMAL, // FontWeight400 441 FW_MEDIUM, // FontWeight500 442 FW_SEMIBOLD, // FontWeight600 443 FW_BOLD, // FontWeight700 444 FW_EXTRABOLD, // FontWeight800 445 FW_HEAVY // FontWeight900 446 }; 447 return gdiFontWeights[fontWeight]; 448 } 449 450 static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont) 451 { 452 // The size here looks unusual. The negative number is intentional. 453 // Unlike WebKit trunk, we don't multiply the size by 32. That seems to be 454 // some kind of artifact of their CG backend, or something. 455 winfont->lfHeight = -fontDescription.computedPixelSize(); 456 winfont->lfWidth = 0; 457 winfont->lfEscapement = 0; 458 winfont->lfOrientation = 0; 459 winfont->lfUnderline = false; 460 winfont->lfStrikeOut = false; 461 winfont->lfCharSet = DEFAULT_CHARSET; 462 winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS; 463 winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings. 464 winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; 465 winfont->lfItalic = fontDescription.italic(); 466 winfont->lfWeight = toGDIFontWeight(fontDescription.weight()); 467 } 468 469 struct TraitsInFamilyProcData { 470 TraitsInFamilyProcData(const AtomicString& familyName) 471 : m_familyName(familyName) 472 { 473 } 474 475 const AtomicString& m_familyName; 476 HashSet<unsigned> m_traitsMasks; 477 }; 478 479 static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam) 480 { 481 TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam); 482 483 unsigned traitsMask = 0; 484 traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask; 485 traitsMask |= FontVariantNormalMask; 486 LONG weight = logFont->lfWeight; 487 traitsMask |= weight == FW_THIN ? FontWeight100Mask : 488 weight == FW_EXTRALIGHT ? FontWeight200Mask : 489 weight == FW_LIGHT ? FontWeight300Mask : 490 weight == FW_NORMAL ? FontWeight400Mask : 491 weight == FW_MEDIUM ? FontWeight500Mask : 492 weight == FW_SEMIBOLD ? FontWeight600Mask : 493 weight == FW_BOLD ? FontWeight700Mask : 494 weight == FW_EXTRABOLD ? FontWeight800Mask : 495 FontWeight900Mask; 496 procData->m_traitsMasks.add(traitsMask); 497 return 1; 498 } 499 500 void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks) 501 { 502 HDC hdc = GetDC(0); 503 504 LOGFONT logFont; 505 logFont.lfCharSet = DEFAULT_CHARSET; 506 unsigned familyLength = min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1)); 507 memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar)); 508 logFont.lfFaceName[familyLength] = 0; 509 logFont.lfPitchAndFamily = 0; 510 511 TraitsInFamilyProcData procData(familyName); 512 EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0); 513 copyToVector(procData.m_traitsMasks, traitsMasks); 514 515 ReleaseDC(0, hdc); 516 } 517 518 FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) 519 { 520 LOGFONT winfont = {0}; 521 FillLogFont(fontDescription, &winfont); 522 523 // Windows will always give us a valid pointer here, even if the face name 524 // is non-existent. We have to double-check and see if the family name was 525 // really used. 526 String winName; 527 HFONT hfont = createFontIndirectAndGetWinName(family, &winfont, &winName); 528 if (!hfont) 529 return 0; 530 531 // FIXME: Do we need to use predefined fonts "guaranteed" to exist 532 // when we're running in layout-test mode? 533 if (!equalIgnoringCase(family, winName)) { 534 // For CJK fonts with both English and native names, 535 // GetTextFace returns a native name under the font's "locale" 536 // and an English name under other locales regardless of 537 // lfFaceName field of LOGFONT. As a result, we need to check 538 // if a font has an alternate name. If there is, we need to 539 // compare it with what's requested in the first place. 540 String altName; 541 if (!LookupAltName(family, altName) || 542 !equalIgnoringCase(altName, winName)) { 543 DeleteObject(hfont); 544 return 0; 545 } 546 } 547 548 return new FontPlatformData(hfont, 549 fontDescription.computedPixelSize()); 550 } 551 552 } 553