Commit 9ab3e68a authored by kojii's avatar kojii Committed by Commit bot

Change the system font fallback to take lang attributes into account on Windows

This patch changes the system font fallback logic on Windows to take
lang attributes into account.

When a code point is missing in all specified fonts, Blink determines
fonts to use by using Unicode properties for the character.

The UI locale is also used for characters of Asian scripts where
multiple scripts share a large set of the code points.

This patch takes the specified lang attribute to take precedence over
the UI locale. When language tag does not help to determine the script
for the unified ideographs, subtags such as script or country are also
used.

All test rebaselines are where lang attributes are used, and new
results use the correct font for the specified lang.

BUG=579492

Review URL: https://codereview.chromium.org/1607943004

Cr-Commit-Position: refs/heads/master@{#370703}
parent b67ca118
...@@ -353,6 +353,16 @@ crbug.com/240374 compositing/overlap-blending/reflection-opacity-huge.html [ Fai ...@@ -353,6 +353,16 @@ crbug.com/240374 compositing/overlap-blending/reflection-opacity-huge.html [ Fai
crbug.com/240374 compositing/overlap-blending/children-opacity-huge.html [ Failure ] crbug.com/240374 compositing/overlap-blending/children-opacity-huge.html [ Failure ]
crbug.com/240374 compositing/overlap-blending/children-opacity-no-overlap.html [ Failure ] crbug.com/240374 compositing/overlap-blending/children-opacity-no-overlap.html [ Failure ]
crbug.com/579492 [ Win7 XP ] fast/forms/datetimelocal/datetimelocal-appearance-l10n.html [ NeedsRebaseline ]
crbug.com/579492 [ Win7 XP ] fast/forms/month/month-appearance-l10n.html [ NeedsRebaseline ]
crbug.com/579492 [ Win7 XP ] fast/ruby/nested-ruby.html [ NeedsRebaseline ]
crbug.com/579492 [ Win7 XP ] fast/text/international/002.html [ NeedsRebaseline ]
crbug.com/579492 [ Win7 XP ] fast/text/international/lang-glyph-cache-separation.html [ NeedsRebaseline ]
crbug.com/579492 [ Win7 XP ] fast/writing-mode/japanese-ruby-vertical-lr.html [ NeedsRebaseline ]
crbug.com/579492 [ Win7 XP ] fast/writing-mode/japanese-ruby-vertical-rl.html [ NeedsRebaseline ]
crbug.com/579492 inspector-protocol/layout-fonts/cjk-ideograph-fallback-by-lang.html [ NeedsRebaseline ]
crbug.com/579492 [ Win ] inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.html [ NeedsRebaseline ]
crbug.com/410145 [ Win ] fast/table/column-in-inline.html [ Failure ] crbug.com/410145 [ Win ] fast/table/column-in-inline.html [ Failure ]
crbug.com/411164 [ Win ] http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Pass Slow ] crbug.com/411164 [ Win ] http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Pass Slow ]
......
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head>
<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script>
<script type="text/javascript" src="../../http/tests/inspector-protocol/css-protocol-test.js"></script>
<script type="text/javascript" src="../../http/tests/inspector-protocol/dom-protocol-test.js"></script>
<script type="text/javascript" src="resources/layout-font-test.js"></script>
</head>
<body>
<div class="test">
<div id="zh-CN" lang="zh-CN">zh-CN: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="zh-TW" lang="zh-TW">zh-TW: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="zh-HK" lang="zh-HK">zh-HK: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="ja" lang="ja">ja: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="ja-JP" lang="ja-JP">ja-JP: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="ko" lang="ko">ko: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="ko-KR" lang="ko-KR">ko-KR: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-CN" lang="en-CN">en-CN: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-JP" lang="en-JP">en-JP: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-KR" lang="en-KR">en-KR: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-HK" lang="en-HK">en-HK: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-TW" lang="en-TW">en-TW: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-HanS" lang="en-HanS">en-HanS: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-HanT" lang="en-HanT">en-HanT: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-HanS-JP" lang="en-HanS-JP">en-HanS-JP: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-HanT-JP" lang="en-HanT-JP">en-HanT-JP: &#x8AA4;&#x904E;&#x9AA8;</div>
<div id="en-US" lang="en-US">en-US: &#x8AA4;&#x904E;&#x9AA8;</div>
</div>
</body>
</html>
zh-CN: 誤過骨
#zh-CN:
"Times New Roman" : 7,
"SimSun" : 3
zh-TW: 誤過骨
#zh-TW:
"Times New Roman" : 7,
"PMingLiU" : 3
zh-HK: 誤過骨
#zh-HK:
"Times New Roman" : 7,
"PMingLiU" : 3
ja: 誤過骨
#ja:
"Times New Roman" : 4,
"MS PGothic" : 3
ko: 誤過骨
#ko:
"Times New Roman" : 4,
"Gulim" : 3
en-CN: 誤過骨
#en-CN:
"Times New Roman" : 7,
"SimSun" : 3
en-JP: 誤過骨
#en-JP:
"Times New Roman" : 7,
"MS PGothic" : 3
en-KR: 誤過骨
#en-KR:
"Times New Roman" : 7,
"Gulim" : 3
en-TW: 誤過骨
#en-TW:
"Times New Roman" : 7,
"PMingLiU" : 3
en-HanS: 誤過骨
#en-HanS:
"Times New Roman" : 9,
"SimSun" : 3
en-HanT: 誤過骨
#en-HanT:
"Times New Roman" : 9,
"PMingLiU" : 3
en-HanS-JP: 誤過骨
#en-HanS-JP:
"Times New Roman" : 12,
"SimSun" : 3
en-HanT-JP: 誤過骨
#en-HanT-JP:
"Times New Roman" : 12,
"PMingLiU" : 3
en-US: 誤過骨
#en-US:
"Times New Roman" : 7,
"MS PGothic" : 3
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさき ゆめみし ゑひもせす(ん)色は匂へど 散りぬるを 我が世誰ぞ 常ならむ 有為の奥山 今日越えて 浅き夢見じ 酔ひもせず(ん) いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさき ゆめみし ゑひもせす(ん)色は匂へど 散りぬるを 我が世誰ぞ 常ならむ 有為の奥山 今日越えて 浅き夢見じ 酔ひもせず(ん)
#japanese_iroha: #japanese_iroha:
"MS PGothic" : 74, "MS PGothic" : 92,
"SimSun" : 18,
"Times New Roman" : 15 "Times New Roman" : 15
키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다. 키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다.
......
...@@ -128,11 +128,11 @@ PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter( ...@@ -128,11 +128,11 @@ PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(
return fontData; return fontData;
} }
// FIXME: Consider passing fontDescription.dominantScript()
// to GetFallbackFamily here.
UScriptCode script; UScriptCode script;
const wchar_t* family = getFallbackFamily(character, const wchar_t* family = getFallbackFamily(character,
fontDescription.genericFamily(), fontDescription.genericFamily(),
fontDescription.script(),
fontDescription.locale(),
&script, &script,
m_fontManager.get()); m_fontManager.get());
FontPlatformData* data = 0; FontPlatformData* data = 0;
......
...@@ -42,6 +42,64 @@ ...@@ -42,6 +42,64 @@
namespace blink { namespace blink {
static bool isUnambiguousUnifiedHanScript(UScriptCode script)
{
// localeToScriptCodeForFontSelection() does not return these values.
ASSERT(script != USCRIPT_HIRAGANA && script != USCRIPT_KATAKANA);
return script == USCRIPT_KATAKANA_OR_HIRAGANA
|| script == USCRIPT_SIMPLIFIED_HAN
|| script == USCRIPT_TRADITIONAL_HAN
|| script == USCRIPT_HANGUL;
}
static UScriptCode scriptCodeForUnifiedHanFromSubtag(const String& subtag)
{
struct SubtagScript {
const char* subtag;
UScriptCode script;
};
static const SubtagScript subtagScriptList[] = {
{ "cn", USCRIPT_SIMPLIFIED_HAN },
{ "hans", USCRIPT_SIMPLIFIED_HAN },
{ "hant", USCRIPT_TRADITIONAL_HAN },
{ "hk", USCRIPT_TRADITIONAL_HAN },
{ "jp", USCRIPT_HIRAGANA },
{ "kr", USCRIPT_HANGUL },
{ "tw", USCRIPT_TRADITIONAL_HAN },
};
typedef HashMap<String, UScriptCode> SubtagScriptMap;
DEFINE_STATIC_LOCAL(SubtagScriptMap, subtagScriptMap, ());
if (subtagScriptMap.isEmpty()) {
for (size_t i = 0; i < WTF_ARRAY_LENGTH(subtagScriptList); ++i)
subtagScriptMap.set(subtagScriptList[i].subtag, subtagScriptList[i].script);
}
const auto& it = subtagScriptMap.find(subtag.lower());
return it != subtagScriptMap.end() ? it->value : USCRIPT_COMMON;
}
UScriptCode scriptCodeForUnifiedHanFromSubtags(const String& locale)
{
// Some sites emit lang="en-JP" when English is set as the preferred
// language. Use script/region subtags of the content locale to pick the
// fallback font for unified Han ideographs.
for (size_t delimiter = locale.find('-'); delimiter != kNotFound; ) {
++delimiter;
size_t end = locale.find('-', delimiter);
UScriptCode script = scriptCodeForUnifiedHanFromSubtag(
locale.substring(delimiter,
end == kNotFound ? UINT_MAX : end - delimiter));
if (script != USCRIPT_COMMON)
return script;
delimiter = end;
}
// Fallback to the UI locale.
return USCRIPT_HAN;
}
UScriptCode scriptCodeForUnifiedHanFromLocale(const icu::Locale& locale) UScriptCode scriptCodeForUnifiedHanFromLocale(const icu::Locale& locale)
{ {
// ICU default locale may have country as an empty string or differently. // ICU default locale may have country as an empty string or differently.
...@@ -52,13 +110,13 @@ UScriptCode scriptCodeForUnifiedHanFromLocale(const icu::Locale& locale) ...@@ -52,13 +110,13 @@ UScriptCode scriptCodeForUnifiedHanFromLocale(const icu::Locale& locale)
if (strcasecmp(locale.getLanguage(), icu::Locale::getKorean().getLanguage()) == 0) if (strcasecmp(locale.getLanguage(), icu::Locale::getKorean().getLanguage()) == 0)
return USCRIPT_HANGUL; return USCRIPT_HANGUL;
const icu::Locale& traditionalChinese = icu::Locale::getTraditionalChinese(); // Chinese and non-CJK languages may be able to determine from subtags.
if (strcasecmp(locale.getLanguage(), traditionalChinese.getLanguage()) == 0 UScriptCode script = scriptCodeForUnifiedHanFromSubtag(locale.getScript());
&& (strcasecmp(locale.getCountry(), traditionalChinese.getCountry()) == 0 if (script != USCRIPT_COMMON)
|| strcasecmp(locale.getCountry(), "HK") == 0 return script;
|| strcasecmp(locale.getScript(), "Hant") == 0)) { script = scriptCodeForUnifiedHanFromSubtag(locale.getCountry());
return USCRIPT_TRADITIONAL_HAN; if (script != USCRIPT_COMMON)
} return script;
// For other locales, use the simplified Chinese font for Han. // For other locales, use the simplified Chinese font for Han.
return USCRIPT_SIMPLIFIED_HAN; return USCRIPT_SIMPLIFIED_HAN;
...@@ -401,6 +459,8 @@ const UChar* getFontFamilyForScript(UScriptCode script, ...@@ -401,6 +459,8 @@ const UChar* getFontFamilyForScript(UScriptCode script,
// font can cover) need to be taken into account // font can cover) need to be taken into account
const UChar* getFallbackFamily(UChar32 character, const UChar* getFallbackFamily(UChar32 character,
FontDescription::GenericFamilyType generic, FontDescription::GenericFamilyType generic,
UScriptCode contentScript,
const AtomicString& contentLocale,
UScriptCode* scriptChecked, UScriptCode* scriptChecked,
SkFontMgr* fontManager) SkFontMgr* fontManager)
{ {
...@@ -425,6 +485,14 @@ const UChar* getFallbackFamily(UChar32 character, ...@@ -425,6 +485,14 @@ const UChar* getFallbackFamily(UChar32 character,
if (script == USCRIPT_COMMON) if (script == USCRIPT_COMMON)
script = getScriptBasedOnUnicodeBlock(character); script = getScriptBasedOnUnicodeBlock(character);
// For unified-Han scripts, try the lang attribute.
if (script == USCRIPT_HAN) {
if (isUnambiguousUnifiedHanScript(contentScript))
script = contentScript;
else
script = scriptCodeForUnifiedHanFromSubtags(contentLocale);
}
family = getFontFamilyForScript(script, generic, fontManager); family = getFontFamilyForScript(script, generic, fontManager);
// Another lame work-around to cover non-BMP characters. // Another lame work-around to cover non-BMP characters.
// If the font family for script is not found or the character is // If the font family for script is not found or the character is
......
...@@ -49,9 +49,12 @@ namespace blink { ...@@ -49,9 +49,12 @@ namespace blink {
// the family is returned. // the family is returned.
PLATFORM_EXPORT const UChar* getFallbackFamily(UChar32 character, PLATFORM_EXPORT const UChar* getFallbackFamily(UChar32 character,
FontDescription::GenericFamilyType, FontDescription::GenericFamilyType,
UScriptCode contentScript,
const AtomicString& contentLocale,
UScriptCode* scriptChecked, UScriptCode* scriptChecked,
SkFontMgr* fontManager); SkFontMgr* fontManager);
PLATFORM_EXPORT UScriptCode scriptCodeForUnifiedHanFromLocale(const icu::Locale&); PLATFORM_EXPORT UScriptCode scriptCodeForUnifiedHanFromLocale(const icu::Locale&);
PLATFORM_EXPORT UScriptCode scriptCodeForUnifiedHanFromSubtags(const String& locale);
} // namespace blink } // namespace blink
......
...@@ -36,4 +36,28 @@ TEST(FontFallbackWinTest, scriptCodeForUnifiedHanFromLocaleTest) ...@@ -36,4 +36,28 @@ TEST(FontFallbackWinTest, scriptCodeForUnifiedHanFromLocaleTest)
icu::Locale("zh", "hant"))); icu::Locale("zh", "hant")));
} }
TEST(FontFallbackWinTest, scriptCodeForUnifiedHanFromSubtagsTest)
{
EXPECT_EQ(USCRIPT_SIMPLIFIED_HAN,
scriptCodeForUnifiedHanFromSubtags("en-CN"));
EXPECT_EQ(USCRIPT_HIRAGANA, scriptCodeForUnifiedHanFromSubtags("en-JP"));
EXPECT_EQ(USCRIPT_HANGUL, scriptCodeForUnifiedHanFromSubtags("en-KR"));
EXPECT_EQ(USCRIPT_TRADITIONAL_HAN,
scriptCodeForUnifiedHanFromSubtags("en-HK"));
EXPECT_EQ(USCRIPT_TRADITIONAL_HAN,
scriptCodeForUnifiedHanFromSubtags("en-TW"));
EXPECT_EQ(USCRIPT_SIMPLIFIED_HAN,
scriptCodeForUnifiedHanFromSubtags("en-HanS"));
EXPECT_EQ(USCRIPT_TRADITIONAL_HAN,
scriptCodeForUnifiedHanFromSubtags("en-HanT"));
EXPECT_EQ(USCRIPT_SIMPLIFIED_HAN,
scriptCodeForUnifiedHanFromSubtags("en-HanS-JP"));
EXPECT_EQ(USCRIPT_TRADITIONAL_HAN,
scriptCodeForUnifiedHanFromSubtags("en-HanT-JP"));
EXPECT_EQ(USCRIPT_HAN, scriptCodeForUnifiedHanFromSubtags("en-US"));
}
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment