Home | History | Annotate | Download | only in chromium
      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