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