Flutter Engine
paragraph_builder_skia.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "paragraph_builder_skia.h"
18 #include "paragraph_skia.h"
19 
20 #include "third_party/skia/modules/skparagraph/include/ParagraphStyle.h"
21 #include "third_party/skia/modules/skparagraph/include/TextStyle.h"
22 #include "txt/paragraph_style.h"
23 
24 namespace skt = skia::textlayout;
25 
26 namespace txt {
27 
28 namespace {
29 
30 // Convert txt::FontWeight values (ranging from 0-8) to SkFontStyle::Weight
31 // values (ranging from 100-900).
32 SkFontStyle::Weight GetSkFontStyleWeight(txt::FontWeight font_weight) {
33  return static_cast<SkFontStyle::Weight>(static_cast<int>(font_weight) * 100 +
34  100);
35 }
36 
37 SkFontStyle MakeSkFontStyle(txt::FontWeight font_weight,
38  txt::FontStyle font_style) {
39  return SkFontStyle(
40  GetSkFontStyleWeight(font_weight), SkFontStyle::Width::kNormal_Width,
41  font_style == txt::FontStyle::normal ? SkFontStyle::Slant::kUpright_Slant
42  : SkFontStyle::Slant::kItalic_Slant);
43 }
44 
45 skt::ParagraphStyle TxtToSkia(const ParagraphStyle& txt) {
46  skt::ParagraphStyle skia;
47  skt::TextStyle text_style;
48 
49  text_style.setFontStyle(MakeSkFontStyle(txt.font_weight, txt.font_style));
50  text_style.setFontSize(SkDoubleToScalar(txt.font_size));
51  text_style.setHeight(SkDoubleToScalar(txt.height));
52  text_style.setHeightOverride(txt.has_height_override);
53  text_style.setFontFamilies({SkString(txt.font_family.c_str())});
54  text_style.setLocale(SkString(txt.locale.c_str()));
55  skia.setTextStyle(text_style);
56 
57  skt::StrutStyle strut_style;
58  strut_style.setFontStyle(
59  MakeSkFontStyle(txt.strut_font_weight, txt.strut_font_style));
60  strut_style.setFontSize(SkDoubleToScalar(txt.strut_font_size));
61  strut_style.setHeight(SkDoubleToScalar(txt.strut_height));
62  strut_style.setHeightOverride(txt.strut_has_height_override);
63 
64  std::vector<SkString> strut_fonts;
65  std::transform(txt.strut_font_families.begin(), txt.strut_font_families.end(),
66  std::back_inserter(strut_fonts),
67  [](const std::string& f) { return SkString(f.c_str()); });
68  strut_style.setFontFamilies(strut_fonts);
69  strut_style.setLeading(txt.strut_leading);
70  strut_style.setForceStrutHeight(txt.force_strut_height);
71  strut_style.setStrutEnabled(txt.strut_enabled);
72  skia.setStrutStyle(strut_style);
73 
74  skia.setTextAlign(static_cast<skt::TextAlign>(txt.text_align));
75  skia.setTextDirection(static_cast<skt::TextDirection>(txt.text_direction));
76  skia.setMaxLines(txt.max_lines);
77  skia.setEllipsis(txt.ellipsis);
78  skia.setTextHeightBehavior(
79  static_cast<skt::TextHeightBehavior>(txt.text_height_behavior));
80 
81  skia.turnHintingOff();
82 
83  return skia;
84 }
85 
86 skt::TextStyle TxtToSkia(const TextStyle& txt) {
87  skt::TextStyle skia;
88 
89  skia.setColor(txt.color);
90  skia.setDecoration(static_cast<skt::TextDecoration>(txt.decoration));
91  skia.setDecorationColor(txt.decoration_color);
92  skia.setDecorationStyle(
93  static_cast<skt::TextDecorationStyle>(txt.decoration_style));
94  skia.setDecorationThicknessMultiplier(
95  SkDoubleToScalar(txt.decoration_thickness_multiplier));
96  skia.setFontStyle(MakeSkFontStyle(txt.font_weight, txt.font_style));
97  skia.setTextBaseline(static_cast<skt::TextBaseline>(txt.text_baseline));
98 
99  std::vector<SkString> skia_fonts;
100  std::transform(txt.font_families.begin(), txt.font_families.end(),
101  std::back_inserter(skia_fonts),
102  [](const std::string& f) { return SkString(f.c_str()); });
103  skia.setFontFamilies(skia_fonts);
104 
105  skia.setFontSize(SkDoubleToScalar(txt.font_size));
106  skia.setLetterSpacing(SkDoubleToScalar(txt.letter_spacing));
107  skia.setWordSpacing(SkDoubleToScalar(txt.word_spacing));
108  skia.setHeight(SkDoubleToScalar(txt.height));
109  skia.setHeightOverride(txt.has_height_override);
110 
111  skia.setLocale(SkString(txt.locale.c_str()));
112  if (txt.has_background) {
113  skia.setBackgroundColor(txt.background);
114  }
115  if (txt.has_foreground) {
116  skia.setForegroundColor(txt.foreground);
117  }
118 
119  skia.resetFontFeatures();
120  for (const auto& ff : txt.font_features.GetFontFeatures()) {
121  skia.addFontFeature(SkString(ff.first.c_str()), ff.second);
122  }
123 
124  skia.resetShadows();
125  for (const txt::TextShadow& txt_shadow : txt.text_shadows) {
126  skt::TextShadow shadow;
127  shadow.fOffset = txt_shadow.offset;
128  shadow.fBlurRadius = txt_shadow.blur_radius;
129  shadow.fColor = txt_shadow.color;
130  skia.addShadow(shadow);
131  }
132 
133  return skia;
134 }
135 
136 } // anonymous namespace
137 
139  const ParagraphStyle& style,
140  std::shared_ptr<FontCollection> font_collection)
141  : builder_(skt::ParagraphBuilder::make(
142  TxtToSkia(style),
143  font_collection->CreateSktFontCollection())),
144  base_style_(style.GetTextStyle()) {}
145 
147 
149  builder_->pushStyle(TxtToSkia(style));
150  txt_style_stack_.push(style);
151 }
152 
154  builder_->pop();
155  txt_style_stack_.pop();
156 }
157 
159  return txt_style_stack_.empty() ? base_style_ : txt_style_stack_.top();
160 }
161 
162 void ParagraphBuilderSkia::AddText(const std::u16string& text) {
163  builder_->addText(text);
164 }
165 
167  skt::PlaceholderStyle placeholder_style;
168  placeholder_style.fHeight = span.height;
169  placeholder_style.fWidth = span.width;
170  placeholder_style.fBaseline = static_cast<skt::TextBaseline>(span.baseline);
171  placeholder_style.fBaselineOffset = span.baseline_offset;
172  placeholder_style.fAlignment =
173  static_cast<skt::PlaceholderAlignment>(span.alignment);
174 
175  builder_->addPlaceholder(placeholder_style);
176 }
177 
178 std::unique_ptr<Paragraph> ParagraphBuilderSkia::Build() {
179  return std::unique_ptr<Paragraph>(new ParagraphSkia(builder_->Build()));
180 }
181 
182 } // namespace txt
FontStyle
Definition: font_style.h:22
SkPoint offset
Definition: text_shadow.h:28
virtual void AddText(const std::u16string &text) override
ParagraphBuilderSkia(const ParagraphStyle &style, std::shared_ptr< FontCollection > font_collection)
double blur_radius
Definition: text_shadow.h:29
FontWeight
Definition: font_weight.h:22
virtual std::unique_ptr< Paragraph > Build() override
virtual void AddPlaceholder(PlaceholderRun &span) override
virtual const TextStyle & PeekStyle() override
PlaceholderAlignment alignment
TextBaseline
Definition: text_baseline.h:22
PlaceholderAlignment
Where to vertically align the placeholder relative to the surrounding text.
virtual void PushStyle(const TextStyle &style) override
TextBaseline baseline