| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "third_party/blink/renderer/core/css/local_font_face_source.h" |
| |
| #include "build/build_config.h" |
| #include "third_party/blink/renderer/core/css/css_custom_font_data.h" |
| #include "third_party/blink/renderer/core/css/css_font_face.h" |
| #include "third_party/blink/renderer/platform/fonts/font_cache.h" |
| #include "third_party/blink/renderer/platform/fonts/font_description.h" |
| #include "third_party/blink/renderer/platform/fonts/font_global_context.h" |
| #include "third_party/blink/renderer/platform/fonts/font_selector.h" |
| #include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h" |
| #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" |
| #include "third_party/blink/renderer/platform/histogram.h" |
| #include "third_party/blink/renderer/platform/wtf/functional.h" |
| |
| namespace blink { |
| |
| namespace { |
| |
| void NotifyFontUniqueNameLookupReadyWeakPtr( |
| base::WeakPtr<LocalFontFaceSource> local_font_face_source) { |
| if (local_font_face_source) |
| local_font_face_source->NotifyFontUniqueNameLookupReady(); |
| } |
| |
| } // namespace |
| |
| LocalFontFaceSource::LocalFontFaceSource(CSSFontFace* css_font_face, |
| FontSelector* font_selector, |
| const String& font_name) |
| : face_(css_font_face), |
| font_selector_(font_selector), |
| font_name_(font_name), |
| weak_factory_(this) { |
| was_resolved_ = IsLocalNonBlocking(); |
| } |
| |
| LocalFontFaceSource::~LocalFontFaceSource() {} |
| |
| bool LocalFontFaceSource::IsLocalNonBlocking() const { |
| FontUniqueNameLookup* unique_name_lookup = |
| FontGlobalContext::Get()->GetFontUniqueNameLookup(); |
| if (!unique_name_lookup) |
| return true; |
| return unique_name_lookup->IsFontUniqueNameLookupReadyForSyncLookup(); |
| } |
| |
| bool LocalFontFaceSource::IsLocalFontAvailable( |
| const FontDescription& font_description) const { |
| return FontCache::GetFontCache()->IsPlatformFontUniqueNameMatchAvailable( |
| font_description, font_name_); |
| } |
| |
| scoped_refptr<SimpleFontData> |
| LocalFontFaceSource::CreateLoadingFallbackFontData( |
| const FontDescription& font_description) { |
| FontCachePurgePreventer font_cache_purge_preventer; |
| scoped_refptr<SimpleFontData> temporary_font = |
| FontCache::GetFontCache()->GetLastResortFallbackFont(font_description, |
| kDoNotRetain); |
| if (!temporary_font) { |
| NOTREACHED(); |
| return nullptr; |
| } |
| scoped_refptr<CSSCustomFontData> css_font_data = |
| CSSCustomFontData::Create(this, CSSCustomFontData::kVisibleFallback); |
| return SimpleFontData::Create(temporary_font->PlatformData(), css_font_data); |
| } |
| |
| scoped_refptr<SimpleFontData> LocalFontFaceSource::CreateFontData( |
| const FontDescription& font_description, |
| const FontSelectionCapabilities&) { |
| if (!IsValid()) |
| return nullptr; |
| |
| if (IsValid() && IsLoading()) { |
| return CreateLoadingFallbackFontData(font_description); |
| } |
| |
| DCHECK(was_resolved_); |
| // FIXME(drott) crbug.com/627143: We still have the issue of matching |
| // family name instead of postscript name for local fonts. However, we |
| // should definitely not try to take into account the full requested |
| // font description including the width, slope, weight styling when |
| // trying to match against local fonts. An unstyled FontDescription |
| // needs to be used here, or practically none at all. Instead we |
| // should only look for the postscript or full font name. |
| // However, when passing a style-neutral FontDescription we can't |
| // match Roboto Bold and Thin anymore on Android given the CSS Google |
| // Fonts sends, compare crbug.com/765980. So for now, we continue to |
| // pass font_description to avoid breaking Google Fonts. |
| FontDescription unstyled_description(font_description); |
| #if !defined(OS_ANDROID) |
| unstyled_description.SetStretch(NormalWidthValue()); |
| unstyled_description.SetStyle(NormalSlopeValue()); |
| unstyled_description.SetWeight(NormalWeightValue()); |
| #endif |
| scoped_refptr<SimpleFontData> font_data = |
| FontCache::GetFontCache()->GetFontData( |
| unstyled_description, font_name_, |
| AlternateFontName::kLocalUniqueFace); |
| histograms_.Record(font_data.get()); |
| return font_data; |
| } |
| |
| void LocalFontFaceSource::BeginLoadIfNeeded() { |
| if (IsLoaded()) |
| return; |
| |
| FontUniqueNameLookup* unique_name_lookup = |
| FontGlobalContext::Get()->GetFontUniqueNameLookup(); |
| DCHECK(unique_name_lookup); |
| unique_name_lookup->PrepareFontUniqueNameLookup( |
| WTF::Bind(&NotifyFontUniqueNameLookupReadyWeakPtr, GetWeakPtr())); |
| face_->DidBeginLoad(); |
| } |
| |
| void LocalFontFaceSource::NotifyFontUniqueNameLookupReady() { |
| was_resolved_ = IsLocalFontAvailable(FontDescription()); |
| |
| PruneTable(); |
| |
| if (face_->FontLoaded(this)) { |
| font_selector_->FontFaceInvalidated(); |
| } |
| } |
| |
| base::WeakPtr<LocalFontFaceSource> LocalFontFaceSource::GetWeakPtr() { |
| return weak_factory_.GetWeakPtr(); |
| } |
| |
| bool LocalFontFaceSource::IsLoaded() const { |
| return IsLocalNonBlocking(); |
| } |
| |
| bool LocalFontFaceSource::IsLoading() const { |
| return !IsLocalNonBlocking(); |
| } |
| |
| bool LocalFontFaceSource::IsValid() const { |
| return IsLoading() || was_resolved_; |
| } |
| |
| void LocalFontFaceSource::LocalFontHistograms::Record(bool load_success) { |
| if (reported_) |
| return; |
| reported_ = true; |
| DEFINE_STATIC_LOCAL(EnumerationHistogram, local_font_used_histogram, |
| ("WebFont.LocalFontUsed", 2)); |
| local_font_used_histogram.Count(load_success ? 1 : 0); |
| } |
| |
| void LocalFontFaceSource::Trace(blink::Visitor* visitor) { |
| visitor->Trace(face_); |
| visitor->Trace(font_selector_); |
| CSSFontFaceSource::Trace(visitor); |
| } |
| |
| } // namespace blink |