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).
GetSkFontStyleWeight(txt::FontWeight font_weight)32 SkFontStyle::Weight GetSkFontStyleWeight(txt::FontWeight font_weight) {
33 return static_cast<SkFontStyle::Weight>(static_cast<int>(font_weight) * 100 +
34 100);
35 }
36
MakeSkFontStyle(txt::FontWeight font_weight,txt::FontStyle font_style)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
TxtToSkia(const ParagraphStyle & txt)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
TxtToSkia(const TextStyle & txt)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 skia.setHalfLeading(txt.half_leading);
111
112 skia.setLocale(SkString(txt.locale.c_str()));
113 if (txt.has_background) {
114 skia.setBackgroundColor(txt.background);
115 }
116 if (txt.has_foreground) {
117 skia.setForegroundColor(txt.foreground);
118 }
119
120 skia.resetFontFeatures();
121 for (const auto& ff : txt.font_features.GetFontFeatures()) {
122 skia.addFontFeature(SkString(ff.first.c_str()), ff.second);
123 }
124
125 skia.resetShadows();
126 for (const txt::TextShadow& txt_shadow : txt.text_shadows) {
127 skt::TextShadow shadow;
128 shadow.fOffset = txt_shadow.offset;
129 shadow.fBlurSigma = txt_shadow.blur_sigma;
130 shadow.fColor = txt_shadow.color;
131 skia.addShadow(shadow);
132 }
133
134 return skia;
135 }
136
137 } // anonymous namespace
138
ParagraphBuilderSkia(const ParagraphStyle & style,std::shared_ptr<FontCollection> font_collection)139 ParagraphBuilderSkia::ParagraphBuilderSkia(
140 const ParagraphStyle& style,
141 std::shared_ptr<FontCollection> font_collection)
142 : builder_(skt::ParagraphBuilder::make(
143 TxtToSkia(style),
144 font_collection->CreateSktFontCollection())),
145 base_style_(style.GetTextStyle()) {}
146
147 ParagraphBuilderSkia::~ParagraphBuilderSkia() = default;
148
PushStyle(const TextStyle & style)149 void ParagraphBuilderSkia::PushStyle(const TextStyle& style) {
150 builder_->pushStyle(TxtToSkia(style));
151 txt_style_stack_.push(style);
152 }
153
Pop()154 void ParagraphBuilderSkia::Pop() {
155 builder_->pop();
156 txt_style_stack_.pop();
157 }
158
PeekStyle()159 const TextStyle& ParagraphBuilderSkia::PeekStyle() {
160 return txt_style_stack_.empty() ? base_style_ : txt_style_stack_.top();
161 }
162
AddText(const std::u16string & text)163 void ParagraphBuilderSkia::AddText(const std::u16string& text) {
164 builder_->addText(text);
165 }
166
AddPlaceholder(PlaceholderRun & span)167 void ParagraphBuilderSkia::AddPlaceholder(PlaceholderRun& span) {
168 skt::PlaceholderStyle placeholder_style;
169 placeholder_style.fHeight = span.height;
170 placeholder_style.fWidth = span.width;
171 placeholder_style.fBaseline = static_cast<skt::TextBaseline>(span.baseline);
172 placeholder_style.fBaselineOffset = span.baseline_offset;
173 placeholder_style.fAlignment =
174 static_cast<skt::PlaceholderAlignment>(span.alignment);
175
176 builder_->addPlaceholder(placeholder_style);
177 }
178
Build()179 std::unique_ptr<Paragraph> ParagraphBuilderSkia::Build() {
180 return std::unique_ptr<Paragraph>(new ParagraphSkia(builder_->Build()));
181 }
182
183 } // namespace txt
184