17a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita/* 27a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita * Copyright 2015 Google Inc. 37a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita * 47a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita * Use of this source code is governed by a BSD-style license that can be 57a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita * found in the LICENSE file. 67a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita */ 77a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 8ff2742eba814c906686b72abd2d1b3e6b720d784Hal Canary#include "SkTypes.h" 9ff2742eba814c906686b72abd2d1b3e6b720d784Hal Canary 10ff2742eba814c906686b72abd2d1b3e6b720d784Hal Canary#ifdef SK_XML 11ff2742eba814c906686b72abd2d1b3e6b720d784Hal Canary 127a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkCanvas.h" 137a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkData.h" 147a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkDOM.h" 157a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkParse.h" 167a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkStream.h" 177a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkSVGCanvas.h" 187a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkXMLWriter.h" 197a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "Test.h" 207a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 217a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include <string.h> 227a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 237a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalitanamespace { 247a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 257a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalitavoid check_text_node(skiatest::Reporter* reporter, 267a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkDOM& dom, 277a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkDOM::Node* root, 287a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkPoint& offset, 297a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita unsigned scalarsPerPos, 307a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* expected) { 3196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (root == nullptr) { 327a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita ERRORF(reporter, "root element not found."); 337a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita return; 347a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 357a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 367a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkDOM::Node* textElem = dom.getFirstChild(root, "text"); 3796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (textElem == nullptr) { 387a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita ERRORF(reporter, "<text> element not found."); 397a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita return; 407a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 417a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, dom.getType(textElem) == SkDOM::kElement_Type); 427a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 437a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkDOM::Node* textNode= dom.getFirstChild(textElem); 4496fcdcc219d2a0d3579719b84b28bede76efba64halcanary REPORTER_ASSERT(reporter, textNode != nullptr); 4596fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (textNode != nullptr) { 467a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, dom.getType(textNode) == SkDOM::kText_Type); 477a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, strcmp(expected, dom.getName(textNode)) == 0); 487a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 497a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 507a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita int textLen = SkToInt(strlen(expected)); 517a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 527a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* x = dom.findAttr(textElem, "x"); 5396fcdcc219d2a0d3579719b84b28bede76efba64halcanary REPORTER_ASSERT(reporter, x != nullptr); 5496fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (x != nullptr) { 557a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita int xposCount = (scalarsPerPos < 1) ? 1 : textLen; 567a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, SkParse::Count(x) == xposCount); 577a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 587a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkAutoTMalloc<SkScalar> xpos(xposCount); 597a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkParse::FindScalars(x, xpos.get(), xposCount); 607a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita if (scalarsPerPos < 1) { 617a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, xpos[0] == offset.x()); 627a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } else { 637a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (int i = 0; i < xposCount; ++i) { 647a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, xpos[i] == SkIntToScalar(expected[i])); 657a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 667a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 677a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 687a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 697a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* y = dom.findAttr(textElem, "y"); 7096fcdcc219d2a0d3579719b84b28bede76efba64halcanary REPORTER_ASSERT(reporter, y != nullptr); 7196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (y != nullptr) { 727a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita int yposCount = (scalarsPerPos < 2) ? 1 : textLen; 737a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, SkParse::Count(y) == yposCount); 747a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 757a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkAutoTMalloc<SkScalar> ypos(yposCount); 767a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkParse::FindScalars(y, ypos.get(), yposCount); 777a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita if (scalarsPerPos < 2) { 787a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, ypos[0] == offset.y()); 797a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } else { 807a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (int i = 0; i < yposCount; ++i) { 817a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, ypos[i] == -SkIntToScalar(expected[i])); 827a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 837a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 847a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 857a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita} 867a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 877a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalitavoid test_whitespace_pos(skiatest::Reporter* reporter, 887a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* txt, 897a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* expected) { 907a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita size_t len = strlen(txt); 917a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 927a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkDOM dom; 937a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkPaint paint; 947a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkPoint offset = SkPoint::Make(10, 20); 957a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 967a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { 977a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkXMLParserWriter writer(dom.beginParsing()); 985df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer); 997a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita svgCanvas->drawText(txt, len, offset.x(), offset.y(), paint); 1007a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1017a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita check_text_node(reporter, dom, dom.finishParsing(), offset, 0, expected); 1027a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1037a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { 1047a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkAutoTMalloc<SkScalar> xpos(len); 1057a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (int i = 0; i < SkToInt(len); ++i) { 1067a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita xpos[i] = SkIntToScalar(txt[i]); 1077a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1087a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1097a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkXMLParserWriter writer(dom.beginParsing()); 1105df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer); 1117a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita svgCanvas->drawPosTextH(txt, len, xpos, offset.y(), paint); 1127a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1137a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita check_text_node(reporter, dom, dom.finishParsing(), offset, 1, expected); 1147a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1157a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { 1167a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkAutoTMalloc<SkPoint> pos(len); 1177a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (int i = 0; i < SkToInt(len); ++i) { 1187a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita pos[i] = SkPoint::Make(SkIntToScalar(txt[i]), -SkIntToScalar(txt[i])); 1197a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1207a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1217a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkXMLParserWriter writer(dom.beginParsing()); 1225df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer); 1237a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita svgCanvas->drawPosText(txt, len, pos, paint); 1247a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1257a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita check_text_node(reporter, dom, dom.finishParsing(), offset, 2, expected); 1267a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita} 1277a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1287a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita} 1297a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1307a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalitaDEF_TEST(SVGDevice_whitespace_pos, reporter) { 1317a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita static const struct { 1327a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* tst_in; 1337a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* tst_out; 1347a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } tests[] = { 1357a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "abcd" , "abcd" }, 1367a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "ab cd" , "ab cd" }, 1377a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "ab \t\t cd", "ab cd" }, 1387a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { " abcd" , "abcd" }, 1397a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { " abcd" , "abcd" }, 1407a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { " \t\t abcd", "abcd" }, 1417a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "abcd " , "abcd " }, // we allow one trailing whitespace char 1427a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "abcd " , "abcd " }, // because it makes no difference and 1437a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "abcd\t " , "abcd\t" }, // simplifies the implementation 1447a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "\t\t \t ab \t\t \t cd \t\t \t ", "ab cd " }, 1457a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita }; 1467a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1477a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (unsigned i = 0; i < SK_ARRAY_COUNT(tests); ++i) { 1487a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita test_whitespace_pos(reporter, tests[i].tst_in, tests[i].tst_out); 1497a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1507a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita} 151ff2742eba814c906686b72abd2d1b3e6b720d784Hal Canary 152ff2742eba814c906686b72abd2d1b3e6b720d784Hal Canary#endif 153