Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
TextValue.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
12#include "include/core/SkRect.h"
23#include "src/utils/SkJSON.h"
24
25#include <algorithm>
26#include <array>
27#include <cstddef>
28#include <limits>
29
30namespace skottie::internal {
31
32bool Parse(const skjson::Value& jv, const internal::AnimationBuilder& abuilder, TextValue* v) {
33 const skjson::ObjectValue* jtxt = jv;
34 if (!jtxt) {
35 return false;
36 }
37
38 const skjson::StringValue* font_name = (*jtxt)["f"];
39 const skjson::StringValue* text = (*jtxt)["t"];
40 const skjson::NumberValue* text_size = (*jtxt)["s"];
41 const skjson::NumberValue* line_height = (*jtxt)["lh"];
42 if (!font_name || !text || !text_size || !line_height) {
43 return false;
44 }
45
46 const auto* font = abuilder.findFont(SkString(font_name->begin(), font_name->size()));
47 if (!font) {
48 abuilder.log(Logger::Level::kError, nullptr, "Unknown font: \"%s\".", font_name->begin());
49 return false;
50 }
51
52 v->fText.set(text->begin(), text->size());
53 v->fTextSize = **text_size;
54 v->fLineHeight = **line_height;
55 v->fTypeface = font->fTypeface;
56 v->fFontFamily = font->fFamily;
57 v->fAscent = font->fAscentPct * -0.01f * v->fTextSize; // negative ascent per SkFontMetrics
58 v->fLineShift = ParseDefault((*jtxt)["ls"], 0.0f);
59
60 static constexpr SkTextUtils::Align gAlignMap[] = {
64 };
65 v->fHAlign = gAlignMap[std::min<size_t>(ParseDefault<size_t>((*jtxt)["j"], 0),
66 std::size(gAlignMap) - 1)];
67
68 // Optional text box size.
69 if (const skjson::ArrayValue* jsz = (*jtxt)["sz"]) {
70 if (jsz->size() == 2) {
71 v->fBox.setWH(ParseDefault<SkScalar>((*jsz)[0], 0),
72 ParseDefault<SkScalar>((*jsz)[1], 0));
73 }
74 }
75
76 // Optional text box position.
77 if (const skjson::ArrayValue* jps = (*jtxt)["ps"]) {
78 if (jps->size() == 2) {
79 v->fBox.offset(ParseDefault<SkScalar>((*jps)[0], 0),
80 ParseDefault<SkScalar>((*jps)[1], 0));
81 }
82 }
83
84 static constexpr Shaper::Direction gDirectionMap[] = {
87 };
88 v->fDirection = gDirectionMap[std::min(ParseDefault<size_t>((*jtxt)["d"], 0),
89 std::size(gDirectionMap) - 1)];
90
91 static constexpr Shaper::ResizePolicy gResizeMap[] = {
95 };
96 // TODO: remove "sk_rs" support after migrating clients.
97 v->fResize = gResizeMap[std::min(std::max(ParseDefault<size_t>((*jtxt)[ "rs"], 0),
98 ParseDefault<size_t>((*jtxt)["sk_rs"], 0)),
99 std::size(gResizeMap) - 1)];
100
101 // Optional min/max font size and line count (used when aute-resizing)
102 v->fMinTextSize = ParseDefault<SkScalar>((*jtxt)["mf"], 0.0f);
103 v->fMaxTextSize = ParseDefault<SkScalar>((*jtxt)["xf"], std::numeric_limits<float>::max());
104 v->fMaxLines = ParseDefault<size_t> ((*jtxt)["xl"], 0);
105
106 // At the moment, BM uses the paragraph box to discriminate point mode vs. paragraph mode.
107 v->fLineBreak = v->fBox.isEmpty()
110
111 // Optional explicit text mode.
112 // N.b.: this is not being exported by BM, only used for testing.
113 auto text_mode = ParseDefault((*jtxt)["m"], -1);
114 if (text_mode >= 0) {
115 // Explicit text mode.
116 v->fLineBreak = (text_mode == 0)
117 ? Shaper::LinebreakPolicy::kExplicit // 'm': 0 -> point text
118 : Shaper::LinebreakPolicy::kParagraph; // 'm': 1 -> paragraph text
119 }
120
121 // Optional capitalization.
122 static constexpr Shaper::Capitalization gCapMap[] = {
125 };
126 v->fCapitalization = gCapMap[std::min<size_t>(ParseDefault<size_t>((*jtxt)["ca"], 0),
127 std::size(gCapMap) - 1)];
128
129 // In point mode, the text is baseline-aligned.
132
133 static constexpr Shaper::VAlign gVAlignMap[] = {
140 };
141 size_t vj;
142 if (skottie::Parse((*jtxt)["vj"], &vj)) {
143 if (vj < std::size(gVAlignMap)) {
144 v->fVAlign = gVAlignMap[vj];
145 } else {
146 abuilder.log(Logger::Level::kWarning, nullptr, "Ignoring unknown 'vj' value: %zu", vj);
147 }
148 } else if (skottie::Parse((*jtxt)["sk_vj"], &vj)) {
149 // Legacy sk_vj values.
150 // TODO: remove after clients update.
151 switch (vj) {
152 case 0:
153 case 1:
154 case 2:
155 static_assert(std::size(gVAlignMap) > 2);
156 v->fVAlign = gVAlignMap[vj];
157 break;
158 case 3:
159 // 'sk_vj': 3 -> kHybridCenter/kScaleToFit
162 break;
163 case 4:
164 // 'sk_vj': 4 -> kHybridCenter/kDownscaleToFit
167 break;
168 default:
169 abuilder.log(Logger::Level::kWarning, nullptr,
170 "Ignoring unknown 'sk_vj' value: %zu", vj);
171 break;
172 }
173 }
174
175 const auto& parse_color = [] (const skjson::ArrayValue* jcolor,
176 SkColor* c) {
177 if (!jcolor) {
178 return false;
179 }
180
181 ColorValue color_vec;
182 if (!skottie::Parse(*jcolor, static_cast<VectorValue*>(&color_vec))) {
183 return false;
184 }
185
186 *c = color_vec;
187 return true;
188 };
189
190 v->fHasFill = parse_color((*jtxt)["fc"], &v->fFillColor);
191 v->fHasStroke = parse_color((*jtxt)["sc"], &v->fStrokeColor);
192
193 if (v->fHasStroke) {
194 v->fStrokeWidth = ParseDefault((*jtxt)["sw"], 1.0f);
195 v->fPaintOrder = ParseDefault((*jtxt)["of"], true)
198
199 static constexpr SkPaint::Join gJoins[] = {
200 SkPaint::kMiter_Join, // lj: 1
201 SkPaint::kRound_Join, // lj: 2
202 SkPaint::kBevel_Join, // lj: 3
203 };
204 v->fStrokeJoin = gJoins[std::min<size_t>(ParseDefault<size_t>((*jtxt)["lj"], 1) - 1,
205 std::size(gJoins) - 1)];
206 }
207
208 return true;
209}
210
211} // namespace skottie::internal
uint32_t SkColor
Definition SkColor.h:37
@ kRound_Join
adds circle
Definition SkPaint.h:360
@ kMiter_Join
extends to miter limit
Definition SkPaint.h:359
@ kBevel_Join
connects outside edges
Definition SkPaint.h:361
void set(const SkString &src)
Definition SkString.h:186
const char * begin() const
Definition SkJSON.h:315
size_t size() const
Definition SkJSON.h:300
void log(Logger::Level, const skjson::Value *, const char fmt[],...) const SK_PRINTF_LIKE(4
Definition Skottie.cpp:71
const FontInfo * findFont(const SkString &name) const
std::u16string text
bool Parse(const skjson::Value &jv, const internal::AnimationBuilder &abuilder, TextValue *v)
Definition TextValue.cpp:32
T ParseDefault(const skjson::Value &v, const T &defaultValue)
Definition SkottieJson.h:23
bool Parse(const skjson::Value &, T *)
void setWH(float width, float height)
Definition SkRect.h:944
void offset(float dx, float dy)
Definition SkRect.h:1016
bool isEmpty() const
Definition SkRect.h:693
sk_sp< SkTypeface > fTypeface
Shaper::Direction fDirection
Shaper::LinebreakPolicy fLineBreak
Shaper::Capitalization fCapitalization
Shaper::ResizePolicy fResize
SkTextUtils::Align fHAlign