OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "ui/gfx/font_fallback.h" | 5 #include "ui/gfx/font_fallback_android.h" |
6 | 6 |
7 #include <map> | |
8 #include <set> | |
7 #include <string> | 9 #include <string> |
8 #include <vector> | 10 #include <vector> |
9 | 11 |
12 #include "base/lazy_instance.h" | |
13 #include "base/memory/ptr_util.h" | |
14 #include "third_party/icu/source/common/unicode/uscript.h" | |
15 #include "third_party/skia/include/core/SkPaint.h" | |
16 #include "third_party/skia/include/core/SkTypeface.h" | |
17 #include "third_party/skia/include/ports/SkFontMgr.h" | |
18 #include "ui/gfx/platform_font_linux.h" | |
19 | |
10 namespace gfx { | 20 namespace gfx { |
11 | 21 |
22 namespace { | |
23 | |
24 enum KnownGlyph { | |
25 UNDEFINED, | |
26 UNKNOWN, | |
27 KNOWN, | |
28 }; | |
29 | |
30 class CachedFont { | |
31 public: | |
32 static std::unique_ptr<CachedFont> CreateForTypeface( | |
33 sk_sp<SkTypeface> typeface) { | |
34 return base::WrapUnique<CachedFont>(new CachedFont(typeface)); | |
35 } | |
Alexei Svitkine (slow)
2017/05/09 14:52:17
Nit: Add an empty line after this.
acondor_
2017/05/09 16:21:51
Done.
| |
36 bool HasGlyphForCharacter(UChar32 character) { | |
37 // In order to increase cache hits, the cache is script based rather than | |
38 // character based. This also limits the cache size to the number of Unicode | |
39 // scripts (174 at the time of writing). | |
40 UErrorCode err; | |
41 UScriptCode script = uscript_getScript(character, &err); | |
42 if (!U_SUCCESS(err) || script == UScriptCode::USCRIPT_INVALID_CODE) | |
43 return false; | |
44 auto& supported = supported_scripts_[script]; | |
45 if (supported != UNDEFINED) | |
46 return supported == KNOWN; | |
47 uint16_t glyph_id; | |
48 paint_.textToGlyphs(&character, sizeof(UChar32), &glyph_id); | |
49 supported = glyph_id ? KNOWN : UNKNOWN; | |
50 return glyph_id; | |
51 } | |
52 std::string GetFontName() { return name_; } | |
53 | |
54 private: | |
55 CachedFont(sk_sp<SkTypeface> skia_face) { | |
56 SkString sk_name; | |
57 skia_face->getFamilyName(&sk_name); | |
58 name_ = sk_name.c_str(); | |
59 paint_.setTypeface(std::move(skia_face)); | |
60 paint_.setTextEncoding(SkPaint::kUTF32_TextEncoding); | |
61 } | |
62 | |
63 SkPaint paint_; | |
64 std::map<UScriptCode, KnownGlyph> supported_scripts_; | |
65 std::string name_; | |
66 }; | |
Alexei Svitkine (slow)
2017/05/09 14:52:17
Nit: DISALLOW_COPY_AND_ASSIGN()
acondor_
2017/05/09 16:21:51
Done.
| |
67 | |
68 using FontCache = std::map<SkFontID, std::unique_ptr<CachedFont>>; | |
69 base::LazyInstance<FontCache>::Leaky g_fonts = LAZY_INSTANCE_INITIALIZER; | |
70 | |
71 class CachedFontSet { | |
72 public: | |
73 CachedFontSet() : locale_() {} | |
74 ~CachedFontSet() = default; | |
Alexei Svitkine (slow)
2017/05/09 14:52:16
Nit: Add an empty line after this.
acondor_
2017/05/09 16:21:51
Done.
| |
75 void SetLocale(const std::string& locale) { | |
76 // Store font list for one locale at a time. | |
77 if (locale != locale_) { | |
78 font_ids_.clear(); | |
79 unknown_chars_.clear(); | |
80 locale_ = locale; | |
81 } | |
82 } | |
83 | |
84 std::string GetFallbackFontNameForChar(UChar32 c) { | |
85 if (unknown_chars_.find(c) != unknown_chars_.end()) | |
86 return ""; | |
87 for (SkFontID font_id : font_ids_) { | |
88 std::unique_ptr<CachedFont>& font = g_fonts.Get()[font_id]; | |
89 if (font->HasGlyphForCharacter(c)) | |
90 return font->GetFontName(); | |
91 } | |
92 sk_sp<SkFontMgr> font_mgr(SkFontMgr::RefDefault()); | |
93 const char* bcp47_locales[] = {locale_.c_str()}; | |
94 sk_sp<SkTypeface> tf(font_mgr->matchFamilyStyleCharacter( | |
95 nullptr, SkFontStyle(), locale_.empty() ? nullptr : bcp47_locales, | |
96 locale_.empty() ? 0 : 1, c)); | |
97 if (tf) { | |
98 SkFontID font_id = tf->uniqueID(); | |
99 font_ids_.push_back(font_id); | |
100 std::unique_ptr<CachedFont>& cached_font = g_fonts.Get()[font_id]; | |
101 if (!cached_font) | |
102 cached_font = CachedFont::CreateForTypeface(tf); | |
103 return cached_font->GetFontName(); | |
104 } | |
105 unknown_chars_.insert(c); | |
106 return std::string(); | |
107 } | |
108 | |
109 private: | |
110 std::string locale_; | |
111 std::vector<SkFontID> font_ids_; | |
112 std::set<UChar32> unknown_chars_; | |
113 }; | |
Alexei Svitkine (slow)
2017/05/09 14:52:17
DISALLOW_COPY_AND_ASSIGN()
acondor_
2017/05/09 16:21:51
Done.
| |
114 | |
115 base::LazyInstance<CachedFontSet>::Leaky g_cached_font_set = | |
116 LAZY_INSTANCE_INITIALIZER; | |
117 | |
118 bool FontSupportsChar(const gfx::Font& font, UChar32 c) { | |
119 sk_sp<SkTypeface> typeface = | |
120 static_cast<PlatformFontLinux*>(font.platform_font())->typeface(); | |
121 std::unique_ptr<CachedFont>& cached_font = | |
122 g_fonts.Get()[typeface->uniqueID()]; | |
123 if (!cached_font) | |
124 cached_font = CachedFont::CreateForTypeface(typeface); | |
125 return cached_font->HasGlyphForCharacter(c); | |
126 } | |
127 | |
128 } // namespace | |
129 | |
12 std::vector<Font> GetFallbackFonts(const Font& font) { | 130 std::vector<Font> GetFallbackFonts(const Font& font) { |
13 return std::vector<Font>(); | 131 return std::vector<Font>(); |
14 } | 132 } |
15 | 133 |
134 std::string GetFallbackFontNameForChar(const Font& default_font, | |
135 UChar32 c, | |
136 const std::string& locale) { | |
137 if (FontSupportsChar(default_font, c)) | |
138 return std::string(); | |
139 CachedFontSet& cached_font_set = g_cached_font_set.Get(); | |
140 cached_font_set.SetLocale(locale); | |
141 return cached_font_set.GetFallbackFontNameForChar(c); | |
142 } | |
143 | |
16 } // namespace gfx | 144 } // namespace gfx |
OLD | NEW |