1 /*
2 * Copyright 2020 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
8 #include "include/utils/SkNoDrawCanvas.h"
9 #include "modules/skresources/include/SkResources.h"
10 #include "modules/skshaper/utils/FactoryHelpers.h"
11 #include "modules/svg/include/SkSVGIDMapper.h"
12 #include "modules/svg/include/SkSVGRenderContext.h"
13 #include "modules/svg/include/SkSVGText.h"
14 #include "modules/svg/include/SkSVGTypes.h"
15 #include "modules/svg/src/SkSVGTextPriv.h"
16 #include "tests/Test.h"
17 #include "tools/fonts/FontToolUtils.h"
18
19 #include <vector>
20
DEF_TEST(Svg_Text_PosProvider,r)21 DEF_TEST(Svg_Text_PosProvider, r) {
22 const auto L = [](float x) { return SkSVGLength(x); };
23 const float N = SkSVGTextContext::PosAttrs()[SkSVGTextContext::PosAttrs::kX];
24
25 static const struct PosTestDesc {
26 size_t offseta;
27 std::vector<SkSVGLength> xa, ya;
28
29 size_t offsetb;
30 std::vector<SkSVGLength> xb, yb;
31
32 std::vector<SkPoint> expected;
33 } gTests[] = {
34 {
35 0, {}, {},
36 0, {}, {},
37
38 { {N,N} }
39 },
40
41 {
42 0, { L(1) }, {},
43 0, { }, {},
44
45 { {1,N}, {N,N} }
46 },
47 {
48 0, { }, {},
49 0, { L(10) }, {},
50
51 { {10,N}, {N,N} }
52 },
53 {
54 0, { L( 1) }, {},
55 0, { L(10) }, {},
56
57 { {10,N}, {N,N} }
58 },
59 {
60 0, { L( 1), L(2) }, {},
61 0, { L(10) }, {},
62
63 { {10,N}, {2,N}, {N,N} }
64 },
65 {
66 0, { L(1), L( 2) }, {},
67 1, { L(20) }, {},
68
69 { {1,N}, {20,N}, {N,N} }
70 },
71 {
72 0, { L(1), L( 2), L(3) }, {},
73 1, { L(20) }, {},
74
75 { {1,N}, {20,N}, {3,N}, {N,N} }
76 },
77 {
78 0, { L(1), L(2), L( 3) }, {},
79 2, { L(30) }, {},
80
81 { {1,N}, {2,N}, {30,N}, {N,N} }
82 },
83 {
84 0, { L(1) }, {},
85 2, { L(30) }, {},
86
87 { {1,N}, {N,N}, {30,N}, {N,N} }
88 },
89
90
91 {
92 0, {}, { L(4) },
93 0, {}, { },
94
95 { {N,4}, {N,N} }
96 },
97 {
98 0, {}, { },
99 0, {}, { L(40) },
100
101 { {N,40}, {N,N} }
102 },
103 {
104 0, {}, { L( 4) },
105 0, {}, { L(40) },
106
107 { {N,40}, {N,N} }
108 },
109 {
110 0, {}, { L( 4), L(5) },
111 0, {}, { L(40) },
112
113 { {N,40}, {N,5}, {N,N} }
114 },
115 {
116 0, {}, { L(4), L( 5) },
117 1, {}, { L(50) },
118
119 { {N,4}, {N,50}, {N,N} }
120 },
121 {
122 0, {}, { L(4), L( 5), L(6) },
123 1, {}, { L(50) },
124
125 { {N,4}, {N,50}, {N,6}, {N,N} }
126 },
127 {
128 0, {}, { L(4), L(5), L( 6) },
129 2, {}, { L(60) },
130
131 { {N,4}, {N,5}, {N,60}, {N,N} }
132 },
133 {
134 0, {}, { L(4) },
135 2, {}, { L(60) },
136
137 { {N,4}, {N,N}, {N,60}, {N,N} }
138 },
139
140 {
141 0, { L( 1), L(2)}, { L( 4) },
142 0, { L(10) }, { L(40), L(50) },
143
144 { {10,40}, {2,50}, {N,N} }
145 },
146 {
147 0, { L(1), L( 2), L(3) }, { L(4), L( 5) },
148 1, { L(20) }, { L(50), L(60) },
149
150 { {1,4}, {20,50}, {3,60}, {N,N} }
151 },
152 };
153
154 const SkSVGTextContext::ShapedTextCallback mock_cb =
155 [](const SkSVGRenderContext&, const sk_sp<SkTextBlob>&, const SkPaint*, const SkPaint*) {};
156
157 auto test = [&](const PosTestDesc& tst) {
158 auto a = SkSVGText::Make();
159 auto b = SkSVGTSpan::Make();
160 a->appendChild(b);
161
162 a->setX(tst.xa);
163 a->setY(tst.ya);
164 b->setX(tst.xb);
165 b->setY(tst.yb);
166
167 const SkSVGIDMapper mapper;
168 const SkSVGLengthContext lctx({0,0});
169 const SkSVGPresentationContext pctx;
170 SkNoDrawCanvas canvas(0, 0);
171 sk_sp<SkFontMgr> fmgr = ToolUtils::TestFontMgr();
172 sk_sp<skresources::ResourceProvider> rp;
173 sk_sp<SkShapers::Factory> shaping = SkShapers::BestAvailable();
174 const SkSVGRenderContext ctx(&canvas,
175 fmgr,
176 rp,
177 mapper,
178 lctx,
179 pctx,
180 {nullptr, nullptr},
181 shaping);
182
183 SkSVGTextContext tctx(ctx, mock_cb);
184 SkSVGTextContext::ScopedPosResolver pa(*a, lctx, &tctx, tst.offseta);
185 SkSVGTextContext::ScopedPosResolver pb(*b, lctx, &tctx, tst.offsetb);
186
187 for (size_t i = 0; i < tst.expected.size(); ++i) {
188 const auto& exp = tst.expected[i];
189 auto pos = i >= tst.offsetb ? pb.resolve(i) : pa.resolve(i);
190
191 REPORTER_ASSERT(r, pos[SkSVGTextContext::PosAttrs::kX] == exp.fX);
192 REPORTER_ASSERT(r, pos[SkSVGTextContext::PosAttrs::kY] == exp.fY);
193 }
194 };
195
196 for (const auto& tst : gTests) {
197 test(tst);
198 }
199 }
200