blob: 5e61bbd076af6ff7fd84b6b1f2c218ce91232722 [file] [log] [blame]
fmalita7a048692015-02-20 13:54:40 -08001/*
2 * Copyright 2015 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
Anas AlJabri84dd1832018-07-31 15:53:05 -07008#define ABORT_TEST(r, cond, ...) \
9 do { \
10 if (cond) { \
11 REPORT_FAILURE(r, #cond, SkStringPrintf(__VA_ARGS__)); \
12 return; \
13 } \
14 } while (0)
15
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "include/core/SkBitmap.h"
17#include "include/core/SkCanvas.h"
18#include "include/core/SkColorFilter.h"
19#include "include/core/SkData.h"
20#include "include/core/SkImage.h"
21#include "include/core/SkShader.h"
22#include "include/core/SkStream.h"
Florin Malita673e87c2019-07-19 13:59:38 -040023#include "include/core/SkTextBlob.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/private/SkTo.h"
Florin Malitaabc96532019-07-19 09:11:29 -040025#include "include/svg/SkSVGCanvas.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "include/utils/SkParse.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "src/shaders/SkImageShader.h"
28#include "tests/Test.h"
Florin Malitaabc96532019-07-19 09:11:29 -040029#include "tools/ToolUtils.h"
fmalita7a048692015-02-20 13:54:40 -080030
31#include <string.h>
32
Alexander Midlash77e3afc2018-03-06 17:21:28 -080033#ifdef SK_XML
34
Mike Kleinc0bd9f92019-04-23 12:05:21 -050035#include "src/svg/SkSVGDevice.h"
36#include "src/xml/SkDOM.h"
37#include "src/xml/SkXMLWriter.h"
Ben Wagner6ce482a2018-03-27 10:57:43 -040038
Florin Malitaabc96532019-07-19 09:11:29 -040039static std::unique_ptr<SkCanvas> MakeDOMCanvas(SkDOM* dom, uint32_t flags = 0) {
Florin Malita562017b2019-02-14 13:42:15 -050040 auto svgDevice = SkSVGDevice::Make(SkISize::Make(100, 100),
Mike Kleinf46d5ca2019-12-11 10:45:01 -050041 std::make_unique<SkXMLParserWriter>(dom->beginParsing()),
Florin Malitaabc96532019-07-19 09:11:29 -040042 flags);
Mike Kleinf46d5ca2019-12-11 10:45:01 -050043 return svgDevice ? std::make_unique<SkCanvas>(svgDevice)
Florin Malita562017b2019-02-14 13:42:15 -050044 : nullptr;
45}
46
fmalita7a048692015-02-20 13:54:40 -080047namespace {
48
Alexander Midlash77e3afc2018-03-06 17:21:28 -080049
fmalita7a048692015-02-20 13:54:40 -080050void check_text_node(skiatest::Reporter* reporter,
51 const SkDOM& dom,
52 const SkDOM::Node* root,
53 const SkPoint& offset,
54 unsigned scalarsPerPos,
Florin Malita673e87c2019-07-19 13:59:38 -040055 const char* txt,
fmalita7a048692015-02-20 13:54:40 -080056 const char* expected) {
halcanary96fcdcc2015-08-27 07:41:13 -070057 if (root == nullptr) {
fmalita7a048692015-02-20 13:54:40 -080058 ERRORF(reporter, "root element not found.");
59 return;
60 }
61
62 const SkDOM::Node* textElem = dom.getFirstChild(root, "text");
halcanary96fcdcc2015-08-27 07:41:13 -070063 if (textElem == nullptr) {
fmalita7a048692015-02-20 13:54:40 -080064 ERRORF(reporter, "<text> element not found.");
65 return;
66 }
67 REPORTER_ASSERT(reporter, dom.getType(textElem) == SkDOM::kElement_Type);
68
69 const SkDOM::Node* textNode= dom.getFirstChild(textElem);
halcanary96fcdcc2015-08-27 07:41:13 -070070 REPORTER_ASSERT(reporter, textNode != nullptr);
71 if (textNode != nullptr) {
fmalita7a048692015-02-20 13:54:40 -080072 REPORTER_ASSERT(reporter, dom.getType(textNode) == SkDOM::kText_Type);
73 REPORTER_ASSERT(reporter, strcmp(expected, dom.getName(textNode)) == 0);
74 }
75
76 int textLen = SkToInt(strlen(expected));
77
78 const char* x = dom.findAttr(textElem, "x");
halcanary96fcdcc2015-08-27 07:41:13 -070079 REPORTER_ASSERT(reporter, x != nullptr);
80 if (x != nullptr) {
Florin Malita673e87c2019-07-19 13:59:38 -040081 int xposCount = textLen;
fmalita7a048692015-02-20 13:54:40 -080082 REPORTER_ASSERT(reporter, SkParse::Count(x) == xposCount);
83
84 SkAutoTMalloc<SkScalar> xpos(xposCount);
85 SkParse::FindScalars(x, xpos.get(), xposCount);
86 if (scalarsPerPos < 1) {
Florin Malita673e87c2019-07-19 13:59:38 -040087 // For default-positioned text, we cannot make any assumptions regarding
88 // the first glyph position when the string has leading whitespace (to be stripped).
89 if (txt[0] != ' ' && txt[0] != '\t') {
90 REPORTER_ASSERT(reporter, xpos[0] == offset.x());
91 }
fmalita7a048692015-02-20 13:54:40 -080092 } else {
93 for (int i = 0; i < xposCount; ++i) {
94 REPORTER_ASSERT(reporter, xpos[i] == SkIntToScalar(expected[i]));
95 }
96 }
97 }
98
99 const char* y = dom.findAttr(textElem, "y");
halcanary96fcdcc2015-08-27 07:41:13 -0700100 REPORTER_ASSERT(reporter, y != nullptr);
101 if (y != nullptr) {
fmalita7a048692015-02-20 13:54:40 -0800102 int yposCount = (scalarsPerPos < 2) ? 1 : textLen;
103 REPORTER_ASSERT(reporter, SkParse::Count(y) == yposCount);
104
105 SkAutoTMalloc<SkScalar> ypos(yposCount);
106 SkParse::FindScalars(y, ypos.get(), yposCount);
107 if (scalarsPerPos < 2) {
108 REPORTER_ASSERT(reporter, ypos[0] == offset.y());
109 } else {
110 for (int i = 0; i < yposCount; ++i) {
Florin Malita673e87c2019-07-19 13:59:38 -0400111 REPORTER_ASSERT(reporter, ypos[i] == 150 - SkIntToScalar(expected[i]));
fmalita7a048692015-02-20 13:54:40 -0800112 }
113 }
114 }
115}
116
117void test_whitespace_pos(skiatest::Reporter* reporter,
118 const char* txt,
119 const char* expected) {
120 size_t len = strlen(txt);
121
122 SkDOM dom;
123 SkPaint paint;
Florin Malita673e87c2019-07-19 13:59:38 -0400124 SkFont font(ToolUtils::create_portable_typeface());
fmalita7a048692015-02-20 13:54:40 -0800125 SkPoint offset = SkPoint::Make(10, 20);
126
127 {
Florin Malita673e87c2019-07-19 13:59:38 -0400128 MakeDOMCanvas(&dom)->drawSimpleText(txt, len, SkTextEncoding::kUTF8,
129 offset.x(), offset.y(), font, paint);
fmalita7a048692015-02-20 13:54:40 -0800130 }
Florin Malita673e87c2019-07-19 13:59:38 -0400131 check_text_node(reporter, dom, dom.finishParsing(), offset, 0, txt, expected);
fmalita7a048692015-02-20 13:54:40 -0800132
133 {
134 SkAutoTMalloc<SkScalar> xpos(len);
135 for (int i = 0; i < SkToInt(len); ++i) {
136 xpos[i] = SkIntToScalar(txt[i]);
137 }
138
Mike Reed212e9062018-12-25 17:35:49 -0500139 auto blob = SkTextBlob::MakeFromPosTextH(txt, len, &xpos[0], offset.y(), font);
Florin Malita673e87c2019-07-19 13:59:38 -0400140 MakeDOMCanvas(&dom)->drawTextBlob(blob, 0, 0, paint);
fmalita7a048692015-02-20 13:54:40 -0800141 }
Florin Malita673e87c2019-07-19 13:59:38 -0400142 check_text_node(reporter, dom, dom.finishParsing(), offset, 1, txt, expected);
fmalita7a048692015-02-20 13:54:40 -0800143
144 {
145 SkAutoTMalloc<SkPoint> pos(len);
146 for (int i = 0; i < SkToInt(len); ++i) {
Florin Malita673e87c2019-07-19 13:59:38 -0400147 pos[i] = SkPoint::Make(SkIntToScalar(txt[i]), 150 - SkIntToScalar(txt[i]));
fmalita7a048692015-02-20 13:54:40 -0800148 }
149
Florin Malita673e87c2019-07-19 13:59:38 -0400150 auto blob = SkTextBlob::MakeFromPosText(txt, len, &pos[0], font);
151 MakeDOMCanvas(&dom)->drawTextBlob(blob, 0, 0, paint);
fmalita7a048692015-02-20 13:54:40 -0800152 }
Florin Malita673e87c2019-07-19 13:59:38 -0400153 check_text_node(reporter, dom, dom.finishParsing(), offset, 2, txt, expected);
fmalita7a048692015-02-20 13:54:40 -0800154}
155
Florin Malita673e87c2019-07-19 13:59:38 -0400156} // namespace
Herb Derby41f4f312018-06-06 17:45:53 +0000157
fmalita7a048692015-02-20 13:54:40 -0800158DEF_TEST(SVGDevice_whitespace_pos, reporter) {
159 static const struct {
160 const char* tst_in;
161 const char* tst_out;
162 } tests[] = {
163 { "abcd" , "abcd" },
164 { "ab cd" , "ab cd" },
165 { "ab \t\t cd", "ab cd" },
166 { " abcd" , "abcd" },
167 { " abcd" , "abcd" },
168 { " \t\t abcd", "abcd" },
169 { "abcd " , "abcd " }, // we allow one trailing whitespace char
170 { "abcd " , "abcd " }, // because it makes no difference and
Florin Malita673e87c2019-07-19 13:59:38 -0400171 { "abcd\t " , "abcd " }, // simplifies the implementation
fmalita7a048692015-02-20 13:54:40 -0800172 { "\t\t \t ab \t\t \t cd \t\t \t ", "ab cd " },
173 };
174
175 for (unsigned i = 0; i < SK_ARRAY_COUNT(tests); ++i) {
176 test_whitespace_pos(reporter, tests[i].tst_in, tests[i].tst_out);
177 }
178}
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800179
Mike Reede25b4472019-04-02 17:49:12 -0400180void SetImageShader(SkPaint* paint, int imageWidth, int imageHeight, SkTileMode xTile,
181 SkTileMode yTile) {
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800182 auto surface = SkSurface::MakeRasterN32Premul(imageWidth, imageHeight);
Mike Reede25b4472019-04-02 17:49:12 -0400183 paint->setShader(surface->makeImageSnapshot()->makeShader(xTile, yTile, nullptr));
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800184}
185
186// Attempt to find the three nodes on which we have expectations:
187// the pattern node, the image within that pattern, and the rect which
188// uses the pattern as a fill.
189// returns false if not all nodes are found.
190bool FindImageShaderNodes(skiatest::Reporter* reporter, const SkDOM* dom, const SkDOM::Node* root,
191 const SkDOM::Node** patternOut, const SkDOM::Node** imageOut,
192 const SkDOM::Node** rectOut) {
193 if (root == nullptr || dom == nullptr) {
194 ERRORF(reporter, "root element not found");
195 return false;
196 }
197
198
199 const SkDOM::Node* rect = dom->getFirstChild(root, "rect");
200 if (rect == nullptr) {
201 ERRORF(reporter, "rect not found");
202 return false;
203 }
204 *rectOut = rect;
205
206 const SkDOM::Node* defs = dom->getFirstChild(root, "defs");
207 if (defs == nullptr) {
208 ERRORF(reporter, "defs not found");
209 return false;
210 }
211
212 const SkDOM::Node* pattern = dom->getFirstChild(defs, "pattern");
213 if (pattern == nullptr) {
214 ERRORF(reporter, "pattern not found");
215 return false;
216 }
217 *patternOut = pattern;
218
219 const SkDOM::Node* image = dom->getFirstChild(pattern, "image");
220 if (image == nullptr) {
221 ERRORF(reporter, "image not found");
222 return false;
223 }
224 *imageOut = image;
225
226 return true;
227}
228
229void ImageShaderTestSetup(SkDOM* dom, SkPaint* paint, int imageWidth, int imageHeight,
Mike Reede25b4472019-04-02 17:49:12 -0400230 int rectWidth, int rectHeight, SkTileMode xTile, SkTileMode yTile) {
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800231 SetImageShader(paint, imageWidth, imageHeight, xTile, yTile);
Florin Malita562017b2019-02-14 13:42:15 -0500232 auto svgCanvas = MakeDOMCanvas(dom);
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800233
234 SkRect bounds{0, 0, SkIntToScalar(rectWidth), SkIntToScalar(rectHeight)};
235 svgCanvas->drawRect(bounds, *paint);
236}
237
238
239DEF_TEST(SVGDevice_image_shader_norepeat, reporter) {
240 SkDOM dom;
241 SkPaint paint;
242 int imageWidth = 3, imageHeight = 3;
243 int rectWidth = 10, rectHeight = 10;
244 ImageShaderTestSetup(&dom, &paint, imageWidth, imageHeight, rectWidth, rectHeight,
Mike Reede25b4472019-04-02 17:49:12 -0400245 SkTileMode::kClamp, SkTileMode::kClamp);
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800246
247 const SkDOM::Node* root = dom.finishParsing();
248
249 const SkDOM::Node *patternNode, *imageNode, *rectNode;
250 bool structureAppropriate =
251 FindImageShaderNodes(reporter, &dom, root, &patternNode, &imageNode, &rectNode);
252 REPORTER_ASSERT(reporter, structureAppropriate);
253
254 // the image should always maintain its size.
255 REPORTER_ASSERT(reporter, atoi(dom.findAttr(imageNode, "width")) == imageWidth);
256 REPORTER_ASSERT(reporter, atoi(dom.findAttr(imageNode, "height")) == imageHeight);
257
258 // making the pattern as large as the container prevents
259 // it from repeating.
260 REPORTER_ASSERT(reporter, strcmp(dom.findAttr(patternNode, "width"), "100%") == 0);
261 REPORTER_ASSERT(reporter, strcmp(dom.findAttr(patternNode, "height"), "100%") == 0);
262}
263
264DEF_TEST(SVGDevice_image_shader_tilex, reporter) {
265 SkDOM dom;
266 SkPaint paint;
267 int imageWidth = 3, imageHeight = 3;
268 int rectWidth = 10, rectHeight = 10;
269 ImageShaderTestSetup(&dom, &paint, imageWidth, imageHeight, rectWidth, rectHeight,
Mike Reede25b4472019-04-02 17:49:12 -0400270 SkTileMode::kRepeat, SkTileMode::kClamp);
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800271
272 const SkDOM::Node* root = dom.finishParsing();
273 const SkDOM::Node* innerSvg = dom.getFirstChild(root, "svg");
274 if (innerSvg == nullptr) {
275 ERRORF(reporter, "inner svg element not found");
276 return;
277 }
278
279 const SkDOM::Node *patternNode, *imageNode, *rectNode;
280 bool structureAppropriate =
281 FindImageShaderNodes(reporter, &dom, innerSvg, &patternNode, &imageNode, &rectNode);
282 REPORTER_ASSERT(reporter, structureAppropriate);
283
284 // the imageNode should always maintain its size.
285 REPORTER_ASSERT(reporter, atoi(dom.findAttr(imageNode, "width")) == imageWidth);
286 REPORTER_ASSERT(reporter, atoi(dom.findAttr(imageNode, "height")) == imageHeight);
287
288 // if the patternNode width matches the imageNode width,
289 // it will repeat in along the x axis.
290 REPORTER_ASSERT(reporter, atoi(dom.findAttr(patternNode, "width")) == imageWidth);
291 REPORTER_ASSERT(reporter, strcmp(dom.findAttr(patternNode, "height"), "100%") == 0);
292}
293
294DEF_TEST(SVGDevice_image_shader_tiley, reporter) {
295 SkDOM dom;
296 SkPaint paint;
297 int imageNodeWidth = 3, imageNodeHeight = 3;
298 int rectNodeWidth = 10, rectNodeHeight = 10;
299 ImageShaderTestSetup(&dom, &paint, imageNodeWidth, imageNodeHeight, rectNodeWidth,
Mike Reede25b4472019-04-02 17:49:12 -0400300 rectNodeHeight, SkTileMode::kClamp, SkTileMode::kRepeat);
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800301
302 const SkDOM::Node* root = dom.finishParsing();
303 const SkDOM::Node* innerSvg = dom.getFirstChild(root, "svg");
304 if (innerSvg == nullptr) {
305 ERRORF(reporter, "inner svg element not found");
306 return;
307 }
308
309 const SkDOM::Node *patternNode, *imageNode, *rectNode;
310 bool structureAppropriate =
311 FindImageShaderNodes(reporter, &dom, innerSvg, &patternNode, &imageNode, &rectNode);
312 REPORTER_ASSERT(reporter, structureAppropriate);
313
314 // the imageNode should always maintain its size.
315 REPORTER_ASSERT(reporter, atoi(dom.findAttr(imageNode, "width")) == imageNodeWidth);
316 REPORTER_ASSERT(reporter, atoi(dom.findAttr(imageNode, "height")) == imageNodeHeight);
317
318 // making the patternNode as large as the container prevents
319 // it from repeating.
320 REPORTER_ASSERT(reporter, strcmp(dom.findAttr(patternNode, "width"), "100%") == 0);
321 REPORTER_ASSERT(reporter, atoi(dom.findAttr(patternNode, "height")) == imageNodeHeight);
322}
323
324DEF_TEST(SVGDevice_image_shader_tileboth, reporter) {
325 SkDOM dom;
326 SkPaint paint;
327 int imageWidth = 3, imageHeight = 3;
328 int rectWidth = 10, rectHeight = 10;
329 ImageShaderTestSetup(&dom, &paint, imageWidth, imageHeight, rectWidth, rectHeight,
Mike Reede25b4472019-04-02 17:49:12 -0400330 SkTileMode::kRepeat, SkTileMode::kRepeat);
Alexander Midlash77e3afc2018-03-06 17:21:28 -0800331
332 const SkDOM::Node* root = dom.finishParsing();
333
334 const SkDOM::Node *patternNode, *imageNode, *rectNode;
335 const SkDOM::Node* innerSvg = dom.getFirstChild(root, "svg");
336 if (innerSvg == nullptr) {
337 ERRORF(reporter, "inner svg element not found");
338 return;
339 }
340 bool structureAppropriate =
341 FindImageShaderNodes(reporter, &dom, innerSvg, &patternNode, &imageNode, &rectNode);
342 REPORTER_ASSERT(reporter, structureAppropriate);
343
344 // the imageNode should always maintain its size.
345 REPORTER_ASSERT(reporter, atoi(dom.findAttr(imageNode, "width")) == imageWidth);
346 REPORTER_ASSERT(reporter, atoi(dom.findAttr(imageNode, "height")) == imageHeight);
347
348 REPORTER_ASSERT(reporter, atoi(dom.findAttr(patternNode, "width")) == imageWidth);
349 REPORTER_ASSERT(reporter, atoi(dom.findAttr(patternNode, "height")) == imageHeight);
350}
351
Anas AlJabri84dd1832018-07-31 15:53:05 -0700352DEF_TEST(SVGDevice_ColorFilters, reporter) {
353 SkDOM dom;
354 SkPaint paint;
Mike Reedb286bc22019-04-08 16:23:20 -0400355 paint.setColorFilter(SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcIn));
Anas AlJabri84dd1832018-07-31 15:53:05 -0700356 {
Florin Malita562017b2019-02-14 13:42:15 -0500357 auto svgCanvas = MakeDOMCanvas(&dom);
Anas AlJabri84dd1832018-07-31 15:53:05 -0700358 SkRect bounds{0, 0, SkIntToScalar(100), SkIntToScalar(100)};
359 svgCanvas->drawRect(bounds, paint);
360 }
361 const SkDOM::Node* rootElement = dom.finishParsing();
362 ABORT_TEST(reporter, !rootElement, "root element not found");
363
364 const SkDOM::Node* filterElement = dom.getFirstChild(rootElement, "filter");
365 ABORT_TEST(reporter, !filterElement, "filter element not found");
366
367 const SkDOM::Node* floodElement = dom.getFirstChild(filterElement, "feFlood");
368 ABORT_TEST(reporter, !floodElement, "feFlood element not found");
369
370 const SkDOM::Node* compositeElement = dom.getFirstChild(filterElement, "feComposite");
371 ABORT_TEST(reporter, !compositeElement, "feComposite element not found");
372
373 REPORTER_ASSERT(reporter, strcmp(dom.findAttr(filterElement, "width"), "100%") == 0);
374 REPORTER_ASSERT(reporter, strcmp(dom.findAttr(filterElement, "height"), "100%") == 0);
375
376 REPORTER_ASSERT(reporter,
Florin Malita3f412f92019-08-22 13:37:32 -0400377 strcmp(dom.findAttr(floodElement, "flood-color"), "red") == 0);
Anas AlJabri84dd1832018-07-31 15:53:05 -0700378 REPORTER_ASSERT(reporter, atoi(dom.findAttr(floodElement, "flood-opacity")) == 1);
379
380 REPORTER_ASSERT(reporter, strcmp(dom.findAttr(compositeElement, "in"), "flood") == 0);
381 REPORTER_ASSERT(reporter, strcmp(dom.findAttr(compositeElement, "operator"), "in") == 0);
382}
383
Florin Malitaabc96532019-07-19 09:11:29 -0400384DEF_TEST(SVGDevice_textpath, reporter) {
385 SkDOM dom;
386 SkFont font(ToolUtils::create_portable_typeface());
387 SkPaint paint;
388
389 // By default, we emit <text> nodes.
390 {
391 auto svgCanvas = MakeDOMCanvas(&dom);
392 svgCanvas->drawString("foo", 100, 100, font, paint);
393 }
394 const auto* rootElement = dom.finishParsing();
395 REPORTER_ASSERT(reporter, rootElement, "root element not found");
396 const auto* textElement = dom.getFirstChild(rootElement, "text");
397 REPORTER_ASSERT(reporter, textElement, "text element not found");
398 const auto* pathElement = dom.getFirstChild(rootElement, "path");
399 REPORTER_ASSERT(reporter, !pathElement, "path element found");
400
401 // With kConvertTextToPaths_Flag, we emit <path> nodes.
402 {
403 auto svgCanvas = MakeDOMCanvas(&dom, SkSVGCanvas::kConvertTextToPaths_Flag);
404 svgCanvas->drawString("foo", 100, 100, font, paint);
405 }
406 rootElement = dom.finishParsing();
407 REPORTER_ASSERT(reporter, rootElement, "root element not found");
408 textElement = dom.getFirstChild(rootElement, "text");
409 REPORTER_ASSERT(reporter, !textElement, "text element found");
410 pathElement = dom.getFirstChild(rootElement, "path");
411 REPORTER_ASSERT(reporter, pathElement, "path element not found");
412}
413
Florin Malita05bab9a2019-08-21 12:13:21 -0400414DEF_TEST(SVGDevice_fill_stroke, reporter) {
415 struct {
416 SkColor color;
417 SkPaint::Style style;
418 const char* expected_fill;
419 const char* expected_stroke;
420 } gTests[] = {
Florin Malita3f412f92019-08-22 13:37:32 -0400421 { SK_ColorBLACK, SkPaint::kFill_Style , nullptr, nullptr },
422 { SK_ColorBLACK, SkPaint::kStroke_Style, "none" , "black" },
423 { SK_ColorRED , SkPaint::kFill_Style , "red" , nullptr },
424 { SK_ColorRED , SkPaint::kStroke_Style, "none" , "red" },
Florin Malita05bab9a2019-08-21 12:13:21 -0400425 };
426
427 for (const auto& tst : gTests) {
428 SkPaint p;
429 p.setColor(tst.color);
430 p.setStyle(tst.style);
431
432 SkDOM dom;
433 {
434 MakeDOMCanvas(&dom)->drawRect(SkRect::MakeWH(100, 100), p);
435 }
436
437 const auto* root = dom.finishParsing();
438 REPORTER_ASSERT(reporter, root, "root element not found");
439 const auto* rect = dom.getFirstChild(root, "rect");
440 REPORTER_ASSERT(reporter, rect, "rect element not found");
441 const auto* fill = dom.findAttr(rect, "fill");
442 REPORTER_ASSERT(reporter, !!fill == !!tst.expected_fill);
443 if (fill) {
444 REPORTER_ASSERT(reporter, strcmp(fill, tst.expected_fill) == 0);
445 }
446 const auto* stroke = dom.findAttr(rect, "stroke");
447 REPORTER_ASSERT(reporter, !!stroke == !!tst.expected_stroke);
448 if (stroke) {
449 REPORTER_ASSERT(reporter, strcmp(stroke, tst.expected_stroke) == 0);
450 }
451 }
452}
453
Hal Canaryff2742e2018-01-30 11:35:47 -0500454#endif