Flutter Engine
 
Loading...
Searching...
No Matches
paragraph_builder_skia.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6#include "paragraph_skia.h"
7
8#include "third_party/skia/modules/skparagraph/include/ParagraphStyle.h"
9#include "third_party/skia/modules/skparagraph/include/TextStyle.h"
10#include "third_party/skia/modules/skunicode/include/SkUnicode_icu.h"
11#include "txt/paragraph_style.h"
12
13namespace skt = skia::textlayout;
14
15namespace txt {
16
17namespace {
18
19constexpr std::string_view kWeightAxisTag = "wght";
20
21template <typename T>
22SkFourByteTag GetFourByteTag(const T& tag) {
23 return SkSetFourByteTag(tag[0], tag[1], tag[2], tag[3]);
24}
25
26SkFontStyle MakeSkFontStyle(int font_weight, txt::FontStyle font_style) {
27 return SkFontStyle(font_weight, SkFontStyle::Width::kNormal_Width,
28 font_style == txt::FontStyle::normal
29 ? SkFontStyle::Slant::kUpright_Slant
30 : SkFontStyle::Slant::kItalic_Slant);
31}
32
33} // anonymous namespace
34
36 const ParagraphStyle& style,
37 const std::shared_ptr<FontCollection>& font_collection,
38 const bool impeller_enabled)
39 : base_style_(style.GetTextStyle()), impeller_enabled_(impeller_enabled) {
40 builder_ = skt::ParagraphBuilder::make(
41 TxtToSkia(style), font_collection->CreateSktFontCollection(),
42 SkUnicodes::ICU::Make());
43}
44
46
48 builder_->pushStyle(TxtToSkia(style));
49 txt_style_stack_.push(style);
50}
51
53 builder_->pop();
54 txt_style_stack_.pop();
55}
56
58 return txt_style_stack_.empty() ? base_style_ : txt_style_stack_.top();
59}
60
61void ParagraphBuilderSkia::AddText(const std::u16string& text) {
62 builder_->addText(text);
63}
64
65void ParagraphBuilderSkia::AddText(const uint8_t* utf8_data,
66 size_t byte_length) {
67 builder_->addText(reinterpret_cast<const char*>(utf8_data), byte_length);
68}
69
71 skt::PlaceholderStyle placeholder_style;
72 placeholder_style.fHeight = span.height;
73 placeholder_style.fWidth = span.width;
74 placeholder_style.fBaseline = static_cast<skt::TextBaseline>(span.baseline);
75 placeholder_style.fBaselineOffset = span.baseline_offset;
76 placeholder_style.fAlignment =
77 static_cast<skt::PlaceholderAlignment>(span.alignment);
78
79 builder_->addPlaceholder(placeholder_style);
80}
81
82std::unique_ptr<Paragraph> ParagraphBuilderSkia::Build() {
83 return std::make_unique<ParagraphSkia>(
84 builder_->Build(), std::move(dl_paints_), impeller_enabled_);
85}
86
87skt::ParagraphPainter::PaintID ParagraphBuilderSkia::CreatePaintID(
88 const flutter::DlPaint& dl_paint) {
89 dl_paints_.push_back(dl_paint);
90 return dl_paints_.size() - 1;
91}
92
93skt::ParagraphStyle ParagraphBuilderSkia::TxtToSkia(const ParagraphStyle& txt) {
94 skt::ParagraphStyle skia;
95 skt::TextStyle text_style;
96
97 // Convert the default color of an SkParagraph text style into a DlPaint.
98 flutter::DlPaint dl_paint;
99 dl_paint.setColor(flutter::DlColor(text_style.getColor()));
100 text_style.setForegroundPaintID(CreatePaintID(dl_paint));
101
102 text_style.setFontStyle(MakeSkFontStyle(txt.font_weight, txt.font_style));
103 text_style.setFontSize(SkDoubleToScalar(txt.font_size));
104 text_style.setHeight(SkDoubleToScalar(txt.height));
105 text_style.setHeightOverride(txt.has_height_override);
106 text_style.setFontFamilies({SkString(txt.font_family.c_str())});
107 text_style.setLocale(SkString(txt.locale.c_str()));
108 SkFontArguments::VariationPosition::Coordinate weight_coord{
109 GetFourByteTag(kWeightAxisTag), static_cast<float>(txt.font_weight)};
110 text_style.setFontArguments(
111 SkFontArguments().setVariationDesignPosition({&weight_coord, 1}));
112 skia.setTextStyle(text_style);
113
114 skt::StrutStyle strut_style;
115 strut_style.setFontStyle(
116 MakeSkFontStyle(txt.strut_font_weight, txt.strut_font_style));
117 strut_style.setFontSize(SkDoubleToScalar(txt.strut_font_size));
118 strut_style.setHeight(SkDoubleToScalar(txt.strut_height));
119 strut_style.setHeightOverride(txt.strut_has_height_override);
120 strut_style.setHalfLeading(txt.strut_half_leading);
121
122 std::vector<SkString> strut_fonts;
123 std::transform(txt.strut_font_families.begin(), txt.strut_font_families.end(),
124 std::back_inserter(strut_fonts),
125 [](const std::string& f) { return SkString(f.c_str()); });
126 strut_style.setFontFamilies(strut_fonts);
127 strut_style.setLeading(txt.strut_leading);
128 strut_style.setForceStrutHeight(txt.force_strut_height);
129 strut_style.setStrutEnabled(txt.strut_enabled);
130 skia.setStrutStyle(strut_style);
131
132 skia.setTextAlign(static_cast<skt::TextAlign>(txt.text_align));
133 skia.setTextDirection(static_cast<skt::TextDirection>(txt.text_direction));
134 skia.setMaxLines(txt.max_lines);
135 skia.setEllipsis(txt.ellipsis);
136 skia.setTextHeightBehavior(
137 static_cast<skt::TextHeightBehavior>(txt.text_height_behavior));
138
139 skia.turnHintingOff();
140 skia.setReplaceTabCharacters(true);
141 skia.setApplyRoundingHack(false);
142
143 return skia;
144}
145
146skt::TextStyle ParagraphBuilderSkia::TxtToSkia(const TextStyle& txt) {
147 skt::TextStyle skia;
148
149 skia.setColor(txt.color);
150 skia.setDecoration(static_cast<skt::TextDecoration>(txt.decoration));
151 skia.setDecorationColor(txt.decoration_color);
152 skia.setDecorationStyle(
153 static_cast<skt::TextDecorationStyle>(txt.decoration_style));
154 skia.setDecorationThicknessMultiplier(
155 SkDoubleToScalar(txt.decoration_thickness_multiplier));
156 skia.setFontStyle(MakeSkFontStyle(txt.font_weight, txt.font_style));
157 skia.setTextBaseline(static_cast<skt::TextBaseline>(txt.text_baseline));
158
159 std::vector<SkString> skia_fonts;
160 std::transform(txt.font_families.begin(), txt.font_families.end(),
161 std::back_inserter(skia_fonts),
162 [](const std::string& f) { return SkString(f.c_str()); });
163 skia.setFontFamilies(skia_fonts);
164
165 skia.setFontSize(SkDoubleToScalar(txt.font_size));
166 skia.setLetterSpacing(SkDoubleToScalar(txt.letter_spacing));
167 skia.setWordSpacing(SkDoubleToScalar(txt.word_spacing));
168 skia.setHeight(SkDoubleToScalar(txt.height));
169 skia.setHeightOverride(txt.has_height_override);
170 skia.setHalfLeading(txt.half_leading);
171
172 skia.setLocale(SkString(txt.locale.c_str()));
173 if (txt.background.has_value()) {
174 skia.setBackgroundPaintID(CreatePaintID(txt.background.value()));
175 }
176 if (txt.foreground.has_value()) {
177 skia.setForegroundPaintID(CreatePaintID(txt.foreground.value()));
178 } else {
179 flutter::DlPaint dl_paint;
180 dl_paint.setColor(flutter::DlColor(txt.color));
181 skia.setForegroundPaintID(CreatePaintID(dl_paint));
182 }
183
184 skia.resetFontFeatures();
185 for (const auto& ff : txt.font_features.GetFontFeatures()) {
186 skia.addFontFeature(SkString(ff.first.c_str()), ff.second);
187 }
188
189 std::vector<SkFontArguments::VariationPosition::Coordinate> coordinates;
190 bool weight_axis_set = false;
191 if (!txt.font_variations.GetAxisValues().empty()) {
192 for (const auto& it : txt.font_variations.GetAxisValues()) {
193 const std::string& axis = it.first;
194 if (axis.length() != 4) {
195 continue;
196 }
197 if (axis == kWeightAxisTag) {
198 weight_axis_set = true;
199 }
200 coordinates.push_back({GetFourByteTag(axis), it.second});
201 }
202 }
203 if (!weight_axis_set) {
204 coordinates.push_back({
205 GetFourByteTag(kWeightAxisTag),
206 static_cast<float>(txt.font_weight),
207 });
208 }
209 SkFontArguments::VariationPosition position = {
210 coordinates.data(), static_cast<int>(coordinates.size())};
211 skia.setFontArguments(SkFontArguments().setVariationDesignPosition(position));
212
213 skia.resetShadows();
214 for (const txt::TextShadow& txt_shadow : txt.text_shadows) {
215 skt::TextShadow shadow;
216 shadow.fOffset = txt_shadow.offset;
217 shadow.fBlurSigma = txt_shadow.blur_sigma;
218 shadow.fColor = txt_shadow.color;
219 skia.addShadow(shadow);
220 }
221
222 return skia;
223}
224
225} // namespace txt
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
virtual const TextStyle & PeekStyle() override
virtual void PushStyle(const TextStyle &style) override
ParagraphBuilderSkia(const ParagraphStyle &style, const std::shared_ptr< FontCollection > &font_collection, const bool impeller_enabled)
virtual std::unique_ptr< Paragraph > Build() override
virtual void AddText(const std::u16string &text) override
virtual void AddPlaceholder(PlaceholderRun &span) override
PlaceholderAlignment alignment
std::u16string text
FontStyle
Definition font_style.h:10