Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / fonts / win / FontCacheSkiaWin.cpp
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 #include "platform/fonts/FontCache.h"
34
35 #include "SkFontMgr.h"
36 #include "SkTypeface_win.h"
37 #include "platform/RuntimeEnabledFeatures.h"
38 #include "platform/fonts/FontDescription.h"
39 #include "platform/fonts/FontFaceCreationParams.h"
40 #include "platform/fonts/SimpleFontData.h"
41 #include "platform/fonts/harfbuzz/FontPlatformDataHarfbuzz.h"
42 #include "platform/fonts/win/FontFallbackWin.h"
43
44 namespace blink {
45
46 HashMap<String, SkTypeface*>* FontCache::s_sideloadedFonts = 0;
47
48 // static
49 void FontCache::addSideloadedFontForTesting(SkTypeface* typeface)
50 {
51     if (!s_sideloadedFonts)
52         s_sideloadedFonts = new HashMap<String, SkTypeface*>;
53     SkString name;
54     typeface->getFamilyName(&name);
55     s_sideloadedFonts->set(name.c_str(), typeface);
56 }
57
58 FontCache::FontCache()
59     : m_purgePreventCount(0)
60 {
61     SkFontMgr* fontManager;
62
63     if (s_useDirectWrite) {
64         fontManager = SkFontMgr_New_DirectWrite(s_directWriteFactory);
65         s_useSubpixelPositioning = RuntimeEnabledFeatures::subpixelFontScalingEnabled();
66     } else {
67         fontManager = SkFontMgr_New_GDI();
68         // Subpixel text positioning is not supported by the GDI backend.
69         s_useSubpixelPositioning = false;
70     }
71
72     ASSERT(fontManager);
73     m_fontManager = adoptPtr(fontManager);
74 }
75
76
77 // Given the desired base font, this will create a SimpleFontData for a specific
78 // font that can be used to render the given range of characters.
79 PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 character, const SimpleFontData*)
80 {
81     // First try the specified font with standard style & weight.
82     if (fontDescription.style() == FontStyleItalic
83         || fontDescription.weight() >= FontWeightBold) {
84         RefPtr<SimpleFontData> fontData = fallbackOnStandardFontStyle(
85             fontDescription, character);
86         if (fontData)
87             return fontData;
88     }
89
90     // FIXME: Consider passing fontDescription.dominantScript()
91     // to GetFallbackFamily here.
92     UScriptCode script;
93     const wchar_t* family = getFallbackFamily(character,
94         fontDescription.genericFamily(),
95         &script,
96         m_fontManager.get());
97     FontPlatformData* data = 0;
98     if (family) {
99         FontFaceCreationParams createByFamily(AtomicString(family, wcslen(family)));
100         data = getFontPlatformData(fontDescription, createByFamily);
101     }
102
103     // Last resort font list : PanUnicode. CJK fonts have a pretty
104     // large repertoire. Eventually, we need to scan all the fonts
105     // on the system to have a Firefox-like coverage.
106     // Make sure that all of them are lowercased.
107     const static wchar_t* const cjkFonts[] = {
108         L"arial unicode ms",
109         L"ms pgothic",
110         L"simsun",
111         L"gulim",
112         L"pmingliu",
113         L"wenquanyi zen hei", // Partial CJK Ext. A coverage but more widely known to Chinese users.
114         L"ar pl shanheisun uni",
115         L"ar pl zenkai uni",
116         L"han nom a", // Complete CJK Ext. A coverage.
117         L"code2000" // Complete CJK Ext. A coverage.
118         // CJK Ext. B fonts are not listed here because it's of no use
119         // with our current non-BMP character handling because we use
120         // Uniscribe for it and that code path does not go through here.
121     };
122
123     const static wchar_t* const commonFonts[] = {
124         L"tahoma",
125         L"arial unicode ms",
126         L"lucida sans unicode",
127         L"microsoft sans serif",
128         L"palatino linotype",
129         // Six fonts below (and code2000 at the end) are not from MS, but
130         // once installed, cover a very wide range of characters.
131         L"dejavu serif",
132         L"dejavu sasns",
133         L"freeserif",
134         L"freesans",
135         L"gentium",
136         L"gentiumalt",
137         L"ms pgothic",
138         L"simsun",
139         L"gulim",
140         L"pmingliu",
141         L"code2000"
142     };
143
144     const wchar_t* const* panUniFonts = 0;
145     int numFonts = 0;
146     if (script == USCRIPT_HAN) {
147         panUniFonts = cjkFonts;
148         numFonts = WTF_ARRAY_LENGTH(cjkFonts);
149     } else {
150         panUniFonts = commonFonts;
151         numFonts = WTF_ARRAY_LENGTH(commonFonts);
152     }
153     // Font returned from getFallbackFamily may not cover |character|
154     // because it's based on script to font mapping. This problem is
155     // critical enough for non-Latin scripts (especially Han) to
156     // warrant an additional (real coverage) check with fontCotainsCharacter.
157     int i;
158     for (i = 0; (!data || !data->fontContainsCharacter(character)) && i < numFonts; ++i) {
159         family = panUniFonts[i];
160         FontFaceCreationParams createByFamily(AtomicString(family, wcslen(family)));
161         data = getFontPlatformData(fontDescription, createByFamily);
162     }
163
164     // When i-th font (0-base) in |panUniFonts| contains a character and
165     // we get out of the loop, |i| will be |i + 1|. That is, if only the
166     // last font in the array covers the character, |i| will be numFonts.
167     // So, we have to use '<=" rather than '<' to see if we found a font
168     // covering the character.
169     if (i <= numFonts)
170         return fontDataFromFontPlatformData(data, DoNotRetain);
171
172     return nullptr;
173 }
174
175 static inline bool equalIgnoringCase(const AtomicString& a, const SkString& b)
176 {
177     return equalIgnoringCase(a, AtomicString::fromUTF8(b.c_str()));
178 }
179
180 static bool typefacesMatchesFamily(const SkTypeface* tf, const AtomicString& family)
181 {
182     SkTypeface::LocalizedStrings* actualFamilies = tf->createFamilyNameIterator();
183     bool matchesRequestedFamily = false;
184     SkTypeface::LocalizedString actualFamily;
185
186     while (actualFamilies->next(&actualFamily)) {
187         if (equalIgnoringCase(family, actualFamily.fString)) {
188             matchesRequestedFamily = true;
189             break;
190         }
191     }
192     actualFamilies->unref();
193
194     // getFamilyName may return a name not returned by the createFamilyNameIterator.
195     // Specifically in cases where Windows substitutes the font based on the
196     // HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes registry entries.
197     if (!matchesRequestedFamily) {
198         SkString familyName;
199         tf->getFamilyName(&familyName);
200         if (equalIgnoringCase(family, familyName))
201             matchesRequestedFamily = true;
202     }
203
204     return matchesRequestedFamily;
205 }
206
207 FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const FontFaceCreationParams& creationParams, float fontSize)
208 {
209     ASSERT(creationParams.creationType() == CreateFontByFamily);
210     CString name;
211     RefPtr<SkTypeface> tf = createTypeface(fontDescription, creationParams, name);
212     if (!tf)
213         return 0;
214
215     // Windows will always give us a valid pointer here, even if the face name
216     // is non-existent. We have to double-check and see if the family name was
217     // really used.
218     // FIXME: Do we need to use predefined fonts "guaranteed" to exist
219     // when we're running in layout-test mode?
220     if (!typefacesMatchesFamily(tf.get(), creationParams.family())) {
221         return 0;
222     }
223
224     FontPlatformData* result = new FontPlatformData(tf,
225         name.data(),
226         fontSize,
227         fontDescription.weight() >= FontWeight600 && !tf->isBold() || fontDescription.isSyntheticBold(),
228         fontDescription.style() == FontStyleItalic && !tf->isItalic() || fontDescription.isSyntheticItalic(),
229         fontDescription.orientation(),
230         s_useSubpixelPositioning);
231
232     struct FamilyMinSize {
233         const wchar_t* family;
234         unsigned minSize;
235     };
236     const static FamilyMinSize minAntiAliasSizeForFont[] = {
237         { L"simsun", 11 },
238         { L"dotum", 12 },
239         { L"gulim", 12 },
240         { L"pmingliu", 11 }
241     };
242     size_t numFonts = WTF_ARRAY_LENGTH(minAntiAliasSizeForFont);
243     for (size_t i = 0; i < numFonts; i++) {
244         FamilyMinSize entry = minAntiAliasSizeForFont[i];
245         if (typefacesMatchesFamily(tf.get(), entry.family)) {
246             result->setMinSizeForAntiAlias(entry.minSize);
247             break;
248         }
249     }
250
251     return result;
252 }
253
254 } // namespace blink