• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
charactersAreAllASCII(const String & s)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
LookupAltName(const String & name,String & altName)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 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 
createFontIndirectAndGetWinName(const String & family,LOGFONT * winfont,String * winName)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 
fontContainsCharacter(const FontPlatformData * fontData,const wchar_t * family,UChar32 character)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.
fontDataFromDescriptionAndLogFont(FontCache * fontCache,const FontDescription & fontDescription,const LOGFONT & font,wchar_t * outFontFamilyName)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 
toGDIFontWeight(FontWeight fontWeight)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 
FillLogFont(const FontDescription & fontDescription,LOGFONT * winfont)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 {
TraitsInFamilyProcDataWebCore::TraitsInFamilyProcData372     TraitsInFamilyProcData(const AtomicString& familyName)
373         : m_familyName(familyName)
374     {
375     }
376 
377     const AtomicString& m_familyName;
378     HashSet<unsigned> m_traitsMasks;
379 };
380 
traitsInFamilyEnumProc(CONST LOGFONT * logFont,CONST TEXTMETRIC * metrics,DWORD fontType,LPARAM lParam)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 {
GetLastResortFallbackFontProcDataWebCore::GetLastResortFallbackFontProcData403     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 
getLastResortFallbackFontProc(const LOGFONT * logFont,const TEXTMETRIC * metrics,DWORD fontType,LPARAM lParam)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 
platformInit()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.
getFontDataForCharacters(const Font & font,const UChar * characters,int length)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 
getSimilarFontPlatformData(const Font & font)516 SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
517 {
518     return 0;
519 }
520 
getLastResortFallbackFont(const FontDescription & description)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 
getTraitsInFamily(const AtomicString & familyName,Vector<unsigned> & traitsMasks)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 
createFontPlatformData(const FontDescription & fontDescription,const AtomicString & family)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