f7e516571c67e052f532663bde572e52e15fff82
[WebKit-https.git] / WebCore / platform / graphics / chromium / FontCacheChromiumWin.cpp
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 Pゴシック, 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 P明朝, 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ゴシック, 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 明朝, 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*, 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*, 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         ASSERT_NOT_REACHED();
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     UnicodeSet* cmap = new 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     if (i < numFonts) // we found the font that covers this character !
398        return getCachedFontData(data);
399
400     return 0;
401
402 }
403
404 const AtomicString& FontCache::alternateFamilyName(const AtomicString& familyName)
405 {
406     // Note that mapping to Courier is removed because 
407     // because it's a bitmap font on Windows.
408     // Alias Courier -> Courier New
409     static AtomicString courier("Courier"), courierNew("Courier New");
410     if (equalIgnoringCase(familyName, courier))
411         return courierNew;
412
413     // Alias Times <-> Times New Roman.
414     static AtomicString times("Times"), timesNewRoman("Times New Roman");
415     if (equalIgnoringCase(familyName, times))
416         return timesNewRoman;
417     if (equalIgnoringCase(familyName, timesNewRoman))
418         return times;
419     
420     // Alias Helvetica <-> Arial
421     static AtomicString arial("Arial"), helvetica("Helvetica");
422     if (equalIgnoringCase(familyName, helvetica))
423         return arial;
424     if (equalIgnoringCase(familyName, arial))
425         return helvetica;
426
427     // We block bitmap fonts altogether so that we have to 
428     // alias MS Sans Serif (bitmap font) -> Microsoft Sans Serif (truetype font)
429     static AtomicString msSans("MS Sans Serif");
430     static AtomicString microsoftSans("Microsoft Sans Serif");
431     if (equalIgnoringCase(familyName, msSans))
432         return microsoftSans;
433
434     // Alias MS Serif (bitmap) -> Times New Roman (truetype font). There's no 
435     // 'Microsoft Sans Serif-equivalent' for Serif. 
436     static AtomicString msSerif("MS Serif");
437     if (equalIgnoringCase(familyName, msSerif))
438         return timesNewRoman;
439
440     // FIXME: should we map 'system' to something ('Tahoma') ? 
441     return emptyAtom;
442 }
443
444 FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
445 {
446     return 0;
447 }
448
449 FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description)
450 {
451     FontDescription::GenericFamilyType generic = description.genericFamily();
452     // FIXME: Mapping webkit generic to GenericFamilyType needs to
453     // be more intelligent. 
454     // This spot rarely gets reached. GetFontDataForCharacters() gets hit a lot
455     // more often (see FIXME comment there). 
456     const wchar_t* family = getFontFamilyForScript(description.dominantScript(), generic);
457
458     if (family)
459         return getCachedFontPlatformData(description, AtomicString(family, wcslen(family)));
460
461     // FIXME: Would be even better to somehow get the user's default font here.
462     // For now we'll pick the default that the user would get without changing
463     // any prefs.
464     static AtomicString timesStr("Times New Roman");
465     static AtomicString courierStr("Courier New");
466     static AtomicString arialStr("Arial");
467
468     AtomicString& fontStr = timesStr;
469     if (generic == FontDescription::SansSerifFamily)
470         fontStr = arialStr;
471     else if (generic == FontDescription::MonospaceFamily)
472         fontStr = courierStr;
473
474     return getCachedFontPlatformData(description, fontStr);
475 }
476
477 static LONG toGDIFontWeight(FontWeight fontWeight)
478 {
479     static LONG gdiFontWeights[] = {
480         FW_THIN,        // FontWeight100
481         FW_EXTRALIGHT,  // FontWeight200
482         FW_LIGHT,       // FontWeight300
483         FW_NORMAL,      // FontWeight400
484         FW_MEDIUM,      // FontWeight500
485         FW_SEMIBOLD,    // FontWeight600
486         FW_BOLD,        // FontWeight700
487         FW_EXTRABOLD,   // FontWeight800
488         FW_HEAVY        // FontWeight900
489     };
490     return gdiFontWeights[fontWeight];
491 }
492
493 // FIXME: This may not be the best place to put this function
494 AtomicString FontCache::getGenericFontForScript(UScriptCode script, const FontDescription& description)
495 {
496     const wchar_t* scriptFont = getFontFamilyForScript( script, description.genericFamily());
497     return scriptFont ? AtomicString(scriptFont, wcslen(scriptFont)) : emptyAtom;
498 }
499
500 static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
501 {
502     // The size here looks unusual.  The negative number is intentional.
503     // Unlike WebKit trunk, we don't multiply the size by 32.  That seems to be
504     // some kind of artifact of their CG backend, or something.
505     winfont->lfHeight = -fontDescription.computedPixelSize();
506     winfont->lfWidth = 0;
507     winfont->lfEscapement = 0;
508     winfont->lfOrientation = 0;
509     winfont->lfUnderline = false;
510     winfont->lfStrikeOut = false;
511     winfont->lfCharSet = DEFAULT_CHARSET;
512     winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
513     winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
514     winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
515     winfont->lfItalic = fontDescription.italic();
516     winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
517 }
518
519 bool FontCache::fontExists(const FontDescription& fontDescription, const AtomicString& family)
520 {
521     LOGFONT winfont = {0};
522     FillLogFont(fontDescription, &winfont);
523     String winName;
524     HFONT hfont = createFontIndirectAndGetWinName(family, &winfont, &winName);
525     if (!hfont)
526       return false;
527
528     DeleteObject(hfont);
529     if (equalIgnoringCase(family, winName))
530       return true;
531     // For CJK fonts with both English and native names, 
532     // GetTextFace returns a native name under the font's "locale"
533     // and an English name under other locales regardless of 
534     // lfFaceName field of LOGFONT. As a result, we need to check
535     // if a font has an alternate name. If there is, we need to
536     // compare it with what's requested in the first place.
537     String altName;
538     return LookupAltName(family, altName) && equalIgnoringCase(altName, winName);
539 }
540
541 struct TraitsInFamilyProcData {
542     TraitsInFamilyProcData(const AtomicString& familyName)
543         : m_familyName(familyName)
544     {
545     }
546
547     const AtomicString& m_familyName;
548     HashSet<unsigned> m_traitsMasks;
549 };
550
551 static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
552 {
553     TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
554
555     unsigned traitsMask = 0;
556     traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
557     traitsMask |= FontVariantNormalMask;
558     LONG weight = logFont->lfWeight;
559     traitsMask |= weight == FW_THIN ? FontWeight100Mask :
560         weight == FW_EXTRALIGHT ? FontWeight200Mask :
561         weight == FW_LIGHT ? FontWeight300Mask :
562         weight == FW_NORMAL ? FontWeight400Mask :
563         weight == FW_MEDIUM ? FontWeight500Mask :
564         weight == FW_SEMIBOLD ? FontWeight600Mask :
565         weight == FW_BOLD ? FontWeight700Mask :
566         weight == FW_EXTRABOLD ? FontWeight800Mask :
567                                  FontWeight900Mask;
568     procData->m_traitsMasks.add(traitsMask);
569     return 1;
570 }
571
572 void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
573 {
574     HDC hdc = GetDC(0);
575
576     LOGFONT logFont;
577     logFont.lfCharSet = DEFAULT_CHARSET;
578     unsigned familyLength = min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1));
579     memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar));
580     logFont.lfFaceName[familyLength] = 0;
581     logFont.lfPitchAndFamily = 0;
582
583     TraitsInFamilyProcData procData(familyName);
584     EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
585     copyToVector(procData.m_traitsMasks, traitsMasks);
586
587     ReleaseDC(0, hdc);
588 }
589
590 FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
591 {
592     LOGFONT winfont = {0};
593     FillLogFont(fontDescription, &winfont);
594
595     // Windows will always give us a valid pointer here, even if the face name 
596     // is non-existent.  We have to double-check and see if the family name was 
597     // really used.
598     String winName;
599     HFONT hfont = createFontIndirectAndGetWinName(family, &winfont, &winName);
600     if (!hfont)
601         return 0;
602
603     // FIXME: Do we need to use predefined fonts "guaranteed" to exist
604     // when we're running in layout-test mode?
605     if (!equalIgnoringCase(family, winName)) {
606         // For CJK fonts with both English and native names, 
607         // GetTextFace returns a native name under the font's "locale"
608         // and an English name under other locales regardless of 
609         // lfFaceName field of LOGFONT. As a result, we need to check
610         // if a font has an alternate name. If there is, we need to
611         // compare it with what's requested in the first place.
612         String altName;
613         if (!LookupAltName(family, altName) || 
614             !equalIgnoringCase(altName, winName)) {
615             DeleteObject(hfont);
616             return 0;
617         }
618     }
619
620     return new FontPlatformData(hfont,
621                                 fontDescription.computedPixelSize());
622 }
623
624 }