| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/gfx/font_utils.h" | 5 #include "config.h" |
| 6 #include "FontUtilsWin.h" |
| 7 |
| 8 #include "UniscribeHelper.h" |
| 6 | 9 |
| 7 #include <limits> | 10 #include <limits> |
| 8 #include <map> | 11 #include <map> |
| 9 | 12 |
| 10 #include "base/gfx/uniscribe.h" | 13 |
| 11 #include "base/logging.h" | 14 #include "base/logging.h" |
| 12 #include "base/singleton.h" | 15 #include "base/singleton.h" |
| 13 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 14 #include "unicode/locid.h" | 17 #include "unicode/locid.h" |
| 15 #include "unicode/uchar.h" | 18 #include "unicode/uchar.h" |
| 16 | 19 |
| 17 namespace gfx { | 20 namespace WebCore { |
| 18 | 21 |
| 19 namespace { | 22 namespace { |
| 20 | 23 |
| 21 // hash_map has extra cost with no sizable gain for a small number of integer | 24 // hash_map has extra cost with no sizable gain for a small number of integer |
| 22 // key items. When the map size becomes much bigger (which will be later as | 25 // key items. When the map size becomes much bigger (which will be later as |
| 23 // more scripts are added) and this turns out to be prominent in the profile, we | 26 // more scripts are added) and this turns out to be prominent in the profile, we |
| 24 // may consider switching to hash_map (or just an array if we support all the | 27 // may consider switching to hash_map (or just an array if we support all the |
| 25 // scripts) | 28 // scripts) |
| 26 typedef std::map<UScriptCode, const wchar_t*> ScriptToFontMap; | 29 typedef std::map<UScriptCode, const UChar*> ScriptToFontMap; |
| 27 | 30 |
| 28 struct ScriptToFontMapSingletonTraits | 31 struct ScriptToFontMapSingletonTraits |
| 29 : public DefaultSingletonTraits<ScriptToFontMap> { | 32 : public DefaultSingletonTraits<ScriptToFontMap> { |
| 30 static ScriptToFontMap* New() { | 33 static ScriptToFontMap* New() { |
| 31 struct FontMap { | 34 struct FontMap { |
| 32 UScriptCode script; | 35 UScriptCode script; |
| 33 const wchar_t* family; | 36 const UChar* family; |
| 34 }; | 37 }; |
| 35 | 38 |
| 36 const static FontMap font_map[] = { | 39 const static FontMap font_map[] = { |
| 37 {USCRIPT_LATIN, L"times new roman"}, | 40 {USCRIPT_LATIN, L"times new roman"}, |
| 38 {USCRIPT_GREEK, L"times new roman"}, | 41 {USCRIPT_GREEK, L"times new roman"}, |
| 39 {USCRIPT_CYRILLIC, L"times new roman"}, | 42 {USCRIPT_CYRILLIC, L"times new roman"}, |
| 40 {USCRIPT_SIMPLIFIED_HAN, L"simsun"}, | 43 {USCRIPT_SIMPLIFIED_HAN, L"simsun"}, |
| 41 //{USCRIPT_TRADITIONAL_HAN, L"pmingliu"}, | 44 //{USCRIPT_TRADITIONAL_HAN, L"pmingliu"}, |
| 42 {USCRIPT_HIRAGANA, L"ms pgothic"}, | 45 {USCRIPT_HIRAGANA, L"ms pgothic"}, |
| 43 {USCRIPT_KATAKANA, L"ms pgothic"}, | 46 {USCRIPT_KATAKANA, L"ms pgothic"}, |
| 44 {USCRIPT_KATAKANA_OR_HIRAGANA, L"ms pgothic"}, | 47 {USCRIPT_KATAKANA_OR_HIRAGANA, L"ms pgothic"}, |
| 45 {USCRIPT_HANGUL, L"gulim"}, | 48 {USCRIPT_HANGUL, L"gulim"}, |
| 46 {USCRIPT_THAI, L"tahoma"}, | 49 {USCRIPT_THAI, L"tahoma"}, |
| 47 {USCRIPT_HEBREW, L"david"}, | 50 {USCRIPT_HEBREW, L"david"}, |
| 48 {USCRIPT_ARABIC, L"tahoma"}, | 51 {USCRIPT_ARABIC, L"tahoma"}, |
| 49 {USCRIPT_DEVANAGARI, L"mangal"}, | 52 {USCRIPT_DEVANAGARI, L"mangal"}, |
| 50 {USCRIPT_BENGALI, L"vrinda"}, | 53 {USCRIPT_BENGALI, L"vrinda"}, |
| 51 {USCRIPT_GURMUKHI, L"raavi"}, | 54 {USCRIPT_GURMUKHI, L"raavi"}, |
| 52 {USCRIPT_GUJARATI, L"shruti"}, | 55 {USCRIPT_GUJARATI, L"shruti"}, |
| 53 {USCRIPT_ORIYA, L"kalinga"}, | 56 {USCRIPT_ORIYA, L"kalinga"}, |
| 54 {USCRIPT_TAMIL, L"latha"}, | 57 {USCRIPT_TAMIL, L"latha"}, |
| 55 {USCRIPT_TELUGU, L"gautami"}, | 58 {USCRIPT_TELUGU, L"gautami"}, |
| 56 {USCRIPT_KANNADA, L"tunga"}, | 59 {USCRIPT_KANNADA, L"tunga"}, |
| 57 {USCRIPT_MALAYALAM, L"kartika"}, | 60 {USCRIPT_MALAYALAM, L"kartika"}, |
| 58 {USCRIPT_LAO, L"dokchampa"}, | 61 {USCRIPT_LAO, L"dokchampa"}, |
| 59 {USCRIPT_TIBETAN, L"microsoft himalaya"}, | 62 {USCRIPT_TIBETAN, L"microsoft himalaya"}, |
| 60 {USCRIPT_GEORGIAN, L"sylfaen"}, | 63 {USCRIPT_GEORGIAN, L"sylfaen"}, |
| 61 {USCRIPT_ARMENIAN, L"sylfaen"}, | 64 {USCRIPT_ARMENIAN, L"sylfaen"}, |
| 62 {USCRIPT_ETHIOPIC, L"nyala"}, | 65 {USCRIPT_ETHIOPIC, L"nyala"}, |
| 63 {USCRIPT_CANADIAN_ABORIGINAL, L"euphemia"}, | 66 {USCRIPT_CANADIAN_ABORIGINAL, L"euphemia"}, |
| 64 {USCRIPT_CHEROKEE, L"plantagenet cherokee"}, | 67 {USCRIPT_CHEROKEE, L"plantagenet cherokee"}, |
| 65 {USCRIPT_YI, L"microsoft yi balti"}, | 68 {USCRIPT_YI, L"microsoft yi balti"}, |
| 66 {USCRIPT_SINHALA, L"iskoola pota"}, | 69 {USCRIPT_SINHALA, L"iskoola pota"}, |
| 67 {USCRIPT_SYRIAC, L"estrangelo edessa"}, | 70 {USCRIPT_SYRIAC, L"estrangelo edessa"}, |
| 68 {USCRIPT_KHMER, L"daunpenh"}, | 71 {USCRIPT_KHMER, L"daunpenh"}, |
| 69 {USCRIPT_THAANA, L"mv boli"}, | 72 {USCRIPT_THAANA, L"mv boli"}, |
| 70 {USCRIPT_MONGOLIAN, L"mongolian balti"}, | 73 {USCRIPT_MONGOLIAN, L"mongolian balti"}, |
| 71 {USCRIPT_MYANMAR, L"padauk"}, | 74 {USCRIPT_MYANMAR, L"padauk"}, |
| 72 // For USCRIPT_COMMON, we map blocks to scripts when | 75 // For USCRIPT_COMMON, we map blocks to scripts when |
| 73 // that makes sense. | 76 // that makes sense. |
| 74 }; | 77 }; |
| 75 | 78 |
| 76 ScriptToFontMap* new_instance = new ScriptToFontMap; | 79 ScriptToFontMap* new_instance = new ScriptToFontMap; |
| 77 // Cannot recover from OOM so that there's no need to check. | 80 // Cannot recover from OOM so that there's no need to check. |
| 78 for (int i = 0; i < arraysize(font_map); ++i) | 81 for (int i = 0; i < arraysize(font_map); ++i) |
| 79 (*new_instance)[font_map[i].script] = font_map[i].family; | 82 (*new_instance)[font_map[i].script] = font_map[i].family; |
| 80 | 83 |
| 81 // Initialize the locale-dependent mapping. | 84 // Initialize the locale-dependent mapping. |
| 82 // Since Chrome synchronizes the ICU default locale with its UI locale, | 85 // Since Chrome synchronizes the ICU default locale with its UI locale, |
| 83 // this ICU locale tells the current UI locale of Chrome. | 86 // this ICU locale tells the current UI locale of Chrome. |
| 84 Locale locale = Locale::getDefault(); | 87 Locale locale = Locale::getDefault(); |
| 85 ScriptToFontMap::const_iterator iter; | 88 ScriptToFontMap::const_iterator iter; |
| 86 if (locale == Locale::getJapanese()) { | 89 if (locale == Locale::getJapanese()) { |
| 87 iter = new_instance->find(USCRIPT_HIRAGANA); | 90 iter = new_instance->find(USCRIPT_HIRAGANA); |
| 88 } else if (locale == Locale::getKorean()) { | 91 } else if (locale == Locale::getKorean()) { |
| 89 iter = new_instance->find(USCRIPT_HANGUL); | 92 iter = new_instance->find(USCRIPT_HANGUL); |
| 90 } else { | 93 } else { |
| 91 // Use Simplified Chinese font for all other locales including | 94 // Use Simplified Chinese font for all other locales including |
| 92 // Traditional Chinese because Simsun (SC font) has a wider | 95 // Traditional Chinese because Simsun (SC font) has a wider |
| 93 // coverage (covering both SC and TC) than PMingLiu (TC font). | 96 // coverage (covering both SC and TC) than PMingLiu (TC font). |
| 94 // This also speeds up the TC version of Chrome when rendering SC pages. | 97 // This also speeds up the TC version of Chrome when rendering SC |
| 95 iter = new_instance->find(USCRIPT_SIMPLIFIED_HAN); | 98 // pages. |
| 99 iter = new_instance->find(USCRIPT_SIMPLIFIED_HAN); |
| 100 } |
| 101 if (iter != new_instance->end()) |
| 102 (*new_instance)[USCRIPT_HAN] = iter->second; |
| 103 |
| 104 return new_instance; |
| 96 } | 105 } |
| 97 if (iter != new_instance->end()) | |
| 98 (*new_instance)[USCRIPT_HAN] = iter->second; | |
| 99 | |
| 100 return new_instance; | |
| 101 } | |
| 102 }; | 106 }; |
| 103 | 107 |
| 104 Singleton<ScriptToFontMap, ScriptToFontMapSingletonTraits> script_font_map; | 108 Singleton<ScriptToFontMap, ScriptToFontMapSingletonTraits> script_font_map; |
| 105 | 109 |
| 106 const int kUndefinedAscent = std::numeric_limits<int>::min(); | 110 const int kUndefinedAscent = std::numeric_limits<int>::min(); |
| 107 | 111 |
| 108 // Given an HFONT, return the ascent. If GetTextMetrics fails, | 112 // Given an HFONT, return the ascent. If GetTextMetrics fails, |
| 109 // kUndefinedAscent is returned, instead. | 113 // kUndefinedAscent is returned, instead. |
| 110 int GetAscent(HFONT hfont) { | 114 int GetAscent(HFONT hfont) { |
| 111 HDC dc = GetDC(NULL); | 115 HDC dc = GetDC(NULL); |
| 112 HGDIOBJ oldFont = SelectObject(dc, hfont); | 116 HGDIOBJ oldFont = SelectObject(dc, hfont); |
| 113 TEXTMETRIC tm; | 117 TEXTMETRIC tm; |
| 114 BOOL got_metrics = GetTextMetrics(dc, &tm); | 118 BOOL got_metrics = GetTextMetrics(dc, &tm); |
| 115 SelectObject(dc, oldFont); | 119 SelectObject(dc, oldFont); |
| 116 ReleaseDC(NULL, dc); | 120 ReleaseDC(NULL, dc); |
| 117 return got_metrics ? tm.tmAscent : kUndefinedAscent; | 121 return got_metrics ? tm.tmAscent : kUndefinedAscent; |
| 118 } | 122 } |
| 119 | 123 |
| 120 struct FontData { | 124 struct FontData { |
| 121 FontData() : hfont(NULL), ascent(kUndefinedAscent), script_cache(NULL) {} | 125 FontData() : hfont(NULL), ascent(kUndefinedAscent), script_cache(NULL) {} |
| 122 HFONT hfont; | 126 HFONT hfont; |
| 123 int ascent; | 127 int ascent; |
| 124 mutable SCRIPT_CACHE script_cache; | 128 mutable SCRIPT_CACHE script_cache; |
| 125 }; | 129 }; |
| 126 | 130 |
| 127 // Again, using hash_map does not earn us much here. | 131 // Again, using hash_map does not earn us much here. |
| 128 // page_cycler_test intl2 gave us a 'better' result with map than with hash_map | 132 // page_cycler_test intl2 gave us a 'better' result with map than with hash_map |
| 129 // even though they're well-within 1-sigma of each other so that the difference | 133 // even though they're well-within 1-sigma of each other so that the difference |
| 130 // is not significant. On the other hand, some pages in intl2 seem to | 134 // is not significant. On the other hand, some pages in intl2 seem to |
| 131 // take longer to load with map in the 1st pass. Need to experiment further. | 135 // take longer to load with map in the 1st pass. Need to experiment further. |
| 132 typedef std::map<std::wstring, FontData*> FontDataCache; | 136 typedef std::map<std::wstring, FontData*> FontDataCache; |
| 133 struct FontDataCacheSingletonTraits | 137 struct FontDataCacheSingletonTraits |
| 134 : public DefaultSingletonTraits<FontDataCache> { | 138 : public DefaultSingletonTraits<FontDataCache> { |
| 135 static void Delete(FontDataCache* cache) { | 139 static void Delete(FontDataCache* cache) { |
| 136 FontDataCache::iterator iter = cache->begin(); | 140 FontDataCache::iterator iter = cache->begin(); |
| 137 while (iter != cache->end()) { | 141 while (iter != cache->end()) { |
| 138 SCRIPT_CACHE script_cache = iter->second->script_cache; | 142 SCRIPT_CACHE script_cache = iter->second->script_cache; |
| 139 if (script_cache) | 143 if (script_cache) |
| 140 ScriptFreeCache(&script_cache); | 144 ScriptFreeCache(&script_cache); |
| 141 delete iter->second; | 145 delete iter->second; |
| 142 ++iter; | 146 ++iter; |
| 147 } |
| 148 delete cache; |
| 143 } | 149 } |
| 144 delete cache; | |
| 145 } | |
| 146 }; | 150 }; |
| 147 | 151 |
| 148 } // namespace | 152 } // namespace |
| 149 | 153 |
| 150 // TODO(jungshik) : this is font fallback code version 0.1 | 154 // TODO(jungshik) : this is font fallback code version 0.1 |
| 151 // - Cover all the scripts | 155 // - Cover all the scripts |
| 152 // - Get the default font for each script/generic family from the | 156 // - Get the default font for each script/generic family from the |
| 153 // preference instead of hardcoding in the source. | 157 // preference instead of hardcoding in the source. |
| 154 // (at least, read values from the registry for IE font settings). | 158 // (at least, read values from the registry for IE font settings). |
| 155 // - Support generic families (from FontDescription) | 159 // - Support generic families (from FontDescription) |
| 156 // - If the default font for a script is not available, | 160 // - If the default font for a script is not available, |
| 157 // try some more fonts known to support it. Finally, we can | 161 // try some more fonts known to support it. Finally, we can |
| 158 // use EnumFontFamilies or similar APIs to come up with a list of | 162 // use EnumFontFamilies or similar APIs to come up with a list of |
| 159 // fonts supporting the script and cache the result. | 163 // fonts supporting the script and cache the result. |
| 160 // - Consider using UnicodeSet (or UnicodeMap) converted from | 164 // - Consider using UnicodeSet (or UnicodeMap) converted from |
| 161 // GLYPHSET (BMP) or directly read from truetype cmap tables to | 165 // GLYPHSET (BMP) or directly read from truetype cmap tables to |
| 162 // keep track of which character is supported by which font | 166 // keep track of which character is supported by which font |
| 163 // - Update script_font_cache in response to WM_FONTCHANGE | 167 // - Update script_font_cache in response to WM_FONTCHANGE |
| 164 | 168 |
| 165 const wchar_t* GetFontFamilyForScript(UScriptCode script, | 169 const UChar* GetFontFamilyForScript(UScriptCode script, |
| 166 GenericFamilyType generic) { | 170 GenericFamilyType generic) { |
| 167 ScriptToFontMap::const_iterator iter = script_font_map->find(script); | 171 ScriptToFontMap::const_iterator iter = script_font_map->find(script); |
| 168 const wchar_t* family = NULL; | 172 const UChar* family = NULL; |
| 169 if (iter != script_font_map->end()) { | 173 if (iter != script_font_map->end()) |
| 170 family = iter->second; | 174 family = iter->second; |
| 171 } | 175 return family; |
| 172 return family; | |
| 173 } | 176 } |
| 174 | 177 |
| 175 // TODO(jungshik) | 178 // TODO(jungshik) |
| 176 // - Handle 'Inherited', 'Common' and 'Unknown' | 179 // - Handle 'Inherited', 'Common' and 'Unknown' |
| 177 // (see http://www.unicode.org/reports/tr24/#Usage_Model ) | 180 // (see http://www.unicode.org/reports/tr24/#Usage_Model ) |
| 178 // For 'Inherited' and 'Common', perhaps we need to | 181 // For 'Inherited' and 'Common', perhaps we need to |
| 179 // accept another parameter indicating the previous family | 182 // accept another parameter indicating the previous family |
| 180 // and just return it. | 183 // and just return it. |
| 181 // - All the characters (or characters up to the point a single | 184 // - All the characters (or characters up to the point a single |
| 182 // font can cover) need to be taken into account | 185 // font can cover) need to be taken into account |
| 183 const wchar_t* GetFallbackFamily(const wchar_t *characters, | 186 const UChar* GetFallbackFamily(const UChar *characters, |
| 184 int length, | 187 int length, |
| 185 GenericFamilyType generic, | 188 GenericFamilyType generic, |
| 186 UChar32 *char_checked, | 189 UChar32 *char_checked, |
| 187 UScriptCode *script_checked) { | 190 UScriptCode *script_checked) { |
| 188 DCHECK(characters && characters[0] && length > 0); | 191 DCHECK(characters && characters[0] && length > 0); |
| 189 UScriptCode script = USCRIPT_COMMON; | 192 UScriptCode script = USCRIPT_COMMON; |
| 190 | 193 |
| 191 // Sometimes characters common to script (e.g. space) is at | 194 // Sometimes characters common to script (e.g. space) is at |
| 192 // the beginning of a string so that we need to skip them | 195 // the beginning of a string so that we need to skip them |
| 193 // to get a font required to render the string. | 196 // to get a font required to render the string. |
| 194 int i = 0; | 197 int i = 0; |
| 195 UChar32 ucs4 = 0; | 198 UChar32 ucs4 = 0; |
| 196 while (i < length && script == USCRIPT_COMMON || | 199 while (i < length && script == USCRIPT_COMMON || |
| 197 script == USCRIPT_INVALID_CODE) { | 200 script == USCRIPT_INVALID_CODE) { |
| 198 U16_NEXT(characters, i, length, ucs4); | 201 U16_NEXT(characters, i, length, ucs4); |
| 199 UErrorCode err = U_ZERO_ERROR; | 202 UErrorCode err = U_ZERO_ERROR; |
| 200 script = uscript_getScript(ucs4, &err); | 203 script = uscript_getScript(ucs4, &err); |
| 201 // silently ignore the error | 204 // silently ignore the error |
| 202 } | 205 } |
| 203 | 206 |
| 204 // hack for full width ASCII. For the full-width ASCII, use the font | 207 // hack for full width ASCII. For the full-width ASCII, use the font |
| 205 // for Han (which is locale-dependent). | 208 // for Han (which is locale-dependent). |
| 206 if (0xFF00 < ucs4 && ucs4 < 0xFF5F) | 209 if (0xFF00 < ucs4 && ucs4 < 0xFF5F) |
| 207 script = USCRIPT_HAN; | 210 script = USCRIPT_HAN; |
| 208 | 211 |
| 209 // There are a lot of characters in USCRIPT_COMMON that can be covered | 212 // There are a lot of characters in USCRIPT_COMMON that can be covered |
| 210 // by fonts for scripts closely related to them. | 213 // by fonts for scripts closely related to them. See |
| 211 // See http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Script=Common:] | 214 // http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Script=Common:] |
| 212 // TODO(jungshik): make this more efficient with a wider coverage | 215 // TODO(jungshik): make this more efficient with a wider coverage |
| 213 if (script == USCRIPT_COMMON || script == USCRIPT_INHERITED) { | 216 if (script == USCRIPT_COMMON || script == USCRIPT_INHERITED) { |
| 214 UBlockCode block = ublock_getCode(ucs4); | 217 UBlockCode block = ublock_getCode(ucs4); |
| 215 switch (block) { | 218 switch (block) { |
| 216 case UBLOCK_BASIC_LATIN: | 219 case UBLOCK_BASIC_LATIN: |
| 217 script = USCRIPT_LATIN; | 220 script = USCRIPT_LATIN; |
| 218 break; | 221 break; |
| 219 case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION: | 222 case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION: |
| 220 script = USCRIPT_HAN; | 223 script = USCRIPT_HAN; |
| 221 break; | 224 break; |
| 222 case UBLOCK_HIRAGANA: | 225 case UBLOCK_HIRAGANA: |
| 223 case UBLOCK_KATAKANA: | 226 case UBLOCK_KATAKANA: |
| 224 script = USCRIPT_HIRAGANA; | 227 script = USCRIPT_HIRAGANA; |
| 225 break; | 228 break; |
| 226 case UBLOCK_ARABIC: | 229 case UBLOCK_ARABIC: |
| 227 script = USCRIPT_ARABIC; | 230 script = USCRIPT_ARABIC; |
| 228 break; | 231 break; |
| 229 case UBLOCK_GREEK: | 232 case UBLOCK_GREEK: |
| 230 script = USCRIPT_GREEK; | 233 script = USCRIPT_GREEK; |
| 231 break; | 234 break; |
| 232 case UBLOCK_DEVANAGARI: | 235 case UBLOCK_DEVANAGARI: |
| 233 // For Danda and Double Danda (U+0964, U+0965), use a Devanagari | 236 // For Danda and Double Danda (U+0964, U+0965), use a Devanagari |
| 234 // font for now although they're used by other scripts as well. | 237 // font for now although they're used by other scripts as well. |
| 235 // Without a context, we can't do any better. | 238 // Without a context, we can't do any better. |
| 236 script = USCRIPT_DEVANAGARI; | 239 script = USCRIPT_DEVANAGARI; |
| 237 break; | 240 break; |
| 238 case UBLOCK_ARMENIAN: | 241 case UBLOCK_ARMENIAN: |
| 239 script = USCRIPT_ARMENIAN; | 242 script = USCRIPT_ARMENIAN; |
| 240 break; | 243 break; |
| 241 case UBLOCK_GEORGIAN: | 244 case UBLOCK_GEORGIAN: |
| 242 script = USCRIPT_GEORGIAN; | 245 script = USCRIPT_GEORGIAN; |
| 243 break; | 246 break; |
| 244 case UBLOCK_KANNADA: | 247 case UBLOCK_KANNADA: |
| 245 script = USCRIPT_KANNADA; | 248 script = USCRIPT_KANNADA; |
| 246 break; | 249 break; |
| 250 } |
| 247 } | 251 } |
| 248 } | |
| 249 | 252 |
| 250 // Another lame work-around to cover non-BMP characters. | 253 // Another lame work-around to cover non-BMP characters. |
| 251 const wchar_t* family = GetFontFamilyForScript(script, generic); | 254 const UChar* family = GetFontFamilyForScript(script, generic); |
| 252 if (!family) { | 255 if (!family) { |
| 253 int plane = ucs4 >> 16; | 256 int plane = ucs4 >> 16; |
| 254 switch (plane) { | 257 switch (plane) { |
| 255 case 1: | 258 case 1: |
| 256 family = L"code2001"; | 259 family = L"code2001"; |
| 257 break; | 260 break; |
| 258 case 2: | 261 case 2: |
| 259 family = L"simsun-extb"; | 262 family = L"simsun-extb"; |
| 260 break; | 263 break; |
| 261 default: | 264 default: |
| 262 family = L"lucida sans unicode"; | 265 family = L"lucida sans unicode"; |
| 266 } |
| 263 } | 267 } |
| 264 } | |
| 265 | 268 |
| 266 if (char_checked) *char_checked = ucs4; | 269 if (char_checked) *char_checked = ucs4; |
| 267 if (script_checked) *script_checked = script; | 270 if (script_checked) *script_checked = script; |
| 268 return family; | 271 return family; |
| 269 } | 272 } |
| 270 | 273 |
| 271 | 274 |
| 272 | 275 |
| 273 // Be aware that this is not thread-safe. | 276 // Be aware that this is not thread-safe. |
| 274 bool GetDerivedFontData(const wchar_t *family, | 277 bool GetDerivedFontData(const UChar *family, |
| 275 int style, | 278 int style, |
| 276 LOGFONT *logfont, | 279 LOGFONT *logfont, |
| 277 int *ascent, | 280 int *ascent, |
| 278 HFONT *hfont, | 281 HFONT *hfont, |
| 279 SCRIPT_CACHE **script_cache) { | 282 SCRIPT_CACHE **script_cache) { |
| 280 DCHECK(logfont && family && *family); | 283 DCHECK(logfont && family && *family); |
| 281 // Using |Singleton| here is not free, but the intl2 page cycler test | 284 // Using |Singleton| here is not free, but the intl2 page cycler test |
| 282 // does not show any noticeable difference with and without it. Leaking | 285 // does not show any noticeable difference with and without it. Leaking |
| 283 // the contents of FontDataCache (especially SCRIPT_CACHE) at the end | 286 // the contents of FontDataCache (especially SCRIPT_CACHE) at the end |
| 284 // of a renderer process may not be a good idea. We may use | 287 // of a renderer process may not be a good idea. We may use |
| 285 // atexit(). However, with no noticeable performance difference, |Singleton| | 288 // atexit(). However, with no noticeable performance difference, |Singleton| |
| 286 // is cleaner, I believe. | 289 // is cleaner, I believe. |
| 287 FontDataCache* font_data_cache = | 290 FontDataCache* font_data_cache = |
| 288 Singleton<FontDataCache, FontDataCacheSingletonTraits>::get(); | 291 Singleton<FontDataCache, FontDataCacheSingletonTraits>::get(); |
| 289 // TODO(jungshik) : This comes up pretty high in the profile so that | 292 // TODO(jungshik) : This comes up pretty high in the profile so that |
| 290 // we need to measure whether using SHA256 (after coercing all the | 293 // we need to measure whether using SHA256 (after coercing all the |
| 291 // fields to char*) is faster than StringPrintf. | 294 // fields to char*) is faster than StringPrintf. |
| 292 std::wstring font_key = StringPrintf(L"%1d:%d:%ls", style, logfont->lfHeight, | 295 std::wstring font_key = StringPrintf(L"%1d:%d:%ls", style, |
| 293 family); | 296 logfont->lfHeight, family); |
| 294 FontDataCache::const_iterator iter = font_data_cache->find(font_key); | 297 FontDataCache::const_iterator iter = font_data_cache->find(font_key); |
| 295 FontData *derived; | 298 FontData *derived; |
| 296 if (iter == font_data_cache->end()) { | 299 if (iter == font_data_cache->end()) { |
| 297 DCHECK(wcslen(family) < LF_FACESIZE); | 300 DCHECK(wcslen(family) < LF_FACESIZE); |
| 298 wcscpy_s(logfont->lfFaceName, LF_FACESIZE, family); | 301 wcscpy_s(logfont->lfFaceName, LF_FACESIZE, family); |
| 299 // TODO(jungshik): CreateFontIndirect always comes up with | 302 // TODO(jungshik): CreateFontIndirect always comes up with |
| 300 // a font even if there's no font matching the name. Need to | 303 // a font even if there's no font matching the name. Need to |
| 301 // check it against what we actually want (as is done in FontCacheWin.cpp) | 304 // check it against what we actually want (as is done in |
| 302 derived = new FontData; | 305 // FontCacheWin.cpp) |
| 303 derived->hfont = CreateFontIndirect(logfont); | 306 derived = new FontData; |
| 304 // GetAscent may return kUndefinedAscent, but we still want to | 307 derived->hfont = CreateFontIndirect(logfont); |
| 305 // cache it so that we won't have to call CreateFontIndirect once | 308 // GetAscent may return kUndefinedAscent, but we still want to |
| 306 // more for HFONT next time. | 309 // cache it so that we won't have to call CreateFontIndirect once |
| 307 derived->ascent = GetAscent(derived->hfont); | 310 // more for HFONT next time. |
| 308 (*font_data_cache)[font_key] = derived; | 311 derived->ascent = GetAscent(derived->hfont); |
| 309 } else { | 312 (*font_data_cache)[font_key] = derived; |
| 310 derived = iter->second; | 313 } else { |
| 311 // Last time, GetAscent failed so that only HFONT was | 314 derived = iter->second; |
| 312 // cached. Try once more assuming that TryPreloadFont | 315 // Last time, GetAscent failed so that only HFONT was |
| 313 // was called by a caller between calls. | 316 // cached. Try once more assuming that TryPreloadFont |
| 314 if (kUndefinedAscent == derived->ascent) | 317 // was called by a caller between calls. |
| 315 derived->ascent = GetAscent(derived->hfont); | 318 if (kUndefinedAscent == derived->ascent) |
| 316 } | 319 derived->ascent = GetAscent(derived->hfont); |
| 317 *hfont = derived->hfont; | 320 } |
| 318 *ascent = derived->ascent; | 321 *hfont = derived->hfont; |
| 319 *script_cache = &(derived->script_cache); | 322 *ascent = derived->ascent; |
| 320 return *ascent != kUndefinedAscent; | 323 *script_cache = &(derived->script_cache); |
| 324 return *ascent != kUndefinedAscent; |
| 321 } | 325 } |
| 322 | 326 |
| 323 int GetStyleFromLogfont(const LOGFONT* logfont) { | 327 int GetStyleFromLogfont(const LOGFONT* logfont) { |
| 324 // TODO(jungshik) : consider defining UNDEFINED or INVALID for style and | 328 // TODO(jungshik) : consider defining UNDEFINED or INVALID for style and |
| 325 // returning it when logfont is NULL | 329 // returning it when logfont is NULL |
| 326 if (!logfont) { | 330 if (!logfont) { |
| 327 NOTREACHED(); | 331 NOTREACHED(); |
| 328 return FONT_STYLE_NORMAL; | 332 return FONT_STYLE_NORMAL; |
| 329 } | 333 } |
| 330 return (logfont->lfItalic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL) | | 334 return (logfont->lfItalic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL) | |
| 331 (logfont->lfUnderline ? FONT_STYLE_UNDERLINED : FONT_STYLE_NORMAL) | | 335 (logfont->lfUnderline ? FONT_STYLE_UNDERLINED : FONT_STYLE_NORMAL) | |
| 332 (logfont->lfWeight >= 700 ? FONT_STYLE_BOLD : FONT_STYLE_NORMAL); | 336 (logfont->lfWeight >= 700 ? FONT_STYLE_BOLD : FONT_STYLE_NORMAL); |
| 333 } | 337 } |
| 334 | 338 |
| 335 } // namespace gfx | 339 } // namespace WebCore |
| 336 | |
| OLD | NEW |