Flutter Engine
The Flutter Engine
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
Definition: TextLayer.cpp:349
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
std::u16string text
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
font
Font Metadata and Metrics.
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