Index: third_party/WebKit/Source/platform/LayoutLocale.cpp |
diff --git a/third_party/WebKit/Source/platform/LayoutLocale.cpp b/third_party/WebKit/Source/platform/LayoutLocale.cpp |
index 20aaa1aa635327b0bbb736515dd6a9a75b38d2d1..0a930c9f931e369448c1314a37a8357756a57c59 100644 |
--- a/third_party/WebKit/Source/platform/LayoutLocale.cpp |
+++ b/third_party/WebKit/Source/platform/LayoutLocale.cpp |
@@ -11,10 +11,14 @@ |
#include "wtf/text/StringHash.h" |
#include <hb.h> |
+#include <unicode/locid.h> |
namespace blink { |
const LayoutLocale* LayoutLocale::s_default = nullptr; |
+const LayoutLocale* LayoutLocale::s_system = nullptr; |
+const LayoutLocale* LayoutLocale::s_defaultForHan = nullptr; |
+bool LayoutLocale::s_defaultForHanComputed = false; |
static hb_language_t toHarfbuzLanguage(const AtomicString& locale) |
{ |
@@ -24,44 +28,107 @@ static hb_language_t toHarfbuzLanguage(const AtomicString& locale) |
// SkFontMgr requires script-based locale names, like "zh-Hant" and "zh-Hans", |
// instead of "zh-CN" and "zh-TW". |
-static CString toSkFontMgrLocale(const String& locale) |
+static const char* toSkFontMgrLocale(UScriptCode script) |
{ |
- if (!locale.startsWith("zh", TextCaseInsensitive)) |
- return locale.ascii(); |
- |
- switch (localeToScriptCodeForFontSelection(locale)) { |
+ switch (script) { |
+ case USCRIPT_KATAKANA_OR_HIRAGANA: |
+ return "ja-JP"; |
+ case USCRIPT_HANGUL: |
+ return "ko-KR"; |
case USCRIPT_SIMPLIFIED_HAN: |
return "zh-Hans"; |
case USCRIPT_TRADITIONAL_HAN: |
return "zh-Hant"; |
default: |
- return locale.ascii(); |
+ return nullptr; |
} |
} |
-const CString& LayoutLocale::localeForSkFontMgr() const |
+const char* LayoutLocale::localeForSkFontMgr() const |
{ |
- if (m_stringForSkFontMgr.isNull()) |
- m_stringForSkFontMgr = toSkFontMgrLocale(m_string); |
- return m_stringForSkFontMgr; |
+ if (m_stringForSkFontMgr.isNull()) { |
+ m_stringForSkFontMgr = toSkFontMgrLocale(m_script); |
+ if (m_stringForSkFontMgr.isNull()) |
+ m_stringForSkFontMgr = m_string.ascii(); |
+ } |
+ return m_stringForSkFontMgr.data(); |
} |
-UScriptCode LayoutLocale::scriptForHan() const |
+static bool isUnambiguousHanScript(UScriptCode script) |
{ |
- if (m_scriptForHan != USCRIPT_COMMON) |
- return m_scriptForHan; |
+ // localeToScriptCodeForFontSelection() does not return these values. |
+ DCHECK(script != USCRIPT_HIRAGANA && script != USCRIPT_KATAKANA); |
+ return script == USCRIPT_KATAKANA_OR_HIRAGANA |
+ || script == USCRIPT_SIMPLIFIED_HAN |
+ || script == USCRIPT_TRADITIONAL_HAN |
+ || script == USCRIPT_HANGUL; |
+} |
- m_scriptForHan = scriptCodeForHanFromLocale(script(), localeString()); |
+void LayoutLocale::computeScriptForHan() const |
+{ |
+ if (isUnambiguousHanScript(m_script)) { |
+ m_scriptForHan = m_script; |
+ m_hasScriptForHan = true; |
+ return; |
+ } |
+ |
+ m_scriptForHan = scriptCodeForHanFromSubtags(m_string); |
if (m_scriptForHan == USCRIPT_COMMON) |
- m_scriptForHan = USCRIPT_HAN; |
+ m_scriptForHan = USCRIPT_SIMPLIFIED_HAN; |
+ else |
+ m_hasScriptForHan = true; |
+ DCHECK(isUnambiguousHanScript(m_scriptForHan)); |
+} |
+ |
+UScriptCode LayoutLocale::scriptForHan() const |
+{ |
+ if (m_scriptForHan == USCRIPT_COMMON) |
+ computeScriptForHan(); |
return m_scriptForHan; |
} |
+bool LayoutLocale::hasScriptForHan() const |
+{ |
+ if (m_scriptForHan == USCRIPT_COMMON) |
+ computeScriptForHan(); |
+ return m_hasScriptForHan; |
+} |
+ |
+const LayoutLocale* LayoutLocale::localeForHan(const LayoutLocale* contentLocale) |
+{ |
+ if (contentLocale && contentLocale->hasScriptForHan()) |
+ return contentLocale; |
+ if (!s_defaultForHanComputed) |
+ setLocaleForHan(nullptr); |
+ return s_defaultForHan; |
+} |
+ |
+void LayoutLocale::setLocaleForHan(const LayoutLocale* locale) |
+{ |
+ if (locale) |
+ s_defaultForHan = locale; |
+ else if (getDefault().hasScriptForHan()) |
+ s_defaultForHan = &getDefault(); |
+ else if (getSystem().hasScriptForHan()) |
+ s_defaultForHan = &getSystem(); |
+ else |
+ s_defaultForHan = nullptr; |
+ s_defaultForHanComputed = true; |
+} |
+ |
+const char* LayoutLocale::localeForHanForSkFontMgr() const |
+{ |
+ const char* locale = toSkFontMgrLocale(scriptForHan()); |
+ DCHECK(locale); |
+ return locale; |
+} |
+ |
LayoutLocale::LayoutLocale(const AtomicString& locale) |
: m_string(locale) |
, m_harfbuzzLanguage(toHarfbuzLanguage(locale)) |
, m_script(localeToScriptCodeForFontSelection(locale)) |
, m_scriptForHan(USCRIPT_COMMON) |
+ , m_hasScriptForHan(false) |
, m_hyphenationComputed(false) |
{ |
} |
@@ -85,24 +152,39 @@ const LayoutLocale* LayoutLocale::get(const AtomicString& locale) |
return result.storedValue->value.get(); |
} |
-static const LayoutLocale* computeDefaultLocale() |
+const LayoutLocale& LayoutLocale::getDefault() |
{ |
+ if (s_default) |
+ return *s_default; |
+ |
AtomicString locale = defaultLanguage(); |
- if (!locale.isEmpty()) |
- return LayoutLocale::get(locale); |
- return LayoutLocale::get("en"); |
+ s_default = get(!locale.isEmpty() ? locale : "en"); |
+ return *s_default; |
} |
-const LayoutLocale& LayoutLocale::getDefault() |
+const LayoutLocale& LayoutLocale::getSystem() |
{ |
- if (!s_default) |
- s_default = computeDefaultLocale(); |
- return *s_default; |
+ if (s_system) |
+ return *s_system; |
+ |
+ // Platforms such as Windows can give more information than the default |
+ // locale, such as "en-JP" for English speakers in Japan. |
+ String name = icu::Locale::getDefault().getName(); |
+ s_system = get(AtomicString(name.replace('_', '-'))); |
+ return *s_system; |
+} |
+ |
+PassRefPtr<LayoutLocale> LayoutLocale::createForTesting(const AtomicString& locale) |
+{ |
+ return adoptRef(new LayoutLocale(locale)); |
} |
void LayoutLocale::clearForTesting() |
{ |
s_default = nullptr; |
+ s_system = nullptr; |
+ s_defaultForHan = nullptr; |
+ s_defaultForHanComputed = false; |
getLocaleMap().clear(); |
} |