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 87a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkCanvas.h" 97a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkData.h" 107a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkDOM.h" 117a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkParse.h" 127a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkStream.h" 137a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkSVGCanvas.h" 147a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "SkXMLWriter.h" 157a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include "Test.h" 167a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 177a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita#include <string.h> 187a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 197a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalitanamespace { 207a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 217a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalitavoid check_text_node(skiatest::Reporter* reporter, 227a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkDOM& dom, 237a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkDOM::Node* root, 247a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkPoint& offset, 257a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita unsigned scalarsPerPos, 267a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* expected) { 2796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (root == nullptr) { 287a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita ERRORF(reporter, "root element not found."); 297a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita return; 307a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 317a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 327a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkDOM::Node* textElem = dom.getFirstChild(root, "text"); 3396fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (textElem == nullptr) { 347a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita ERRORF(reporter, "<text> element not found."); 357a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita return; 367a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 377a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, dom.getType(textElem) == SkDOM::kElement_Type); 387a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 397a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const SkDOM::Node* textNode= dom.getFirstChild(textElem); 4096fcdcc219d2a0d3579719b84b28bede76efba64halcanary REPORTER_ASSERT(reporter, textNode != nullptr); 4196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (textNode != nullptr) { 427a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, dom.getType(textNode) == SkDOM::kText_Type); 437a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, strcmp(expected, dom.getName(textNode)) == 0); 447a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 457a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 467a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita int textLen = SkToInt(strlen(expected)); 477a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 487a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* x = dom.findAttr(textElem, "x"); 4996fcdcc219d2a0d3579719b84b28bede76efba64halcanary REPORTER_ASSERT(reporter, x != nullptr); 5096fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (x != nullptr) { 517a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita int xposCount = (scalarsPerPos < 1) ? 1 : textLen; 527a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, SkParse::Count(x) == xposCount); 537a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 547a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkAutoTMalloc<SkScalar> xpos(xposCount); 557a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkParse::FindScalars(x, xpos.get(), xposCount); 567a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita if (scalarsPerPos < 1) { 577a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, xpos[0] == offset.x()); 587a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } else { 597a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (int i = 0; i < xposCount; ++i) { 607a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, xpos[i] == SkIntToScalar(expected[i])); 617a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 627a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 637a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 647a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 657a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* y = dom.findAttr(textElem, "y"); 6696fcdcc219d2a0d3579719b84b28bede76efba64halcanary REPORTER_ASSERT(reporter, y != nullptr); 6796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (y != nullptr) { 687a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita int yposCount = (scalarsPerPos < 2) ? 1 : textLen; 697a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, SkParse::Count(y) == yposCount); 707a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 717a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkAutoTMalloc<SkScalar> ypos(yposCount); 727a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkParse::FindScalars(y, ypos.get(), yposCount); 737a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita if (scalarsPerPos < 2) { 747a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, ypos[0] == offset.y()); 757a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } else { 767a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (int i = 0; i < yposCount; ++i) { 777a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita REPORTER_ASSERT(reporter, ypos[i] == -SkIntToScalar(expected[i])); 787a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 797a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 807a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 817a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita} 827a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 837a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalitavoid test_whitespace_pos(skiatest::Reporter* reporter, 847a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* txt, 857a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* expected) { 867a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita size_t len = strlen(txt); 877a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 887a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkDOM dom; 897a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkPaint paint; 907a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkPoint offset = SkPoint::Make(10, 20); 917a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 927a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { 937a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkXMLParserWriter writer(dom.beginParsing()); 945df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer); 957a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita svgCanvas->drawText(txt, len, offset.x(), offset.y(), paint); 967a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 977a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita check_text_node(reporter, dom, dom.finishParsing(), offset, 0, expected); 987a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 997a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { 1007a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkAutoTMalloc<SkScalar> xpos(len); 1017a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (int i = 0; i < SkToInt(len); ++i) { 1027a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita xpos[i] = SkIntToScalar(txt[i]); 1037a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1047a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1057a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkXMLParserWriter writer(dom.beginParsing()); 1065df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer); 1077a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita svgCanvas->drawPosTextH(txt, len, xpos, offset.y(), paint); 1087a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1097a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita check_text_node(reporter, dom, dom.finishParsing(), offset, 1, expected); 1107a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1117a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { 1127a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkAutoTMalloc<SkPoint> pos(len); 1137a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (int i = 0; i < SkToInt(len); ++i) { 1147a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita pos[i] = SkPoint::Make(SkIntToScalar(txt[i]), -SkIntToScalar(txt[i])); 1157a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1167a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1177a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita SkXMLParserWriter writer(dom.beginParsing()); 1185df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer); 1197a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita svgCanvas->drawPosText(txt, len, pos, paint); 1207a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1217a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita check_text_node(reporter, dom, dom.finishParsing(), offset, 2, expected); 1227a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita} 1237a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1247a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita} 1257a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1267a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalitaDEF_TEST(SVGDevice_whitespace_pos, reporter) { 1277a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita static const struct { 1287a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* tst_in; 1297a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita const char* tst_out; 1307a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } tests[] = { 1317a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "abcd" , "abcd" }, 1327a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "ab cd" , "ab cd" }, 1337a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "ab \t\t cd", "ab cd" }, 1347a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { " abcd" , "abcd" }, 1357a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { " abcd" , "abcd" }, 1367a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { " \t\t abcd", "abcd" }, 1377a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "abcd " , "abcd " }, // we allow one trailing whitespace char 1387a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "abcd " , "abcd " }, // because it makes no difference and 1397a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "abcd\t " , "abcd\t" }, // simplifies the implementation 1407a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita { "\t\t \t ab \t\t \t cd \t\t \t ", "ab cd " }, 1417a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita }; 1427a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita 1437a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita for (unsigned i = 0; i < SK_ARRAY_COUNT(tests); ++i) { 1447a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita test_whitespace_pos(reporter, tests[i].tst_in, tests[i].tst_out); 1457a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita } 1467a048690d3cb6b3c1bdef594c3bd4b66f6b400c1fmalita} 147