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 "Font.h"
     36 #include "FontUtilsChromiumWin.h"
     37 #include "HashMap.h"
     38 #include "HashSet.h"
     39 #include "PlatformBridge.h"
     40 #include "SimpleFontData.h"
     41 #include <unicode/uniset.h>
     42 #include <wtf/text/StringHash.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 // FIXME: consider adding to WebKit String class
     54 static bool charactersAreAllASCII(const String& s)
     55 {
     56     return WTF::charactersAreAllASCII(s.characters(), s.length());
     57 }
     58 
     59 // When asked for a CJK font with a native name under a non-CJK locale or
     60 // asked for a CJK font with a Romanized name under a CJK locale,
     61 // |GetTextFace| (after |CreateFont*|) returns a 'bogus' value (e.g. Arial).
     62 // This is not consistent with what MSDN says !!
     63 // Therefore, before we call |CreateFont*|, we have to map a Romanized name to
     64 // the corresponding native name under a CJK locale and vice versa
     65 // under a non-CJK locale.
     66 // See the corresponding gecko bugs at
     67 // https://bugzilla.mozilla.org/show_bug.cgi?id=373952
     68 // https://bugzilla.mozilla.org/show_bug.cgi?id=231426
     69 static bool LookupAltName(const String& name, String& altName)
     70 {
     71     struct FontCodepage {
     72         WCHAR* name;
     73         int codePage;
     74     };
     75 
     76     struct NamePair {
     77         WCHAR* name;
     78         FontCodepage altNameCodepage;
     79     };
     80 
     81     const int japaneseCodepage = 932;
     82     const int simplifiedChineseCodepage = 936;
     83     const int koreanCodepage = 949;
     84     const int traditionalChineseCodepage = 950;
     85 
     86     // FIXME(jungshik) : This list probably covers 99% of cases.
     87     // To cover the remaining 1% and cut down the file size,
     88     // consider accessing 'NAME' table of a truetype font
     89     // using |GetFontData| and caching the mapping.
     90     // In the table below, the ASCII keys are all lower-cased for
     91     // case-insensitive matching.
     92     static const NamePair namePairs[] = {
     93         //  , MS PGothic
     94         {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", {L"MS PGothic", japaneseCodepage}},
     95         {L"ms pgothic", {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", japaneseCodepage}},
     96         //  , MS PMincho
     97         {L"\xFF2D\xFF33 \xFF30\x660E\x671D", {L"MS PMincho", japaneseCodepage}},
     98         {L"ms pmincho", {L"\xFF2D\xFF33 \xFF30\x660E\x671D", japaneseCodepage}},
     99         // , MS Gothic
    100         {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", {L"MS Gothic", japaneseCodepage}},
    101         {L"ms gothic", {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", japaneseCodepage}},
    102         //  , MS Mincho
    103         {L"\xFF2D\xFF33 \x660E\x671D", {L"MS Mincho", japaneseCodepage}},
    104         {L"ms mincho", {L"\xFF2D\xFF33 \x660E\x671D", japaneseCodepage}},
    105         // , Meiryo
    106         {L"\x30E1\x30A4\x30EA\x30AA", {L"Meiryo", japaneseCodepage}},
    107         {L"meiryo", {L"\x30E1\x30A4\x30EA\x30AA", japaneseCodepage}},
    108         // , Batang
    109         {L"\xBC14\xD0D5", {L"Batang", koreanCodepage}},
    110         {L"batang", {L"\xBC14\xD0D5", koreanCodepage}},
    111         // , Batangche
    112         {L"\xBC14\xD0D5\xCCB4", {L"Batangche", koreanCodepage}},
    113         {L"batangche", {L"\xBC14\xD0D5\xCCB4", koreanCodepage}},
    114         // , Gulim
    115         {L"\xAD74\xB9BC", {L"Gulim", koreanCodepage}},
    116         {L"gulim", {L"\xAD74\xB9BC", koreanCodepage}},
    117         // , Gulimche
    118         {L"\xAD74\xB9BC\xCCB4", {L"Gulimche", koreanCodepage}},
    119         {L"gulimche", {L"\xAD74\xB9BC\xCCB4", koreanCodepage}},
    120         // , Dotum
    121         {L"\xB3CB\xC6C0", {L"Dotum", koreanCodepage}},
    122         {L"dotum", {L"\xB3CB\xC6C0", koreanCodepage}},
    123         // , Dotumche
    124         {L"\xB3CB\xC6C0\xCCB4", {L"Dotumche", koreanCodepage}},
    125         {L"dotumche", {L"\xB3CB\xC6C0\xCCB4", koreanCodepage}},
    126         // , Gungsuh
    127         {L"\xAD81\xC11C", {L"Gungsuh", koreanCodepage}},
    128         {L"gungsuh", {L"\xAD81\xC11C", koreanCodepage}},
    129         // , Gungsuhche
    130         {L"\xAD81\xC11C\xCCB4", {L"Gungsuhche", koreanCodepage}},
    131         {L"gungsuhche", {L"\xAD81\xC11C\xCCB4", koreanCodepage}},
    132         //  , Malgun Gothic
    133         {L"\xB9D1\xC740 \xACE0\xB515", {L"Malgun Gothic", koreanCodepage}},
    134         {L"malgun gothic", {L"\xB9D1\xC740 \xACE0\xB515", koreanCodepage}},
    135         // , SimSun
    136         {L"\x5B8B\x4F53", {L"SimSun", simplifiedChineseCodepage}},
    137         {L"simsun", {L"\x5B8B\x4F53", simplifiedChineseCodepage}},
    138         // -ExtB, SimSun-ExtB
    139         {L"\x5B8B\x4F53-ExtB", {L"SimSun-ExtB", simplifiedChineseCodepage}},
    140         {L"simsun-extb", {L"\x5B8B\x4F53-extb", simplifiedChineseCodepage}},
    141         // , SimHei
    142         {L"\x9ED1\x4F53", {L"SimHei", simplifiedChineseCodepage}},
    143         {L"simhei", {L"\x9ED1\x4F53", simplifiedChineseCodepage}},
    144         // , NSimSun
    145         {L"\x65B0\x5B8B\x4F53", {L"NSimSun", simplifiedChineseCodepage}},
    146         {L"nsimsun", {L"\x65B0\x5B8B\x4F53", simplifiedChineseCodepage}},
    147         // , Microsoft Yahei
    148         {L"\x5FAE\x8F6F\x96C5\x9ED1", {L"Microsoft Yahei", simplifiedChineseCodepage}},
    149         {L"microsoft yahei", {L"\x5FAE\x8F6F\x96C5\x9ED1", simplifiedChineseCodepage}},
    150         // , FangSong
    151         {L"\x4EFF\x5B8B",  {L"FangSong", simplifiedChineseCodepage}},
    152         {L"fangsong", {L"\x4EFF\x5B8B", simplifiedChineseCodepage}},
    153         // , KaiTi
    154         {L"\x6977\x4F53", {L"KaiTi", simplifiedChineseCodepage}},
    155         {L"kaiti", {L"\x6977\x4F53", simplifiedChineseCodepage}},
    156         // _GB2312, FangSong_GB2312
    157         {L"\x4EFF\x5B8B_GB2312",  {L"FangSong_GB2312", simplifiedChineseCodepage}},
    158         {L"fangsong_gb2312", {L"\x4EFF\x5B8B_gb2312", simplifiedChineseCodepage}},
    159         // _GB2312, KaiTi_GB2312
    160         {L"\x6977\x4F53", {L"KaiTi_GB2312", simplifiedChineseCodepage}},
    161         {L"kaiti_gb2312", {L"\x6977\x4F53_gb2312", simplifiedChineseCodepage}},
    162         // , PMingLiu
    163         {L"\x65B0\x7D30\x660E\x9AD4", {L"PMingLiu", traditionalChineseCodepage}},
    164         {L"pmingliu", {L"\x65B0\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
    165         // -ExtB, PMingLiu-ExtB
    166         {L"\x65B0\x7D30\x660E\x9AD4-ExtB", {L"PMingLiu-ExtB", traditionalChineseCodepage}},
    167         {L"pmingliu-extb", {L"\x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}},
    168         // , MingLiu
    169         {L"\x7D30\x660E\x9AD4", {L"MingLiu", traditionalChineseCodepage}},
    170         {L"mingliu", {L"\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
    171         // -ExtB, MingLiu-ExtB
    172         {L"\x7D30\x660E\x9AD4-ExtB", {L"MingLiu-ExtB", traditionalChineseCodepage}},
    173         {L"mingliu-extb", {L"x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}},
    174         // , Microsoft JhengHei
    175         {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", {L"Microsoft JhengHei", traditionalChineseCodepage}},
    176         {L"microsoft jhengHei", {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", traditionalChineseCodepage}},
    177         // , DFKai-SB
    178         {L"\x6A19\x6977\x9AD4", {L"DFKai-SB", traditionalChineseCodepage}},
    179         {L"dfkai-sb", {L"\x6A19\x6977\x9AD4", traditionalChineseCodepage}},
    180         // WenQuanYi Zen Hei
    181         {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", {L"WenQuanYi Zen Hei", traditionalChineseCodepage}},
    182         {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", traditionalChineseCodepage}},
    183         // WenQuanYi Zen Hei
    184         {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", {L"WenQuanYi Zen Hei", simplifiedChineseCodepage}},
    185         {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", simplifiedChineseCodepage}},
    186         // AR PL ShanHeiSun Uni,
    187         {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069",
    188          {L"AR PL ShanHeiSun Uni", traditionalChineseCodepage}},
    189         {L"ar pl shanheisun uni",
    190          {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", traditionalChineseCodepage}},
    191         // AR PL ShanHeiSun Uni,
    192         {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069",
    193          {L"AR PL ShanHeiSun Uni", simplifiedChineseCodepage}},
    194         {L"ar pl shanheisun uni",
    195          {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", simplifiedChineseCodepage}},
    196         // AR PL ZenKai Uni
    197         // Traditional Chinese and Simplified Chinese names are
    198         // identical.
    199         {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", traditionalChineseCodepage}},
    200         {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", traditionalChineseCodepage}},
    201         {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", simplifiedChineseCodepage}},
    202         {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", simplifiedChineseCodepage}},
    203     };
    204 
    205     typedef HashMap<String, const FontCodepage*> NameMap;
    206     static NameMap* fontNameMap = 0;
    207 
    208     if (!fontNameMap) {
    209         fontNameMap = new NameMap;
    210         for (size_t i = 0; i < WTF_ARRAY_LENGTH(namePairs); ++i)
    211             fontNameMap->set(String(namePairs[i].name), &(namePairs[i].altNameCodepage));
    212     }
    213 
    214     bool isAscii = false;
    215     String n;
    216     // use |lower| only for ASCII names
    217     // For non-ASCII names, we don't want to invoke an expensive
    218     // and unnecessary |lower|.
    219     if (charactersAreAllASCII(name)) {
    220         isAscii = true;
    221         n = name.lower();
    222     } else
    223         n = name;
    224 
    225     NameMap::iterator iter = fontNameMap->find(n);
    226     if (iter == fontNameMap->end())
    227         return false;
    228 
    229     static int systemCp = ::GetACP();
    230     int fontCp = iter->second->codePage;
    231 
    232     if ((isAscii && systemCp == fontCp) || (!isAscii && systemCp != fontCp)) {
    233         altName = String(iter->second->name);
    234         return true;
    235     }
    236 
    237     return false;
    238 }
    239 
    240 static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winfont, String* winName)
    241 {
    242     int len = min(static_cast<int>(family.length()), LF_FACESIZE - 1);
    243     memcpy(winfont->lfFaceName, family.characters(), len * sizeof(WORD));
    244     winfont->lfFaceName[len] = '\0';
    245 
    246     HFONT hfont = CreateFontIndirect(winfont);
    247     if (!hfont)
    248         return 0;
    249 
    250     HDC dc = GetDC(0);
    251     HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont));
    252     WCHAR name[LF_FACESIZE];
    253     unsigned resultLength = GetTextFace(dc, LF_FACESIZE, name);
    254     if (resultLength > 0)
    255         resultLength--; // ignore the null terminator
    256 
    257     SelectObject(dc, oldFont);
    258     ReleaseDC(0, dc);
    259     *winName = String(name, resultLength);
    260     return hfont;
    261 }
    262 
    263 // This maps font family names to their repertoires of supported Unicode
    264 // characters. Because it's family names rather than font faces we use
    265 // as keys, there might be edge cases where one face of a font family
    266 // has a different repertoire from another face of the same family.
    267 typedef HashMap<const wchar_t*, icu::UnicodeSet*> FontCmapCache;
    268 
    269 static bool fontContainsCharacter(const FontPlatformData* fontData,
    270                                   const wchar_t* family, UChar32 character)
    271 {
    272     // FIXME: For non-BMP characters, GetFontUnicodeRanges is of
    273     // no use. We have to read directly from the cmap table of a font.
    274     // Return true for now.
    275     if (character > 0xFFFF)
    276         return true;
    277 
    278     // This cache is just leaked on shutdown.
    279     static FontCmapCache* fontCmapCache = 0;
    280     if (!fontCmapCache)
    281         fontCmapCache = new FontCmapCache;
    282 
    283     HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family);
    284     if (it != fontCmapCache->end())
    285         return it->second->contains(character);
    286 
    287     HFONT hfont = fontData->hfont();
    288     HDC hdc = GetDC(0);
    289     HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont));
    290     int count = GetFontUnicodeRanges(hdc, 0);
    291     if (!count && PlatformBridge::ensureFontLoaded(hfont))
    292         count = GetFontUnicodeRanges(hdc, 0);
    293     if (!count) {
    294         LOG_ERROR("Unable to get the font unicode range after second attempt");
    295         SelectObject(hdc, oldFont);
    296         ReleaseDC(0, hdc);
    297         return true;
    298     }
    299 
    300     static Vector<char, 512> glyphsetBuffer;
    301     glyphsetBuffer.resize(GetFontUnicodeRanges(hdc, 0));
    302     GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(glyphsetBuffer.data());
    303     // In addition, refering to the OS/2 table and converting the codepage list
    304     // to the coverage map might be faster.
    305     count = GetFontUnicodeRanges(hdc, glyphset);
    306     ASSERT(count > 0);
    307     SelectObject(hdc, oldFont);
    308     ReleaseDC(0, hdc);
    309 
    310     // FIXME: consider doing either of the following two:
    311     // 1) port back ICU 4.0's faster look-up code for UnicodeSet
    312     // 2) port Mozilla's CompressedCharMap or gfxSparseBitset
    313     unsigned i = 0;
    314     icu::UnicodeSet* cmap = new icu::UnicodeSet;
    315     while (i < glyphset->cRanges) {
    316         WCHAR start = glyphset->ranges[i].wcLow;
    317         cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1);
    318         i++;
    319     }
    320     cmap->freeze();
    321     // We don't lowercase |family| because all of them are under our control
    322     // and they're already lowercased.
    323     fontCmapCache->set(family, cmap);
    324     return cmap->contains(character);
    325 }
    326 
    327 // Tries the given font and save it |outFontFamilyName| if it succeeds.
    328 static SimpleFontData* fontDataFromDescriptionAndLogFont(FontCache* fontCache, const FontDescription& fontDescription, const LOGFONT& font, wchar_t* outFontFamilyName)
    329 {
    330     SimpleFontData* fontData = fontCache->getCachedFontData(fontDescription, font.lfFaceName);
    331     if (fontData)
    332         memcpy(outFontFamilyName, font.lfFaceName, sizeof(font.lfFaceName));
    333     return fontData;
    334 }
    335 
    336 static LONG toGDIFontWeight(FontWeight fontWeight)
    337 {
    338     static LONG gdiFontWeights[] = {
    339         FW_THIN, // FontWeight100
    340         FW_EXTRALIGHT, // FontWeight200
    341         FW_LIGHT, // FontWeight300
    342         FW_NORMAL, // FontWeight400
    343         FW_MEDIUM, // FontWeight500
    344         FW_SEMIBOLD, // FontWeight600
    345         FW_BOLD, // FontWeight700
    346         FW_EXTRABOLD, // FontWeight800
    347         FW_HEAVY // FontWeight900
    348     };
    349     return gdiFontWeights[fontWeight];
    350 }
    351 
    352 static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
    353 {
    354     // The size here looks unusual.  The negative number is intentional.
    355     // Unlike WebKit trunk, we don't multiply the size by 32.  That seems to be
    356     // some kind of artifact of their CG backend, or something.
    357     winfont->lfHeight = -fontDescription.computedPixelSize();
    358     winfont->lfWidth = 0;
    359     winfont->lfEscapement = 0;
    360     winfont->lfOrientation = 0;
    361     winfont->lfUnderline = false;
    362     winfont->lfStrikeOut = false;
    363     winfont->lfCharSet = DEFAULT_CHARSET;
    364     winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
    365     winfont->lfQuality = PlatformBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
    366     winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
    367     winfont->lfItalic = fontDescription.italic();
    368     winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
    369 }
    370 
    371 struct TraitsInFamilyProcData {
    372     TraitsInFamilyProcData(const AtomicString& familyName)
    373         : m_familyName(familyName)
    374     {
    375     }
    376 
    377     const AtomicString& m_familyName;
    378     HashSet<unsigned> m_traitsMasks;
    379 };
    380 
    381 static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
    382 {
    383     TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
    384 
    385     unsigned traitsMask = 0;
    386     traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
    387     traitsMask |= FontVariantNormalMask;
    388     LONG weight = logFont->lfWeight;
    389     traitsMask |= weight == FW_THIN ? FontWeight100Mask :
    390         weight == FW_EXTRALIGHT ? FontWeight200Mask :
    391         weight == FW_LIGHT ? FontWeight300Mask :
    392         weight == FW_NORMAL ? FontWeight400Mask :
    393         weight == FW_MEDIUM ? FontWeight500Mask :
    394         weight == FW_SEMIBOLD ? FontWeight600Mask :
    395         weight == FW_BOLD ? FontWeight700Mask :
    396         weight == FW_EXTRABOLD ? FontWeight800Mask :
    397                                  FontWeight900Mask;
    398     procData->m_traitsMasks.add(traitsMask);
    399     return 1;
    400 }
    401 
    402 struct GetLastResortFallbackFontProcData {
    403     GetLastResortFallbackFontProcData(FontCache* fontCache, const FontDescription* fontDescription, wchar_t* fontName)
    404         : m_fontCache(fontCache)
    405         , m_fontDescription(fontDescription)
    406         , m_fontName(fontName)
    407         , m_fontData(0)
    408     {
    409     }
    410 
    411     FontCache* m_fontCache;
    412     const FontDescription* m_fontDescription;
    413     wchar_t* m_fontName;
    414     SimpleFontData* m_fontData;
    415 };
    416 
    417 static int CALLBACK getLastResortFallbackFontProc(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
    418 {
    419     GetLastResortFallbackFontProcData* procData = reinterpret_cast<GetLastResortFallbackFontProcData*>(lParam);
    420     procData->m_fontData = fontDataFromDescriptionAndLogFont(procData->m_fontCache, *procData->m_fontDescription, *logFont, procData->m_fontName);
    421     return !procData->m_fontData;
    422 }
    423 
    424 void FontCache::platformInit()
    425 {
    426     // Not needed on Windows.
    427 }
    428 
    429 // Given the desired base font, this will create a SimpleFontData for a specific
    430 // font that can be used to render the given range of characters.
    431 const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
    432 {
    433     // FIXME: Consider passing fontDescription.dominantScript()
    434     // to GetFallbackFamily here.
    435     FontDescription fontDescription = font.fontDescription();
    436     UChar32 c;
    437     UScriptCode script;
    438     const wchar_t* family = getFallbackFamily(characters, length,
    439         fontDescription.genericFamily(), &c, &script);
    440     FontPlatformData* data = 0;
    441     if (family)
    442         data = getCachedFontPlatformData(font.fontDescription(),  AtomicString(family, wcslen(family)), false);
    443 
    444     // Last resort font list : PanUnicode. CJK fonts have a pretty
    445     // large repertoire. Eventually, we need to scan all the fonts
    446     // on the system to have a Firefox-like coverage.
    447     // Make sure that all of them are lowercased.
    448     const static wchar_t* const cjkFonts[] = {
    449         L"arial unicode ms",
    450         L"ms pgothic",
    451         L"simsun",
    452         L"gulim",
    453         L"pmingliu",
    454         L"wenquanyi zen hei", // partial CJK Ext. A coverage but more
    455                               // widely known to Chinese users.
    456         L"ar pl shanheisun uni",
    457         L"ar pl zenkai uni",
    458         L"han nom a",  // Complete CJK Ext. A coverage
    459         L"code2000",   // Complete CJK Ext. A coverage
    460         // CJK Ext. B fonts are not listed here because it's of no use
    461         // with our current non-BMP character handling because we use
    462         // Uniscribe for it and that code path does not go through here.
    463     };
    464 
    465     const static wchar_t* const commonFonts[] = {
    466         L"tahoma",
    467         L"arial unicode ms",
    468         L"lucida sans unicode",
    469         L"microsoft sans serif",
    470         L"palatino linotype",
    471         // Six fonts below (and code2000 at the end) are not from MS, but
    472         // once installed, cover a very wide range of characters.
    473         L"dejavu serif",
    474         L"dejavu sasns",
    475         L"freeserif",
    476         L"freesans",
    477         L"gentium",
    478         L"gentiumalt",
    479         L"ms pgothic",
    480         L"simsun",
    481         L"gulim",
    482         L"pmingliu",
    483         L"code2000",
    484     };
    485 
    486     const wchar_t* const* panUniFonts = 0;
    487     int numFonts = 0;
    488     if (script == USCRIPT_HAN) {
    489         panUniFonts = cjkFonts;
    490         numFonts = WTF_ARRAY_LENGTH(cjkFonts);
    491     } else {
    492         panUniFonts = commonFonts;
    493         numFonts = WTF_ARRAY_LENGTH(commonFonts);
    494     }
    495     // Font returned from GetFallbackFamily may not cover |characters|
    496     // because it's based on script to font mapping. This problem is
    497     // critical enough for non-Latin scripts (especially Han) to
    498     // warrant an additional (real coverage) check with fontCotainsCharacter.
    499     int i;
    500     for (i = 0; (!data || !fontContainsCharacter(data, family, c)) && i < numFonts; ++i) {
    501         family = panUniFonts[i];
    502         data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family)));
    503     }
    504     // When i-th font (0-base) in |panUniFonts| contains a character and
    505     // we get out of the loop, |i| will be |i + 1|. That is, if only the
    506     // last font in the array covers the character, |i| will be numFonts.
    507     // So, we have to use '<=" rather than '<' to see if we found a font
    508     // covering the character.
    509     if (i <= numFonts)
    510        return getCachedFontData(data);
    511 
    512     return 0;
    513 
    514 }
    515 
    516 SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
    517 {
    518     return 0;
    519 }
    520 
    521 SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description)
    522 {
    523     FontDescription::GenericFamilyType generic = description.genericFamily();
    524 
    525     // FIXME: Would be even better to somehow get the user's default font here.
    526     // For now we'll pick the default that the user would get without changing
    527     // any prefs.
    528     static AtomicString timesStr("Times New Roman");
    529     static AtomicString courierStr("Courier New");
    530     static AtomicString arialStr("Arial");
    531 
    532     AtomicString& fontStr = timesStr;
    533     if (generic == FontDescription::SansSerifFamily)
    534         fontStr = arialStr;
    535     else if (generic == FontDescription::MonospaceFamily)
    536         fontStr = courierStr;
    537 
    538     SimpleFontData* simpleFont = getCachedFontData(description, fontStr);
    539     if (simpleFont)
    540         return simpleFont;
    541 
    542     // Fall back to system fonts as Win Safari does because this function must
    543     // return a valid font. Once we find a valid system font, we save its name
    544     // to a static variable and use it to prevent trying system fonts again.
    545     static wchar_t fallbackFontName[LF_FACESIZE] = {0};
    546     if (fallbackFontName[0])
    547         return getCachedFontData(description, fallbackFontName);
    548 
    549     // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available.
    550     if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) {
    551         LOGFONT defaultGUILogFont;
    552         GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont);
    553         if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, defaultGUILogFont, fallbackFontName))
    554             return simpleFont;
    555     }
    556 
    557     // Fall back to Non-client metrics fonts.
    558     NONCLIENTMETRICS nonClientMetrics = {0};
    559     nonClientMetrics.cbSize = sizeof(nonClientMetrics);
    560     if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) {
    561         if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfMessageFont, fallbackFontName))
    562             return simpleFont;
    563         if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfMenuFont, fallbackFontName))
    564             return simpleFont;
    565         if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfStatusFont, fallbackFontName))
    566             return simpleFont;
    567         if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfCaptionFont, fallbackFontName))
    568             return simpleFont;
    569         if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfSmCaptionFont, fallbackFontName))
    570             return simpleFont;
    571     }
    572 
    573     // Fall back to all the fonts installed in this PC. When a font has a
    574     // localized name according to the system locale as well as an English name,
    575     // both GetTextFace() and EnumFontFamilies() return the localized name. So,
    576     // FontCache::createFontPlatformData() does not filter out the fonts
    577     // returned by this EnumFontFamilies() call.
    578     HDC dc = GetDC(0);
    579     if (dc) {
    580         GetLastResortFallbackFontProcData procData(this, &description, fallbackFontName);
    581         EnumFontFamilies(dc, 0, getLastResortFallbackFontProc, reinterpret_cast<LPARAM>(&procData));
    582         ReleaseDC(0, dc);
    583 
    584         if (procData.m_fontData)
    585             return procData.m_fontData;
    586     }
    587 
    588     ASSERT_NOT_REACHED();
    589     return 0;
    590 }
    591 
    592 void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
    593 {
    594     HDC hdc = GetDC(0);
    595 
    596     LOGFONT logFont;
    597     logFont.lfCharSet = DEFAULT_CHARSET;
    598     unsigned familyLength = min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1));
    599     memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar));
    600     logFont.lfFaceName[familyLength] = 0;
    601     logFont.lfPitchAndFamily = 0;
    602 
    603     TraitsInFamilyProcData procData(familyName);
    604     EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
    605     copyToVector(procData.m_traitsMasks, traitsMasks);
    606 
    607     ReleaseDC(0, hdc);
    608 }
    609 
    610 FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
    611 {
    612     LOGFONT winfont = {0};
    613     FillLogFont(fontDescription, &winfont);
    614 
    615     // Windows will always give us a valid pointer here, even if the face name
    616     // is non-existent.  We have to double-check and see if the family name was
    617     // really used.
    618     String winName;
    619     HFONT hfont = createFontIndirectAndGetWinName(family, &winfont, &winName);
    620     if (!hfont)
    621         return 0;
    622 
    623     // FIXME: Do we need to use predefined fonts "guaranteed" to exist
    624     // when we're running in layout-test mode?
    625     if (!equalIgnoringCase(family, winName)) {
    626         // For CJK fonts with both English and native names,
    627         // GetTextFace returns a native name under the font's "locale"
    628         // and an English name under other locales regardless of
    629         // lfFaceName field of LOGFONT. As a result, we need to check
    630         // if a font has an alternate name. If there is, we need to
    631         // compare it with what's requested in the first place.
    632         String altName;
    633         if (!LookupAltName(family, altName) ||
    634             !equalIgnoringCase(altName, winName)) {
    635             DeleteObject(hfont);
    636             return 0;
    637         }
    638     }
    639 
    640     return new FontPlatformData(hfont,
    641                                 fontDescription.computedPixelSize());
    642 }
    643 
    644 }
    645