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
48using std::min;
49
50namespace WebCore
51{
52
53// FIXME: consider adding to WebKit String class
54static 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
69static 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 Pゴシック, 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 P明朝, 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ゴシック, 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 明朝, 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
240static 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.
267typedef HashMap<const wchar_t*, icu::UnicodeSet*> FontCmapCache;
268
269static 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.
328static 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
336static 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
352static 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
371struct 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
381static 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
402struct 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
417static 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
424void 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.
431const 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
516SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
517{
518    return 0;
519}
520
521SimpleFontData* 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
592void 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
610FontPlatformData* 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