1 /*
2  * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
31 
32 #include <limits>
33 #include <memory>
34 
35 #include "base/debug/alias.h"
36 #include "base/feature_list.h"
37 #include "base/memory/ptr_util.h"
38 #include "base/trace_event/process_memory_dump.h"
39 #include "base/trace_event/trace_event.h"
40 #include "build/build_config.h"
41 #include "third_party/blink/public/platform/platform.h"
42 #include "third_party/blink/renderer/platform/font_family_names.h"
43 #include "third_party/blink/renderer/platform/fonts/alternate_font_family.h"
44 #include "third_party/blink/renderer/platform/fonts/font_cache_client.h"
45 #include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
46 #include "third_party/blink/renderer/platform/fonts/font_data_cache.h"
47 #include "third_party/blink/renderer/platform/fonts/font_description.h"
48 #include "third_party/blink/renderer/platform/fonts/font_fallback_map.h"
49 #include "third_party/blink/renderer/platform/fonts/font_global_context.h"
50 #include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
51 #include "third_party/blink/renderer/platform/fonts/font_smoothing_mode.h"
52 #include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
53 #include "third_party/blink/renderer/platform/fonts/shaping/shape_cache.h"
54 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
55 #include "third_party/blink/renderer/platform/fonts/text_rendering_mode.h"
56 #include "third_party/blink/renderer/platform/instrumentation/histogram.h"
57 #include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h"
58 #include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
59 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
60 #include "third_party/blink/renderer/platform/text/layout_locale.h"
61 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
62 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
63 #include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
64 #include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
65 #include "third_party/blink/renderer/platform/wtf/vector.h"
66 #include "ui/gfx/font_list.h"
67 
68 #if defined(OS_WIN)
69 #include "third_party/skia/include/ports/SkTypeface_win.h"
70 #endif
71 
72 namespace blink {
73 
74 namespace {
75 const base::Feature kFontCacheNoSizeInKey{"FontCacheNoSizeInKey",
76                                           base::FEATURE_DISABLED_BY_DEFAULT};
77 }
78 
79 const char kColorEmojiLocale[] = "und-Zsye";
80 
81 SkFontMgr* FontCache::static_font_manager_ = nullptr;
82 
83 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
84 float FontCache::device_scale_factor_ = 1.0;
85 #endif
86 
87 #if defined(OS_WIN)
88 bool FontCache::antialiased_text_enabled_ = false;
89 bool FontCache::lcd_text_enabled_ = false;
90 bool FontCache::use_skia_font_fallback_ = false;
91 #endif  // defined(OS_WIN)
92 
GetFontCache(CreateIfNeeded create)93 FontCache* FontCache::GetFontCache(CreateIfNeeded create) {
94   return FontGlobalContext::GetFontCache(create);
95 }
96 
FontCache()97 FontCache::FontCache()
98     : no_size_in_key_(base::FeatureList::IsEnabled(kFontCacheNoSizeInKey)),
99       purge_prevent_count_(0),
100       font_manager_(sk_ref_sp(static_font_manager_)),
101       font_size_limit_(std::nextafter(
102           (static_cast<float>(std::numeric_limits<unsigned>::max()) - 2.f) /
103               static_cast<float>(blink::FontCacheKey::PrecisionMultiplier()),
104           0.f)) {
105 #if defined(OS_WIN)
106   if (!font_manager_) {
107     // This code path is only for unit tests. This SkFontMgr does not work in
108     // sandboxed environments, but injecting this initialization code to all
109     // unit tests isn't easy.
110     font_manager_ = SkFontMgr_New_DirectWrite();
111     // Set |is_test_font_mgr_| to capture if this is not happening in the
112     // production code. crbug.com/561873
113     is_test_font_mgr_ = true;
114   }
115   DCHECK(font_manager_.get());
116 #endif
117 }
118 
119 #if !defined(OS_MAC)
SystemFontPlatformData(const FontDescription & font_description)120 FontPlatformData* FontCache::SystemFontPlatformData(
121     const FontDescription& font_description) {
122   const AtomicString& family = FontCache::SystemFontFamily();
123 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA) || defined(OS_BSD)
124   if (family.IsEmpty() || family == font_family_names::kSystemUi)
125     return nullptr;
126 #else
127   DCHECK(!family.IsEmpty() && family != font_family_names::kSystemUi);
128 #endif
129   return GetFontPlatformData(font_description, FontFaceCreationParams(family),
130                              AlternateFontName::kNoAlternate);
131 }
132 #endif
133 
GetFontPlatformData(const FontDescription & font_description,const FontFaceCreationParams & creation_params,AlternateFontName alternate_font_name)134 FontPlatformData* FontCache::GetFontPlatformData(
135     const FontDescription& font_description,
136     const FontFaceCreationParams& creation_params,
137     AlternateFontName alternate_font_name) {
138   TRACE_EVENT0("fonts", "FontCache::GetFontPlatformData");
139 
140   if (!platform_init_) {
141     platform_init_ = true;
142     PlatformInit();
143   }
144 
145 #if !defined(OS_MAC)
146   if (creation_params.CreationType() == kCreateFontByFamily &&
147       creation_params.Family() == font_family_names::kSystemUi) {
148     return SystemFontPlatformData(font_description);
149   }
150 #endif
151 
152   float size = font_description.EffectiveFontSize();
153   size = std::min(size, font_size_limit_);
154 
155   unsigned rounded_size = size * FontCacheKey::PrecisionMultiplier();
156 
157   // Assert that the computed hash map key rounded_size value does not hit
158   // the empty (max()) or deleted (max()-1) sentinel values of the hash map,
159   // compare UnsignedWithZeroKeyHashTraits() in hash_traits.h.
160   DCHECK_LT(rounded_size, std::numeric_limits<unsigned>::max() - 1);
161   // Assert that rounded_size was not reset to 0 due to an integer overflow,
162   // i.e. if size was non-zero, rounded_size can't be zero, but if size was 0,
163   // it may be 0.
164   DCHECK_EQ(!!size, !!rounded_size);
165 
166   bool is_unique_match =
167       alternate_font_name == AlternateFontName::kLocalUniqueFace;
168   FontCacheKey key =
169       font_description.CacheKey(creation_params, is_unique_match);
170   DCHECK(!key.IsHashTableDeletedValue());
171 
172   if (no_size_in_key_) {
173     // Clear font size from they key. Size is not required in the primary key
174     // because per-size FontPlatformData are held in a nested map.
175     key.ClearFontSize();
176   }
177 
178   // Remove the font size from the cache key, and handle the font size
179   // separately in the inner HashMap. So that different size of FontPlatformData
180   // can share underlying SkTypeface.
181   FontPlatformData* result;
182   bool found_result;
183 
184   {
185     // addResult's scope must end before we recurse for alternate family names
186     // below, to avoid triggering its dtor hash-changed asserts.
187     SizedFontPlatformDataSet* sized_fonts =
188         &font_platform_data_cache_.insert(key, SizedFontPlatformDataSet())
189              .stored_value->value;
190     bool was_empty = sized_fonts->IsEmpty();
191 
192     // Take a different size instance of the same font before adding an entry to
193     // |sizedFont|.
194     FontPlatformData* another_size =
195         was_empty ? nullptr : sized_fonts->begin()->value.get();
196     auto add_result = sized_fonts->insert(rounded_size, nullptr);
197     std::unique_ptr<FontPlatformData>* found = &add_result.stored_value->value;
198     if (add_result.is_new_entry) {
199       if (was_empty) {
200         *found = CreateFontPlatformData(font_description, creation_params, size,
201                                         alternate_font_name);
202       } else if (another_size) {
203         *found = ScaleFontPlatformData(*another_size, font_description,
204                                        creation_params, size);
205       }
206     }
207 
208     result = found->get();
209     found_result = result || !add_result.is_new_entry;
210   }
211 
212   if (!found_result &&
213       alternate_font_name == AlternateFontName::kAllowAlternate &&
214       creation_params.CreationType() == kCreateFontByFamily) {
215     // We were unable to find a font. We have a small set of fonts that we alias
216     // to other names, e.g., Arial/Helvetica, Courier/Courier New, etc. Try
217     // looking up the font under the aliased name.
218     const AtomicString& alternate_name =
219         AlternateFamilyName(creation_params.Family());
220     if (!alternate_name.IsEmpty()) {
221       FontFaceCreationParams create_by_alternate_family(alternate_name);
222       result = GetFontPlatformData(font_description, create_by_alternate_family,
223                                    AlternateFontName::kNoAlternate);
224     }
225     if (result) {
226       // Cache the result under the old name.
227       auto* adding =
228           &font_platform_data_cache_.insert(key, SizedFontPlatformDataSet())
229                .stored_value->value;
230       adding->Set(rounded_size, std::make_unique<FontPlatformData>(*result));
231     }
232   }
233 
234   return result;
235 }
236 
ScaleFontPlatformData(const FontPlatformData & font_platform_data,const FontDescription & font_description,const FontFaceCreationParams & creation_params,float font_size)237 std::unique_ptr<FontPlatformData> FontCache::ScaleFontPlatformData(
238     const FontPlatformData& font_platform_data,
239     const FontDescription& font_description,
240     const FontFaceCreationParams& creation_params,
241     float font_size) {
242   TRACE_EVENT0("fonts,ui", "FontCache::ScaleFontPlatformData");
243 
244 #if defined(OS_MAC)
245   return CreateFontPlatformData(font_description, creation_params, font_size);
246 #else
247   return std::make_unique<FontPlatformData>(font_platform_data, font_size);
248 #endif
249 }
250 
GetShapeCache(const FallbackListCompositeKey & key)251 ShapeCache* FontCache::GetShapeCache(const FallbackListCompositeKey& key) {
252   FallbackListShaperCache::iterator it = fallback_list_shaper_cache_.find(key);
253   ShapeCache* result = nullptr;
254   if (it == fallback_list_shaper_cache_.end()) {
255     result = new ShapeCache();
256     fallback_list_shaper_cache_.Set(key, base::WrapUnique(result));
257   } else {
258     result = it->value.get();
259   }
260 
261   DCHECK(result);
262   return result;
263 }
264 
SetFontManager(sk_sp<SkFontMgr> font_manager)265 void FontCache::SetFontManager(sk_sp<SkFontMgr> font_manager) {
266   DCHECK(!static_font_manager_);
267   static_font_manager_ = font_manager.release();
268 }
269 
AcceptLanguagesChanged(const String & accept_languages)270 void FontCache::AcceptLanguagesChanged(const String& accept_languages) {
271   LayoutLocale::AcceptLanguagesChanged(accept_languages);
272   GetFontCache()->InvalidateShapeCache();
273 }
274 
GetFontData(const FontDescription & font_description,const AtomicString & family,AlternateFontName altername_font_name,ShouldRetain should_retain)275 scoped_refptr<SimpleFontData> FontCache::GetFontData(
276     const FontDescription& font_description,
277     const AtomicString& family,
278     AlternateFontName altername_font_name,
279     ShouldRetain should_retain) {
280   if (FontPlatformData* platform_data = GetFontPlatformData(
281           font_description,
282           FontFaceCreationParams(
283               AdjustFamilyNameToAvoidUnsupportedFonts(family)),
284           altername_font_name)) {
285     return FontDataFromFontPlatformData(
286         platform_data, should_retain, font_description.SubpixelAscentDescent());
287   }
288 
289   return nullptr;
290 }
291 
FontDataFromFontPlatformData(const FontPlatformData * platform_data,ShouldRetain should_retain,bool subpixel_ascent_descent)292 scoped_refptr<SimpleFontData> FontCache::FontDataFromFontPlatformData(
293     const FontPlatformData* platform_data,
294     ShouldRetain should_retain,
295     bool subpixel_ascent_descent) {
296 #if DCHECK_IS_ON()
297   if (should_retain == kDoNotRetain)
298     DCHECK(purge_prevent_count_);
299 #endif
300 
301   return font_data_cache_.Get(platform_data, should_retain,
302                               subpixel_ascent_descent);
303 }
304 
IsPlatformFamilyMatchAvailable(const FontDescription & font_description,const AtomicString & family)305 bool FontCache::IsPlatformFamilyMatchAvailable(
306     const FontDescription& font_description,
307     const AtomicString& family) {
308   return GetFontPlatformData(
309       font_description,
310       FontFaceCreationParams(AdjustFamilyNameToAvoidUnsupportedFonts(family)),
311       AlternateFontName::kNoAlternate);
312 }
313 
IsPlatformFontUniqueNameMatchAvailable(const FontDescription & font_description,const AtomicString & unique_font_name)314 bool FontCache::IsPlatformFontUniqueNameMatchAvailable(
315     const FontDescription& font_description,
316     const AtomicString& unique_font_name) {
317   return GetFontPlatformData(font_description,
318                              FontFaceCreationParams(unique_font_name),
319                              AlternateFontName::kLocalUniqueFace);
320 }
321 
FirstAvailableOrFirst(const String & families)322 String FontCache::FirstAvailableOrFirst(const String& families) {
323   // The conversions involve at least two string copies, and more if non-ASCII.
324   // For now we prefer shared code over the cost because a) inputs are
325   // only from grd/xtb and all ASCII, and b) at most only a few times per
326   // setting change/script.
327   return String::FromUTF8(
328       gfx::FontList::FirstAvailableOrFirst(families.Utf8().c_str()));
329 }
330 
GetNonRetainedLastResortFallbackFont(const FontDescription & font_description)331 SimpleFontData* FontCache::GetNonRetainedLastResortFallbackFont(
332     const FontDescription& font_description) {
333   auto font = GetLastResortFallbackFont(font_description, kDoNotRetain);
334   if (font)
335     font->AddRef();
336   return font.get();
337 }
338 
FallbackFontForCharacter(const FontDescription & description,UChar32 lookup_char,const SimpleFontData * font_data_to_substitute,FontFallbackPriority fallback_priority)339 scoped_refptr<SimpleFontData> FontCache::FallbackFontForCharacter(
340     const FontDescription& description,
341     UChar32 lookup_char,
342     const SimpleFontData* font_data_to_substitute,
343     FontFallbackPriority fallback_priority) {
344   TRACE_EVENT0("fonts", "FontCache::FallbackFontForCharacter");
345 
346   // In addition to PUA, do not perform fallback for non-characters either. Some
347   // of these are sentinel characters to detect encodings and do appear on
348   // websites. More details on
349   // http://www.unicode.org/faq/private_use.html#nonchar1 - See also
350   // crbug.com/862352 where performing fallback for U+FFFE causes a memory
351   // regression.
352   if (Character::IsPrivateUse(lookup_char) ||
353       Character::IsNonCharacter(lookup_char))
354     return nullptr;
355   return PlatformFallbackFontForCharacter(
356       description, lookup_char, font_data_to_substitute, fallback_priority);
357 }
358 
ReleaseFontData(const SimpleFontData * font_data)359 void FontCache::ReleaseFontData(const SimpleFontData* font_data) {
360   font_data_cache_.Release(font_data);
361 }
362 
PurgePlatformFontDataCache()363 void FontCache::PurgePlatformFontDataCache() {
364   TRACE_EVENT0("fonts,ui", "FontCache::PurgePlatformFontDataCache");
365   Vector<FontCacheKey> keys_to_remove;
366   keys_to_remove.ReserveInitialCapacity(font_platform_data_cache_.size());
367   for (auto& sized_fonts : font_platform_data_cache_) {
368     Vector<unsigned> sizes_to_remove;
369     sizes_to_remove.ReserveInitialCapacity(sized_fonts.value.size());
370     for (const auto& platform_data : sized_fonts.value) {
371       if (platform_data.value &&
372           !font_data_cache_.Contains(platform_data.value.get()))
373         sizes_to_remove.push_back(platform_data.key);
374     }
375     sized_fonts.value.RemoveAll(sizes_to_remove);
376     if (sized_fonts.value.IsEmpty())
377       keys_to_remove.push_back(sized_fonts.key);
378   }
379   font_platform_data_cache_.RemoveAll(keys_to_remove);
380 }
381 
PurgeFallbackListShaperCache()382 void FontCache::PurgeFallbackListShaperCache() {
383   TRACE_EVENT0("fonts,ui", "FontCache::PurgeFallbackListShaperCache");
384   unsigned items = 0;
385   FallbackListShaperCache::iterator iter;
386   for (iter = fallback_list_shaper_cache_.begin();
387        iter != fallback_list_shaper_cache_.end(); ++iter) {
388     items += iter->value->size();
389   }
390   fallback_list_shaper_cache_.clear();
391   DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, shape_cache_histogram,
392                                   ("Blink.Fonts.ShapeCache", 1, 1000000, 50));
393   shape_cache_histogram.Count(items);
394 }
395 
InvalidateShapeCache()396 void FontCache::InvalidateShapeCache() {
397   PurgeFallbackListShaperCache();
398 }
399 
Purge(PurgeSeverity purge_severity)400 void FontCache::Purge(PurgeSeverity purge_severity) {
401   // Ideally we should never be forcing the purge while the
402   // FontCachePurgePreventer is in scope, but we call purge() at any timing
403   // via MemoryPressureListenerRegistry.
404   if (purge_prevent_count_)
405     return;
406 
407   if (!font_data_cache_.Purge(purge_severity))
408     return;
409 
410   PurgePlatformFontDataCache();
411   PurgeFallbackListShaperCache();
412 }
413 
AddClient(FontCacheClient * client)414 void FontCache::AddClient(FontCacheClient* client) {
415   CHECK(client);
416   if (!font_cache_clients_) {
417     font_cache_clients_ =
418         MakeGarbageCollected<HeapHashSet<WeakMember<FontCacheClient>>>();
419     font_cache_clients_.RegisterAsStaticReference();
420   }
421   DCHECK(!font_cache_clients_->Contains(client));
422   font_cache_clients_->insert(client);
423 }
424 
Generation()425 uint16_t FontCache::Generation() {
426   return generation_;
427 }
428 
Invalidate()429 void FontCache::Invalidate() {
430   TRACE_EVENT0("fonts,ui", "FontCache::Invalidate");
431   font_platform_data_cache_.clear();
432   generation_++;
433 
434   if (font_cache_clients_) {
435     for (const auto& client : *font_cache_clients_)
436       client->FontCacheInvalidated();
437   }
438 
439   Purge(kForcePurge);
440 }
441 
CrashWithFontInfo(const FontDescription * font_description)442 void FontCache::CrashWithFontInfo(const FontDescription* font_description) {
443   FontCache* font_cache = nullptr;
444   SkFontMgr* font_mgr = nullptr;
445   int num_families = std::numeric_limits<int>::min();
446   bool is_test_font_mgr = false;
447   if (FontGlobalContext::Get(kDoNotCreate)) {
448     font_cache = FontCache::GetFontCache();
449     if (font_cache) {
450 #if defined(OS_WIN)
451       is_test_font_mgr = font_cache->is_test_font_mgr_;
452 #endif
453       font_mgr = font_cache->font_manager_.get();
454       if (font_mgr)
455         num_families = font_mgr->countFamilies();
456     }
457   }
458 
459   // In production, these 3 font managers must match.
460   // They don't match in unit tests or in single process mode.
461   SkFontMgr* static_font_mgr = static_font_manager_;
462   SkFontMgr* skia_default_font_mgr = SkFontMgr::RefDefault().get();
463   base::debug::Alias(&font_mgr);
464   base::debug::Alias(&static_font_mgr);
465   base::debug::Alias(&skia_default_font_mgr);
466 
467   FontDescription font_description_copy = *font_description;
468   base::debug::Alias(&font_description_copy);
469   base::debug::Alias(&is_test_font_mgr);
470   base::debug::Alias(&num_families);
471 
472   CHECK(false);
473 }
474 
DumpFontPlatformDataCache(base::trace_event::ProcessMemoryDump * memory_dump)475 void FontCache::DumpFontPlatformDataCache(
476     base::trace_event::ProcessMemoryDump* memory_dump) {
477   DCHECK(IsMainThread());
478   base::trace_event::MemoryAllocatorDump* dump =
479       memory_dump->CreateAllocatorDump("font_caches/font_platform_data_cache");
480   size_t font_platform_data_objects_size =
481       font_platform_data_cache_.size() * sizeof(FontPlatformData);
482   dump->AddScalar("size", "bytes", font_platform_data_objects_size);
483   memory_dump->AddSuballocation(dump->guid(),
484                                 WTF::Partitions::kAllocatedObjectPoolName);
485 }
486 
DumpShapeResultCache(base::trace_event::ProcessMemoryDump * memory_dump)487 void FontCache::DumpShapeResultCache(
488     base::trace_event::ProcessMemoryDump* memory_dump) {
489   DCHECK(IsMainThread());
490   base::trace_event::MemoryAllocatorDump* dump =
491       memory_dump->CreateAllocatorDump("font_caches/shape_caches");
492   size_t shape_result_cache_size = 0;
493   FallbackListShaperCache::iterator iter;
494   for (iter = fallback_list_shaper_cache_.begin();
495        iter != fallback_list_shaper_cache_.end(); ++iter) {
496     shape_result_cache_size += iter->value->ByteSize();
497   }
498   dump->AddScalar("size", "bytes", shape_result_cache_size);
499   memory_dump->AddSuballocation(dump->guid(),
500                                 WTF::Partitions::kAllocatedObjectPoolName);
501 }
502 
CreateTypefaceFromUniqueName(const FontFaceCreationParams & creation_params)503 sk_sp<SkTypeface> FontCache::CreateTypefaceFromUniqueName(
504     const FontFaceCreationParams& creation_params) {
505   FontUniqueNameLookup* unique_name_lookup =
506       FontGlobalContext::Get()->GetFontUniqueNameLookup();
507   DCHECK(unique_name_lookup);
508   sk_sp<SkTypeface> uniquely_identified_font =
509       unique_name_lookup->MatchUniqueName(creation_params.Family());
510   if (uniquely_identified_font) {
511     return uniquely_identified_font;
512   }
513   return nullptr;
514 }
515 
516 // static
GetBcp47LocaleForRequest(const FontDescription & font_description,FontFallbackPriority fallback_priority)517 FontCache::Bcp47Vector FontCache::GetBcp47LocaleForRequest(
518     const FontDescription& font_description,
519     FontFallbackPriority fallback_priority) {
520   Bcp47Vector result;
521 
522   // Fill in the list of locales in the reverse priority order.
523   // Skia expects the highest array index to be the first priority.
524   const LayoutLocale* content_locale = font_description.Locale();
525   if (const LayoutLocale* han_locale =
526           LayoutLocale::LocaleForHan(content_locale)) {
527     result.push_back(han_locale->LocaleForHanForSkFontMgr());
528   }
529   result.push_back(LayoutLocale::GetDefault().LocaleForSkFontMgr());
530   if (content_locale)
531     result.push_back(content_locale->LocaleForSkFontMgr());
532 
533   if (fallback_priority == FontFallbackPriority::kEmojiEmoji)
534     result.push_back(kColorEmojiLocale);
535   return result;
536 }
537 
GetFontFallbackMap()538 FontFallbackMap& FontCache::GetFontFallbackMap() {
539   if (!font_fallback_map_) {
540     font_fallback_map_ = MakeGarbageCollected<FontFallbackMap>(nullptr);
541     AddClient(font_fallback_map_);
542   }
543   return *font_fallback_map_;
544 }
545 
546 }  // namespace blink
547