1 /*
2 * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
3 * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
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 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "third_party/blink/renderer/core/css/css_font_selector.h"
28
29 #include "build/build_config.h"
30 #include "third_party/blink/renderer/core/css/css_segmented_font_face.h"
31 #include "third_party/blink/renderer/core/css/css_value_list.h"
32 #include "third_party/blink/renderer/core/css/font_face_set_document.h"
33 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
34 #include "third_party/blink/renderer/core/dom/document.h"
35 #include "third_party/blink/renderer/core/frame/local_frame.h"
36 #include "third_party/blink/renderer/core/frame/settings.h"
37 #include "third_party/blink/renderer/core/frame/web_feature.h"
38 #include "third_party/blink/renderer/core/loader/frame_loader.h"
39 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
40 #include "third_party/blink/renderer/platform/fonts/font_fallback_map.h"
41 #include "third_party/blink/renderer/platform/fonts/font_matching_metrics.h"
42 #include "third_party/blink/renderer/platform/fonts/font_selector_client.h"
43 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
44 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
45 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
46
47 namespace blink {
48
CSSFontSelector(Document * document)49 CSSFontSelector::CSSFontSelector(Document* document)
50 : document_(document),
51 generic_font_family_settings_(
52 document->GetFrame()->GetSettings()->GetGenericFontFamilySettings()) {
53 // FIXME: An old comment used to say there was no need to hold a reference to
54 // document_ because "we are guaranteed to be destroyed before the document".
55 // But there does not seem to be any such guarantee.
56 DCHECK(document_);
57 DCHECK(document_->GetFrame());
58 FontCache::GetFontCache()->AddClient(this);
59 FontFaceSetDocument::From(*document)->AddFontFacesToFontFaceCache(
60 &font_face_cache_);
61 }
62
63 CSSFontSelector::~CSSFontSelector() = default;
64
RegisterForInvalidationCallbacks(FontSelectorClient * client)65 void CSSFontSelector::RegisterForInvalidationCallbacks(
66 FontSelectorClient* client) {
67 CHECK(client);
68 clients_.insert(client);
69 }
70
UnregisterForInvalidationCallbacks(FontSelectorClient * client)71 void CSSFontSelector::UnregisterForInvalidationCallbacks(
72 FontSelectorClient* client) {
73 clients_.erase(client);
74 }
75
DispatchInvalidationCallbacks(FontInvalidationReason reason)76 void CSSFontSelector::DispatchInvalidationCallbacks(
77 FontInvalidationReason reason) {
78 font_face_cache_.IncrementVersion();
79
80 HeapVector<Member<FontSelectorClient>> clients;
81 CopyToVector(clients_, clients);
82 for (auto& client : clients) {
83 if (client) {
84 client->FontsNeedUpdate(this, reason);
85 }
86 }
87 }
88
FontFaceInvalidated(FontInvalidationReason reason)89 void CSSFontSelector::FontFaceInvalidated(FontInvalidationReason reason) {
90 DispatchInvalidationCallbacks(reason);
91 }
92
FontCacheInvalidated()93 void CSSFontSelector::FontCacheInvalidated() {
94 DispatchInvalidationCallbacks(FontInvalidationReason::kGeneralInvalidation);
95 }
96
GetFontData(const FontDescription & font_description,const AtomicString & family_name)97 scoped_refptr<FontData> CSSFontSelector::GetFontData(
98 const FontDescription& font_description,
99 const AtomicString& family_name) {
100 if (CSSSegmentedFontFace* face =
101 font_face_cache_.Get(font_description, family_name)) {
102 document_->GetFontMatchingMetrics()->ReportWebFontFamily(family_name);
103 return face->GetFontData(font_description);
104 }
105
106 document_->GetFontMatchingMetrics()->ReportSystemFontFamily(family_name);
107
108 // Try to return the correct font based off our settings, in case we were
109 // handed the generic font family name.
110 AtomicString settings_family_name = FamilyNameFromSettings(
111 generic_font_family_settings_, font_description, family_name);
112 if (settings_family_name.IsEmpty())
113 return nullptr;
114
115 document_->GetFontMatchingMetrics()->ReportFontFamilyLookupByGenericFamily(
116 family_name, font_description.GetScript(),
117 font_description.GenericFamily(), settings_family_name);
118
119 scoped_refptr<SimpleFontData> font_data =
120 FontCache::GetFontCache()->GetFontData(font_description,
121 settings_family_name);
122
123 document_->GetFontMatchingMetrics()->ReportFontLookupByUniqueOrFamilyName(
124 settings_family_name, font_description, font_data.get());
125
126 return font_data;
127 }
128
WillUseFontData(const FontDescription & font_description,const AtomicString & family,const String & text)129 void CSSFontSelector::WillUseFontData(const FontDescription& font_description,
130 const AtomicString& family,
131 const String& text) {
132 CSSSegmentedFontFace* face = font_face_cache_.Get(font_description, family);
133 if (face)
134 face->WillUseFontData(font_description, text);
135 }
136
WillUseRange(const FontDescription & font_description,const AtomicString & family,const FontDataForRangeSet & range_set)137 void CSSFontSelector::WillUseRange(const FontDescription& font_description,
138 const AtomicString& family,
139 const FontDataForRangeSet& range_set) {
140 CSSSegmentedFontFace* face = font_face_cache_.Get(font_description, family);
141 if (face)
142 face->WillUseRange(font_description, range_set);
143 }
144
IsPlatformFamilyMatchAvailable(const FontDescription & font_description,const AtomicString & passed_family)145 bool CSSFontSelector::IsPlatformFamilyMatchAvailable(
146 const FontDescription& font_description,
147 const AtomicString& passed_family) {
148 AtomicString family = FamilyNameFromSettings(generic_font_family_settings_,
149 font_description, passed_family);
150 if (family.IsEmpty())
151 family = passed_family;
152 return FontCache::GetFontCache()->IsPlatformFamilyMatchAvailable(
153 font_description, family);
154 }
155
UpdateGenericFontFamilySettings(Document & document)156 void CSSFontSelector::UpdateGenericFontFamilySettings(Document& document) {
157 if (!document.GetSettings())
158 return;
159 generic_font_family_settings_ =
160 document.GetSettings()->GetGenericFontFamilySettings();
161 FontCacheInvalidated();
162 }
163
ReportNotDefGlyph() const164 void CSSFontSelector::ReportNotDefGlyph() const {
165 DCHECK(document_);
166 UseCounter::Count(document_, WebFeature::kFontShapingNotDefGlyphObserved);
167 }
168
ReportSuccessfulFontFamilyMatch(const AtomicString & font_family_name)169 void CSSFontSelector::ReportSuccessfulFontFamilyMatch(
170 const AtomicString& font_family_name) {
171 DCHECK(document_);
172 document_->GetFontMatchingMetrics()->ReportSuccessfulFontFamilyMatch(
173 font_family_name);
174 }
175
ReportFailedFontFamilyMatch(const AtomicString & font_family_name)176 void CSSFontSelector::ReportFailedFontFamilyMatch(
177 const AtomicString& font_family_name) {
178 DCHECK(document_);
179 document_->GetFontMatchingMetrics()->ReportFailedFontFamilyMatch(
180 font_family_name);
181 }
182
ReportSuccessfulLocalFontMatch(const AtomicString & font_name)183 void CSSFontSelector::ReportSuccessfulLocalFontMatch(
184 const AtomicString& font_name) {
185 DCHECK(document_);
186 document_->GetFontMatchingMetrics()->ReportSuccessfulLocalFontMatch(
187 font_name);
188 }
189
ReportFailedLocalFontMatch(const AtomicString & font_name)190 void CSSFontSelector::ReportFailedLocalFontMatch(
191 const AtomicString& font_name) {
192 DCHECK(document_);
193 document_->GetFontMatchingMetrics()->ReportFailedLocalFontMatch(font_name);
194 }
195
ReportFontLookupByUniqueOrFamilyName(const AtomicString & name,const FontDescription & font_description,SimpleFontData * resulting_font_data)196 void CSSFontSelector::ReportFontLookupByUniqueOrFamilyName(
197 const AtomicString& name,
198 const FontDescription& font_description,
199 SimpleFontData* resulting_font_data) {
200 DCHECK(document_);
201 document_->GetFontMatchingMetrics()->ReportFontLookupByUniqueOrFamilyName(
202 name, font_description, resulting_font_data);
203 }
204
ReportFontLookupByUniqueNameOnly(const AtomicString & name,const FontDescription & font_description,SimpleFontData * resulting_font_data,bool is_loading_fallback)205 void CSSFontSelector::ReportFontLookupByUniqueNameOnly(
206 const AtomicString& name,
207 const FontDescription& font_description,
208 SimpleFontData* resulting_font_data,
209 bool is_loading_fallback) {
210 DCHECK(document_);
211 document_->GetFontMatchingMetrics()->ReportFontLookupByUniqueNameOnly(
212 name, font_description, resulting_font_data, is_loading_fallback);
213 }
214
ReportFontLookupByFallbackCharacter(UChar32 fallback_character,FontFallbackPriority fallback_priority,const FontDescription & font_description,SimpleFontData * resulting_font_data)215 void CSSFontSelector::ReportFontLookupByFallbackCharacter(
216 UChar32 fallback_character,
217 FontFallbackPriority fallback_priority,
218 const FontDescription& font_description,
219 SimpleFontData* resulting_font_data) {
220 DCHECK(document_);
221 document_->GetFontMatchingMetrics()->ReportFontLookupByFallbackCharacter(
222 fallback_character, fallback_priority, font_description,
223 resulting_font_data);
224 }
225
ReportLastResortFallbackFontLookup(const FontDescription & font_description,SimpleFontData * resulting_font_data)226 void CSSFontSelector::ReportLastResortFallbackFontLookup(
227 const FontDescription& font_description,
228 SimpleFontData* resulting_font_data) {
229 DCHECK(document_);
230 document_->GetFontMatchingMetrics()->ReportLastResortFallbackFontLookup(
231 font_description, resulting_font_data);
232 }
233
Trace(Visitor * visitor) const234 void CSSFontSelector::Trace(Visitor* visitor) const {
235 visitor->Trace(document_);
236 visitor->Trace(font_face_cache_);
237 visitor->Trace(clients_);
238 FontSelector::Trace(visitor);
239 }
240
241 } // namespace blink
242