Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(597)

Unified Diff: ui/gfx/font_fallback_android.cc

Issue 2863693002: Fallback Font Cache and Character Hinting for VRShell (Closed)
Patch Set: using ICU script to increase cache hits Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/gfx/font_fallback_android.cc
diff --git a/ui/gfx/font_fallback_android.cc b/ui/gfx/font_fallback_android.cc
index e41fa9d28a2eba75f2808088028f394849decc63..53dd7e4f664386cc254cc7061001071bdccc2ab7 100644
--- a/ui/gfx/font_fallback_android.cc
+++ b/ui/gfx/font_fallback_android.cc
@@ -2,15 +2,159 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/gfx/font_fallback.h"
+#include "ui/gfx/font_fallback_android.h"
+#include <array>
+#include <map>
+#include <set>
#include <string>
#include <vector>
+#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
+#include "third_party/icu/source/common/unicode/uscript.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
+#include "ui/gfx/platform_font_linux.h"
+
namespace gfx {
+namespace {
+
+constexpr int kMaxLocales = 1;
+
+enum KnownGlyph {
+ UNDEFINED,
+ UNKNOWN,
+ KNOWN,
+};
+
+using ScriptCharMap = std::array<UChar32, UScriptCode::USCRIPT_CODE_LIMIT>;
+base::LazyInstance<ScriptCharMap>::Leaky g_script_char_map =
mthiesse 2017/05/08 14:46:35 Doesn't look like you need this map. Just change
acondor_ 2017/05/08 16:55:29 Good catch. Done.
+ LAZY_INSTANCE_INITIALIZER;
+
+class CachedFont {
+ public:
+ static std::unique_ptr<CachedFont> CreateForTypeface(
+ sk_sp<SkTypeface> typeface) {
+ return base::WrapUnique<CachedFont>(new CachedFont(typeface));
+ }
+ bool HasGlyphForCharacter(UChar32 character) {
+ // In order to increase cache hits, look for a character of the same
+ // script that was requested before. If this is the first one, store
+ // it for future lookups.
+ UErrorCode err;
+ UScriptCode script = uscript_getScript(character, &err);
+ UChar32 c;
+ if (U_SUCCESS(err)) {
+ UChar32& representative = g_script_char_map.Get()[script];
+ if (!representative)
+ representative = character;
+ c = representative;
+ } else {
+ c = character;
+ }
+ auto& supported = supported_characters_[c];
+ if (supported != UNDEFINED)
+ return supported == KNOWN;
+ uint16_t glyph_id;
+ paint_.textToGlyphs(&c, sizeof(UChar32), &glyph_id);
+ supported = glyph_id ? KNOWN : UNKNOWN;
+ return glyph_id;
+ }
+ std::string GetFontName() { return name_; }
+
+ private:
+ CachedFont(sk_sp<SkTypeface> skia_face) {
+ SkString sk_name;
+ skia_face->getFamilyName(&sk_name);
+ name_ = sk_name.c_str();
+ paint_.setTypeface(std::move(skia_face));
+ paint_.setTextEncoding(SkPaint::kUTF32_TextEncoding);
+ }
+
+ SkPaint paint_;
+ std::map<UChar32, KnownGlyph> supported_characters_;
+ std::string name_;
+};
+
+using FontCache = std::map<SkFontID, std::unique_ptr<CachedFont>>;
+base::LazyInstance<FontCache>::Leaky g_fonts = LAZY_INSTANCE_INITIALIZER;
+
+class CachedFontSet {
+ public:
+ CachedFontSet() : locale_() {}
+ ~CachedFontSet() = default;
+ void SetLocale(const std::string& locale) {
+ // Store font list for one locale at a time.
+ if (locale != locale_) {
+ font_ids_.clear();
+ unknown_chars_.clear();
+ locale_ = locale;
+ }
+ }
+
+ std::string GetFallbackFontNameForChar(UChar32 c) {
+ if (unknown_chars_.find(c) != unknown_chars_.end())
+ return "";
+ for (SkFontID font_id : font_ids_) {
+ std::unique_ptr<CachedFont>& font = g_fonts.Get()[font_id];
+ if (font->HasGlyphForCharacter(c))
+ return font->GetFontName();
+ }
+ sk_sp<SkFontMgr> font_mgr(SkFontMgr::RefDefault());
+ const char* bcp47_locales[kMaxLocales];
mthiesse 2017/05/08 14:46:35 I think this code would be more readable if you go
acondor_ 2017/05/08 16:55:29 The array is needed, but I got rid of the rest.
+ int locale_count = 0;
+ if (!locale_.empty())
+ bcp47_locales[locale_count++] = locale_.c_str();
+ sk_sp<SkTypeface> tf(font_mgr->matchFamilyStyleCharacter(
+ nullptr, SkFontStyle(), bcp47_locales, locale_count, c));
+ if (tf) {
+ SkFontID font_id = tf->uniqueID();
+ font_ids_.push_back(font_id);
+ std::unique_ptr<CachedFont>& cached_font = g_fonts.Get()[font_id];
+ if (!cached_font)
+ cached_font = CachedFont::CreateForTypeface(tf);
+ return cached_font->GetFontName();
+ }
+ unknown_chars_.insert(c);
+ return std::string();
+ }
+
+ private:
+ std::string locale_;
+ std::vector<SkFontID> font_ids_;
+ std::set<UChar32> unknown_chars_;
+};
+
+base::LazyInstance<CachedFontSet>::Leaky g_cached_font_set =
+ LAZY_INSTANCE_INITIALIZER;
+
+bool FontSupportsChar(const gfx::Font& font, UChar32 c) {
+ sk_sp<SkTypeface> typeface =
+ static_cast<PlatformFontLinux*>(font.platform_font())->typeface();
+ std::unique_ptr<CachedFont>& cached_font =
+ g_fonts.Get()[typeface->uniqueID()];
+ if (!cached_font)
+ cached_font = CachedFont::CreateForTypeface(typeface);
+ return cached_font->HasGlyphForCharacter(c);
+}
+
+} // namespace
+
std::vector<Font> GetFallbackFonts(const Font& font) {
return std::vector<Font>();
}
+std::string GetFallbackFontNameForChar(const Font& font,
+ UChar32 c,
+ const std::string& locale) {
+ if (FontSupportsChar(font, c))
+ return std::string();
+ CachedFontSet& cached_font_set = g_cached_font_set.Get();
+ cached_font_set.SetLocale(locale);
+ return cached_font_set.GetFallbackFontNameForChar(c);
+}
+
} // namespace gfx

Powered by Google App Engine
This is Rietveld 408576698