1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
4 * All rights reserved.
5 * Copyright (C) 2013 Google Inc. All rights reserved.
6 * Copyright (C) 2015 Collabora Ltd. All rights reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25 #include "third_party/blink/renderer/core/css/resolver/font_builder.h"
26
27 #include "third_party/blink/renderer/core/css/css_font_selector.h"
28 #include "third_party/blink/renderer/core/css/style_engine.h"
29 #include "third_party/blink/renderer/core/css_value_keywords.h"
30 #include "third_party/blink/renderer/core/dom/document.h"
31 #include "third_party/blink/renderer/core/frame/local_frame.h"
32 #include "third_party/blink/renderer/core/frame/settings.h"
33 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
34 #include "third_party/blink/renderer/core/style/computed_style.h"
35 #include "third_party/blink/renderer/platform/font_family_names.h"
36 #include "third_party/blink/renderer/platform/fonts/font_description.h"
37
38 namespace blink {
39
FontBuilder(Document * document)40 FontBuilder::FontBuilder(Document* document) : document_(document), flags_(0) {
41 DCHECK(!document || document->GetFrame());
42 }
43
SetInitial(float effective_zoom)44 void FontBuilder::SetInitial(float effective_zoom) {
45 DCHECK(document_->GetSettings());
46 if (!document_->GetSettings())
47 return;
48
49 SetFamilyDescription(font_description_,
50 FontBuilder::InitialFamilyDescription());
51 SetSize(font_description_, FontBuilder::InitialSize());
52 }
53
DidChangeEffectiveZoom()54 void FontBuilder::DidChangeEffectiveZoom() {
55 Set(PropertySetFlag::kEffectiveZoom);
56 }
57
DidChangeTextOrientation()58 void FontBuilder::DidChangeTextOrientation() {
59 Set(PropertySetFlag::kTextOrientation);
60 }
61
DidChangeWritingMode()62 void FontBuilder::DidChangeWritingMode() {
63 Set(PropertySetFlag::kWritingMode);
64 }
65
StandardFontFamily() const66 FontFamily FontBuilder::StandardFontFamily() const {
67 FontFamily family;
68 family.SetFamily(StandardFontFamilyName());
69 return family;
70 }
71
StandardFontFamilyName() const72 AtomicString FontBuilder::StandardFontFamilyName() const {
73 Settings* settings = document_->GetSettings();
74 if (settings)
75 return settings->GetGenericFontFamilySettings().Standard();
76 return AtomicString();
77 }
78
GenericFontFamilyName(FontDescription::GenericFamilyType generic_family) const79 AtomicString FontBuilder::GenericFontFamilyName(
80 FontDescription::GenericFamilyType generic_family) const {
81 switch (generic_family) {
82 default:
83 NOTREACHED();
84 FALLTHROUGH;
85 case FontDescription::kNoFamily:
86 return AtomicString();
87 case FontDescription::kStandardFamily:
88 return StandardFontFamilyName();
89 case FontDescription::kSerifFamily:
90 return font_family_names::kWebkitSerif;
91 case FontDescription::kSansSerifFamily:
92 return font_family_names::kWebkitSansSerif;
93 case FontDescription::kMonospaceFamily:
94 return font_family_names::kWebkitMonospace;
95 case FontDescription::kCursiveFamily:
96 return font_family_names::kWebkitCursive;
97 case FontDescription::kFantasyFamily:
98 return font_family_names::kWebkitFantasy;
99 }
100 }
101
FontSizeForKeyword(unsigned keyword,bool is_monospace) const102 float FontBuilder::FontSizeForKeyword(unsigned keyword,
103 bool is_monospace) const {
104 return FontSizeFunctions::FontSizeForKeyword(document_, keyword,
105 is_monospace);
106 }
107
SetFamilyDescription(const FontDescription::FamilyDescription & family_description)108 void FontBuilder::SetFamilyDescription(
109 const FontDescription::FamilyDescription& family_description) {
110 SetFamilyDescription(font_description_, family_description);
111 }
112
SetWeight(FontSelectionValue weight)113 void FontBuilder::SetWeight(FontSelectionValue weight) {
114 Set(PropertySetFlag::kWeight);
115
116 font_description_.SetWeight(weight);
117 }
118
SetStyle(FontSelectionValue slope)119 void FontBuilder::SetStyle(FontSelectionValue slope) {
120 Set(PropertySetFlag::kStyle);
121
122 font_description_.SetStyle(slope);
123 }
124
SetStretch(FontSelectionValue stretch)125 void FontBuilder::SetStretch(FontSelectionValue stretch) {
126 Set(PropertySetFlag::kStretch);
127
128 font_description_.SetStretch(stretch);
129 }
130
SetSize(const FontDescription::Size & size)131 void FontBuilder::SetSize(const FontDescription::Size& size) {
132 SetSize(font_description_, size);
133 }
134
SetSizeAdjust(float aspect_value)135 void FontBuilder::SetSizeAdjust(float aspect_value) {
136 Set(PropertySetFlag::kSizeAdjust);
137
138 font_description_.SetSizeAdjust(aspect_value);
139 }
140
SetLocale(scoped_refptr<const LayoutLocale> locale)141 void FontBuilder::SetLocale(scoped_refptr<const LayoutLocale> locale) {
142 Set(PropertySetFlag::kLocale);
143
144 font_description_.SetLocale(std::move(locale));
145 }
146
SetVariantCaps(FontDescription::FontVariantCaps caps)147 void FontBuilder::SetVariantCaps(FontDescription::FontVariantCaps caps) {
148 Set(PropertySetFlag::kVariantCaps);
149
150 font_description_.SetVariantCaps(caps);
151 }
152
SetVariantEastAsian(const FontVariantEastAsian east_asian)153 void FontBuilder::SetVariantEastAsian(const FontVariantEastAsian east_asian) {
154 Set(PropertySetFlag::kVariantEastAsian);
155
156 font_description_.SetVariantEastAsian(east_asian);
157 }
158
SetVariantLigatures(const FontDescription::VariantLigatures & ligatures)159 void FontBuilder::SetVariantLigatures(
160 const FontDescription::VariantLigatures& ligatures) {
161 Set(PropertySetFlag::kVariantLigatures);
162
163 font_description_.SetVariantLigatures(ligatures);
164 }
165
SetVariantNumeric(const FontVariantNumeric & variant_numeric)166 void FontBuilder::SetVariantNumeric(const FontVariantNumeric& variant_numeric) {
167 Set(PropertySetFlag::kVariantNumeric);
168
169 font_description_.SetVariantNumeric(variant_numeric);
170 }
171
SetTextRendering(TextRenderingMode text_rendering_mode)172 void FontBuilder::SetTextRendering(TextRenderingMode text_rendering_mode) {
173 Set(PropertySetFlag::kTextRendering);
174
175 font_description_.SetTextRendering(text_rendering_mode);
176 }
177
SetKerning(FontDescription::Kerning kerning)178 void FontBuilder::SetKerning(FontDescription::Kerning kerning) {
179 Set(PropertySetFlag::kKerning);
180
181 font_description_.SetKerning(kerning);
182 }
183
SetFontOpticalSizing(OpticalSizing font_optical_sizing)184 void FontBuilder::SetFontOpticalSizing(OpticalSizing font_optical_sizing) {
185 Set(PropertySetFlag::kFontOpticalSizing);
186
187 font_description_.SetFontOpticalSizing(font_optical_sizing);
188 }
189
SetFontSmoothing(FontSmoothingMode foont_smoothing_mode)190 void FontBuilder::SetFontSmoothing(FontSmoothingMode foont_smoothing_mode) {
191 Set(PropertySetFlag::kFontSmoothing);
192
193 font_description_.SetFontSmoothing(foont_smoothing_mode);
194 }
195
SetFeatureSettings(scoped_refptr<FontFeatureSettings> settings)196 void FontBuilder::SetFeatureSettings(
197 scoped_refptr<FontFeatureSettings> settings) {
198 Set(PropertySetFlag::kFeatureSettings);
199 font_description_.SetFeatureSettings(std::move(settings));
200 }
201
SetVariationSettings(scoped_refptr<FontVariationSettings> settings)202 void FontBuilder::SetVariationSettings(
203 scoped_refptr<FontVariationSettings> settings) {
204 Set(PropertySetFlag::kVariationSettings);
205 font_description_.SetVariationSettings(std::move(settings));
206 }
207
SetFamilyDescription(FontDescription & font_description,const FontDescription::FamilyDescription & family_description)208 void FontBuilder::SetFamilyDescription(
209 FontDescription& font_description,
210 const FontDescription::FamilyDescription& family_description) {
211 Set(PropertySetFlag::kFamily);
212
213 bool is_initial =
214 family_description.generic_family == FontDescription::kStandardFamily &&
215 family_description.family.FamilyIsEmpty();
216
217 font_description.SetGenericFamily(family_description.generic_family);
218 font_description.SetFamily(is_initial ? StandardFontFamily()
219 : family_description.family);
220 }
221
SetSize(FontDescription & font_description,const FontDescription::Size & size)222 void FontBuilder::SetSize(FontDescription& font_description,
223 const FontDescription::Size& size) {
224 float specified_size = size.value;
225
226 if (specified_size < 0)
227 return;
228
229 Set(PropertySetFlag::kSize);
230
231 // Overly large font sizes will cause crashes on some platforms (such as
232 // Windows). Cap font size here to make sure that doesn't happen.
233 specified_size = std::min(kMaximumAllowedFontSize, specified_size);
234
235 font_description.SetKeywordSize(size.keyword);
236 font_description.SetSpecifiedSize(specified_size);
237 font_description.SetIsAbsoluteSize(size.is_absolute);
238 }
239
GetComputedSizeFromSpecifiedSize(FontDescription & font_description,float effective_zoom,float specified_size)240 float FontBuilder::GetComputedSizeFromSpecifiedSize(
241 FontDescription& font_description,
242 float effective_zoom,
243 float specified_size) {
244 DCHECK(document_);
245 float zoom_factor = effective_zoom;
246 // Apply the text zoom factor preference. The preference is exposed in
247 // accessibility settings in Chrome for Android to improve readability.
248 if (LocalFrame* frame = document_->GetFrame())
249 zoom_factor *= frame->TextZoomFactor();
250
251 return FontSizeFunctions::GetComputedSizeFromSpecifiedSize(
252 document_, zoom_factor, font_description.IsAbsoluteSize(),
253 specified_size);
254 }
255
CheckForGenericFamilyChange(const FontDescription & parent_description,FontDescription & new_description)256 void FontBuilder::CheckForGenericFamilyChange(
257 const FontDescription& parent_description,
258 FontDescription& new_description) {
259 DCHECK(document_);
260 if (new_description.IsAbsoluteSize())
261 return;
262
263 if (new_description.IsMonospace() == parent_description.IsMonospace())
264 return;
265
266 // For now, lump all families but monospace together.
267 if (new_description.GenericFamily() != FontDescription::kMonospaceFamily &&
268 parent_description.GenericFamily() != FontDescription::kMonospaceFamily)
269 return;
270
271 // We know the parent is monospace or the child is monospace, and that font
272 // size was unspecified. We want to scale our font size as appropriate.
273 // If the font uses a keyword size, then we refetch from the table rather than
274 // multiplying by our scale factor.
275 float size;
276 if (new_description.KeywordSize()) {
277 size = FontSizeForKeyword(new_description.KeywordSize(),
278 new_description.IsMonospace());
279 } else {
280 Settings* settings = document_->GetSettings();
281 float fixed_scale_factor =
282 (settings && settings->GetDefaultFixedFontSize() &&
283 settings->GetDefaultFontSize())
284 ? static_cast<float>(settings->GetDefaultFixedFontSize()) /
285 settings->GetDefaultFontSize()
286 : 1;
287 size = parent_description.IsMonospace()
288 ? new_description.SpecifiedSize() / fixed_scale_factor
289 : new_description.SpecifiedSize() * fixed_scale_factor;
290 }
291
292 new_description.SetSpecifiedSize(size);
293 }
294
UpdateSpecifiedSize(FontDescription & font_description,const ComputedStyle & style,const ComputedStyle * parent_style)295 void FontBuilder::UpdateSpecifiedSize(FontDescription& font_description,
296 const ComputedStyle& style,
297 const ComputedStyle* parent_style) {
298 float specified_size = font_description.SpecifiedSize();
299
300 if (!specified_size && font_description.KeywordSize())
301 specified_size = FontSizeForKeyword(font_description.KeywordSize(),
302 font_description.IsMonospace());
303
304 font_description.SetSpecifiedSize(specified_size);
305
306 // TODO(crbug.com/1086680): Avoid nullptr parent style.
307 const FontDescription& parent_description =
308 parent_style ? parent_style->GetFontDescription()
309 : style.GetFontDescription();
310
311 CheckForGenericFamilyChange(parent_description, font_description);
312 }
313
UpdateAdjustedSize(FontDescription & font_description,const ComputedStyle & style,FontSelector * font_selector)314 void FontBuilder::UpdateAdjustedSize(FontDescription& font_description,
315 const ComputedStyle& style,
316 FontSelector* font_selector) {
317 const float specified_size = font_description.SpecifiedSize();
318 if (!font_description.HasSizeAdjust() || !specified_size)
319 return;
320
321 // We need to create a temporal Font to get xHeight of a primary font.
322 // The aspect value is based on the xHeight of the font for the computed font
323 // size, so we need to reset the adjustedSize to computedSize. See
324 // FontDescription::EffectiveFontSize.
325 font_description.SetAdjustedSize(font_description.ComputedSize());
326
327 Font font(font_description, font_selector);
328
329 const SimpleFontData* font_data = font.PrimaryFont();
330
331 if (!font_data || !font_data->GetFontMetrics().HasXHeight())
332 return;
333
334 const float size_adjust = font_description.SizeAdjust();
335 float aspect_value = font_data->GetFontMetrics().XHeight() / specified_size;
336 float adjusted_size = (size_adjust / aspect_value) * specified_size;
337 adjusted_size = GetComputedSizeFromSpecifiedSize(
338 font_description, style.EffectiveZoom(), adjusted_size);
339
340 adjusted_size = TextAutosizer::ComputeAutosizedFontSize(
341 adjusted_size, style.TextAutosizingMultiplier(), style.EffectiveZoom());
342 font_description.SetAdjustedSize(adjusted_size);
343 }
344
UpdateComputedSize(FontDescription & font_description,const ComputedStyle & style)345 void FontBuilder::UpdateComputedSize(FontDescription& font_description,
346 const ComputedStyle& style) {
347 float computed_size =
348 GetComputedSizeFromSpecifiedSize(font_description, style.EffectiveZoom(),
349 font_description.SpecifiedSize());
350 computed_size = TextAutosizer::ComputeAutosizedFontSize(
351 computed_size, style.TextAutosizingMultiplier(), style.EffectiveZoom());
352 font_description.SetComputedSize(computed_size);
353 }
354
UpdateFontDescription(FontDescription & description,FontOrientation font_orientation)355 void FontBuilder::UpdateFontDescription(FontDescription& description,
356 FontOrientation font_orientation) {
357 if (IsSet(PropertySetFlag::kFamily)) {
358 description.SetGenericFamily(font_description_.GenericFamily());
359 description.SetFamily(font_description_.Family());
360 }
361 if (IsSet(PropertySetFlag::kSize)) {
362 description.SetKeywordSize(font_description_.KeywordSize());
363 description.SetSpecifiedSize(font_description_.SpecifiedSize());
364 description.SetIsAbsoluteSize(font_description_.IsAbsoluteSize());
365 }
366
367 if (IsSet(PropertySetFlag::kSizeAdjust))
368 description.SetSizeAdjust(font_description_.SizeAdjust());
369 if (IsSet(PropertySetFlag::kWeight))
370 description.SetWeight(font_description_.Weight());
371 if (IsSet(PropertySetFlag::kStretch))
372 description.SetStretch(font_description_.Stretch());
373 if (IsSet(PropertySetFlag::kFeatureSettings))
374 description.SetFeatureSettings(font_description_.FeatureSettings());
375 if (IsSet(PropertySetFlag::kLocale))
376 description.SetLocale(font_description_.Locale());
377 if (IsSet(PropertySetFlag::kStyle))
378 description.SetStyle(font_description_.Style());
379 if (IsSet(PropertySetFlag::kVariantCaps))
380 description.SetVariantCaps(font_description_.VariantCaps());
381 if (IsSet(PropertySetFlag::kVariantEastAsian))
382 description.SetVariantEastAsian(font_description_.VariantEastAsian());
383 if (IsSet(PropertySetFlag::kVariantLigatures))
384 description.SetVariantLigatures(font_description_.GetVariantLigatures());
385 if (IsSet(PropertySetFlag::kVariantNumeric))
386 description.SetVariantNumeric(font_description_.VariantNumeric());
387 if (IsSet(PropertySetFlag::kVariationSettings))
388 description.SetVariationSettings(font_description_.VariationSettings());
389 if (IsSet(PropertySetFlag::kTextRendering))
390 description.SetTextRendering(font_description_.TextRendering());
391 if (IsSet(PropertySetFlag::kKerning))
392 description.SetKerning(font_description_.GetKerning());
393 if (IsSet(PropertySetFlag::kFontOpticalSizing))
394 description.SetFontOpticalSizing(font_description_.FontOpticalSizing());
395 if (IsSet(PropertySetFlag::kFontSmoothing))
396 description.SetFontSmoothing(font_description_.FontSmoothing());
397 if (IsSet(PropertySetFlag::kTextOrientation) ||
398 IsSet(PropertySetFlag::kWritingMode))
399 description.SetOrientation(font_orientation);
400
401 float size = description.SpecifiedSize();
402 if (!size && description.KeywordSize()) {
403 size = FontSizeForKeyword(description.KeywordSize(),
404 description.IsMonospace());
405 }
406
407 description.SetSpecifiedSize(size);
408 description.SetComputedSize(size);
409 if (size && description.HasSizeAdjust())
410 description.SetAdjustedSize(size);
411 }
412
CreateFont(ComputedStyle & style,const ComputedStyle * parent_style)413 void FontBuilder::CreateFont(ComputedStyle& style,
414 const ComputedStyle* parent_style) {
415 DCHECK(document_);
416
417 if (!flags_)
418 return;
419
420 FontDescription description = style.GetFontDescription();
421
422 UpdateFontDescription(description, style.ComputeFontOrientation());
423 UpdateSpecifiedSize(description, style, parent_style);
424 UpdateComputedSize(description, style);
425
426 FontSelector* font_selector = document_->GetStyleEngine().GetFontSelector();
427 UpdateAdjustedSize(description, style, font_selector);
428
429 style.SetFontInternal(Font(description, font_selector));
430 flags_ = 0;
431 }
432
CreateFontForDocument(ComputedStyle & document_style)433 void FontBuilder::CreateFontForDocument(ComputedStyle& document_style) {
434 DCHECK(document_);
435 FontDescription font_description = FontDescription();
436 font_description.SetLocale(document_style.GetFontDescription().Locale());
437
438 SetFamilyDescription(font_description,
439 FontBuilder::InitialFamilyDescription());
440 SetSize(font_description,
441 FontDescription::Size(FontSizeFunctions::InitialKeywordSize(), 0.0f,
442 false));
443 UpdateSpecifiedSize(font_description, document_style, &document_style);
444 UpdateComputedSize(font_description, document_style);
445
446 font_description.SetOrientation(document_style.ComputeFontOrientation());
447
448 FontSelector* font_selector = document_->GetStyleEngine().GetFontSelector();
449 document_style.SetFontInternal(Font(font_description, font_selector));
450 }
451
452 } // namespace blink
453