Index: third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp |
diff --git a/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp b/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp |
index 01af49b0f0ab61a413226b661a21956fc7a2c75e..b40b1cbe464ed40f218d28f553fef1945f41bf09 100644 |
--- a/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp |
+++ b/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp |
@@ -9,22 +9,29 @@ |
#include "base/metrics/histogram.h" |
#include "base/timer/elapsed_timer.h" |
#include "mojo/public/cpp/system/platform_handle.h" |
+#include "platform/text/hyphenation/HyphenatorAOSP.h" |
#include "public/platform/Platform.h" |
#include "public/platform/ServiceRegistry.h" |
#include "public/platform/modules/hyphenation/hyphenation.mojom-blink.h" |
namespace blink { |
+using Hyphenator = android::Hyphenator; |
+ |
class HyphenationMinikin : public Hyphenation { |
public: |
bool openDictionary(const AtomicString& locale); |
size_t lastHyphenLocation(const StringView& text, size_t beforeIndex) const override; |
+ Vector<size_t, 8> hyphenLocations(const StringView&) const override; |
private: |
static base::PlatformFile openDictionaryFile(const AtomicString& locale); |
+ std::vector<uint8_t> hyphenate(const StringView&) const; |
+ |
base::MemoryMappedFile m_file; |
+ std::unique_ptr<Hyphenator> m_hyphenator; |
}; |
static mojom::blink::HyphenationPtr connectToRemoteService() |
@@ -71,23 +78,96 @@ bool HyphenationMinikin::openDictionary(const AtomicString& locale) |
return false; |
} |
- // TODO(kojii): Create dictionary from m_file when Minikin is ready. |
+ m_hyphenator = wrapUnique(Hyphenator::loadBinary(m_file.data())); |
return true; |
} |
+std::vector<uint8_t> HyphenationMinikin::hyphenate(const StringView& text) const |
+{ |
+ std::vector<uint8_t> result; |
+ if (text.is8Bit()) { |
+ String text16Bit = text.toString(); |
+ text16Bit.ensure16Bit(); |
+ m_hyphenator->hyphenate(&result, text16Bit.characters16(), text16Bit.length()); |
+ } else { |
+ m_hyphenator->hyphenate(&result, text.characters16(), text.length()); |
+ } |
+ return result; |
+} |
+ |
size_t HyphenationMinikin::lastHyphenLocation(const StringView& text, size_t beforeIndex) const |
{ |
- // TODO(kojii): Call minikin using the dictionary when Minikin is ready. |
+ if (text.length() < minimumPrefixLength + minimumSuffixLength) |
+ return 0; |
+ |
+ std::vector<uint8_t> result = hyphenate(text); |
+ static_assert(minimumPrefixLength >= 1, "Change the 'if' above if this fails"); |
+ for (size_t i = text.length() - minimumSuffixLength - 1; |
+ i >= minimumPrefixLength; i--) { |
+ if (result[i]) |
+ return i; |
+ } |
return 0; |
} |
+Vector<size_t, 8> HyphenationMinikin::hyphenLocations(const StringView& text) const |
+{ |
+ Vector<size_t, 8> hyphenLocations; |
+ if (text.length() < minimumPrefixLength + minimumSuffixLength) |
+ return hyphenLocations; |
+ |
+ std::vector<uint8_t> result = hyphenate(text); |
+ static_assert(minimumPrefixLength >= 1, "Change the 'if' above if this fails"); |
+ for (size_t i = text.length() - minimumSuffixLength - 1; |
+ i >= minimumPrefixLength; i--) { |
+ if (result[i]) |
+ hyphenLocations.append(i); |
+ } |
+ return hyphenLocations; |
+} |
+ |
+using LocaleMap = HashMap<AtomicString, AtomicString, CaseFoldingHash>; |
+ |
+static LocaleMap createLocaleFallbackMap() |
+{ |
+ // This data is from CLDR, compiled by AOSP. |
+ // https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/Hyphenator.java |
+ using LocaleFallback = const char*[2]; |
+ static LocaleFallback localeFallbackData[] = { |
+ { "en-AS", "en-US" }, // English (American Samoa) |
+ { "en-GU", "en-US" }, // English (Guam) |
+ { "en-MH", "en-US" }, // English (Marshall Islands) |
+ { "en-MP", "en-US" }, // English (Northern Mariana Islands) |
+ { "en-PR", "en-US" }, // English (Puerto Rico) |
+ { "en-UM", "en-US" }, // English (United States Minor Outlying Islands) |
+ { "en-VI", "en-US" }, // English (Virgin Islands) |
+ { "no", "nb" }, |
+ { "am", "und-Ethi" }, // Amharic |
+ { "byn", "und-Ethi" }, // Blin |
+ { "gez", "und-Ethi" }, // Geʻez |
+ { "ti", "und-Ethi" }, // Tigrinya |
+ { "wal", "und-Ethi" }, // Wolaytta |
+ }; |
+ LocaleMap map; |
+ for (const auto& it : localeFallbackData) |
+ map.add(it[0], it[1]); |
+ return map; |
+} |
+ |
PassRefPtr<Hyphenation> Hyphenation::platformGetHyphenation(const AtomicString& locale) |
{ |
RefPtr<HyphenationMinikin> hyphenation(adoptRef(new HyphenationMinikin)); |
- if (!hyphenation->openDictionary(locale)) |
- return nullptr; |
- return hyphenation.release(); |
+ if (hyphenation->openDictionary(locale.lowerASCII())) |
+ return hyphenation.release(); |
+ hyphenation.clear(); |
+ |
+ DEFINE_STATIC_LOCAL(LocaleMap, localeFallback, (createLocaleFallbackMap())); |
+ const auto& it = localeFallback.find(locale); |
+ if (it != localeFallback.end()) |
+ return get(it->value); |
+ |
+ return nullptr; |
} |
} // namespace blink |