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