1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2020 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include <unordered_map>
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMgr.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontStyle.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/include/Skottie.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/include/SkottieProperty.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper_factory.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/utils/FactoryHelpers.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker using namespace skottie;
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker namespace {
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker class RecordMatchFamilyStyleSkFontMgr : public SkFontMgr {
26*c8dee2aaSAndroid Build Coastguard Worker public:
styleRequestedWhenMatchingFamily(const char * family) const27*c8dee2aaSAndroid Build Coastguard Worker const SkFontStyle* styleRequestedWhenMatchingFamily(const char* family) const {
28*c8dee2aaSAndroid Build Coastguard Worker auto s = fStyleRequestedWhenMatchingFamily.find(family);
29*c8dee2aaSAndroid Build Coastguard Worker return s != fStyleRequestedWhenMatchingFamily.end() ? &s->second : nullptr;
30*c8dee2aaSAndroid Build Coastguard Worker }
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker private:
onCountFamilies() const33*c8dee2aaSAndroid Build Coastguard Worker int onCountFamilies() const override { return 0; }
onGetFamilyName(int index,SkString * familyName) const34*c8dee2aaSAndroid Build Coastguard Worker void onGetFamilyName(int index, SkString* familyName) const override {}
onCreateStyleSet(int index) const35*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkFontStyleSet> onCreateStyleSet(int index) const override { return nullptr; }
36*c8dee2aaSAndroid Build Coastguard Worker
onMatchFamily(const char[]) const37*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkFontStyleSet> onMatchFamily(const char[]) const override { return nullptr; }
38*c8dee2aaSAndroid Build Coastguard Worker
onMatchFamilyStyle(const char family[],const SkFontStyle & style) const39*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> onMatchFamilyStyle(const char family[],
40*c8dee2aaSAndroid Build Coastguard Worker const SkFontStyle& style) const override {
41*c8dee2aaSAndroid Build Coastguard Worker fStyleRequestedWhenMatchingFamily[family] = style;
42*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
43*c8dee2aaSAndroid Build Coastguard Worker }
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const44*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style,
45*c8dee2aaSAndroid Build Coastguard Worker const char* bcp47[], int bcp47Count,
46*c8dee2aaSAndroid Build Coastguard Worker SkUnichar character) const override {
47*c8dee2aaSAndroid Build Coastguard Worker fStyleRequestedWhenMatchingFamily[familyName] = style;
48*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker
onMakeFromData(sk_sp<SkData>,int ttcIndex) const51*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override {
52*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
53*c8dee2aaSAndroid Build Coastguard Worker }
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,int ttcIndex) const54*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
55*c8dee2aaSAndroid Build Coastguard Worker int ttcIndex) const override {
56*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
57*c8dee2aaSAndroid Build Coastguard Worker }
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,const SkFontArguments &) const58*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
59*c8dee2aaSAndroid Build Coastguard Worker const SkFontArguments&) const override {
60*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
61*c8dee2aaSAndroid Build Coastguard Worker }
onMakeFromFile(const char path[],int ttcIndex) const62*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
63*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
64*c8dee2aaSAndroid Build Coastguard Worker }
65*c8dee2aaSAndroid Build Coastguard Worker
onLegacyMakeTypeface(const char familyName[],SkFontStyle) const66*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override {
67*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
68*c8dee2aaSAndroid Build Coastguard Worker }
69*c8dee2aaSAndroid Build Coastguard Worker
70*c8dee2aaSAndroid Build Coastguard Worker mutable std::unordered_map<std::string, SkFontStyle> fStyleRequestedWhenMatchingFamily;
71*c8dee2aaSAndroid Build Coastguard Worker };
72*c8dee2aaSAndroid Build Coastguard Worker
73*c8dee2aaSAndroid Build Coastguard Worker } // namespace
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker // This test relies on Skottie internals/implementation details, and may need to
76*c8dee2aaSAndroid Build Coastguard Worker // be updated in the future, if Skottie font resolution changes.
DEF_TEST(Skottie_Text_Style,r)77*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Skottie_Text_Style, r) {
78*c8dee2aaSAndroid Build Coastguard Worker static constexpr char json[] =
79*c8dee2aaSAndroid Build Coastguard Worker R"({
80*c8dee2aaSAndroid Build Coastguard Worker "v": "5.2.1",
81*c8dee2aaSAndroid Build Coastguard Worker "w": 100,
82*c8dee2aaSAndroid Build Coastguard Worker "h": 100,
83*c8dee2aaSAndroid Build Coastguard Worker "fr": 10,
84*c8dee2aaSAndroid Build Coastguard Worker "ip": 0,
85*c8dee2aaSAndroid Build Coastguard Worker "op": 100,
86*c8dee2aaSAndroid Build Coastguard Worker "fonts": {
87*c8dee2aaSAndroid Build Coastguard Worker "list": [
88*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f1", "fFamily": "f1", "fStyle" : "Regular" },
89*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f2", "fFamily": "f2", "fStyle" : "Medium" },
90*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f3", "fFamily": "f3", "fStyle" : "Bold" },
91*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f4", "fFamily": "f4", "fStyle" : "Light" },
92*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f5", "fFamily": "f5", "fStyle" : "Extra" },
93*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f6", "fFamily": "f6", "fStyle" : "ExtraBold" },
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f7" , "fFamily": "f7" , "fStyle" : "Regular Italic" },
96*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f8" , "fFamily": "f8" , "fStyle" : "Medium Italic" },
97*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f9" , "fFamily": "f9" , "fStyle" : "Bold Italic" },
98*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f10", "fFamily": "f10", "fStyle" : "Light Oblique" },
99*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f11", "fFamily": "f11", "fStyle" : "Extra Oblique" },
100*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f12", "fFamily": "f12", "fStyle" : "Extrabold Oblique" },
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f13", "fFamily": "f13", "fStyle" : "Italic" },
103*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f14", "fFamily": "f14", "fStyle" : "Oblique" },
104*c8dee2aaSAndroid Build Coastguard Worker { "fName" : "f15", "fFamily": "f15", "fStyle" : "" }
105*c8dee2aaSAndroid Build Coastguard Worker ]
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker })";
108*c8dee2aaSAndroid Build Coastguard Worker
109*c8dee2aaSAndroid Build Coastguard Worker SkMemoryStream stream(json, strlen(json));
110*c8dee2aaSAndroid Build Coastguard Worker auto fmgr = sk_make_sp<RecordMatchFamilyStyleSkFontMgr>();
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker auto anim = Animation::Builder()
113*c8dee2aaSAndroid Build Coastguard Worker .setFontManager(fmgr)
114*c8dee2aaSAndroid Build Coastguard Worker .setTextShapingFactory(SkShapers::BestAvailable())
115*c8dee2aaSAndroid Build Coastguard Worker .make(&stream);
116*c8dee2aaSAndroid Build Coastguard Worker
117*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, anim);
118*c8dee2aaSAndroid Build Coastguard Worker
119*c8dee2aaSAndroid Build Coastguard Worker static constexpr struct {
120*c8dee2aaSAndroid Build Coastguard Worker const char* family;
121*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle::Weight weight;
122*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle::Slant slant;
123*c8dee2aaSAndroid Build Coastguard Worker } expected[] = {
124*c8dee2aaSAndroid Build Coastguard Worker { "f1" , SkFontStyle::kNormal_Weight , SkFontStyle::kUpright_Slant },
125*c8dee2aaSAndroid Build Coastguard Worker { "f2" , SkFontStyle::kMedium_Weight , SkFontStyle::kUpright_Slant },
126*c8dee2aaSAndroid Build Coastguard Worker { "f3" , SkFontStyle::kBold_Weight , SkFontStyle::kUpright_Slant },
127*c8dee2aaSAndroid Build Coastguard Worker { "f4" , SkFontStyle::kLight_Weight , SkFontStyle::kUpright_Slant },
128*c8dee2aaSAndroid Build Coastguard Worker { "f5" , SkFontStyle::kExtraBold_Weight, SkFontStyle::kUpright_Slant },
129*c8dee2aaSAndroid Build Coastguard Worker { "f6" , SkFontStyle::kExtraBold_Weight, SkFontStyle::kUpright_Slant },
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker { "f7" , SkFontStyle::kNormal_Weight , SkFontStyle::kItalic_Slant },
132*c8dee2aaSAndroid Build Coastguard Worker { "f8" , SkFontStyle::kMedium_Weight , SkFontStyle::kItalic_Slant },
133*c8dee2aaSAndroid Build Coastguard Worker { "f9" , SkFontStyle::kBold_Weight , SkFontStyle::kItalic_Slant },
134*c8dee2aaSAndroid Build Coastguard Worker { "f10", SkFontStyle::kLight_Weight , SkFontStyle::kOblique_Slant },
135*c8dee2aaSAndroid Build Coastguard Worker { "f11", SkFontStyle::kExtraBold_Weight, SkFontStyle::kOblique_Slant },
136*c8dee2aaSAndroid Build Coastguard Worker { "f12", SkFontStyle::kExtraBold_Weight, SkFontStyle::kOblique_Slant },
137*c8dee2aaSAndroid Build Coastguard Worker
138*c8dee2aaSAndroid Build Coastguard Worker { "f13", SkFontStyle::kNormal_Weight , SkFontStyle::kItalic_Slant },
139*c8dee2aaSAndroid Build Coastguard Worker { "f14", SkFontStyle::kNormal_Weight , SkFontStyle::kOblique_Slant },
140*c8dee2aaSAndroid Build Coastguard Worker { "f15", SkFontStyle::kNormal_Weight , SkFontStyle::kUpright_Slant },
141*c8dee2aaSAndroid Build Coastguard Worker };
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker for (const auto& exp : expected) {
144*c8dee2aaSAndroid Build Coastguard Worker const auto* style = fmgr->styleRequestedWhenMatchingFamily(exp.family);
145*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, style);
146*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, style->weight() == exp.weight);
147*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, style->slant () == exp.slant );
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Skottie_Text_LayoutError,r)151*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Skottie_Text_LayoutError, r) {
152*c8dee2aaSAndroid Build Coastguard Worker // Text node properties:
153*c8dee2aaSAndroid Build Coastguard Worker // - scale to fit
154*c8dee2aaSAndroid Build Coastguard Worker // - box width: 100
155*c8dee2aaSAndroid Build Coastguard Worker // - min font size: 70
156*c8dee2aaSAndroid Build Coastguard Worker // - string: Foo Bar Baz
157*c8dee2aaSAndroid Build Coastguard Worker //
158*c8dee2aaSAndroid Build Coastguard Worker // Layout should fail with these unsatisfiable constraints.
159*c8dee2aaSAndroid Build Coastguard Worker static constexpr char json[] =
160*c8dee2aaSAndroid Build Coastguard Worker R"({
161*c8dee2aaSAndroid Build Coastguard Worker "v": "5.2.1",
162*c8dee2aaSAndroid Build Coastguard Worker "w": 100,
163*c8dee2aaSAndroid Build Coastguard Worker "h": 100,
164*c8dee2aaSAndroid Build Coastguard Worker "fr": 10,
165*c8dee2aaSAndroid Build Coastguard Worker "ip": 0,
166*c8dee2aaSAndroid Build Coastguard Worker "op": 100,
167*c8dee2aaSAndroid Build Coastguard Worker "fonts": {
168*c8dee2aaSAndroid Build Coastguard Worker "list": [{
169*c8dee2aaSAndroid Build Coastguard Worker "fFamily": "Arial",
170*c8dee2aaSAndroid Build Coastguard Worker "fName": "Arial",
171*c8dee2aaSAndroid Build Coastguard Worker "fStyle": "Bold"
172*c8dee2aaSAndroid Build Coastguard Worker }]
173*c8dee2aaSAndroid Build Coastguard Worker },
174*c8dee2aaSAndroid Build Coastguard Worker "layers": [{
175*c8dee2aaSAndroid Build Coastguard Worker "ty": 5,
176*c8dee2aaSAndroid Build Coastguard Worker "t": {
177*c8dee2aaSAndroid Build Coastguard Worker "d": {
178*c8dee2aaSAndroid Build Coastguard Worker "k": [{
179*c8dee2aaSAndroid Build Coastguard Worker "t": 0,
180*c8dee2aaSAndroid Build Coastguard Worker "s": {
181*c8dee2aaSAndroid Build Coastguard Worker "f": "Arial",
182*c8dee2aaSAndroid Build Coastguard Worker "t": "Foo Bar Baz",
183*c8dee2aaSAndroid Build Coastguard Worker "s": 24,
184*c8dee2aaSAndroid Build Coastguard Worker "fc": [1,1,1,1],
185*c8dee2aaSAndroid Build Coastguard Worker "lh": 70,
186*c8dee2aaSAndroid Build Coastguard Worker "ps": [0, 0],
187*c8dee2aaSAndroid Build Coastguard Worker "sz": [100, 100],
188*c8dee2aaSAndroid Build Coastguard Worker "mf": 70,
189*c8dee2aaSAndroid Build Coastguard Worker "rs": 1
190*c8dee2aaSAndroid Build Coastguard Worker }
191*c8dee2aaSAndroid Build Coastguard Worker }]
192*c8dee2aaSAndroid Build Coastguard Worker }
193*c8dee2aaSAndroid Build Coastguard Worker }
194*c8dee2aaSAndroid Build Coastguard Worker }]
195*c8dee2aaSAndroid Build Coastguard Worker })";
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker class Logger final : public skottie::Logger {
198*c8dee2aaSAndroid Build Coastguard Worker public:
199*c8dee2aaSAndroid Build Coastguard Worker const std::vector<SkString>& errors() const { return fErrors; }
200*c8dee2aaSAndroid Build Coastguard Worker
201*c8dee2aaSAndroid Build Coastguard Worker private:
202*c8dee2aaSAndroid Build Coastguard Worker void log(Level lvl, const char message[], const char* = nullptr) override {
203*c8dee2aaSAndroid Build Coastguard Worker if (lvl == Level::kError) {
204*c8dee2aaSAndroid Build Coastguard Worker fErrors.emplace_back(message);
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker }
207*c8dee2aaSAndroid Build Coastguard Worker
208*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkString> fErrors;
209*c8dee2aaSAndroid Build Coastguard Worker };
210*c8dee2aaSAndroid Build Coastguard Worker
211*c8dee2aaSAndroid Build Coastguard Worker class PortableRP final : public skresources::ResourceProvider {
212*c8dee2aaSAndroid Build Coastguard Worker private:
213*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> loadTypeface(const char[], const char[]) const override {
214*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::CreatePortableTypeface("Serif", SkFontStyle());
215*c8dee2aaSAndroid Build Coastguard Worker }
216*c8dee2aaSAndroid Build Coastguard Worker };
217*c8dee2aaSAndroid Build Coastguard Worker
218*c8dee2aaSAndroid Build Coastguard Worker SkMemoryStream stream(json, strlen(json));
219*c8dee2aaSAndroid Build Coastguard Worker auto logger = sk_make_sp<Logger>();
220*c8dee2aaSAndroid Build Coastguard Worker
221*c8dee2aaSAndroid Build Coastguard Worker auto anim = Animation::Builder()
222*c8dee2aaSAndroid Build Coastguard Worker .setLogger(logger)
223*c8dee2aaSAndroid Build Coastguard Worker .setResourceProvider(sk_make_sp<PortableRP>())
224*c8dee2aaSAndroid Build Coastguard Worker .make(&stream);
225*c8dee2aaSAndroid Build Coastguard Worker
226*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, anim);
227*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, logger->errors().size() == 1);
228*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, logger->errors()[0].startsWith("Text layout failed"));
229*c8dee2aaSAndroid Build Coastguard Worker }
230*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Skottie_Text_FontFamily,r)231*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Skottie_Text_FontFamily, r) {
232*c8dee2aaSAndroid Build Coastguard Worker static constexpr char json[] =
233*c8dee2aaSAndroid Build Coastguard Worker R"({
234*c8dee2aaSAndroid Build Coastguard Worker "v": "5.2.1",
235*c8dee2aaSAndroid Build Coastguard Worker "w": 100,
236*c8dee2aaSAndroid Build Coastguard Worker "h": 100,
237*c8dee2aaSAndroid Build Coastguard Worker "fr": 10,
238*c8dee2aaSAndroid Build Coastguard Worker "ip": 0,
239*c8dee2aaSAndroid Build Coastguard Worker "op": 100,
240*c8dee2aaSAndroid Build Coastguard Worker "fonts": {
241*c8dee2aaSAndroid Build Coastguard Worker "list": [{
242*c8dee2aaSAndroid Build Coastguard Worker "fFamily": "family_1",
243*c8dee2aaSAndroid Build Coastguard Worker "fName": "Font1",
244*c8dee2aaSAndroid Build Coastguard Worker "fStyle": "Bold"
245*c8dee2aaSAndroid Build Coastguard Worker }]
246*c8dee2aaSAndroid Build Coastguard Worker },
247*c8dee2aaSAndroid Build Coastguard Worker "layers": [{
248*c8dee2aaSAndroid Build Coastguard Worker "ty": 5,
249*c8dee2aaSAndroid Build Coastguard Worker "t": {
250*c8dee2aaSAndroid Build Coastguard Worker "d": {
251*c8dee2aaSAndroid Build Coastguard Worker "k": [{
252*c8dee2aaSAndroid Build Coastguard Worker "t": 0,
253*c8dee2aaSAndroid Build Coastguard Worker "s": {
254*c8dee2aaSAndroid Build Coastguard Worker "f": "Font1",
255*c8dee2aaSAndroid Build Coastguard Worker "t": "Foo Bar Baz",
256*c8dee2aaSAndroid Build Coastguard Worker "s": 24,
257*c8dee2aaSAndroid Build Coastguard Worker "fc": [1,1,1,1],
258*c8dee2aaSAndroid Build Coastguard Worker "lh": 70,
259*c8dee2aaSAndroid Build Coastguard Worker "ps": [0, 0],
260*c8dee2aaSAndroid Build Coastguard Worker "sz": [100, 100],
261*c8dee2aaSAndroid Build Coastguard Worker "mf": 70,
262*c8dee2aaSAndroid Build Coastguard Worker "rs": 0
263*c8dee2aaSAndroid Build Coastguard Worker }
264*c8dee2aaSAndroid Build Coastguard Worker }]
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker }
267*c8dee2aaSAndroid Build Coastguard Worker }]
268*c8dee2aaSAndroid Build Coastguard Worker })";
269*c8dee2aaSAndroid Build Coastguard Worker
270*c8dee2aaSAndroid Build Coastguard Worker class TextObserver final : public PropertyObserver {
271*c8dee2aaSAndroid Build Coastguard Worker public:
272*c8dee2aaSAndroid Build Coastguard Worker const std::unique_ptr<TextPropertyHandle>& text() const { return fText; }
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker private:
275*c8dee2aaSAndroid Build Coastguard Worker void onTextProperty(const char node_name[],
276*c8dee2aaSAndroid Build Coastguard Worker const LazyHandle<TextPropertyHandle>& lh) override {
277*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fText); // only one text prop in test
278*c8dee2aaSAndroid Build Coastguard Worker fText = lh();
279*c8dee2aaSAndroid Build Coastguard Worker }
280*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<TextPropertyHandle> fText;
281*c8dee2aaSAndroid Build Coastguard Worker };
282*c8dee2aaSAndroid Build Coastguard Worker
283*c8dee2aaSAndroid Build Coastguard Worker auto fmgr = sk_make_sp<RecordMatchFamilyStyleSkFontMgr>();
284*c8dee2aaSAndroid Build Coastguard Worker auto prop_observer = sk_make_sp<TextObserver>();
285*c8dee2aaSAndroid Build Coastguard Worker
286*c8dee2aaSAndroid Build Coastguard Worker SkMemoryStream stream(json, strlen(json));
287*c8dee2aaSAndroid Build Coastguard Worker auto anim = Animation::Builder()
288*c8dee2aaSAndroid Build Coastguard Worker .setFontManager(fmgr)
289*c8dee2aaSAndroid Build Coastguard Worker .setPropertyObserver(prop_observer)
290*c8dee2aaSAndroid Build Coastguard Worker .setTextShapingFactory(SkShapers::BestAvailable())
291*c8dee2aaSAndroid Build Coastguard Worker .make(&stream);
292*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, anim);
293*c8dee2aaSAndroid Build Coastguard Worker
294*c8dee2aaSAndroid Build Coastguard Worker // Original family name was passed to fontmgr.
295*c8dee2aaSAndroid Build Coastguard Worker const auto* style1 = fmgr->styleRequestedWhenMatchingFamily("family_1");
296*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, style1);
297*c8dee2aaSAndroid Build Coastguard Worker
298*c8dee2aaSAndroid Build Coastguard Worker const auto& text_handle = prop_observer->text();
299*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, text_handle);
300*c8dee2aaSAndroid Build Coastguard Worker auto txt = (*text_handle).get();
301*c8dee2aaSAndroid Build Coastguard Worker txt.fFontFamily = "family_2";
302*c8dee2aaSAndroid Build Coastguard Worker (*text_handle).set(txt);
303*c8dee2aaSAndroid Build Coastguard Worker
304*c8dee2aaSAndroid Build Coastguard Worker // Updated family name was passed to fontmgr.
305*c8dee2aaSAndroid Build Coastguard Worker const auto* style2 = fmgr->styleRequestedWhenMatchingFamily("family_2");
306*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, style2);
307*c8dee2aaSAndroid Build Coastguard Worker }
308