1 /*
2 * Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "TestSvgParser.h"
20
21
22 #include <QPainterPath>
23 #include <QTest>
24 #include <svg/SvgUtil.h>
25 #include <KoShapeStrokeModel.h>
26
27
28 #include "SvgParserTestingUtils.h"
29
30 #include "../../sdk/tests/qimage_test_util.h"
31
32 #ifdef USE_ROUND_TRIP
33 #include "SvgWriter.h"
34 #include <QBuffer>
35 #include <QDomDocument>
36 #endif
37
38
testUnitPx()39 void TestSvgParser::testUnitPx()
40 {
41 const QString data =
42 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
43 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
44
45 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
46 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
47
48 "</svg>";
49
50 SvgTester t (data);
51 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
52 t.run();
53
54 KoShape *shape = t.findShape("testRect");
55 QVERIFY(shape);
56
57 QCOMPARE(shape->boundingRect(), QRectF(0,0,10,20));
58 QCOMPARE(shape->absoluteTransformation(), QTransform());
59 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
60 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(0,0));
61 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(10,20));
62 }
63
testUnitPxResolution()64 void TestSvgParser::testUnitPxResolution()
65 {
66 const QString data =
67 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
68 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
69
70 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
71 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
72
73 "</svg>";
74
75 SvgTester t (data);
76 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 144 /* ppi */);
77 t.run();
78
79 KoShape *shape = t.findShape("testRect");
80 QVERIFY(shape);
81
82 QCOMPARE(shape->boundingRect(), QRectF(0,0,5,10));
83 QCOMPARE(shape->absoluteTransformation(), QTransform::fromScale(0.5, 0.5));
84 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
85 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(0,0));
86 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(5,10));
87 }
88
89
testUnitPt()90 void TestSvgParser::testUnitPt()
91 {
92 const QString data =
93 "<svg width=\"10pt\" height=\"20pt\" viewBox=\"0 0 10 20\""
94 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
95
96 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
97 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
98
99 "</svg>";
100
101 SvgTester t (data);
102 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 666 /* ppi */);
103 t.run();
104
105 KoShape *shape = t.findShape("testRect");
106 QVERIFY(shape);
107
108 QCOMPARE(shape->boundingRect(), kisGrowRect(QRectF(0,0,10,20), 0));
109 QCOMPARE(shape->absoluteTransformation(), QTransform());
110 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
111 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(0,0));
112 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(10,20));
113 }
114
testUnitIn()115 void TestSvgParser::testUnitIn()
116 {
117 const QString data =
118 "<svg width=\"10in\" height=\"20in\" viewBox=\"0 0 10 20\""
119 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
120
121 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
122 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
123
124 "</svg>";
125
126 SvgTester t (data);
127 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 666 /* ppi */);
128 t.run();
129
130 KoShape *shape = t.findShape("testRect");
131 QVERIFY(shape);
132
133 QCOMPARE(shape->boundingRect(), QRectF(0,0,720,1440));
134 QCOMPARE(shape->absoluteTransformation(), QTransform::fromScale(72, 72));
135 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
136 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(0,0));
137 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(720,1440));
138 }
139
testUnitPercentInitial()140 void TestSvgParser::testUnitPercentInitial()
141 {
142 const QString data =
143 "<svg width=\"12.5%\" height=\"25%\" viewBox=\"0 0 10 20\""
144 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
145
146 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
147 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
148
149 "</svg>";
150
151 SvgTester t (data);
152 t.parser.setResolution(QRectF(0, 0, 80, 80) /* px */, 144 /* ppi */);
153 t.run();
154
155 KoShape *shape = t.findShape("testRect");
156 QVERIFY(shape);
157
158 QCOMPARE(shape->boundingRect(), QRectF(0,0,5,10));
159 QCOMPARE(shape->absoluteTransformation(), QTransform::fromScale(0.5, 0.5));
160 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
161 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(0,0));
162 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(5,10));
163 }
164
testScalingViewport()165 void TestSvgParser::testScalingViewport()
166 {
167 const QString data =
168 "<svg width=\"10px\" height=\"20px\" viewBox=\"60 70 20 40\""
169 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
170
171 "<rect id=\"testRect\" x=\"64\" y=\"74\" width=\"12\" height=\"32\""
172 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
173
174 "</svg>";
175
176 SvgTester t (data);
177 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
178 t.run();
179
180 KoShape *shape = t.findShape("testRect");
181 QVERIFY(shape);
182
183 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(4, 4) * QTransform::fromScale(0.5, 0.5));
184 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
185 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(2,2));
186 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(8,2));
187 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(2,18));
188 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(8,18));
189 }
190
testScalingViewportKeepMeet1()191 void TestSvgParser::testScalingViewportKeepMeet1()
192 {
193 const QString data =
194 "<svg width=\"10px\" height=\"30px\" viewBox=\"60 70 20 40\""
195 " preserveAspectRatio=\" xMinYMin meet\""
196 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
197
198 "<rect id=\"testRect\" x=\"64\" y=\"74\" width=\"12\" height=\"32\""
199 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
200
201 "</svg>";
202
203 SvgTester t (data);
204 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
205 t.run();
206
207 KoShape *shape = t.findShape("testRect");
208 QVERIFY(shape);
209
210 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(4, 4) * QTransform::fromScale(0.5, 0.5));
211 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
212 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(2,2));
213 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(8,2));
214 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(2,18));
215 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(8,18));
216 }
217
testScalingViewportKeepMeet2()218 void TestSvgParser::testScalingViewportKeepMeet2()
219 {
220 const QString data =
221 "<svg width=\"15px\" height=\"20px\" viewBox=\"60 70 20 40\""
222 " preserveAspectRatio=\" xMinYMin meet\""
223 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
224
225 "<rect id=\"testRect\" x=\"64\" y=\"74\" width=\"12\" height=\"32\""
226 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
227
228 "</svg>";
229
230 SvgTester t (data);
231 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
232 t.run();
233
234 KoShape *shape = t.findShape("testRect");
235 QVERIFY(shape);
236
237 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(4, 4) * QTransform::fromScale(0.5, 0.5));
238 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
239 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(2,2));
240 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(8,2));
241 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(2,18));
242 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(8,18));
243 }
244
testScalingViewportKeepMeetAlign()245 void TestSvgParser::testScalingViewportKeepMeetAlign()
246 {
247 const QString data =
248 "<svg width=\"10px\" height=\"30px\" viewBox=\"60 70 20 40\""
249 " preserveAspectRatio=\" xMaxYMax meet\""
250 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
251
252 "<rect id=\"testRect\" x=\"64\" y=\"74\" width=\"12\" height=\"32\""
253 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
254
255 "</svg>";
256
257 SvgTester t (data);
258 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
259 t.run();
260
261 KoShape *shape = t.findShape("testRect");
262 QVERIFY(shape);
263
264 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(4, 24) * QTransform::fromScale(0.5, 0.5));
265 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
266 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(2,12));
267 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(8,12));
268 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(2,28));
269 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(8,28));
270 }
271
testScalingViewportKeepSlice1()272 void TestSvgParser::testScalingViewportKeepSlice1()
273 {
274 const QString data =
275 "<svg width=\"5px\" height=\"20px\" viewBox=\"60 70 20 40\""
276 " preserveAspectRatio=\" xMinYMin slice\""
277 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
278
279 "<rect id=\"testRect\" x=\"64\" y=\"74\" width=\"12\" height=\"32\""
280 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
281
282 "</svg>";
283
284 SvgTester t (data);
285 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
286 t.run();
287
288 KoShape *shape = t.findShape("testRect");
289 QVERIFY(shape);
290
291 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(4, 4) * QTransform::fromScale(0.5, 0.5));
292 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
293 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(2,2));
294 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(8,2));
295 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(2,18));
296 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(8,18));
297 }
298
testScalingViewportKeepSlice2()299 void TestSvgParser::testScalingViewportKeepSlice2()
300 {
301 const QString data =
302 "<svg width=\"10px\" height=\"15px\" viewBox=\"60 70 20 40\""
303 " preserveAspectRatio=\" xMinYMin slice\""
304 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
305
306 "<rect id=\"testRect\" x=\"64\" y=\"74\" width=\"12\" height=\"32\""
307 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
308
309 "</svg>";
310
311 SvgTester t (data);
312 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
313 t.run();
314
315 KoShape *shape = t.findShape("testRect");
316 QVERIFY(shape);
317
318 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(4, 4) * QTransform::fromScale(0.5, 0.5));
319 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
320 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(2,2));
321 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(8,2));
322 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(2,18));
323 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(8,18));
324 }
325
testScalingViewportResolution()326 void TestSvgParser::testScalingViewportResolution()
327 {
328 const QString data =
329 "<svg width=\"10px\" height=\"20px\" viewBox=\"60 70 20 40\""
330 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
331
332 "<rect id=\"testRect\" x=\"64\" y=\"74\" width=\"12\" height=\"32\""
333 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
334
335 "</svg>";
336
337 SvgTester t (data);
338 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 144 /* ppi */);
339 t.run();
340
341 KoShape *shape = t.findShape("testRect");
342 QVERIFY(shape);
343
344 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(4, 4) * QTransform::fromScale(0.25, 0.25));
345 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
346 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(1,1));
347 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(4,1));
348 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(1,9));
349 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(4,9));
350 }
351
testScalingViewportPercentInternal()352 void TestSvgParser::testScalingViewportPercentInternal()
353 {
354 const QString data =
355 "<svg width=\"10px\" height=\"20px\" viewBox=\"60 70 20 40\""
356 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
357
358 "<rect id=\"testRect\" x=\"320%\" y=\"185%\" width=\"60%\" height=\"80%\""
359 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
360
361 "</svg>";
362
363 SvgTester t (data);
364 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
365 t.run();
366
367 KoShape *shape = t.findShape("testRect");
368 QVERIFY(shape);
369
370 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(4, 4) * QTransform::fromScale(0.5, 0.5));
371 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
372 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(2,2));
373 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(8,2));
374 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(2,18));
375 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(8,18));
376 }
377
378
testParsePreserveAspectRatio()379 void TestSvgParser::testParsePreserveAspectRatio()
380 {
381 {
382 SvgUtil::PreserveAspectRatioParser p(" defer xMinYMax meet");
383 QCOMPARE(p.defer, true);
384 QCOMPARE(p.mode, Qt::KeepAspectRatio);
385 QCOMPARE(p.xAlignment, SvgUtil::PreserveAspectRatioParser::Min);
386 QCOMPARE(p.yAlignment, SvgUtil::PreserveAspectRatioParser::Max);
387 }
388
389 {
390 SvgUtil::PreserveAspectRatioParser p(" xMinYMid slice");
391 QCOMPARE(p.defer, false);
392 QCOMPARE(p.mode, Qt::KeepAspectRatioByExpanding);
393 QCOMPARE(p.xAlignment, SvgUtil::PreserveAspectRatioParser::Min);
394 QCOMPARE(p.yAlignment, SvgUtil::PreserveAspectRatioParser::Middle);
395 }
396
397 {
398 SvgUtil::PreserveAspectRatioParser p(" xmidYMid ");
399 QCOMPARE(p.defer, false);
400 QCOMPARE(p.mode, Qt::KeepAspectRatio);
401 QCOMPARE(p.xAlignment, SvgUtil::PreserveAspectRatioParser::Middle);
402 QCOMPARE(p.yAlignment, SvgUtil::PreserveAspectRatioParser::Middle);
403 }
404
405 {
406 SvgUtil::PreserveAspectRatioParser p(" NoNe ");
407 QCOMPARE(p.defer, false);
408 QCOMPARE(p.mode, Qt::IgnoreAspectRatio);
409 QCOMPARE(p.xAlignment, SvgUtil::PreserveAspectRatioParser::Min);
410 QCOMPARE(p.yAlignment, SvgUtil::PreserveAspectRatioParser::Min);
411 }
412
413 {
414 SvgUtil::PreserveAspectRatioParser p("defer NoNe ");
415 QCOMPARE(p.defer, true);
416 QCOMPARE(p.mode, Qt::IgnoreAspectRatio);
417 QCOMPARE(p.xAlignment, SvgUtil::PreserveAspectRatioParser::Min);
418 QCOMPARE(p.yAlignment, SvgUtil::PreserveAspectRatioParser::Min);
419 }
420
421 {
422 SvgUtil::PreserveAspectRatioParser p("sweet brown fox jumps over a nice svg file");
423 QCOMPARE(p.defer, false);
424 QCOMPARE(p.mode, Qt::IgnoreAspectRatio);
425 QCOMPARE(p.xAlignment, SvgUtil::PreserveAspectRatioParser::Min);
426 QCOMPARE(p.yAlignment, SvgUtil::PreserveAspectRatioParser::Min);
427 }
428 }
429
430 #include "parsers/SvgTransformParser.h"
431
testParseTransform()432 void TestSvgParser::testParseTransform()
433 {
434 {
435 QString str("translate(-111.0, 33) translate(-111.0, 33) matrix (1 1 0 0 1, 3), translate(1)"
436 "scale(0.5) rotate(10) rotate(10, 3 3) skewX(1) skewY(2)");
437
438 SvgTransformParser p(str);
439 QCOMPARE(p.isValid(), true);
440 }
441
442 {
443 // forget about one brace
444 QString str("translate(-111.0, 33) translate(-111.0, 33 matrix (1 1 0 0 1, 3), translate(1)"
445 "scale(0.5) rotate(10) rotate(10, 3 3) skewX(1) skewY(2)");
446
447 SvgTransformParser p(str);
448 QCOMPARE(p.isValid(), false);
449 }
450
451 {
452 SvgTransformParser p("translate(100, 50)");
453 QCOMPARE(p.isValid(), true);
454 QCOMPARE(p.transform(), QTransform::fromTranslate(100, 50));
455 }
456
457 {
458 SvgTransformParser p("translate(100 50)");
459 QCOMPARE(p.isValid(), true);
460 QCOMPARE(p.transform(), QTransform::fromTranslate(100, 50));
461 }
462
463 {
464 SvgTransformParser p("translate(100)");
465 QCOMPARE(p.isValid(), true);
466 QCOMPARE(p.transform(), QTransform::fromTranslate(100, 0));
467 }
468
469 {
470 SvgTransformParser p("scale(100, 50)");
471 QCOMPARE(p.isValid(), true);
472 QCOMPARE(p.transform(), QTransform::fromScale(100, 50));
473 }
474
475 {
476 SvgTransformParser p("scale(100)");
477 QCOMPARE(p.isValid(), true);
478 QCOMPARE(p.transform(), QTransform::fromScale(100, 100));
479 }
480
481 {
482 SvgTransformParser p("rotate(90 70 74.0)");
483 QCOMPARE(p.isValid(), true);
484 QTransform t;
485 t.rotate(90);
486 t = QTransform::fromTranslate(-70, -74) * t * QTransform::fromTranslate(70, 74);
487 qDebug() << ppVar(p.transform());
488 QCOMPARE(p.transform(), t);
489 }
490 }
491
testScalingViewportTransform()492 void TestSvgParser::testScalingViewportTransform()
493 {
494 /**
495 * Note: 'transform' affects all the attributes of the *current*
496 * element, while 'viewBox' affects only the descendants!
497 */
498
499 const QString data =
500 "<svg width=\"5px\" height=\"10px\" viewBox=\"60 70 20 40\""
501 " transform=\"scale(2)\""
502 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
503
504 "<rect id=\"testRect\" x=\"64\" y=\"74\" width=\"12\" height=\"32\""
505 " transform=\"translate(6)\""
506 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
507
508 "</svg>";
509
510 SvgTester t (data);
511 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
512 t.run();
513
514 KoShape *shape = t.findShape("testRect");
515 QVERIFY(shape);
516
517 QCOMPARE(shape->absoluteTransformation(), QTransform::fromTranslate(10, 4) * QTransform::fromScale(0.5, 0.5));
518 QCOMPARE(shape->outlineRect(), QRectF(0,0,12,32));
519 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(5,2));
520 QCOMPARE(shape->absolutePosition(KoFlake::TopRight), QPointF(11,2));
521 QCOMPARE(shape->absolutePosition(KoFlake::BottomLeft), QPointF(5,18));
522 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(11,18));
523 }
524
testTransformNesting()525 void TestSvgParser::testTransformNesting()
526 {
527 const QString data =
528 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
529 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
530
531 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
532 " transform=\"translate(10,10), scale(2, 1)\""
533 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
534
535 "</svg>";
536
537 SvgTester t (data);
538 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
539 t.run();
540
541 KoShape *shape = t.findShape("testRect");
542 QVERIFY(shape);
543
544 QCOMPARE(shape->boundingRect(), QRectF(10,10,20,20));
545 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
546 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(10,10));
547 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(30,30));
548 }
549
testTransformNestingGroups()550 void TestSvgParser::testTransformNestingGroups()
551 {
552 const QString data =
553 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
554 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
555
556 "<g transform=\"translate(10,10)\">"
557 " <rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
558 " transform=\"scale(2, 1)\""
559 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
560 "</g>"
561
562 "</svg>";
563
564 SvgTester t (data);
565 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
566 t.run();
567
568 KoShape *shape = t.findShape("testRect");
569 QVERIFY(shape);
570
571 QCOMPARE(shape->boundingRect(), QRectF(10,10, 20, 20));
572 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
573 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(10,10));
574 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(30,30));
575 }
576
testTransformRotation1()577 void TestSvgParser::testTransformRotation1()
578 {
579 const QString data =
580 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
581 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
582
583 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
584 " transform=\"rotate(90)\""
585 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
586
587 "</svg>";
588
589 SvgTester t (data);
590 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
591 t.run();
592
593 KoShape *shape = t.findShape("testRect");
594 QVERIFY(shape);
595
596 QCOMPARE(shape->boundingRect(), QRectF(-20,0,20,10));
597 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
598 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(0,0));
599 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(-20,10));
600 }
601
testTransformRotation2()602 void TestSvgParser::testTransformRotation2()
603 {
604 const QString data =
605 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
606 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
607
608 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
609 " transform=\"rotate(-90 10 5)\""
610 " fill=\"none\" stroke=\"none\" stroke-width=\"10\"/>"
611
612 "</svg>";
613
614 SvgTester t (data);
615 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 72 /* ppi */);
616 t.run();
617
618 KoShape *shape = t.findShape("testRect");
619 QVERIFY(shape);
620
621 QCOMPARE(shape->boundingRect(), QRectF(5,5,20,10));
622 QCOMPARE(shape->outlineRect(), QRectF(0,0,10,20));
623 QCOMPARE(shape->absolutePosition(KoFlake::TopLeft), QPointF(5,15));
624 QCOMPARE(shape->absolutePosition(KoFlake::BottomRight), QPointF(25,5));
625 }
626
627
628
testRenderStrokeNone()629 void TestSvgParser::testRenderStrokeNone()
630 {
631 const QString data =
632 "<svg width=\"30px\" height=\"30px\""
633 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
634
635 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
636 " fill=\"cyan\" stroke=\"none\" stroke-width=\"1\"/>"
637
638 "</svg>";
639
640 SvgRenderTester t (data);
641 t.test_standard_30px_72ppi("stroke_none");
642 }
643
testRenderStrokeColorName()644 void TestSvgParser::testRenderStrokeColorName()
645 {
646 const QString data =
647 "<svg width=\"30px\" height=\"30px\""
648 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
649
650 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
651 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"1\"/>"
652
653 "</svg>";
654
655 SvgRenderTester t (data);
656 t.test_standard_30px_72ppi("stroke_blue");
657 }
658
testRenderStrokeColorHex3()659 void TestSvgParser::testRenderStrokeColorHex3()
660 {
661 const QString data =
662 "<svg width=\"30px\" height=\"30px\""
663 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
664
665 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
666 " fill=\"cyan\" stroke=\"#00f\" stroke-width=\"1\"/>"
667
668 "</svg>";
669
670 SvgRenderTester t (data);
671 t.test_standard_30px_72ppi("stroke_blue");
672 }
673
testRenderStrokeColorHex6()674 void TestSvgParser::testRenderStrokeColorHex6()
675 {
676 const QString data =
677 "<svg width=\"30px\" height=\"30px\""
678 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
679
680 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
681 " fill=\"cyan\" stroke=\"#0000ff\" stroke-width=\"1\"/>"
682
683 "</svg>";
684
685 SvgRenderTester t (data);
686 t.test_standard_30px_72ppi("stroke_blue");
687 }
688
testRenderStrokeColorRgbValues()689 void TestSvgParser::testRenderStrokeColorRgbValues()
690 {
691 const QString data =
692 "<svg width=\"30px\" height=\"30px\""
693 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
694
695 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
696 " fill=\"cyan\" stroke=\"rgb(0, 0 ,255)\" stroke-width=\"1\"/>"
697
698 "</svg>";
699
700 SvgRenderTester t (data);
701 t.test_standard_30px_72ppi("stroke_blue");
702 }
703
testRenderStrokeColorRgbPercent()704 void TestSvgParser::testRenderStrokeColorRgbPercent()
705 {
706 const QString data =
707 "<svg width=\"30px\" height=\"30px\""
708 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
709
710 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
711 " fill=\"cyan\" stroke=\"rgb(0, 0 ,100%)\" stroke-width=\"1\"/>"
712
713 "</svg>";
714
715 SvgRenderTester t (data);
716 t.test_standard_30px_72ppi("stroke_blue");
717 }
718
testRenderStrokeColorCurrent()719 void TestSvgParser::testRenderStrokeColorCurrent()
720 {
721 const QString data =
722 "<svg width=\"30px\" height=\"30px\""
723 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
724
725 "<g color=\"blue\">"
726 " <rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
727 " fill=\"cyan\" stroke=\"currentColor\" stroke-width=\"1\"/>"
728 "</g>"
729
730 "</svg>";
731
732 SvgRenderTester t (data);
733 t.test_standard_30px_72ppi("stroke_blue");
734 }
735
testRenderStrokeColorNonexistentIri()736 void TestSvgParser::testRenderStrokeColorNonexistentIri()
737 {
738 const QString data =
739 "<svg width=\"30px\" height=\"30px\""
740 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
741
742 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
743 " fill=\"cyan\" stroke=\"url(notexists) blue\" stroke-width=\"1\"/>"
744
745 "</svg>";
746
747 SvgRenderTester t (data);
748 t.test_standard_30px_72ppi("stroke_blue");
749 }
750
testRenderStrokeWidth()751 void TestSvgParser::testRenderStrokeWidth()
752 {
753 const QString data =
754 "<svg width=\"30px\" height=\"30px\""
755 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
756
757 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
758 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"2\"/>"
759
760 "</svg>";
761
762 SvgRenderTester t (data);
763 t.test_standard_30px_72ppi("stroke_blue_width_2");
764 }
765
testRenderStrokeZeroWidth()766 void TestSvgParser::testRenderStrokeZeroWidth()
767 {
768 const QString data =
769 "<svg width=\"30px\" height=\"30px\""
770 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
771
772 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
773 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"0\"/>"
774
775 "</svg>";
776
777 SvgRenderTester t (data);
778 t.test_standard_30px_72ppi("stroke_none");
779 }
780
testRenderStrokeOpacity()781 void TestSvgParser::testRenderStrokeOpacity()
782 {
783 const QString data =
784 "<svg width=\"30px\" height=\"30px\""
785 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
786
787 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
788 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"4\" stroke-opacity=\"0.3\"/>"
789
790 "</svg>";
791
792 SvgRenderTester t (data);
793 t.setFuzzyThreshold(1);
794 t.test_standard_30px_72ppi("stroke_blue_0_3_opacity");
795 }
796
testRenderStrokeJointRound()797 void TestSvgParser::testRenderStrokeJointRound()
798 {
799 const QString data =
800 "<svg width=\"30px\" height=\"30px\""
801 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
802
803 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
804 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"4\" stroke-linejoin=\"round\"/>"
805
806 "</svg>";
807
808 SvgRenderTester t (data);
809 t.test_standard_30px_72ppi("stroke_blue_join_round");
810 }
811
testRenderStrokeLinecap()812 void TestSvgParser::testRenderStrokeLinecap()
813 {
814 const QString data =
815 "<svg width=\"30px\" height=\"30px\""
816 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
817
818 "<polyline id=\"testRect\" points=\"5,5 10,25 15,5\""
819 " fill=\"none\" stroke=\"blue\" stroke-width=\"5\" stroke-linecap=\"round\"/>"
820
821 "</svg>";
822
823 SvgRenderTester t (data);
824 t.test_standard_30px_72ppi("stroke_blue_linecap_round");
825 }
826
testRenderStrokeMiterLimit()827 void TestSvgParser::testRenderStrokeMiterLimit()
828 {
829 // TODO:seems like doesn't work!!
830 qWarning() << "WARNING: Miter limit test is skipped!!!";
831 return;
832
833 const QString data =
834 "<svg width=\"30px\" height=\"30px\""
835 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
836
837 "<polyline id=\"testRect\" points=\"5,5 10,25 15,5\""
838 " fill=\"none\" stroke=\"blue\" stroke-width=\"5\" stroke-miterlimit=\"1.114\"/>"
839
840 "</svg>";
841
842 SvgRenderTester t (data);
843 t.test_standard_30px_72ppi("stroke_blue_miter_limit");
844 }
845
testRenderStrokeDashArrayEven()846 void TestSvgParser::testRenderStrokeDashArrayEven()
847 {
848 const QString data =
849 "<svg width=\"30px\" height=\"30px\""
850 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
851
852 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
853 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"2\" stroke-dasharray=\"3 2, 5 2\"/>"
854
855 "</svg>";
856
857 SvgRenderTester t (data);
858 t.test_standard_30px_72ppi("stroke_blue_dasharray_even");
859 }
860
testRenderStrokeDashArrayEvenOffset()861 void TestSvgParser::testRenderStrokeDashArrayEvenOffset()
862 {
863 const QString data =
864 "<svg width=\"30px\" height=\"30px\""
865 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
866
867 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
868 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"2\" stroke-dasharray=\"3 2, 5 2\""
869 " stroke-dashoffset=\"1\"/>"
870
871 "</svg>";
872
873 SvgRenderTester t (data);
874 t.test_standard_30px_72ppi("stroke_blue_dasharray_even_offset");
875 }
876
testRenderStrokeDashArrayOdd()877 void TestSvgParser::testRenderStrokeDashArrayOdd()
878 {
879 // SVG 1.1: if the dasharray is odd, repeat it
880
881 const QString data =
882 "<svg width=\"30px\" height=\"30px\""
883 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
884
885 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
886 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"2\" stroke-dasharray=\"3 2, 5\"/>"
887
888 "</svg>";
889
890 SvgRenderTester t (data);
891 t.test_standard_30px_72ppi("stroke_blue_dasharray_odd");
892 }
893
testRenderStrokeDashArrayRelative()894 void TestSvgParser::testRenderStrokeDashArrayRelative()
895 {
896 // SVG 1.1: relative to view box
897 // (40 x 50) * sqrt(2) => dash length = 5 px
898
899 const QString data =
900 "<svg width=\"42.4264px\" height=\"56.56854px\""
901 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
902
903 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
904 " fill=\"cyan\" stroke=\"blue\" stroke-width=\"2\" stroke-dasharray=\"10% 10%\"/>"
905
906 "</svg>";
907
908 SvgRenderTester t (data);
909 t.test_standard_30px_72ppi("stroke_blue_dasharray_relative");
910 }
911
testRenderFillDefault()912 void TestSvgParser::testRenderFillDefault()
913 {
914 const QString data =
915 "<svg width=\"30px\" height=\"30px\""
916 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
917
918 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\"/>"
919
920 "</svg>";
921
922 SvgRenderTester t (data);
923 t.test_standard_30px_72ppi("fill_black");
924 }
925
testRenderFillRuleNonZero()926 void TestSvgParser::testRenderFillRuleNonZero()
927 {
928 const QString data =
929 "<svg width=\"30px\" height=\"30px\""
930 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
931
932 "<polyline id=\"testRect\" points=\"5,5 15,11 15,19 5,25 5,19 15,5 15,25 5,11 5,5\""
933 " fill=\"black\" fill-rule=\"nonzero\"/>"
934
935 "</svg>";
936
937 SvgRenderTester t (data);
938 t.test_standard_30px_72ppi("fill_non_zero");
939 }
940
testRenderFillRuleEvenOdd()941 void TestSvgParser::testRenderFillRuleEvenOdd()
942 {
943 const QString data =
944 "<svg width=\"30px\" height=\"30px\""
945 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
946
947 "<polyline id=\"testRect\" points=\"5,5 15,11 15,19 5,25 5,19 15,5 15,25 5,11 5,5\""
948 " fill=\"black\" fill-rule=\"evenodd\"/>"
949
950 "</svg>";
951
952 SvgRenderTester t (data);
953 t.test_standard_30px_72ppi("fill_even_odd");
954 }
955
testRenderFillOpacity()956 void TestSvgParser::testRenderFillOpacity()
957 {
958 const QString data =
959 "<svg width=\"30px\" height=\"30px\""
960 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
961
962 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
963 " fill=\"cyan\" fill-opacity=\"0.3\"/>"
964
965 "</svg>";
966
967 SvgRenderTester t (data);
968 t.setFuzzyThreshold(1);
969 t.test_standard_30px_72ppi("fill_opacity_0_3");
970 }
971
testRenderDisplayAttribute()972 void TestSvgParser::testRenderDisplayAttribute()
973 {
974 const QString data =
975 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
976 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
977
978 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
979 " fill=\"black\" display=\"none\"/>"
980
981 "</svg>";
982
983 SvgTester t (data);
984 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 144 /* ppi */);
985 t.run();
986
987 KoShape *shape = t.findShape("testRect");
988 QVERIFY(shape);
989
990 QCOMPARE(shape->isVisible(), false);
991 }
992
testRenderVisibilityAttribute()993 void TestSvgParser::testRenderVisibilityAttribute()
994 {
995 {
996 const QString data =
997 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
998 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
999
1000 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
1001 " fill=\"black\" visibility=\"visible\"/>"
1002
1003 "</svg>";
1004
1005 SvgTester t (data);
1006 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 144 /* ppi */);
1007 t.run();
1008
1009 KoShape *shape = t.findShape("testRect");
1010 QVERIFY(shape);
1011
1012 QCOMPARE(shape->isVisible(), true);
1013 }
1014
1015 {
1016 const QString data =
1017 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
1018 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1019
1020 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
1021 " fill=\"black\" visibility=\"hidden\"/>"
1022
1023 "</svg>";
1024
1025 SvgTester t (data);
1026 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 144 /* ppi */);
1027 t.run();
1028
1029 KoShape *shape = t.findShape("testRect");
1030 QVERIFY(shape);
1031
1032 QCOMPARE(shape->isVisible(), false);
1033 }
1034
1035 {
1036 const QString data =
1037 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
1038 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1039
1040 "<rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
1041 " fill=\"black\" visibility=\"collapse\"/>"
1042
1043 "</svg>";
1044
1045 SvgTester t (data);
1046 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 144 /* ppi */);
1047 t.run();
1048
1049 KoShape *shape = t.findShape("testRect");
1050 QVERIFY(shape);
1051
1052 QCOMPARE(shape->isVisible(), false);
1053 }
1054 }
1055
testRenderVisibilityInheritance()1056 void TestSvgParser::testRenderVisibilityInheritance()
1057 {
1058 const QString data =
1059 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
1060 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1061
1062 "<g visibility=\"none\">"
1063 " <rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
1064 " fill=\"black\" visibility=\"visible\"/>"
1065 "</g>"
1066
1067 "</svg>";
1068
1069 SvgTester t (data);
1070 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 144 /* ppi */);
1071 t.run();
1072
1073 KoShape *shape = t.findShape("testRect");
1074 QVERIFY(shape);
1075
1076 QCOMPARE(shape->isVisible(false), true);
1077 QCOMPARE(shape->isVisible(true), false);
1078 }
1079
testRenderDisplayInheritance()1080 void TestSvgParser::testRenderDisplayInheritance()
1081 {
1082 const QString data =
1083 "<svg width=\"10px\" height=\"20px\" viewBox=\"0 0 10 20\""
1084 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1085
1086 "<g display=\"none\">"
1087 " <rect id=\"testRect\" x=\"0\" y=\"0\" width=\"10\" height=\"20\""
1088 " fill=\"black\" visibility=\"visible\"/>"
1089 "</g>"
1090
1091 "</svg>";
1092
1093 SvgTester t (data);
1094 t.parser.setResolution(QRectF(0, 0, 600, 400) /* px */, 144 /* ppi */);
1095 t.run();
1096
1097 KoShape *shape = t.findShape("testRect");
1098 QVERIFY(shape);
1099
1100 QCOMPARE(shape->isVisible(false), true);
1101 QEXPECT_FAIL("", "TODO: Fix 'display' attribute not to be inherited in shapes hierarchy!", Continue);
1102 QCOMPARE(shape->isVisible(true), true);
1103 }
1104
testRenderStrokeWithInlineStyle()1105 void TestSvgParser::testRenderStrokeWithInlineStyle()
1106 {
1107 const QString data =
1108 "<svg width=\"30px\" height=\"30px\""
1109 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1110
1111 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1112 " style = \"fill: cyan; stroke :blue; stroke-width:2;\"/>"
1113
1114 "</svg>";
1115
1116 SvgRenderTester t (data);
1117 t.test_standard_30px_72ppi("stroke_blue_width_2");
1118 }
1119
testIccColor()1120 void TestSvgParser::testIccColor()
1121 {
1122 const QString data =
1123 "<svg width=\"30px\" height=\"30px\""
1124 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1125
1126 "<g xml:base=\"icc\">"
1127 " <color-profile xlink:href=\"sRGB-elle-V4-srgbtrc.icc\""
1128 " local=\"133a66607cffeebdd64dd433ada9bf4e\" name=\"default-profile\"/>"
1129
1130 " <color-profile xlink:href=\"sRGB-elle-V4-srgbtrc.icc\""
1131 " local=\"133a66607cffeebdd64dd433ada9bf4e\" name=\"some-other-name\"/>"
1132
1133 " <rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1134 " style = \"fill: cyan; stroke :blue; stroke-width:2;\"/>"
1135 "</g>"
1136
1137 "</svg>";
1138
1139 SvgRenderTester t (data);
1140
1141 int numFetches = 0;
1142
1143 t.parser.setFileFetcher(
1144 [&numFetches](const QString &name) {
1145 numFetches++;
1146 const QString fileName = TestUtil::fetchDataFileLazy(name);
1147 QFile file(fileName);
1148 KIS_ASSERT(file.exists());
1149 file.open(QIODevice::ReadOnly);
1150 return file.readAll();
1151 });
1152
1153 t.test_standard_30px_72ppi("stroke_blue_width_2");
1154 QCOMPARE(numFetches, 1);
1155 }
1156
testRenderFillLinearGradientRelativePercent()1157 void TestSvgParser::testRenderFillLinearGradientRelativePercent()
1158 {
1159 const QString data =
1160 "<svg width=\"30px\" height=\"30px\""
1161 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1162
1163 "<defs>"
1164 " <linearGradient id=\"testGrad\" x1=\"0%\" y1=\"50%\" x2=\"100%\" y2=\"50%\">"
1165 " <stop offset=\"20%\" stop-color=\"#F60\" />"
1166 " <stop offset=\"80%\" stop-color=\"#FF6\" />"
1167 " </linearGradient>"
1168 "</defs>"
1169
1170 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1171 " style = \"fill:url(#testGrad) magenta; stroke:none; stroke-width:2;\"/>"
1172
1173 "</svg>";
1174
1175 SvgRenderTester t (data);
1176 t.test_standard_30px_72ppi("fill_gradient");
1177 }
1178
testRenderFillLinearGradientRelativePortion()1179 void TestSvgParser::testRenderFillLinearGradientRelativePortion()
1180 {
1181 const QString data =
1182 "<svg width=\"30px\" height=\"30px\""
1183 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1184
1185 "<linearGradient id=\"testGrad\" x1=\"0\" y1=\"0.5\" x2=\"1.0\" y2=\"0.5\">"
1186 " <stop offset=\"20%\" stop-color=\"#F60\" />"
1187 " <stop offset=\"80%\" stop-color=\"#FF6\" />"
1188 "</linearGradient>"
1189
1190 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1191 " style = \"fill:url(#testGrad) magenta; stroke:none; stroke-width:2;\"/>"
1192
1193 "</svg>";
1194
1195 SvgRenderTester t (data);
1196 t.test_standard_30px_72ppi("fill_gradient");
1197 }
1198
testRenderFillLinearGradientUserCoord()1199 void TestSvgParser::testRenderFillLinearGradientUserCoord()
1200 {
1201 const QString data =
1202 "<svg width=\"30px\" height=\"30px\" viewBox=\"60 70 60 90\""
1203 " preserveAspectRatio=\"none meet\""
1204 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1205
1206 "<linearGradient id=\"testGrad\" x1=\"70\" y1=\"115\" x2=\"90\" y2=\"115\""
1207 " gradientUnits=\"userSpaceOnUse\">"
1208 " <stop offset=\"20%\" stop-color=\"#F60\" />"
1209 " <stop offset=\"80%\" stop-color=\"#FF6\" />"
1210 "</linearGradient>"
1211
1212 "<rect id=\"testRect\" x=\"70\" y=\"85\" width=\"20\" height=\"60\""
1213 " fill=\"url(#testGrad) magenta\" stroke=\"none\"/>"
1214
1215 "</svg>";
1216
1217 SvgRenderTester t (data);
1218 t.test_standard_30px_72ppi("fill_gradient");
1219 }
1220
testRenderFillLinearGradientStopPortion()1221 void TestSvgParser::testRenderFillLinearGradientStopPortion()
1222 {
1223 const QString data =
1224 "<svg width=\"30px\" height=\"30px\""
1225 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1226
1227 "<linearGradient id=\"testGrad\" x1=\"0\" y1=\"0.5\" x2=\"1.0\" y2=\"0.5\">"
1228 " <stop offset=\"0.2\" stop-color=\"#F60\" />"
1229 " <stop offset=\"0.8\" stop-color=\"#FF6\" />"
1230 "</linearGradient>"
1231
1232 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1233 " style = \"fill:url(#testGrad) magenta; stroke:none; stroke-width:2;\"/>"
1234
1235 "</svg>";
1236
1237 SvgRenderTester t (data);
1238 t.test_standard_30px_72ppi("fill_gradient");
1239 }
1240
testRenderFillLinearGradientTransform()1241 void TestSvgParser::testRenderFillLinearGradientTransform()
1242 {
1243 const QString data =
1244 "<svg width=\"30px\" height=\"30px\""
1245 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1246
1247 "<linearGradient id=\"testGrad\" x1=\"0\" y1=\"0.5\" x2=\"1.0\" y2=\"0.5\""
1248 " gradientTransform=\"rotate(90, 0.5, 0.5)\">"
1249
1250 " <stop offset=\"0.2\" stop-color=\"#F60\" />"
1251 " <stop offset=\"0.8\" stop-color=\"#FF6\" />"
1252 "</linearGradient>"
1253
1254 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1255 " style = \"fill:url(#testGrad) magenta; stroke:none; stroke-width:2;\"/>"
1256
1257 "</svg>";
1258
1259 SvgRenderTester t (data);
1260 t.test_standard_30px_72ppi("fill_gradient_vertical");
1261 }
1262
testRenderFillLinearGradientTransformUserCoord()1263 void TestSvgParser::testRenderFillLinearGradientTransformUserCoord()
1264 {
1265 const QString data =
1266 "<svg width=\"30px\" height=\"30px\" viewBox=\"60 70 60 90\""
1267 " preserveAspectRatio=\"none meet\""
1268 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1269
1270 "<linearGradient id=\"testGrad\" x1=\"70\" y1=\"115\" x2=\"90\" y2=\"115\""
1271 " gradientUnits=\"userSpaceOnUse\""
1272 " gradientTransform=\"rotate(90, 80, 115)\">"
1273
1274 " <stop offset=\"20%\" stop-color=\"#F60\" />"
1275 " <stop offset=\"80%\" stop-color=\"#FF6\" />"
1276 "</linearGradient>"
1277
1278 "<rect id=\"testRect\" x=\"70\" y=\"85\" width=\"20\" height=\"60\""
1279 " fill=\"url(#testGrad) magenta\" stroke=\"none\"/>"
1280
1281 "</svg>";
1282
1283 SvgRenderTester t (data);
1284 t.test_standard_30px_72ppi("fill_gradient_vertical_in_user");
1285 }
1286
testRenderFillLinearGradientRotatedShape()1287 void TestSvgParser::testRenderFillLinearGradientRotatedShape()
1288 {
1289 // DK: I'm not sure I fully understand if it is a correct transformation,
1290 // but inkscape opens the file in the same way...
1291
1292 const QString data =
1293 "<svg width=\"30px\" height=\"30px\""
1294 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1295
1296 "<linearGradient id=\"testGrad\" x1=\"0\" y1=\"0.5\" x2=\"1.0\" y2=\"0.5\""
1297 " gradientTransform=\"rotate(90, 0.5, 0.5)\">"
1298
1299 " <stop offset=\"0.2\" stop-color=\"#F60\" />"
1300 " <stop offset=\"0.8\" stop-color=\"#FF6\" />"
1301 "</linearGradient>"
1302
1303 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1304 " style = \"fill:url(#testGrad) magenta; stroke:none; stroke-width:2;\""
1305 " transform=\"rotate(90, 10, 12.5)\"/>"
1306
1307 "</svg>";
1308
1309 SvgRenderTester t (data);
1310 t.test_standard_30px_72ppi("fill_gradient_shape_rotated", false);
1311 }
1312
testRenderFillLinearGradientRotatedShapeUserCoord()1313 void TestSvgParser::testRenderFillLinearGradientRotatedShapeUserCoord()
1314 {
1315 // DK: I'm not sure I fully understand if it is a correct transformation,
1316 // but inkscape opens the file in the same way...
1317
1318 const QString data =
1319 "<svg width=\"30px\" height=\"30px\" viewBox=\"60 70 60 90\""
1320 " preserveAspectRatio=\"none meet\""
1321 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1322
1323 "<linearGradient id=\"testGrad\" x1=\"70\" y1=\"115\" x2=\"90\" y2=\"115\""
1324 " gradientUnits=\"userSpaceOnUse\">"
1325
1326 " <stop offset=\"20%\" stop-color=\"#F60\" />"
1327 " <stop offset=\"80%\" stop-color=\"#FF6\" />"
1328 "</linearGradient>"
1329
1330 "<rect id=\"testRect\" x=\"70\" y=\"85\" width=\"20\" height=\"60\""
1331 " fill=\"url(#testGrad) magenta\" stroke=\"none\""
1332 " transform=\"rotate(90, 80, 115)\"/>"
1333
1334 "</svg>";
1335
1336 SvgRenderTester t (data);
1337 t.test_standard_30px_72ppi("fill_gradient_shape_rotated_in_user", false);
1338 }
1339
testRenderFillRadialGradient()1340 void TestSvgParser::testRenderFillRadialGradient()
1341 {
1342 const QString data =
1343 "<svg width=\"30px\" height=\"30px\""
1344 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1345
1346 "<radialGradient id=\"testGrad\" cx=\"0.5\" cy=\"0.5\" fx=\"0.2\" fy=\"0.2\" r=\"0.5\">"
1347 " <stop offset=\"0.2\" stop-color=\"#F60\" />"
1348 " <stop offset=\"0.8\" stop-color=\"#FF6\" />"
1349 "</radialGradient>"
1350
1351 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1352 " style = \"fill:url(#testGrad) magenta; stroke:none; stroke-width:2;\"/>"
1353 "</svg>";
1354
1355 SvgRenderTester t (data);
1356 t.setFuzzyThreshold(1);
1357 t.test_standard_30px_72ppi("fill_gradient_radial");
1358 }
1359
testRenderFillRadialGradientUserCoord()1360 void TestSvgParser::testRenderFillRadialGradientUserCoord()
1361 {
1362 const QString data =
1363 "<svg width=\"30px\" height=\"30px\""
1364 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1365
1366 "<radialGradient id=\"testGrad\" cx=\"10\" cy=\"12.5\" fx=\"7\" fy=\"9\" r=\"5\""
1367 " gradientUnits=\"userSpaceOnUse\">"
1368
1369 " <stop offset=\"0.2\" stop-color=\"#F60\" />"
1370 " <stop offset=\"0.8\" stop-color=\"#FF6\" />"
1371 "</radialGradient>"
1372
1373 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1374 " style = \"fill:url(#testGrad) magenta; stroke:none; stroke-width:2;\"/>"
1375 "</svg>";
1376
1377 SvgRenderTester t (data);
1378 t.setFuzzyThreshold(1);
1379 t.test_standard_30px_72ppi("fill_gradient_radial_in_user");
1380 }
1381
testRenderFillLinearGradientUserCoordPercent()1382 void TestSvgParser::testRenderFillLinearGradientUserCoordPercent()
1383 {
1384 const QString data =
1385 "<svg width=\"30px\" height=\"30px\" viewBox=\"60 70 60 90\""
1386 " preserveAspectRatio=\"none meet\""
1387 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1388
1389 "<linearGradient id=\"testGrad\" x1=\"116.667%\" y1=\"127.778%\" x2=\"150%\" y2=\"127.778%\""
1390 " gradientUnits=\"userSpaceOnUse\">"
1391 " <stop offset=\"20%\" stop-color=\"#F60\" />"
1392 " <stop offset=\"80%\" stop-color=\"#FF6\" />"
1393 "</linearGradient>"
1394
1395 "<rect id=\"testRect\" x=\"70\" y=\"85\" width=\"20\" height=\"60\""
1396 " fill=\"url(#testGrad) magenta\" stroke=\"none\"/>"
1397
1398 "</svg>";
1399
1400 SvgRenderTester t (data);
1401 t.test_standard_30px_72ppi("fill_gradient");
1402 }
1403
testRenderStrokeLinearGradient()1404 void TestSvgParser::testRenderStrokeLinearGradient()
1405 {
1406 const QString data =
1407 "<svg width=\"30px\" height=\"30px\""
1408 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
1409
1410 "<defs>"
1411 " <linearGradient id=\"testGrad\" x1=\"0%\" y1=\"50%\" x2=\"100%\" y2=\"50%\">"
1412 " <stop offset=\"20%\" stop-color=\"#F60\" />"
1413 " <stop offset=\"80%\" stop-color=\"#FF6\" />"
1414 " </linearGradient>"
1415 "</defs>"
1416
1417 "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
1418 " style = \"grey; stroke:url(#testGrad); stroke-width:3; stroke-dasharray:3,1\"/>"
1419
1420 "</svg>";
1421
1422 SvgRenderTester t (data);
1423 t.test_standard_30px_72ppi("stroke_gradient_dashed");
1424 }
1425
rotateTransform(qreal degree,const QPointF & center)1426 QTransform rotateTransform(qreal degree, const QPointF ¢er) {
1427 QTransform rotate;
1428 rotate.rotate(degree);
1429 return
1430 QTransform::fromTranslate(-center.x(), -center.y()) *
1431 rotate *
1432 QTransform::fromTranslate(center.x(), center.y());
1433 }
1434
viewTransform(const QRectF & src,const QRectF & dst)1435 QTransform viewTransform(const QRectF &src, const QRectF &dst) {
1436 return QTransform::fromTranslate(-src.x(), -src.y()) *
1437 QTransform::fromScale(dst.width() / src.width(),
1438 dst.height() / src.height()) *
1439 QTransform::fromTranslate(dst.x(), dst.y());
1440
1441 }
1442
1443
testRenderMeshGradient_bilinear_1by1_UserCoord()1444 void TestSvgParser::testRenderMeshGradient_bilinear_1by1_UserCoord()
1445 {
1446 QString data =
1447 "<svg"
1448 " width=\"50px\""
1449 " height=\"50px\""
1450 " version=\"1.1\""
1451 " id=\"svg8\">"
1452 " <defs"
1453 " id=\"defs2\">"
1454 " <meshgradient"
1455 " id=\"meshgradient901\""
1456 " gradientUnits=\"userSpaceOnUse\""
1457 " x=\"0\""
1458 " y=\"0\">"
1459 " <meshrow"
1460 " id=\"meshrow903\">"
1461 " <meshpatch"
1462 " id=\"meshpatch905\">"
1463 " <stop"
1464 " path=\"c 15,0 30,0 45,0\""
1465 " style=\"stop-color:#ffffff;stop-opacity:1\""
1466 " id=\"stop907\" />"
1467 " <stop"
1468 " path=\"c 0,15 0,30 0,45\""
1469 " style=\"stop-color:#ff0000;stop-opacity:1\""
1470 " id=\"stop909\" />"
1471 " <stop"
1472 " path=\"c -15,0 -30,0 -45,0\""
1473 " style=\"stop-color:#ffffff;stop-opacity:1\""
1474 " id=\"stop911\" />"
1475 " <stop"
1476 " path=\"c 0,-15 0,-30 0,-45\""
1477 " style=\"stop-color:#ff0000;stop-opacity:1\""
1478 " id=\"stop913\" />"
1479 " </meshpatch>"
1480 " </meshrow>"
1481 " </meshgradient>"
1482 " </defs>"
1483 " <rect"
1484 " style=\"fill:url(#meshgradient901);fill-opacity:1;filter:url(#filter859)\""
1485 " id=\"testRect\""
1486 " width=\"45\""
1487 " height=\"45\""
1488 " x=\"0\""
1489 " y=\"0\" />"
1490 "</svg>";
1491
1492
1493 SvgRenderTester t(data);
1494 t.setFuzzyThreshold(5);
1495 t.test_standard("meshgradient_bilinear_1by1_in_user", QSize(50, 50), 72);
1496 }
1497
testRenderMeshGradient_bicubic_1by1_UserCoord()1498 void TestSvgParser::testRenderMeshGradient_bicubic_1by1_UserCoord()
1499 {
1500 QString data =
1501 "<svg id=\"svg8\""
1502 " version=\"1.1\""
1503 " height=\"100px\""
1504 " width=\"100px\">"
1505 " <defs"
1506 " id=\"defs2\">"
1507 " <meshgradient"
1508 " type=\"bicubic\""
1509 " y=\"-10\""
1510 " x=\"-10\""
1511 " gradientUnits=\"userSpaceOnUse\""
1512 " id=\"meshgradient1989\">"
1513 " <meshrow"
1514 " id=\"meshrow1991\">"
1515 " <meshpatch"
1516 " id=\"meshpatch1993\">"
1517 " <stop"
1518 " id=\"stop1995\""
1519 " style=\"stop-color:#ffffff;stop-opacity:1\""
1520 " path=\"c 30,0 60,0 90,0\" />"
1521 " <stop"
1522 " id=\"stop1997\""
1523 " style=\"stop-color:#ff0000;stop-opacity:1\""
1524 " path=\"c 0,30 0,60 0,90\" />"
1525 " <stop"
1526 " id=\"stop1999\""
1527 " style=\"stop-color:#ffffff;stop-opacity:1\""
1528 " path=\"c -30,0 -60,0 -90,0\" />"
1529 " <stop"
1530 " id=\"stop2001\""
1531 " style=\"stop-color:#ff0000;stop-opacity:1\""
1532 " path=\"c 0,-30 0,-60 0,-90\" />"
1533 " </meshpatch>"
1534 " </meshrow>"
1535 " </meshgradient>"
1536 " </defs>"
1537 " <rect"
1538 " y=\"-10\""
1539 " x=\"-10\""
1540 " height=\"90\""
1541 " width=\"90\""
1542 " id=\"testRect\""
1543 " style=\"fill:url(#meshgradient1989);fill-opacity:1\" />"
1544 "</svg>";
1545
1546
1547 SvgRenderTester t(data);
1548 t.setFuzzyThreshold(5);
1549 t.test_standard("meshgradient_bicubic_1by1_in_user", QSize(100, 100), 72);
1550 }
1551
testRenderMeshGradient_bilinear_2by2_UserCoord()1552 void TestSvgParser::testRenderMeshGradient_bilinear_2by2_UserCoord()
1553 {
1554 QString data =
1555 "<svg"
1556 " version=\"1.1\""
1557 " width=\"100px\""
1558 " height=\"100px\""
1559 " id=\"svg856\">"
1560 " <defs"
1561 " id=\"defs850\">"
1562 " <meshgradient"
1563 " y=\"0\""
1564 " x=\"0\""
1565 " gradientUnits=\"userSpaceOnUse\""
1566 " id=\"meshgradient832\">"
1567 " <meshrow"
1568 " id=\"meshrow834\">"
1569 " <meshpatch"
1570 " id=\"meshpatch836\">"
1571 " <stop"
1572 " id=\"stop838\""
1573 " style=\"stop-color:#ffffff;stop-opacity:1\""
1574 " path=\"c 13.3333,0 26.6667,0 40,0\" />"
1575 " <stop"
1576 " id=\"stop840\""
1577 " style=\"stop-color:#000000;stop-opacity:1\""
1578 " path=\"c 0,13.3333 0,26.6667 0,40\" />"
1579 " <stop"
1580 " id=\"stop842\""
1581 " style=\"stop-color:#ffffff;stop-opacity:1\""
1582 " path=\"c -13.3333,0 -26.6667,0 -40,0\" />"
1583 " <stop"
1584 " id=\"stop844\""
1585 " style=\"stop-color:#000000;stop-opacity:1\""
1586 " path=\"c 0,-13.3333 0,-26.6667 0,-40\" />"
1587 " </meshpatch>"
1588 " <meshpatch"
1589 " id=\"meshpatch846\">"
1590 " <stop"
1591 " id=\"stop848\""
1592 " path=\"c 13.3333,0 26.6667,0 40,0\" />"
1593 " <stop"
1594 " id=\"stop850\""
1595 " style=\"stop-color:#ffffff;stop-opacity:1\""
1596 " path=\"c 0,13.3333 0,26.6667 0,40\" />"
1597 " <stop"
1598 " id=\"stop852\""
1599 " style=\"stop-color:#000000;stop-opacity:1\""
1600 " path=\"c -13.3333,0 -26.6667,0 -40,0\" />"
1601 " </meshpatch>"
1602 " </meshrow>"
1603 " <meshrow"
1604 " id=\"meshrow854\">"
1605 " <meshpatch"
1606 " id=\"meshpatch856\">"
1607 " <stop"
1608 " id=\"stop858\""
1609 " path=\"c 0,13.3333 0,26.6667 0,40\" />"
1610 " <stop"
1611 " id=\"stop860\""
1612 " style=\"stop-color:#000000;stop-opacity:1\""
1613 " path=\"c -13.3333,0 -26.6667,0 -40,0\" />"
1614 " <stop"
1615 " id=\"stop862\""
1616 " style=\"stop-color:#ffffff;stop-opacity:1\""
1617 " path=\"c 0,-13.3333 0,-26.6667 0,-40\" />"
1618 " </meshpatch>"
1619 " <meshpatch"
1620 " id=\"meshpatch864\">"
1621 " <stop"
1622 " id=\"stop866\""
1623 " path=\"c 0,13.3333 0,26.6667 0,40\" />"
1624 " <stop"
1625 " id=\"stop868\""
1626 " style=\"stop-color:#ffffff;stop-opacity:1\""
1627 " path=\"c -13.3333,0 -26.6667,0 -40,0\" />"
1628 " </meshpatch>"
1629 " </meshrow>"
1630 " </meshgradient>"
1631 " </defs>"
1632 ""
1633 " <rect"
1634 " style=\"fill:url(#meshgradient832);fill-opacity:1\""
1635 " id=\"testRect\""
1636 " width=\"80\""
1637 " height=\"80\""
1638 " x=\"0\""
1639 " y=\"0\" />"
1640 "</svg>";
1641
1642 SvgRenderTester t(data);
1643 t.setFuzzyThreshold(5);
1644 t.test_standard("meshgradient_bilinear_2by2_in_user", QSize(100, 100), 72);
1645 }
1646
testRenderMeshGradient_bicubic_2by2_UserCoord()1647 void TestSvgParser::testRenderMeshGradient_bicubic_2by2_UserCoord()
1648 {
1649 QString data =
1650 "<svg width=\"100px\""
1651 " height=\"100px\">"
1652 "<defs>"
1653 " <meshgradient id=\"meshgradient0\""
1654 " gradientUnits=\"userSpaceOnUse\" "
1655 " x=\"0\" "
1656 " y=\"0\" "
1657 " type=\"bicubic\">"
1658 " <meshrow "
1659 " id=\"meshrow0\">"
1660 " <meshpatch "
1661 " id=\"meshpatch0\">"
1662 " <stop path=\"C 13.33328,0 26.66664,0 40,0\" "
1663 " stop-color=\"#ffffff\" stop-opacity=\"1\"/>"
1664 " <stop path=\"C 40,13.33328 40,26.66664 40,40\" "
1665 " stop-color=\"#000000\" stop-opacity=\"1\"/>"
1666 " <stop path=\"C 26.66672,40 13.33336,40 0,40\" "
1667 " stop-color=\"#ffffff\" stop-opacity=\"1\"/>"
1668 " <stop path=\"C 0,26.66672 0,13.33336 0,0\" "
1669 " stop-color=\"#000000\" stop-opacity=\"1\"/>"
1670 " </meshpatch>"
1671 " <meshpatch "
1672 " id=\"meshpatch1\">"
1673 " <stop path=\"C 53.33328,0 66.666640,0 80,0\"/>"
1674 " <stop path=\"C 80,13.33328 80,26.66664 80,40\" "
1675 " stop-color=\"#ffffff\" stop-opacity=\"1\"/>"
1676 " <stop path=\"C 66.66672,40 53.33336,40 40,40\" "
1677 " stop-color=\"#000000\" stop-opacity=\"1\"/>"
1678 " </meshpatch>"
1679 " </meshrow>"
1680 " <meshrow "
1681 " id=\"meshrow1\">"
1682 " <meshpatch "
1683 " id=\"meshpatch2\">"
1684 " <stop path=\"C 40,53.33328 40,66.66664 40,80\"/>"
1685 " <stop path=\"C 26.66672,80 13.33336,80 0,80\" "
1686 " stop-color=\"#000000\" stop-opacity=\"1\"/>"
1687 " <stop path=\"C 0,66.66672 0,53.33336 0,40\" "
1688 " stop-color=\"#ffffff\" stop-opacity=\"1\"/>"
1689 " </meshpatch>"
1690 " <meshpatch "
1691 " id=\"meshpatch3\">"
1692 " <stop path=\"C 80,53.33328 80,66.66664 80,80\"/>"
1693 " <stop path=\"C 66.66672,80 53.33336,80 40,80\" "
1694 " stop-color=\"#ffffff\" stop-opacity=\"1\"/>"
1695 " </meshpatch>"
1696 " </meshrow>"
1697 " </meshgradient>"
1698 " </defs>"
1699 ""
1700 "<rect id=\"testRect\" fill=\"url(#meshgradient0)\" width=\"80\" height=\"80\"/>"
1701 "</svg>";
1702
1703 SvgRenderTester t(data);
1704 t.setFuzzyThreshold(5);
1705 t.test_standard("meshgradient_bicubic_2by2", QSize(100, 100), 72);
1706 }
1707
testRenderMeshGradient_bilinear_1by1_Obb()1708 void TestSvgParser::testRenderMeshGradient_bilinear_1by1_Obb()
1709 {
1710 // inkscape adds 1px border (unreliably) when the bbox doesn't the meshpatch's curves
1711 qWarning() << "WARNING: skipped, the edge couldn't be reliably verified";
1712 return;
1713 // inkscape is _very_ weird with meshgradients in OBB coordinate system
1714 QString data =
1715 "<svg width=\"100px\" height=\"100px\""
1716 " version=\"1.1\" id=\"svg8\" >"
1717 " <defs>"
1718 " <meshgradient id=\"meshgradient1635\" gradientUnits=\"objectBoundingBox\" x=\"0\" y=\"0\">"
1719 " <meshrow"
1720 " id=\"meshrow2306\">"
1721 " <meshpatch"
1722 " id=\"meshpatch2296\">"
1723 " <stop"
1724 " id=\"stop2288\""
1725 " stop-color=\"#000000\""
1726 " path=\"c 0.25,-0.25 0.75, 0.25 1,0\" />"
1727 " <stop"
1728 " id=\"stop2290\""
1729 " stop-color=\"#0000ff\""
1730 " path=\"c 0.25, 0.25 -0.25, 0.75 0,1\" />"
1731 " <stop"
1732 " id=\"stop2292\""
1733 " stop-color=\"#00ff00\""
1734 " path=\"c -0.25, 0.25 -0.75,-0.25 -1,0\" />"
1735 " <stop"
1736 " id=\"stop2294\""
1737 " stop-color=\"ff0000\""
1738 " path=\"c -0.25,-0.25, 0.25,-0.75\" />"
1739 " </meshpatch>"
1740 " </meshrow>"
1741 " </meshgradient>"
1742 " </defs>"
1743 " <rect"
1744 " style=\"fill:url(#meshgradient1635);fill-opacity:1\""
1745 " id=\"testRect\""
1746 " width=\"70\""
1747 " height=\"70\""
1748 " x=\"0\""
1749 " y=\"0\" />"
1750 "</svg>";
1751
1752 SvgRenderTester t(data);
1753 t.setFuzzyThreshold(5);
1754 t.test_standard("meshgradient_bilinear_1by1_in_obb", QSize(100, 100), 72);
1755 }
1756
testRenderMeshGradient_bicubic_2by2_Obb()1757 void TestSvgParser::testRenderMeshGradient_bicubic_2by2_Obb()
1758 {
1759 // inkscape is _very_ weird with meshgradients in OBB coordinate system
1760 QString data =
1761 "<svg"
1762 " version=\"1.1\""
1763 " width=\"100px\""
1764 " height=\"100px\""
1765 " id=\"svg856\">"
1766 " <defs"
1767 " id=\"defs850\">"
1768 " <meshgradient"
1769 " y=\"0\""
1770 " x=\"0\""
1771 " gradientUnits=\"objectBoundingBox\""
1772 " id=\"meshgradient832\""
1773 " type=\"bicubic\" >"
1774 " <meshrow"
1775 " id=\"meshrow834\">"
1776 " <meshpatch"
1777 " id=\"meshpatch836\">"
1778 " <stop"
1779 " id=\"stop838\""
1780 " style=\"stop-color:#ffffff;stop-opacity:1\""
1781 " path=\"c 0.166666,0 0.333333,0 0.5,0\" />"
1782 " <stop"
1783 " id=\"stop840\""
1784 " style=\"stop-color:#000000;stop-opacity:1\""
1785 " path=\"c 0,0.166666 0,0.333333 0,0.5\" />"
1786 " <stop"
1787 " id=\"stop842\""
1788 " style=\"stop-color:#ffffff;stop-opacity:1\""
1789 " path=\"c -0.166666,0 -0.333333,0 -0.5,0\" />"
1790 " <stop"
1791 " id=\"stop844\""
1792 " style=\"stop-color:#000000;stop-opacity:1\""
1793 " path=\"c 0,-0.166666 0,-0.333333 0,-0.5\" />"
1794 " </meshpatch>"
1795 " <meshpatch"
1796 " id=\"meshpatch846\">"
1797 " <stop"
1798 " id=\"stop848\""
1799 " path=\"c 0.166666,0 0.333333,0 0.5,0\" />"
1800 " <stop"
1801 " id=\"stop850\""
1802 " style=\"stop-color:#ffffff;stop-opacity:1\""
1803 " path=\"c 0,0.166666 0,0.333333 0,0.5\" />"
1804 " <stop"
1805 " id=\"stop852\""
1806 " style=\"stop-color:#000000;stop-opacity:1\""
1807 " path=\"c -0.166666,0 -0.333333,0 -0.5,0\" />"
1808 " </meshpatch>"
1809 " </meshrow>"
1810 " <meshrow"
1811 " id=\"meshrow854\">"
1812 " <meshpatch"
1813 " id=\"meshpatch856\">"
1814 " <stop"
1815 " id=\"stop858\""
1816 " path=\"c 0,0.166666 0,0.333333 0,0.5\" />"
1817 " <stop"
1818 " id=\"stop860\""
1819 " style=\"stop-color:#000000;stop-opacity:1\""
1820 " path=\"c -0.166666,0 -0.333333,0 -0.5,0\" />"
1821 " <stop"
1822 " id=\"stop862\""
1823 " style=\"stop-color:#ffffff;stop-opacity:1\""
1824 " path=\"c 0,-0.166666 0,-0.333333 0,-0.5\" />"
1825 " </meshpatch>"
1826 " <meshpatch"
1827 " id=\"meshpatch864\">"
1828 " <stop"
1829 " id=\"stop866\""
1830 " path=\"c 0,0.166666 0,0.333333 0,0.5\" />"
1831 " <stop"
1832 " id=\"stop868\""
1833 " style=\"stop-color:#ffffff;stop-opacity:1\""
1834 " path=\"c -0.166666,0 -0.333333,0 -0.5,0\" />"
1835 " </meshpatch>"
1836 " </meshrow>"
1837 " </meshgradient>"
1838 " </defs>"
1839 ""
1840 " <rect"
1841 " style=\"fill:url(#meshgradient832);fill-opacity:1\""
1842 " id=\"testRect\""
1843 " width=\"80\""
1844 " height=\"80\""
1845 " x=\"0\""
1846 " y=\"0\" />"
1847 "</svg>";
1848
1849
1850 SvgRenderTester t(data);
1851 t.setFuzzyThreshold(5);
1852 t.test_standard("meshgradient_bicubic_2by2", QSize(100, 100), 72);
1853 }
1854
testRenderMeshGradient_MeshTransform_UserCoord()1855 void TestSvgParser::testRenderMeshGradient_MeshTransform_UserCoord()
1856 {
1857 QString data =
1858 "<svg"
1859 " id=\"svg8\""
1860 " version=\"1.1\""
1861 " height=\"100px\""
1862 " width=\"100px\">"
1863 " <defs"
1864 " id=\"defs2\">"
1865 " <meshgradient"
1866 " y=\"0\""
1867 " x=\"0\""
1868 " gradientUnits=\"userSpaceOnUse\""
1869 " id=\"meshgradient1989\""
1870 " transform=\"translate(90, 0) rotate(90)\">"
1871 " <meshrow"
1872 " id=\"meshrow1991\">"
1873 " <meshpatch"
1874 " id=\"meshpatch1993\">"
1875 " <stop"
1876 " id=\"stop1995\""
1877 " style=\"stop-color:#ffffff;stop-opacity:1\""
1878 " path=\"c 30,0 60,0 90,0\" />"
1879 " <stop"
1880 " id=\"stop1997\""
1881 " style=\"stop-color:#ff0000;stop-opacity:1\""
1882 " path=\"c 0,30 0,60 0,90\" />"
1883 " <stop"
1884 " id=\"stop1999\""
1885 " style=\"stop-color:#ffffff;stop-opacity:1\""
1886 " path=\"c -30,0 -60,0 -90,0\" />"
1887 " <stop"
1888 " id=\"stop2001\""
1889 " style=\"stop-color:#ff0000;stop-opacity:1\""
1890 " path=\"c 0,-30 0,-60 0,-90\" />"
1891 " </meshpatch>"
1892 " </meshrow>"
1893 " </meshgradient>"
1894 " </defs>"
1895 " <rect"
1896 " y=\"0\""
1897 " x=\"0\""
1898 " height=\"100\""
1899 " width=\"100\""
1900 " id=\"testRect\""
1901 " style=\"fill:url(#meshgradient1989);fill-opacity:1\" />"
1902 "</svg>";
1903
1904 SvgRenderTester t(data);
1905 t.setFuzzyThreshold(5);
1906 t.test_standard("meshgradient_meshtransform_in_user", QSize(100, 100), 72);
1907 }
1908
testRenderMeshGradient_ShapeTransform_UserCoord()1909 void TestSvgParser::testRenderMeshGradient_ShapeTransform_UserCoord()
1910 {
1911 // QString data = fetchSvgFile("svg_render", "meshgradient_shapetransform_in_user");
1912 QString data =
1913 "<svg"
1914 " width=\"100px\""
1915 " height=\"100px\""
1916 " version=\"1.1\""
1917 " id=\"svg8\">"
1918 " <defs"
1919 " id=\"defs2\">"
1920 " <meshgradient"
1921 " y=\"-79.791451\""
1922 " x=\"-154.33087\""
1923 " gradientUnits=\"userSpaceOnUse\""
1924 " id=\"meshgradient839\">"
1925 " <meshrow"
1926 " id=\"meshrow841\">"
1927 " <meshpatch"
1928 " id=\"meshpatch843\">"
1929 " <stop"
1930 " id=\"stop845\""
1931 " style=\"stop-color:#ffffff;stop-opacity:1\""
1932 " path=\"c 51.0352,0 102.07,0 153.105,0\" />"
1933 " <stop"
1934 " id=\"stop847\""
1935 " style=\"stop-color:#000000;stop-opacity:1\""
1936 " path=\"c 0,52.6788 0,105.358 0,158.036\" />"
1937 " <stop"
1938 " id=\"stop849\""
1939 " style=\"stop-color:#ffffff;stop-opacity:1\""
1940 " path=\"c -51.0352,0 -102.07,0 -153.105,0\" />"
1941 " <stop"
1942 " id=\"stop851\""
1943 " style=\"stop-color:#000000;stop-opacity:1\""
1944 " path=\"c 0,-52.6788 0,-105.358 0,-158.036\" />"
1945 " </meshpatch>"
1946 " </meshrow>"
1947 " </meshgradient>"
1948 " </defs>"
1949 " <rect"
1950 " style=\"fill:url(#meshgradient839);fill-opacity:1\""
1951 " id=\"testRect\""
1952 " width=\"153.10547\""
1953 " height=\"158.03641\""
1954 " x=\"-154.33087\""
1955 " y=\"-79.791451\""
1956 " transform=\"matrix(-0.71410131,-0.70004237,0.70026385,-0.71388413,0,0)\" />"
1957 "</svg>";
1958
1959
1960 SvgRenderTester t(data);
1961 t.setFuzzyThreshold(5);
1962 t.test_standard("meshgradient_shapetransform_in_user", QSize(100, 100), 72);
1963 }
1964
testRenderMeshGradient_MeshTransform_Obb()1965 void TestSvgParser::testRenderMeshGradient_MeshTransform_Obb()
1966 {
1967 // inkscape is _very_ weird with meshgradients in OBB coordinate system
1968 QString data =
1969 "<svg"
1970 " version=\"1.1\""
1971 " height=\"100px\""
1972 " width=\"100px\">"
1973 " <defs"
1974 " id=\"defs2\">"
1975 " <meshgradient"
1976 " y=\"0\""
1977 " x=\"0\""
1978 " transform=\"translate(0.7, 0) rotate(90)\""
1979 " gradientUnits=\"objectBoundingBox\""
1980 " id=\"meshgradient901\">"
1981 " <meshrow"
1982 " id=\"meshrow903\">"
1983 " <meshpatch"
1984 " id=\"meshpatch905\">"
1985 " <stop"
1986 " id=\"stop907\""
1987 " style=\"stop-color:#ffffff;stop-opacity:1\""
1988 " path=\"c 0.166666,0 0.333333,0 0.5,0\" />"
1989 " <stop"
1990 " id=\"stop909\""
1991 " style=\"stop-color:#ff0000;stop-opacity:1\""
1992 " path=\"c 0,0.166666 0,0.333333 0,0.5\" />"
1993 " <stop"
1994 " id=\"stop911\""
1995 " style=\"stop-color:#ffffff;stop-opacity:1\""
1996 " path=\"c -0.166666,0 -0.333333,0 -0.5,0\" />"
1997 " <stop"
1998 " id=\"stop913\""
1999 " style=\"stop-color:#ff0000;stop-opacity:1\""
2000 " path=\"c 0,-0.166666 0,-0.333333 0,-0.5\" />"
2001 " </meshpatch>"
2002 " <meshpatch"
2003 " id=\"meshpatch915\">"
2004 " <stop"
2005 " id=\"stop917\""
2006 " path=\"c 0.166666,0 0.333333,0 0.5,0\" />"
2007 " <stop"
2008 " id=\"stop919\""
2009 " style=\"stop-color:#ffffff;stop-opacity:1\""
2010 " path=\"c 0,0.166666 0,0.333333 0,0.5\" />"
2011 " <stop"
2012 " id=\"stop921\""
2013 " style=\"stop-color:#ff0000;stop-opacity:1\""
2014 " path=\"c -0.166666,0 -0.333333,0 -0.5,0\" />"
2015 " </meshpatch>"
2016 " </meshrow>"
2017 " </meshgradient>"
2018 " </defs>"
2019 " <rect"
2020 " y=\"0\""
2021 " x=\"0\""
2022 " height=\"90\""
2023 " width=\"90\""
2024 " id=\"testRect\""
2025 " style=\"fill:url(#meshgradient901);fill-opacity:1;filter:url(#filter859)\" />"
2026 "</svg>";
2027
2028
2029 SvgRenderTester t(data);
2030 t.setFuzzyThreshold(5);
2031 t.test_standard("meshgradient_meshtransform_in_obb", QSize(100, 100), 72);
2032 }
2033
testRenderMeshGradient_ShapeTransform_Obb()2034 void TestSvgParser::testRenderMeshGradient_ShapeTransform_Obb()
2035 {
2036 // inkscape is _very_ weird with meshgradients in OBB coordinate system
2037 QString data =
2038 "<svg"
2039 " width=\"100px\""
2040 " height=\"100px\""
2041 " version=\"1.1\""
2042 " id=\"svg8\">"
2043 " <defs"
2044 " id=\"defs2\">"
2045 " <meshgradient"
2046 " y=\"0\""
2047 " x=\"0\""
2048 " gradientUnits=\"objectBoundingBox\""
2049 " id=\"meshgradient839\">"
2050 " <meshrow"
2051 " id=\"meshrow841\">"
2052 " <meshpatch"
2053 " id=\"meshpatch843\">"
2054 " <stop"
2055 " id=\"stop845\""
2056 " style=\"stop-color:#ffffff;stop-opacity:1\""
2057 " path=\"c 0.33333,0 0.666666,0 1,0\" />"
2058 " <stop"
2059 " id=\"stop847\""
2060 " style=\"stop-color:#000000;stop-opacity:1\""
2061 " path=\"c 0,0.33333 0,0.66667 0,1\" />"
2062 " <stop"
2063 " id=\"stop849\""
2064 " style=\"stop-color:#ffffff;stop-opacity:1\""
2065 " path=\"c -0.33333,0 -0.666666,0 -1,0\" />"
2066 " <stop"
2067 " id=\"stop851\""
2068 " style=\"stop-color:#000000;stop-opacity:1\""
2069 " path=\"c 0,-0.33333 0,-0.66667 0,-1\" />"
2070 " </meshpatch>"
2071 " </meshrow>"
2072 " </meshgradient>"
2073 " </defs>"
2074 " <rect"
2075 " style=\"fill:url(#meshgradient839);fill-opacity:1\""
2076 " id=\"testRect\""
2077 " width=\"153.10547\""
2078 " height=\"158.03641\""
2079 " x=\"-154.33087\""
2080 " y=\"-79.791451\""
2081 " transform=\"matrix(-0.71410131,-0.70004237,0.70026385,-0.71388413,0,0)\" />"
2082 "</svg>";
2083
2084 SvgRenderTester t(data);
2085 t.setFuzzyThreshold(3);
2086 t.test_standard("meshgradient_shapetransform_in_obb", QSize(100, 100), 72);
2087 }
2088
testRenderMeshGradient_transparent()2089 void TestSvgParser::testRenderMeshGradient_transparent()
2090 {
2091 // here I use Krita's output, due to my lack of knowledge about Inkscape's RGBA
2092 // output format. But the results, have been verified - SZ
2093 QString data =
2094 "<svg"
2095 " width=\"100px\""
2096 " height=\"100px\""
2097 " version=\"1.1\""
2098 " id=\"svg8\">"
2099 " <defs"
2100 " id=\"defs2\">"
2101 " <meshgradient"
2102 " id=\"meshgradient1989\""
2103 " gradientUnits=\"userSpaceOnUse\""
2104 " x=\"-10\""
2105 " y=\"-10\""
2106 " type=\"bilinear\">"
2107 " <meshrow"
2108 " id=\"meshrow1991\">"
2109 " <meshpatch"
2110 " id=\"meshpatch1993\">"
2111 " <stop"
2112 " path=\"c 30,0 60,0 90,0\""
2113 " style=\"stop-color:#ffffff;stop-opacity:1\""
2114 " id=\"stop1995\" />"
2115 " <stop"
2116 " path=\"c 0,30 0,60 0,90\""
2117 " style=\"stop-color:#ff0000;stop-opacity:1\""
2118 " id=\"stop1997\" />"
2119 " <stop"
2120 " path=\"c -30,0 -60,0 -90,0\""
2121 " style=\"stop-color:#ffffff;stop-opacity:0\""
2122 " id=\"stop1999\" />"
2123 " <stop"
2124 " path=\"c 0,-30 0,-60 0,-90\""
2125 " style=\"stop-color:#ff0000;stop-opacity:1\""
2126 " id=\"stop2001\" />"
2127 " </meshpatch>"
2128 " </meshrow>"
2129 " </meshgradient>"
2130 " </defs>"
2131 " <rect"
2132 " style=\"fill:url(#meshgradient1989);fill-opacity:1\""
2133 " id=\"testRect\""
2134 " width=\"90\""
2135 " height=\"90\""
2136 " x=\"-10\""
2137 " y=\"-10\" />"
2138 "</svg>";
2139
2140 SvgRenderTester t(data);
2141 t.setFuzzyThreshold(5);
2142 t.setCheckQImagePremultiplied(true);
2143 t.test_standard("meshgradient_transparent", QSize(100, 100), 72);
2144 }
2145
testRenderMeshGradient_reversed()2146 void TestSvgParser::testRenderMeshGradient_reversed()
2147 {
2148 // Not sure if this is part of specs, but this brings up an underlying problem:
2149 // bounds in QPainterPath are inclusive on right and bottom side, so an extra 1px
2150 // border is drawn.
2151 QString data =
2152 "<svg"
2153 " id=\"svg856\""
2154 " height=\"100px\""
2155 " width=\"100px\""
2156 ">"
2157 " <defs"
2158 " id=\"defs850\">"
2159 " <meshgradient"
2160 " y=\"0\""
2161 " x=\"80\""
2162 " gradientUnits=\"userSpaceOnUse\""
2163 " id=\"meshgradient903\">"
2164 " <meshrow"
2165 " id=\"meshrow905\">"
2166 " <meshpatch"
2167 " id=\"meshpatch907\">"
2168 " <stop"
2169 " id=\"stop909\""
2170 " style=\"stop-color:#ffffff;stop-opacity:1\""
2171 " path=\"c -13.3333,0 -26.6667,0 -40,0\" />"
2172 " <stop"
2173 " id=\"stop911\""
2174 " style=\"stop-color:#000000;stop-opacity:1\""
2175 " path=\"c 0,26.6667 0,53.3333 0,80\" />"
2176 " <stop"
2177 " id=\"stop913\""
2178 " style=\"stop-color:#ffffff;stop-opacity:1\""
2179 " path=\"c 13.3333,0 26.6667,0 40,0\" />"
2180 " <stop"
2181 " id=\"stop915\""
2182 " style=\"stop-color:#000000;stop-opacity:1\""
2183 " path=\"c 0,-26.6667 0,-53.3333 0,-80\" />"
2184 " </meshpatch>"
2185 " <meshpatch"
2186 " id=\"meshpatch917\">"
2187 " <stop"
2188 " id=\"stop919\""
2189 " path=\"c -13.3333,0 -26.6667,0 -40,0\" />"
2190 " <stop"
2191 " id=\"stop921\""
2192 " style=\"stop-color:#ffffff;stop-opacity:1\""
2193 " path=\"c 0,26.6667 0,53.3333 0,80\" />"
2194 " <stop"
2195 " id=\"stop923\""
2196 " style=\"stop-color:#000000;stop-opacity:1\""
2197 " path=\"c 13.3333,0 26.6667,0 40,0\" />"
2198 " </meshpatch>"
2199 " </meshrow>"
2200 " </meshgradient>"
2201 " </defs>"
2202 " <rect"
2203 " y=\"0\""
2204 " x=\"0\""
2205 " height=\"90\""
2206 " width=\"90\""
2207 " id=\"testRect\""
2208 " style=\"fill:url(#meshgradient903);fill-opacity:1\" />"
2209 "</svg>";
2210
2211 SvgRenderTester t(data);
2212 t.setFuzzyThreshold(5);
2213 t.test_standard("meshgradient_reversed", QSize(100, 100), 72);
2214 }
2215
bakeShape(const QPainterPath & path,const QTransform & bakeTransform,bool contentIsObb=false,const QRectF & shapeBoundingRect=QRectF (),bool contentIsViewBox=false,const QRectF & viewBoxRect=QRectF (),const QRectF & refRect=QRectF ())2216 QPainterPath bakeShape(const QPainterPath &path,
2217 const QTransform &bakeTransform,
2218 bool contentIsObb = false, const QRectF &shapeBoundingRect = QRectF(),
2219 bool contentIsViewBox = false, const QRectF &viewBoxRect= QRectF(), const QRectF &refRect = QRectF())
2220 {
2221 const QTransform relativeToShape(shapeBoundingRect.width(), 0, 0, shapeBoundingRect.height(),
2222 shapeBoundingRect.x(), shapeBoundingRect.y());
2223
2224 QTransform newTransform = bakeTransform;
2225
2226 if (contentIsObb) {
2227 newTransform = relativeToShape * newTransform;
2228 }
2229
2230 if (contentIsViewBox) {
2231 newTransform = viewTransform(viewBoxRect, refRect) * newTransform;
2232 }
2233
2234 return newTransform.map(path);
2235 }
2236
2237 #include <KoBakedShapeRenderer.h>
2238
renderBakedPath(QPainter & painter,const QPainterPath & bakedFillPath,const QTransform & bakedTransform,const QRect & shapeOutline,const QTransform & shapeTransform,const QRectF & referenceRect,bool contentIsObb,const QRectF & bakedShapeBoundingRect,bool referenceIsObb,const QTransform & patternTransform,QImage * stampResult)2239 void renderBakedPath(QPainter &painter,
2240 const QPainterPath &bakedFillPath, const QTransform &bakedTransform,
2241 const QRect &shapeOutline, const QTransform &shapeTransform,
2242 const QRectF &referenceRect,
2243 bool contentIsObb, const QRectF &bakedShapeBoundingRect,
2244 bool referenceIsObb,
2245 const QTransform &patternTransform,
2246 QImage *stampResult)
2247 {
2248 painter.setTransform(QTransform());
2249 painter.setPen(Qt::NoPen);
2250
2251 QPainterPath shapeOutlinePath;
2252 shapeOutlinePath.addRect(shapeOutline);
2253
2254 KoBakedShapeRenderer renderer(
2255 shapeOutlinePath,
2256 shapeTransform,
2257 bakedTransform,
2258 referenceRect,
2259 contentIsObb, bakedShapeBoundingRect,
2260 referenceIsObb,
2261 patternTransform);
2262
2263 QPainter *patchPainter = renderer.bakeShapePainter();
2264 patchPainter->fillPath(bakedFillPath, Qt::blue);
2265 patchPainter->end();
2266
2267 renderer.renderShape(painter);
2268
2269 if (stampResult) {
2270 *stampResult = renderer.patchImage();
2271 }
2272 }
2273
testManualRenderPattern_ContentUser_RefObb()2274 void TestSvgParser::testManualRenderPattern_ContentUser_RefObb()
2275 {
2276 const QRectF referenceRect(0, 0, 1.0, 0.5);
2277
2278 QPainterPath fillPath;
2279 fillPath.addRect(QRect(2, 2, 6, 6));
2280 fillPath.addRect(QRect(8, 4, 3, 2));
2281
2282 QTransform bakedTransform = QTransform::fromTranslate(10, 10) * QTransform::fromScale(2, 2);
2283 QPainterPath bakedFillPath = bakeShape(fillPath, bakedTransform);
2284
2285 QRect shape1OutlineRect(0,0,10,20);
2286
2287 QImage stampResult;
2288 QImage fillResult(QSize(60,60), QImage::Format_ARGB32);
2289 QPainter gc(&fillResult);
2290
2291 fillResult.fill(0);
2292 renderBakedPath(gc,
2293 bakedFillPath, bakedTransform,
2294 shape1OutlineRect, bakedTransform,
2295 referenceRect,
2296 false, QRectF(),
2297 true,
2298 QTransform(),
2299 &stampResult);
2300
2301 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_user_r_obb_patch1"));
2302 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_user_r_obb_fill1"));
2303
2304 QRect shape2OutlineRect(5,5,20,10);
2305 QTransform shape2Transform = QTransform::fromScale(2, 2) * QTransform::fromTranslate(5, 5);
2306
2307 fillResult.fill(0);
2308 renderBakedPath(gc,
2309 bakedFillPath, bakedTransform,
2310 shape2OutlineRect, shape2Transform,
2311 referenceRect,
2312 false, QRectF(),
2313 true,
2314 QTransform(),
2315 &stampResult);
2316
2317 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_user_r_obb_patch2"));
2318 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_user_r_obb_fill2"));
2319 }
2320
testManualRenderPattern_ContentObb_RefObb()2321 void TestSvgParser::testManualRenderPattern_ContentObb_RefObb()
2322 {
2323 const QRectF referenceRect(0.3, 0.3, 0.4, 0.4);
2324
2325 QPainterPath fillPath;
2326 fillPath.addRect(QRectF(0.4, 0.4, 0.2, 0.2));
2327 fillPath.addRect(QRectF(0.6, 0.5, 0.1, 0.1));
2328 fillPath.addRect(QRectF(0.3, 0.4, 0.1, 0.1));
2329
2330
2331 const QRect bakedShapeRect(2,2,10,10);
2332 QTransform bakedTransform = QTransform::fromTranslate(10, 10) * QTransform::fromScale(2, 2);
2333
2334 QPainterPath bakedFillPath = bakeShape(fillPath, bakedTransform, true, bakedShapeRect);
2335
2336 QImage stampResult;
2337 QImage fillResult(QSize(60,60), QImage::Format_ARGB32);
2338 QPainter gc(&fillResult);
2339
2340 // Round trip to the same shape
2341
2342 fillResult.fill(0);
2343 renderBakedPath(gc,
2344 bakedFillPath, bakedTransform,
2345 bakedShapeRect, bakedTransform,
2346 referenceRect,
2347 true, bakedShapeRect,
2348 true,
2349 QTransform(),
2350 &stampResult);
2351
2352 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_obb_r_obb_patch1"));
2353 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_obb_r_obb_fill1"));
2354
2355 // Move to a different shape
2356
2357 QRect shape2OutlineRect(5,5,20,10);
2358 QTransform shape2Transform = QTransform::fromScale(2, 2) * QTransform::fromTranslate(5, 5);
2359
2360 fillResult.fill(0);
2361 renderBakedPath(gc,
2362 bakedFillPath, bakedTransform,
2363 shape2OutlineRect, shape2Transform,
2364 referenceRect,
2365 true, bakedShapeRect,
2366 true,
2367 QTransform(),
2368 &stampResult);
2369
2370 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_obb_r_obb_patch2"));
2371 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_obb_r_obb_fill2"));
2372 }
2373
testManualRenderPattern_ContentUser_RefUser()2374 void TestSvgParser::testManualRenderPattern_ContentUser_RefUser()
2375 {
2376 const QRectF referenceRect(5, 2, 8, 8);
2377
2378 QPainterPath fillPath;
2379 fillPath.addRect(QRect(2, 2, 6, 6));
2380 fillPath.addRect(QRect(8, 4, 3, 2));
2381
2382
2383 QTransform bakedTransform = QTransform::fromTranslate(10, 10) * QTransform::fromScale(2, 2);
2384 QPainterPath bakedFillPath = bakeShape(fillPath, bakedTransform);
2385
2386 QRect shape1OutlineRect(0,0,10,20);
2387
2388 QImage stampResult;
2389 QImage fillResult(QSize(60,60), QImage::Format_ARGB32);
2390 QPainter gc(&fillResult);
2391
2392 fillResult.fill(0);
2393 renderBakedPath(gc,
2394 bakedFillPath, bakedTransform,
2395 shape1OutlineRect, bakedTransform,
2396 referenceRect,
2397 false, QRectF(),
2398 false,
2399 QTransform(),
2400 &stampResult);
2401
2402 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_user_r_user_patch1"));
2403 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_user_r_user_fill1"));
2404
2405 QRect shape2OutlineRect(5,5,20,10);
2406 QTransform shape2Transform = QTransform::fromScale(2, 2) * QTransform::fromTranslate(5, 5);
2407
2408 fillResult.fill(0);
2409 renderBakedPath(gc,
2410 bakedFillPath, bakedTransform,
2411 shape2OutlineRect, shape2Transform,
2412 referenceRect,
2413 false, QRectF(),
2414 false,
2415 QTransform(),
2416 &stampResult);
2417
2418 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_user_r_user_patch2"));
2419 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_user_r_user_fill2"));
2420 }
2421
testManualRenderPattern_ContentObb_RefObb_Transform_Rotate()2422 void TestSvgParser::testManualRenderPattern_ContentObb_RefObb_Transform_Rotate()
2423 {
2424 const QRectF referenceRect(0.0, 0.0, 0.4, 0.2);
2425
2426 QPainterPath fillPath;
2427 fillPath.addRect(QRectF(0.0, 0.0, 0.5, 0.1));
2428 fillPath.addRect(QRectF(0.0, 0.1, 0.1, 0.1));
2429
2430 const QRect bakedShapeRect(2,1,10,10);
2431 QTransform bakedTransform = QTransform::fromScale(2, 2) * QTransform::fromTranslate(10,10);
2432
2433 QPainterPath bakedFillPath = bakeShape(fillPath, bakedTransform, true, bakedShapeRect);
2434
2435 QImage stampResult;
2436 QImage fillResult(QSize(60,60), QImage::Format_ARGB32);
2437 QPainter gc(&fillResult);
2438
2439 QTransform patternTransform;
2440 patternTransform.rotate(90);
2441 patternTransform = patternTransform * QTransform::fromTranslate(0.5, 0.0);
2442
2443 // Round trip to the same shape
2444
2445 fillResult.fill(0);
2446 renderBakedPath(gc,
2447 bakedFillPath, bakedTransform,
2448 bakedShapeRect, bakedTransform,
2449 referenceRect,
2450 true, bakedShapeRect,
2451 true,
2452 patternTransform,
2453 &stampResult);
2454
2455 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_obb_r_obb_rotate_patch1"));
2456 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_obb_r_obb_rotate_fill1"));
2457
2458 QRect shape2OutlineRect(5,5,20,10);
2459 QTransform shape2Transform = QTransform::fromScale(2, 2) * QTransform::fromTranslate(5, 5);
2460
2461 fillResult.fill(0);
2462 renderBakedPath(gc,
2463 bakedFillPath, bakedTransform,
2464 shape2OutlineRect, shape2Transform,
2465 referenceRect,
2466 true, bakedShapeRect,
2467 true,
2468 patternTransform,
2469 &stampResult);
2470
2471 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_obb_r_obb_rotate_patch2"));
2472 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_obb_r_obb_rotate_fill2"));
2473 }
2474
2475
testManualRenderPattern_ContentView_RefObb()2476 void TestSvgParser::testManualRenderPattern_ContentView_RefObb()
2477 {
2478 const QRectF referenceRect(0, 0, 0.5, 1.0/3.0);
2479 const QRectF viewRect(10,10,60,90);
2480
2481 QPainterPath fillPath;
2482 fillPath.addRect(QRect(30, 10, 20, 60));
2483 fillPath.addRect(QRect(50, 40, 20, 30));
2484
2485
2486 QRect shape1OutlineRect(10,20,40,120);
2487
2488 QTransform bakedTransform = QTransform::fromScale(2, 0.5) * QTransform::fromTranslate(40,30);
2489 QPainterPath bakedFillPath = bakeShape(fillPath, bakedTransform,
2490 true, shape1OutlineRect,
2491 true, viewRect, referenceRect);
2492
2493 QImage stampResult;
2494 QImage fillResult(QSize(220,160), QImage::Format_ARGB32);
2495 QPainter gc(&fillResult);
2496
2497 fillResult.fill(0);
2498 renderBakedPath(gc,
2499 bakedFillPath, bakedTransform,
2500 shape1OutlineRect, bakedTransform,
2501 referenceRect,
2502 true, shape1OutlineRect,
2503 true,
2504 QTransform(),
2505 &stampResult);
2506
2507 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_view_r_obb_patch1"));
2508 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_view_r_obb_fill1"));
2509
2510 QRect shape2OutlineRect(20,10,60,90);
2511 QTransform shape2Transform = QTransform::fromScale(2, 1) * QTransform::fromTranslate(50, 50);
2512
2513 fillResult.fill(0);
2514 renderBakedPath(gc,
2515 bakedFillPath, bakedTransform,
2516 shape2OutlineRect, shape2Transform,
2517 referenceRect,
2518 true, shape1OutlineRect,
2519 true,
2520 rotateTransform(90, QPointF(0, 1.0 / 3.0)),
2521 &stampResult);
2522
2523 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_view_r_obb_patch2"));
2524 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_view_r_obb_fill2"));
2525 }
2526
testManualRenderPattern_ContentView_RefUser()2527 void TestSvgParser::testManualRenderPattern_ContentView_RefUser()
2528 {
2529 const QRectF referenceRect(60, 0, 30, 20);
2530 const QRectF viewRect(10,10,60,90);
2531
2532 QPainterPath fillPath;
2533 fillPath.addRect(QRect(30, 10, 20, 60));
2534 fillPath.addRect(QRect(50, 40, 20, 30));
2535
2536
2537 QRect shape1OutlineRect(10,20,40,120);
2538
2539 QTransform bakedTransform = QTransform::fromScale(2, 0.5) * QTransform::fromTranslate(40,30);
2540 QPainterPath bakedFillPath = bakeShape(fillPath, bakedTransform,
2541 false, shape1OutlineRect,
2542 true, viewRect, referenceRect);
2543
2544 QImage stampResult;
2545 QImage fillResult(QSize(220,160), QImage::Format_ARGB32);
2546 QPainter gc(&fillResult);
2547
2548 fillResult.fill(0);
2549 renderBakedPath(gc,
2550 bakedFillPath, bakedTransform,
2551 shape1OutlineRect, bakedTransform,
2552 referenceRect,
2553 false, shape1OutlineRect,
2554 false,
2555 QTransform(),
2556 &stampResult);
2557
2558 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_view_r_user_patch1"));
2559 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_view_r_user_fill1"));
2560
2561 QRect shape2OutlineRect(20,10,60,90);
2562 QTransform shape2Transform = QTransform::fromScale(2, 1) * QTransform::fromTranslate(50, 50);
2563
2564 QTransform patternTransform2 = rotateTransform(90, QPointF()) * QTransform::fromTranslate(40, 10);
2565
2566 fillResult.fill(0);
2567 renderBakedPath(gc,
2568 bakedFillPath, bakedTransform,
2569 shape2OutlineRect, shape2Transform,
2570 referenceRect,
2571 false, shape1OutlineRect,
2572 false,
2573 patternTransform2,
2574 &stampResult);
2575
2576 QVERIFY(TestUtil::checkQImage(stampResult, "svg_render", "render", "pattern_c_view_r_user_patch2"));
2577 QVERIFY(TestUtil::checkQImage(fillResult, "svg_render", "render", "pattern_c_view_r_user_fill2"));
2578 }
2579
testRenderPattern_r_User_c_User()2580 void TestSvgParser::testRenderPattern_r_User_c_User()
2581 {
2582 const QString data =
2583 "<svg width=\"30px\" height=\"30px\""
2584 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2585
2586 "<defs>"
2587 " <pattern id=\"TestPattern\" patternUnits=\"userSpaceOnUse\""
2588 " patternContentUnits=\"userSpaceOnUse\""
2589 " x=\"60\" y=\"0\" width=\"30\" height=\"20\">"
2590
2591 " <g id=\"patternRect\">"
2592 " <rect id=\"patternRect1\" x=\"70\" y=\"0\" width=\"10\" height=\"13.3333\""
2593 " fill=\"red\" stroke=\"none\" />"
2594
2595 " <rect id=\"patternRect2\" x=\"80\" y=\"6.3333\" width=\"10\" height=\"6.6666\""
2596 " fill=\"red\" stroke=\"none\" />"
2597 " </g>"
2598
2599 " </pattern>"
2600 "</defs>"
2601
2602 "<g>"
2603 " <rect id=\"testRect\" x=\"10\" y=\"20\" width=\"40\" height=\"120\""
2604 " transform=\"translate(40 30) scale(2 0.5)\""
2605 " fill=\"url(#TestPattern)blue\" stroke=\"none\"/>"
2606 "</g>"
2607
2608 "</svg>";
2609
2610 SvgRenderTester t (data);
2611
2612 t.test_standard_30px_72ppi("fill_pattern_base", false, QSize(160, 160));
2613 }
2614
testRenderPattern_InfiniteRecursionWhenInherited()2615 void TestSvgParser::testRenderPattern_InfiniteRecursionWhenInherited()
2616 {
2617 const QString data =
2618 "<svg width=\"30px\" height=\"30px\""
2619 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2620
2621 "<defs>"
2622 " <pattern id=\"TestPattern\" patternUnits=\"userSpaceOnUse\""
2623 " patternContentUnits=\"userSpaceOnUse\""
2624 " x=\"60\" y=\"0\" width=\"30\" height=\"20\">"
2625
2626 " <g id=\"patternRect\">"
2627 " <rect id=\"patternRect1\" x=\"70\" y=\"0\" width=\"10\" height=\"13.3333\""
2628 " stroke=\"none\" />"
2629
2630 " <rect id=\"patternRect2\" x=\"80\" y=\"6.3333\" width=\"10\" height=\"6.6666\""
2631 " stroke=\"none\" />"
2632 " </g>"
2633
2634 " </pattern>"
2635 "</defs>"
2636
2637 "<g>"
2638 " <rect id=\"testRect\" x=\"10\" y=\"20\" width=\"40\" height=\"120\""
2639 " transform=\"translate(40 30) scale(2 0.5)\""
2640 " fill=\"url(#TestPattern)blue\" stroke=\"none\"/>"
2641 "</g>"
2642
2643 "</svg>";
2644
2645 SvgRenderTester t (data);
2646
2647 t.test_standard_30px_72ppi("fill_pattern_base_black", false, QSize(160, 160));
2648 }
2649
testRenderPattern_r_User_c_View()2650 void TestSvgParser::testRenderPattern_r_User_c_View()
2651 {
2652 const QString data =
2653 "<svg width=\"30px\" height=\"30px\""
2654 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2655
2656 "<defs>"
2657 " <pattern id=\"TestPattern\" patternUnits=\"userSpaceOnUse\""
2658 " viewBox=\"10 10 60 90\""
2659 " preserveAspectRatio=\"none meet\""
2660 " x=\"60\" y=\"0\" width=\"30\" height=\"20\">"
2661
2662 " <g id=\"patternRect\">"
2663 " <rect id=\"patternRect1\" x=\"30\" y=\"10\" width=\"20\" height=\"60\""
2664 " fill=\"red\" stroke=\"none\" />"
2665
2666 // y is changed to 39 from 40 to fix a rounding issue!
2667 " <rect id=\"patternRect2\" x=\"50\" y=\"39\" width=\"20\" height=\"30\""
2668 " fill=\"red\" stroke=\"none\" />"
2669 " </g>"
2670
2671 " </pattern>"
2672 "</defs>"
2673
2674 "<g>"
2675 " <rect id=\"testRect\" x=\"10\" y=\"20\" width=\"40\" height=\"120\""
2676 " transform=\"translate(40 30) scale(2 0.5)\""
2677 " fill=\"url(#TestPattern)blue\" stroke=\"none\"/>"
2678 "</g>"
2679
2680 "</svg>";
2681
2682 SvgRenderTester t (data);
2683
2684 t.test_standard_30px_72ppi("fill_pattern_base", false, QSize(160, 160));
2685 }
2686
testRenderPattern_r_User_c_Obb()2687 void TestSvgParser::testRenderPattern_r_User_c_Obb()
2688 {
2689 const QString data =
2690 "<svg width=\"30px\" height=\"30px\""
2691 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2692
2693 "<defs>"
2694 " <pattern id=\"TestPattern\" patternUnits=\"userSpaceOnUse\""
2695 " patternContentUnits=\"objectBoundingBox\""
2696 " x=\"60\" y=\"0\" width=\"30\" height=\"20\">"
2697
2698 " <g id=\"patternRect\">"
2699 " <rect id=\"patternRect1\" x=\"1.5\" y=\"-0.1666\" width=\"0.25\" height=\"0.111\""
2700 " fill=\"red\" stroke=\"none\" />"
2701
2702 " <rect id=\"patternRect2\" x=\"1.75\" y=\"-0.12\" width=\"0.25\" height=\"0.07\""
2703 " fill=\"red\" stroke=\"none\" />"
2704 " </g>"
2705
2706 " </pattern>"
2707 "</defs>"
2708
2709 "<g>"
2710 " <rect id=\"testRect\" x=\"10\" y=\"20\" width=\"40\" height=\"120\""
2711 " transform=\"translate(40 30) scale(2 0.5)\""
2712 " fill=\"url(#TestPattern)blue\" stroke=\"none\"/>"
2713 "</g>"
2714
2715 "</svg>";
2716
2717 SvgRenderTester t (data);
2718
2719 t.test_standard_30px_72ppi("fill_pattern_base", false, QSize(160, 160));
2720 }
2721
testRenderPattern_r_User_c_View_Rotated()2722 void TestSvgParser::testRenderPattern_r_User_c_View_Rotated()
2723 {
2724 const QString data =
2725 "<svg width=\"30px\" height=\"30px\""
2726 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2727
2728 "<defs>"
2729 " <pattern id=\"TestPattern\" patternUnits=\"userSpaceOnUse\""
2730 " viewBox=\"10 10 60 90\""
2731 " preserveAspectRatio=\"none meet\""
2732 " x=\"60\" y=\"0\" width=\"30\" height=\"20\""
2733 " patternTransform=\"translate(40 10) rotate(90)\">"
2734
2735 " <g id=\"patternRect\">"
2736 " <rect id=\"patternRect1\" x=\"30\" y=\"10\" width=\"20\" height=\"60\""
2737 " fill=\"red\" stroke=\"none\" />"
2738 " <rect id=\"patternRect2\" x=\"50\" y=\"40\" width=\"20\" height=\"30\""
2739 " fill=\"red\" stroke=\"none\" />"
2740 " </g>"
2741
2742 " </pattern>"
2743 "</defs>"
2744
2745 "<g>"
2746 " <rect id=\"testRect\" x=\"20\" y=\"10\" width=\"60\" height=\"90\""
2747 " transform=\"translate(50 50) scale(2 1)\""
2748 " fill=\"url(#TestPattern)blue\" stroke=\"none\"/>"
2749 "</g>"
2750
2751 "</svg>";
2752
2753 SvgRenderTester t (data);
2754
2755 t.test_standard_30px_72ppi("fill_pattern_rotated", false, QSize(220, 160));
2756 }
2757
testRenderPattern_r_Obb_c_View_Rotated()2758 void TestSvgParser::testRenderPattern_r_Obb_c_View_Rotated()
2759 {
2760 /**
2761 * This test case differs from any application existent in the world :(
2762 *
2763 * Chrome and Firefox premultiply the patternTransform instead of doing post-
2764 * multiplication. Photoshop forgets to multiply the reference rect on it.
2765 *
2766 * So...
2767 */
2768
2769 const QString data =
2770 "<svg width=\"30px\" height=\"30px\""
2771 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2772
2773 "<defs>"
2774 " <pattern id=\"TestPattern\" patternUnits=\"objectBoundingBox\""
2775 " viewBox=\"10 10 60 90\""
2776 " preserveAspectRatio=\"none meet\""
2777 " x=\"0\" y=\"0\" width=\"0.5\" height=\"0.333\""
2778 " patternTransform=\"translate(0 0) rotate(90)\">"
2779
2780 " <g id=\"patternRect\">"
2781 " <rect id=\"patternRect1\" x=\"30\" y=\"10\" width=\"20\" height=\"60\""
2782 " fill=\"red\" stroke=\"none\" />"
2783 " <rect id=\"patternRect2\" x=\"50\" y=\"40\" width=\"20\" height=\"30\""
2784 " fill=\"red\" stroke=\"none\" />"
2785 " </g>"
2786
2787 " </pattern>"
2788 "</defs>"
2789
2790 "<g>"
2791 " <rect id=\"testRect\" x=\"20\" y=\"10\" width=\"60\" height=\"90\""
2792 " transform=\"translate(50 50) scale(1 1)\""
2793 " fill=\"url(#TestPattern)blue\" stroke=\"none\"/>"
2794 "</g>"
2795
2796 "</svg>";
2797
2798 SvgRenderTester t (data);
2799
2800 t.test_standard_30px_72ppi("fill_pattern_rotated_odd", false, QSize(220, 160));
2801 }
2802
2803 #include <KoPathShape.h>
2804 #include <KoColorBackground.h>
2805 #include <KoClipPath.h>
2806 #include <commands/KoShapeGroupCommand.h>
2807
testKoClipPathRendering()2808 void TestSvgParser::testKoClipPathRendering()
2809 {
2810 QPainterPath path1;
2811 path1.addRect(QRect(5,5,15,15));
2812
2813 QPainterPath path2;
2814 path2.addRect(QRect(10,10,15,15));
2815
2816 QPainterPath clipPath1;
2817 clipPath1.addRect(QRect(10, 0, 10, 30));
2818
2819 QPainterPath clipPath2;
2820 clipPath2.moveTo(0,7);
2821 clipPath2.lineTo(30,7);
2822 clipPath2.lineTo(15,30);
2823 clipPath2.lineTo(0,7);
2824
2825 QScopedPointer<KoPathShape> shape1(KoPathShape::createShapeFromPainterPath(path1));
2826 shape1->setBackground(QSharedPointer<KoColorBackground>(new KoColorBackground(Qt::blue)));
2827
2828 QScopedPointer<KoPathShape> shape2(KoPathShape::createShapeFromPainterPath(path2));
2829 shape2->setBackground(QSharedPointer<KoColorBackground>(new KoColorBackground(Qt::red)));
2830
2831 QScopedPointer<KoPathShape> clipShape1(KoPathShape::createShapeFromPainterPath(clipPath1));
2832 KoClipPath *koClipPath1 = new KoClipPath({clipShape1.take()}, KoFlake::UserSpaceOnUse);
2833 koClipPath1->setClipRule(Qt::WindingFill);
2834 shape1->setClipPath(koClipPath1);
2835
2836 QScopedPointer<KoShapeGroup> group(new KoShapeGroup());
2837 {
2838 QList<KoShape*> shapes({shape1.take(), shape2.take()});
2839
2840 KoShapeGroupCommand cmd(group.data(), shapes, false);
2841 cmd.redo();
2842 }
2843
2844 QScopedPointer<KoPathShape> clipShape2(KoPathShape::createShapeFromPainterPath(clipPath2));
2845 KoClipPath *koClipPath2 = new KoClipPath({clipShape2.take()}, KoFlake::UserSpaceOnUse);
2846 koClipPath2->setClipRule(Qt::WindingFill);
2847 group->setClipPath(koClipPath2);
2848
2849 SvgRenderTester::testRender(group.take(), "load", "clip_render_test", QSize(30,30));
2850 }
2851
testKoClipPathRelativeRendering()2852 void TestSvgParser::testKoClipPathRelativeRendering()
2853 {
2854 QPainterPath path1;
2855 path1.addRect(QRect(5,5,15,15));
2856
2857 QPainterPath path2;
2858 path2.addRect(QRect(10,10,15,15));
2859
2860 QPainterPath clipPath1;
2861 clipPath1.addRect(QRect(10, 0, 10, 30));
2862
2863 QPainterPath clipPath2;
2864 clipPath2.moveTo(0,0);
2865 clipPath2.lineTo(1,0);
2866 clipPath2.lineTo(0.5,1);
2867 clipPath2.lineTo(0,0);
2868
2869 QScopedPointer<KoPathShape> shape1(KoPathShape::createShapeFromPainterPath(path1));
2870 shape1->setBackground(QSharedPointer<KoColorBackground>(new KoColorBackground(Qt::blue)));
2871
2872 QScopedPointer<KoPathShape> shape2(KoPathShape::createShapeFromPainterPath(path2));
2873 shape2->setBackground(QSharedPointer<KoColorBackground>(new KoColorBackground(Qt::red)));
2874
2875 QScopedPointer<KoPathShape> clipShape1(KoPathShape::createShapeFromPainterPath(clipPath1));
2876 KoClipPath *koClipPath1 = new KoClipPath({clipShape1.take()}, KoFlake::UserSpaceOnUse);
2877 koClipPath1->setClipRule(Qt::WindingFill);
2878 shape1->setClipPath(koClipPath1);
2879
2880 QScopedPointer<KoShapeGroup> group(new KoShapeGroup());
2881 {
2882 QList<KoShape*> shapes({shape1.take(), shape2.take()});
2883
2884 KoShapeGroupCommand cmd(group.data(), shapes, false);
2885 cmd.redo();
2886 }
2887
2888 QScopedPointer<KoPathShape> clipShape2(KoPathShape::createShapeFromPainterPath(clipPath2));
2889 KoClipPath *koClipPath2 = new KoClipPath({clipShape2.take()}, KoFlake::ObjectBoundingBox);
2890 koClipPath2->setClipRule(Qt::WindingFill);
2891 group->setClipPath(koClipPath2);
2892
2893 SvgRenderTester::testRender(group.take(), "load", "relative_clip_render_test", QSize(30,30));
2894 }
2895
testRenderClipPath_User()2896 void TestSvgParser::testRenderClipPath_User()
2897 {
2898 const QString data =
2899 "<svg width=\"30px\" height=\"30px\""
2900 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2901
2902 "<clipPath id=\"clip1\" clipPathUnits=\"userSpaceOnUse\">"
2903 " <rect id=\"clipRect1\" x=\"10\" y=\"0\" width=\"10\" height=\"30\""
2904 " fill=\"red\" stroke=\"none\" />"
2905 " <rect id=\"clipRect1\" x=\"10\" y=\"0\" width=\"10\" height=\"30\""
2906 " fill=\"yellow\" stroke=\"none\" />"
2907 "</clipPath>"
2908
2909 "<clipPath id=\"clip2\" clipPathUnits=\"userSpaceOnUse\">"
2910 " <path id=\"clipRect1\" d=\"M 0 7 L 30 7 15 30 0 7 z\""
2911 " fill=\"red\" stroke=\"none\" />"
2912 "</clipPath>"
2913
2914 "<g id=\"testRect\" clip-path=\"url(#clip2)\">"
2915 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"15\""
2916 " fill=\"blue\" stroke=\"none\" clip-path=\"url(#clip1)\"/>"
2917
2918 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
2919 " fill=\"red\" stroke=\"none\"/>"
2920 "</g>"
2921
2922 "</svg>";
2923
2924 SvgRenderTester t (data);
2925
2926 t.test_standard_30px_72ppi("clip_render_test", false);
2927 }
2928
testRenderClipPath_Obb()2929 void TestSvgParser::testRenderClipPath_Obb()
2930 {
2931 const QString data =
2932 "<svg width=\"30px\" height=\"30px\""
2933 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2934
2935 "<clipPath id=\"clip1\" clipPathUnits=\"userSpaceOnUse\">"
2936 " <rect id=\"clipRect1\" x=\"10\" y=\"0\" width=\"10\" height=\"30\""
2937 " fill=\"red\" stroke=\"none\" />"
2938 " <rect id=\"clipRect1\" x=\"10\" y=\"0\" width=\"10\" height=\"30\""
2939 " fill=\"yellow\" stroke=\"none\" />"
2940 "</clipPath>"
2941
2942 "<clipPath id=\"clip2\" clipPathUnits=\"objectBoundingBox\">"
2943 " <path id=\"clipRect1\" d=\"M 0 0 L 1 0 0.5 1 0 0 z\""
2944 " fill=\"red\" stroke=\"none\" />"
2945 "</clipPath>"
2946
2947 "<g id=\"testRect\" clip-path=\"url(#clip2)\">"
2948 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"15\""
2949 " fill=\"blue\" stroke=\"none\" clip-path=\"url(#clip1)\"/>"
2950
2951 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
2952 " fill=\"red\" stroke=\"none\"/>"
2953 "</g>"
2954
2955 "</svg>";
2956
2957 SvgRenderTester t (data);
2958
2959 t.test_standard_30px_72ppi("relative_clip_render_test", false);
2960 }
2961
testRenderClipPath_Obb_Transform()2962 void TestSvgParser::testRenderClipPath_Obb_Transform()
2963 {
2964 const QString data =
2965 "<svg width=\"30px\" height=\"30px\""
2966 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
2967
2968 "<clipPath id=\"clip1\" clipPathUnits=\"userSpaceOnUse\""
2969 " transform=\"rotate(90,15,15)\">"
2970 " <rect id=\"clipRect1\" x=\"10\" y=\"0\" width=\"10\" height=\"30\""
2971 " fill=\"red\" stroke=\"none\" />"
2972 " <rect id=\"clipRect1\" x=\"10\" y=\"0\" width=\"10\" height=\"30\""
2973 " fill=\"yellow\" stroke=\"none\" />"
2974 "</clipPath>"
2975
2976 "<clipPath id=\"clip2\" clipPathUnits=\"objectBoundingBox\""
2977 " transform=\"rotate(90 0.5 0.5)\">"
2978 " <path id=\"clipRect1\" d=\"M 0 0 L 1 0 0.5 1 0 0 z\""
2979 " fill=\"red\" stroke=\"none\" />"
2980 "</clipPath>"
2981
2982 "<g id=\"testRect\" clip-path=\"url(#clip2)\">"
2983 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"15\""
2984 " fill=\"blue\" stroke=\"none\" clip-path=\"url(#clip1)\"/>"
2985
2986 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
2987 " fill=\"red\" stroke=\"none\"/>"
2988 "</g>"
2989
2990 "</svg>";
2991
2992 SvgRenderTester t (data);
2993
2994 t.test_standard_30px_72ppi("clip_render_test_rotated", false);
2995 }
2996
testRenderClipMask_Obb()2997 void TestSvgParser::testRenderClipMask_Obb()
2998 {
2999 const QString data =
3000 "<svg width=\"30px\" height=\"30px\""
3001 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3002
3003 "<defs>"
3004
3005 " <linearGradient id=\"Gradient\" gradientUnits=\"objectBoundingBox\""
3006 " x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">"
3007
3008 " <stop offset=\"0\" stop-color=\"white\" stop-opacity=\"0\" />"
3009 " <stop offset=\"1\" stop-color=\"white\" stop-opacity=\"1\" />"
3010
3011 " </linearGradient>"
3012
3013 " <mask id=\"Mask\" maskUnits=\"objectBoundingBox\""
3014 " maskContentUnits=\"objectBoundingBox\""
3015 " x=\"0.2\" y=\"0.2\" width=\"0.6\" height=\"0.6\">"
3016
3017 " <rect x=\"0\" y=\"0\" width=\"1\" height=\"1\" fill=\"url(#Gradient)\" />"
3018
3019 " </mask>"
3020
3021 "</defs>"
3022
3023
3024 "<g id=\"testRect\">"
3025 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"15\""
3026 " fill=\"blue\" stroke=\"none\"/>"
3027
3028 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
3029 " fill=\"red\" stroke=\"none\" mask=\"url(#Mask)\" />"
3030 "</g>"
3031
3032 "</svg>";
3033
3034 SvgRenderTester t (data);
3035
3036 t.test_standard_30px_72ppi("clip_mask_obb", false);
3037 }
3038
testRenderClipMaskOnGroup_Obb()3039 void TestSvgParser::testRenderClipMaskOnGroup_Obb()
3040 {
3041 const QString data =
3042 "<svg width=\"30px\" height=\"30px\""
3043 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3044
3045 "<defs>"
3046
3047 " <linearGradient id=\"Gradient\" gradientUnits=\"objectBoundingBox\""
3048 " x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">"
3049
3050 " <stop offset=\"0\" stop-color=\"white\" stop-opacity=\"0\" />"
3051 " <stop offset=\"1\" stop-color=\"white\" stop-opacity=\"1\" />"
3052
3053 " </linearGradient>"
3054
3055 " <mask id=\"Mask\" maskUnits=\"objectBoundingBox\""
3056 " maskContentUnits=\"objectBoundingBox\""
3057 " x=\"0.2\" y=\"0.2\" width=\"0.6\" height=\"0.6\">"
3058
3059 " <rect x=\"0\" y=\"0\" width=\"1\" height=\"1\" fill=\"url(#Gradient)\" />"
3060
3061 " </mask>"
3062
3063 "</defs>"
3064
3065
3066 "<g id=\"testRect\" mask=\"url(#Mask)\">"
3067 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"15\""
3068 " fill=\"blue\" stroke=\"none\"/>"
3069
3070 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
3071 " fill=\"red\" stroke=\"none\" />"
3072 "</g>"
3073
3074 "</svg>";
3075
3076 SvgRenderTester t (data);
3077
3078 t.test_standard_30px_72ppi("clip_mask_on_group_obb", false);
3079 }
3080
fileFetcherFunc(const QString & name)3081 QByteArray fileFetcherFunc(const QString &name)
3082 {
3083 const QString fileName = TestUtil::fetchDataFileLazy(name);
3084 QFile file(fileName);
3085 KIS_ASSERT(file.exists());
3086 file.open(QIODevice::ReadOnly);
3087 return file.readAll();
3088 }
3089
testRenderClipMask_User_Clip_Obb()3090 void TestSvgParser::testRenderClipMask_User_Clip_Obb()
3091 {
3092 const QString data =
3093 "<svg width=\"30px\" height=\"30px\""
3094 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3095
3096 //"<defs>"
3097
3098 " <linearGradient id=\"Gradient\" gradientUnits=\"objectBoundingBox\""
3099 " x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">"
3100
3101 " <stop offset=\"0\" stop-color=\"white\" stop-opacity=\"0\" />"
3102 " <stop offset=\"1\" stop-color=\"white\" stop-opacity=\"1\" />"
3103
3104 " </linearGradient>"
3105
3106 " <mask id=\"Mask\" maskUnits=\"objectBoundingBox\""
3107 " maskContentUnits=\"userSpaceOnUse\""
3108 " x=\"0.2\" y=\"0.2\" width=\"0.6\" height=\"0.6\">"
3109
3110 " <rect x=\"10\" y=\"10\" width=\"15\" height=\"15\" fill=\"url(#Gradient)\" />"
3111
3112 " </mask>"
3113
3114 //"</defs>"
3115
3116
3117 "<g id=\"testRect\">"
3118 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"15\""
3119 " fill=\"blue\" stroke=\"none\"/>"
3120
3121 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
3122 " fill=\"red\" stroke=\"none\" mask=\"url(#Mask)\" />"
3123 "</g>"
3124
3125 "</svg>";
3126
3127 SvgRenderTester t (data);
3128
3129 t.test_standard_30px_72ppi("clip_mask_obb", false);
3130 }
3131
testRenderClipMask_User_Clip_User()3132 void TestSvgParser::testRenderClipMask_User_Clip_User()
3133 {
3134 const QString data =
3135 "<svg width=\"30px\" height=\"30px\""
3136 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3137
3138 //"<defs>"
3139
3140 " <linearGradient id=\"Gradient\" gradientUnits=\"objectBoundingBox\""
3141 " x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">"
3142
3143 " <stop offset=\"0\" stop-color=\"white\" stop-opacity=\"0\" />"
3144 " <stop offset=\"1\" stop-color=\"white\" stop-opacity=\"1\" />"
3145
3146 " </linearGradient>"
3147
3148 " <mask id=\"Mask\" maskUnits=\"userSpaceOnUse\""
3149 " maskContentUnits=\"userSpaceOnUse\""
3150 " x=\"13\" y=\"13\" width=\"9\" height=\"9\">"
3151
3152 " <rect x=\"10\" y=\"10\" width=\"15\" height=\"15\" fill=\"url(#Gradient)\" />"
3153
3154 " </mask>"
3155
3156 //"</defs>"
3157
3158
3159 "<g id=\"testRect\">"
3160 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"15\""
3161 " fill=\"blue\" stroke=\"none\"/>"
3162
3163 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
3164 " fill=\"red\" stroke=\"none\" mask=\"url(#Mask)\" />"
3165 "</g>"
3166
3167 "</svg>";
3168
3169 SvgRenderTester t (data);
3170
3171 t.test_standard_30px_72ppi("clip_mask_obb", false);
3172 }
3173
testRenderImage_AspectDefault()3174 void TestSvgParser::testRenderImage_AspectDefault()
3175 {
3176 const QString data =
3177 "<svg width=\"30px\" height=\"30px\""
3178 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3179
3180 "<g id=\"testRect\">"
3181 " <rect id=\"testRect1\" x=\"2\" y=\"2\" width=\"26\" height=\"26\""
3182 " fill=\"green\" stroke=\"none\"/>"
3183
3184 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"10\""
3185 " fill=\"white\" stroke=\"none\"/>"
3186
3187
3188 " <image x=\"5\" y=\"5\" width=\"15\" height=\"10\""
3189 " xlink:href=\"svg_render/testing_ref_image.png\">"
3190
3191 " <title>My image</title>"
3192
3193 " </image>"
3194
3195 "</g>"
3196
3197 "</svg>";
3198
3199 SvgRenderTester t (data);
3200 t.parser.setFileFetcher(fileFetcherFunc);
3201
3202 t.test_standard_30px_72ppi("image_aspect_default", false);
3203 }
3204
testRenderImage_AspectNone()3205 void TestSvgParser::testRenderImage_AspectNone()
3206 {
3207 const QString data =
3208 "<svg width=\"30px\" height=\"30px\""
3209 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3210
3211 "<g id=\"testRect\">"
3212 " <rect id=\"testRect1\" x=\"2\" y=\"2\" width=\"26\" height=\"26\""
3213 " fill=\"green\" stroke=\"none\"/>"
3214
3215 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"10\""
3216 " fill=\"white\" stroke=\"none\"/>"
3217
3218
3219 " <image x=\"5\" y=\"5\" width=\"15\" height=\"10\""
3220 " preserveAspectRatio=\"none\""
3221 " xlink:href=\"svg_render/testing_ref_image.png\">"
3222
3223 " <title>My image</title>"
3224
3225 " </image>"
3226
3227 "</g>"
3228
3229 "</svg>";
3230
3231 SvgRenderTester t (data);
3232 t.setFuzzyThreshold(5);
3233 t.parser.setFileFetcher(fileFetcherFunc);
3234
3235 t.test_standard_30px_72ppi("image_aspect_none", false);
3236 }
3237
testRenderImage_AspectMeet()3238 void TestSvgParser::testRenderImage_AspectMeet()
3239 {
3240 const QString data =
3241 "<svg width=\"30px\" height=\"30px\""
3242 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3243
3244 "<g id=\"testRect\">"
3245 " <rect id=\"testRect1\" x=\"2\" y=\"2\" width=\"26\" height=\"26\""
3246 " fill=\"green\" stroke=\"none\"/>"
3247
3248 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"10\""
3249 " fill=\"white\" stroke=\"none\"/>"
3250
3251
3252 " <image x=\"5\" y=\"5\" width=\"15\" height=\"10\""
3253 " preserveAspectRatio=\"xMinYMin meet\""
3254 " xlink:href=\"svg_render/testing_ref_image.png\">"
3255
3256 " <title>My image</title>"
3257
3258 " </image>"
3259
3260 "</g>"
3261
3262 "</svg>";
3263
3264 SvgRenderTester t (data);
3265 t.parser.setFileFetcher(fileFetcherFunc);
3266
3267 t.test_standard_30px_72ppi("image_aspect_meet", false);
3268 }
3269
testRectShapeRoundUniformX()3270 void TestSvgParser::testRectShapeRoundUniformX()
3271 {
3272 const QString data =
3273 "<svg width=\"30px\" height=\"30px\""
3274 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3275
3276 " <rect id=\"testRect\" x=\"5\" y=\"5\" width=\"20\" height=\"20\""
3277 " rx=\"5\""
3278 " fill=\"blue\" stroke=\"none\"/>"
3279
3280 "</svg>";
3281
3282 SvgRenderTester t (data);
3283
3284 t.test_standard_30px_72ppi("rect_5_5", false);
3285 }
3286
testRectShapeRoundUniformY()3287 void TestSvgParser::testRectShapeRoundUniformY()
3288 {
3289 const QString data =
3290 "<svg width=\"30px\" height=\"30px\""
3291 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3292
3293 " <rect id=\"testRect\" x=\"5\" y=\"5\" width=\"20\" height=\"20\""
3294 " rx=\"5\""
3295 " fill=\"blue\" stroke=\"none\"/>"
3296
3297 "</svg>";
3298
3299 SvgRenderTester t (data);
3300
3301 t.test_standard_30px_72ppi("rect_5_5", false);
3302 }
3303
testRectShapeRoundXY()3304 void TestSvgParser::testRectShapeRoundXY()
3305 {
3306 const QString data =
3307 "<svg width=\"30px\" height=\"30px\""
3308 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3309
3310 " <rect id=\"testRect\" x=\"5\" y=\"5\" width=\"20\" height=\"20\""
3311 " rx=\"5\" ry=\"10\""
3312 " fill=\"blue\" stroke=\"none\"/>"
3313
3314 "</svg>";
3315
3316 SvgRenderTester t (data);
3317
3318 t.test_standard_30px_72ppi("rect_5_10", false);
3319 }
3320
testRectShapeRoundXYOverflow()3321 void TestSvgParser::testRectShapeRoundXYOverflow()
3322 {
3323 const QString data =
3324 "<svg width=\"30px\" height=\"30px\""
3325 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3326
3327 " <rect id=\"testRect\" x=\"5\" y=\"5\" width=\"20\" height=\"20\""
3328 " rx=\"5\" ry=\"25\""
3329 " fill=\"blue\" stroke=\"none\"/>"
3330
3331 "</svg>";
3332
3333 SvgRenderTester t (data);
3334
3335 t.test_standard_30px_72ppi("rect_5_10", false);
3336 }
3337
testCircleShape()3338 void TestSvgParser::testCircleShape()
3339 {
3340 const QString data =
3341 "<svg width=\"30px\" height=\"30px\""
3342 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3343
3344 " <circle id=\"testRect\" cx=\"15\" cy=\"15\" r=\"10\""
3345 " fill=\"blue\" stroke=\"white\"/>"
3346
3347 "</svg>";
3348
3349 SvgRenderTester t (data);
3350
3351 t.test_standard_30px_72ppi("circle", false);
3352 }
3353
testEllipseShape()3354 void TestSvgParser::testEllipseShape()
3355 {
3356 const QString data =
3357 "<svg width=\"30px\" height=\"30px\""
3358 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3359
3360 " <ellipse id=\"testRect\" cx=\"15\" cy=\"15\" rx=\"10\" ry=\"5\""
3361 " fill=\"blue\" stroke=\"white\"/>"
3362
3363 "</svg>";
3364
3365 SvgRenderTester t (data);
3366
3367 t.test_standard_30px_72ppi("ellipse", false);
3368 }
3369
testLineShape()3370 void TestSvgParser::testLineShape()
3371 {
3372 const QString data =
3373 "<svg width=\"30px\" height=\"30px\""
3374 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3375
3376 " <line id=\"testRect\" x1=\"5\" y1=\"5\" x2=\"25\" y2=\"15\""
3377 " fill=\"blue\" stroke=\"white\"/>"
3378
3379 "</svg>";
3380
3381 SvgRenderTester t (data);
3382
3383 t.test_standard_30px_72ppi("line", false);
3384 }
3385
testPolylineShape()3386 void TestSvgParser::testPolylineShape()
3387 {
3388 const QString data =
3389 "<svg width=\"30px\" height=\"30px\""
3390 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3391
3392 " <polyline id=\"testRect\" points=\"5,5 10, 5 10,10 5,10 \n"
3393 " 5 ,15 15 , 15 15,20 20,20 20,10 25,10 25,25 5,25\""
3394 " fill=\"red\" stroke=\"white\"/>"
3395
3396 "</svg>";
3397
3398 SvgRenderTester t (data);
3399
3400 t.test_standard_30px_72ppi("polyline", false);
3401 }
3402
testPolygonShape()3403 void TestSvgParser::testPolygonShape()
3404 {
3405 const QString data =
3406 "<svg width=\"30px\" height=\"30px\""
3407 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3408
3409 " <polygon id=\"testRect\" points=\"5,5 10, 5 10,10 5,10 \n"
3410 " 5 ,15 15 , 15 15,20 20,20 20,10 25,10 25,25 5,25\""
3411 " fill=\"red\" stroke=\"white\"/>"
3412
3413 "</svg>";
3414
3415 SvgRenderTester t (data);
3416
3417 t.test_standard_30px_72ppi("polygon", false);
3418 }
3419
testPathShape()3420 void TestSvgParser::testPathShape()
3421 {
3422 const QString data =
3423 "<svg width=\"30px\" height=\"30px\""
3424 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3425
3426 " <path id=\"testRect\""
3427 " d=\"M 5,5 h 5 l 0,5 L5,10 l 0,5 l10,0 v5 l 5, 0 L20, 10 l 5,0 L 25,25 L 5,25 z\""
3428 " fill=\"red\" stroke=\"white\"/>"
3429
3430 "</svg>";
3431
3432 SvgRenderTester t (data);
3433
3434 t.test_standard_30px_72ppi("polygon", false);
3435 }
3436
testDefsHidden()3437 void TestSvgParser::testDefsHidden()
3438 {
3439 const QString data =
3440 "<svg width=\"30px\" height=\"30px\""
3441 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3442
3443 "<g id=\"testRect\">"
3444 " <defs>"
3445 " <rect id=\"testRect1\" x=\"5\" y=\"5\" width=\"15\" height=\"15\""
3446 " fill=\"blue\" stroke=\"none\"/>"
3447 " </defs>"
3448
3449 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
3450 " fill=\"red\" stroke=\"none\"/>"
3451 "</g>"
3452
3453 "</svg>";
3454
3455 SvgRenderTester t (data);
3456
3457 t.test_standard_30px_72ppi("test_defs_hidden", false);
3458 }
3459
testDefsUseInheritance()3460 void TestSvgParser::testDefsUseInheritance()
3461 {
3462 const QString data =
3463 "<svg width=\"30px\" height=\"30px\""
3464 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3465
3466
3467
3468 "<g id=\"unrenderedRect\" fill=\"green\" >"
3469 " <defs>"
3470 " <rect id=\"testRect1\" x=\"1\" y=\"1\" width=\"15\" height=\"15\""
3471 " stroke=\"none\"/>"
3472 " </defs>"
3473 "</g>"
3474
3475
3476 /**
3477 * NOTES:
3478 * 1) width/height attributes for <use> are not implemented yet
3479 * 2) x and y are summed up
3480 * 3) stroke="white" is overridden by the original templated object
3481 * 4) fill="green" attribute from <defs> is not inherited
3482 */
3483
3484 "<g id=\"testRect\" fill=\"blue\" >"
3485 " <use x=\"4\" y=\"4\" xlink:href=\"#testRect1\""
3486 " stroke=\"white\" stroke-width=\"1\" />"
3487
3488 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
3489 " fill=\"red\" stroke=\"none\"/>"
3490 "</g>"
3491
3492 "</svg>";
3493
3494 SvgRenderTester t (data);
3495
3496 t.test_standard_30px_72ppi("defs_use_inheritance", false);
3497 }
3498
testUseWithoutDefs()3499 void TestSvgParser::testUseWithoutDefs()
3500 {
3501 const QString data =
3502 "<svg width=\"30px\" height=\"30px\""
3503 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3504
3505 // technical rect for rendering
3506 "<g id=\"testRect\">"
3507
3508 "<g id=\"renderedRect1\" fill=\"green\" >"
3509 " <rect id=\"testRect1\" x=\"1\" y=\"1\" width=\"15\" height=\"15\""
3510 " stroke=\"none\"/>"
3511 "</g>"
3512
3513
3514 /**
3515 * NOTES:
3516 * 1) width/height attributes for <use> are not implemented yet
3517 * 2) x and y are summed up
3518 * 3) stroke="white" is overridden by the original templated object
3519 * 4) fill="green" attribute from <defs> is not inherited
3520 */
3521
3522 "<g id=\"renderedRect2\" fill=\"blue\" >"
3523 " <use x=\"4\" y=\"4\" xlink:href=\"#testRect1\""
3524 " stroke=\"white\" stroke-width=\"1\" />"
3525
3526 " <rect id=\"testRect2\" x=\"10\" y=\"10\" width=\"15\" height=\"15\""
3527 " fill=\"red\" stroke=\"none\"/>"
3528 "</g>"
3529
3530 "</g>"
3531
3532 "</svg>";
3533
3534 SvgRenderTester t (data);
3535
3536 t.test_standard_30px_72ppi("use_without_defs", false);
3537 }
3538
testMarkersAutoOrientation()3539 void TestSvgParser::testMarkersAutoOrientation()
3540 {
3541 const QString data =
3542 "<svg width=\"30px\" height=\"30px\""
3543 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3544
3545 "<marker id=\"SimpleRectMarker\""
3546 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3547
3548 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3549 " fill=\"red\" stroke=\"none\"/>"
3550 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3551 " fill=\"yellow\" stroke=\"none\"/>"
3552 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3553 " fill=\"white\" stroke=\"none\"/>"
3554 "</marker>"
3555
3556 "<path id=\"testRect\""
3557 " style=\"fill:none;stroke:#000000;stroke-width:1px;marker-start:url(#SimpleRectMarker);marker-end:url(#SimpleRectMarker);marker-mid:url(#SimpleRectMarker)\""
3558 " d=\"M5,15 C5,5 25,5 25,15 L15,25\"/>"
3559
3560 "</svg>";
3561
3562 SvgRenderTester t (data);
3563
3564 t.test_standard_30px_72ppi("markers", false);
3565 }
3566
testMarkersAutoOrientationScaled()3567 void TestSvgParser::testMarkersAutoOrientationScaled()
3568 {
3569 const QString data =
3570 "<svg width=\"30px\" height=\"30px\""
3571 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3572
3573 "<marker id=\"SimpleRectMarker\""
3574 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3575
3576 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3577 " fill=\"red\" stroke=\"none\"/>"
3578 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3579 " fill=\"yellow\" stroke=\"none\"/>"
3580 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3581 " fill=\"white\" stroke=\"none\"/>"
3582 "</marker>"
3583
3584 "<path id=\"testRect\""
3585 " style=\"fill:none;stroke:#000000;stroke-width:2px;marker-start:url(#SimpleRectMarker);marker-end:url(#SimpleRectMarker);marker-mid:url(#SimpleRectMarker)\""
3586 " d=\"M5,15 C5,5 25,5 25,15 L15,25\"/>"
3587
3588 "</svg>";
3589
3590 SvgRenderTester t (data);
3591
3592 t.test_standard_30px_72ppi("markers_scaled", false);
3593 }
3594
testMarkersAutoOrientationScaledUserCoordinates()3595 void TestSvgParser::testMarkersAutoOrientationScaledUserCoordinates()
3596 {
3597 const QString data =
3598 "<svg width=\"30px\" height=\"30px\""
3599 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3600
3601 "<marker id=\"SimpleRectMarker\""
3602 " markerUnits = \"userSpaceOnUse\""
3603 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3604
3605 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3606 " fill=\"red\" stroke=\"none\"/>"
3607 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3608 " fill=\"yellow\" stroke=\"none\"/>"
3609 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3610 " fill=\"white\" stroke=\"none\"/>"
3611 "</marker>"
3612
3613 "<path id=\"testRect\""
3614 " style=\"fill:none;stroke:#000000;stroke-width:2px;marker-start:url(#SimpleRectMarker);marker-end:url(#SimpleRectMarker);marker-mid:url(#SimpleRectMarker)\""
3615 " d=\"M5,15 C5,5 25,5 25,15 L15,25\"/>"
3616
3617 "</svg>";
3618
3619 SvgRenderTester t (data);
3620
3621 t.test_standard_30px_72ppi("markers_user_coordinates", false);
3622 }
3623
testMarkersCustomOrientation()3624 void TestSvgParser::testMarkersCustomOrientation()
3625 {
3626 const QString data =
3627 "<svg width=\"30px\" height=\"30px\""
3628 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3629
3630 "<marker id=\"SimpleRectMarker\""
3631 " orient=\"45\" refY=\"12.5\" refX=\"12.5\" >"
3632
3633 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3634 " fill=\"red\" stroke=\"none\"/>"
3635 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3636 " fill=\"yellow\" stroke=\"none\"/>"
3637 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3638 " fill=\"white\" stroke=\"none\"/>"
3639 "</marker>"
3640
3641 "<path id=\"testRect\""
3642 " style=\"fill:none;stroke:#000000;stroke-width:1px;marker-start:url(#SimpleRectMarker);marker-end:url(#SimpleRectMarker);marker-mid:url(#SimpleRectMarker)\""
3643 " d=\"M5,15 C5,5 25,5 25,15 L15,25\"/>"
3644
3645 "</svg>";
3646
3647 SvgRenderTester t (data);
3648
3649 t.test_standard_30px_72ppi("markers_custom_orientation", false);
3650 }
3651
testMarkersDifferent()3652 void TestSvgParser::testMarkersDifferent()
3653 {
3654 const QString data =
3655 "<svg width=\"30px\" height=\"30px\""
3656 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3657
3658 "<marker id=\"SimpleRectMarker1\""
3659 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3660
3661 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3662 " fill=\"red\" stroke=\"none\"/>"
3663 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3664 " fill=\"yellow\" stroke=\"none\"/>"
3665 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3666 " fill=\"white\" stroke=\"none\"/>"
3667 "</marker>"
3668
3669 "<marker id=\"SimpleRectMarker2\""
3670 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3671
3672 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3673 " fill=\"green\" stroke=\"none\"/>"
3674 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3675 " fill=\"yellow\" stroke=\"none\"/>"
3676 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3677 " fill=\"white\" stroke=\"none\"/>"
3678 "</marker>"
3679
3680 "<marker id=\"SimpleRectMarker3\""
3681 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3682
3683 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3684 " fill=\"blue\" stroke=\"none\"/>"
3685 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3686 " fill=\"yellow\" stroke=\"none\"/>"
3687 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3688 " fill=\"white\" stroke=\"none\"/>"
3689 "</marker>"
3690
3691 "<path id=\"testRect\""
3692 " style=\"fill:none;stroke:#000000;stroke-width:1px;marker-start:url(#SimpleRectMarker1);marker-end:url(#SimpleRectMarker2);marker-mid:url(#SimpleRectMarker3)\""
3693 " d=\"M5,15 C5,5 25,5 25,15 L15,25\"/>"
3694
3695 "</svg>";
3696
3697 SvgRenderTester t (data);
3698
3699 t.test_standard_30px_72ppi("markers_different", false);
3700 }
3701
testMarkersFillAsShape()3702 void TestSvgParser::testMarkersFillAsShape()
3703 {
3704 const QString data =
3705 "<svg width=\"30px\" height=\"30px\""
3706 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3707
3708 "<defs>"
3709 " <linearGradient id=\"testGrad\" x1=\"0%\" y1=\"50%\" x2=\"100%\" y2=\"50%\">"
3710 " <stop offset=\"5%\" stop-color=\"#F60\" />"
3711 " <stop offset=\"80%\" stop-color=\"#FF6\" />"
3712 " </linearGradient>"
3713
3714 " <marker id=\"SimpleRectMarker\""
3715 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3716
3717 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3718 " fill=\"red\" stroke=\"none\"/>"
3719 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3720 " fill=\"yellow\" stroke=\"none\"/>"
3721 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3722 " fill=\"white\" stroke=\"none\"/>"
3723 " </marker>"
3724
3725 "</defs>"
3726
3727 "<path id=\"testRect\""
3728 " style=\"fill:none;stroke:url(#testGrad) magenta;stroke-width:2px;marker-start:url(#SimpleRectMarker);marker-end:url(#SimpleRectMarker);marker-mid:url(#SimpleRectMarker);krita|marker-fill-method:auto\""
3729 " d=\"M5,15 C5,5 25,5 25,15 L15,25\"/>"
3730 //" d=\"M5,15 L25,15\"/>"
3731
3732 "</svg>";
3733
3734 SvgRenderTester t (data);
3735
3736 t.test_standard_30px_72ppi("markers_scaled_fill_as_shape", false);
3737 }
3738
testMarkersOnClosedPath()3739 void TestSvgParser::testMarkersOnClosedPath()
3740 {
3741 const QString data =
3742 "<svg width=\"30px\" height=\"30px\""
3743 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3744
3745 "<marker id=\"SimpleRectMarker1\""
3746 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3747
3748 " <rect id=\"markerRect\" x=\"9\" y=\"9\" width=\"7\" height=\"7\""
3749 " fill=\"red\" stroke=\"none\"/>"
3750 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3751 " fill=\"yellow\" stroke=\"none\"/>"
3752 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3753 " fill=\"white\" stroke=\"none\"/>"
3754 "</marker>"
3755
3756 "<marker id=\"SimpleRectMarker2\""
3757 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3758
3759 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3760 " fill=\"green\" stroke=\"none\"/>"
3761 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3762 " fill=\"yellow\" stroke=\"none\"/>"
3763 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3764 " fill=\"white\" stroke=\"none\"/>"
3765 "</marker>"
3766
3767 "<marker id=\"SimpleRectMarker3\""
3768 " orient=\"auto\" refY=\"12.5\" refX=\"12.5\" >"
3769
3770 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3771 " fill=\"blue\" stroke=\"none\"/>"
3772 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3773 " fill=\"yellow\" stroke=\"none\"/>"
3774 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3775 " fill=\"white\" stroke=\"none\"/>"
3776 "</marker>"
3777
3778 "<path id=\"testRect\""
3779 " style=\"fill:none;stroke:#000000;stroke-width:1px;marker-start:url(#SimpleRectMarker1);marker-end:url(#SimpleRectMarker2);marker-mid:url(#SimpleRectMarker3)\""
3780 " d=\"M5,15 C5,5 25,5 25,15 L15,25 z\"/>"
3781
3782 "</svg>";
3783
3784 SvgRenderTester t (data);
3785
3786 t.test_standard_30px_72ppi("markers_on_closed_path", false);
3787 }
3788
3789
testGradientRecoveringTransform()3790 void TestSvgParser::testGradientRecoveringTransform()
3791 {
3792 // used for experimenting purposes only!
3793
3794 QImage image(100,100,QImage::Format_ARGB32);
3795 image.fill(0);
3796 QPainter painter(&image);
3797
3798 painter.setPen(QPen(Qt::black, 0));
3799
3800
3801 QLinearGradient gradient(0, 0.5, 1, 0.5);
3802 gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
3803
3804 //QLinearGradient gradient(0, 50, 100, 50);
3805 //gradient.setCoordinateMode(QGradient::LogicalMode);
3806
3807 gradient.setColorAt(0.0, Qt::red);
3808 gradient.setColorAt(1.0, Qt::blue);
3809
3810 QTransform gradientTransform;
3811 gradientTransform.shear(0.2, 0);
3812
3813 {
3814 QBrush brush(gradient);
3815 brush.setTransform(gradientTransform);
3816 painter.setBrush(brush);
3817 }
3818
3819 QRect mainShape(3,3,94,94);
3820 painter.drawRect(mainShape);
3821
3822 QTransform gradientToUser(mainShape.width(), 0, 0, mainShape.height(),
3823 mainShape.x(), mainShape.y());
3824
3825 QRect smallShape(0,0,20,20);
3826 QTransform smallShapeTransform;
3827
3828 {
3829 smallShapeTransform =
3830 QTransform::fromTranslate(-smallShape.center().x(), -smallShape.center().y());
3831
3832 QTransform r; r.rotate(90);
3833 smallShapeTransform *= r;
3834
3835 smallShapeTransform *=
3836 QTransform::fromTranslate(mainShape.center().x(), mainShape.center().y());
3837 }
3838
3839
3840 {
3841 gradient.setCoordinateMode(QGradient::LogicalMode);
3842 QBrush brush(gradient);
3843 brush.setTransform(gradientTransform * gradientToUser * smallShapeTransform.inverted());
3844 painter.setBrush(brush);
3845 painter.setPen(Qt::NoPen);
3846 }
3847
3848 painter.setTransform(smallShapeTransform);
3849 painter.drawRect(smallShape);
3850
3851 //image.save("gradient_recovering_transform.png");
3852 }
3853
testMarkersAngularUnits()3854 void TestSvgParser::testMarkersAngularUnits()
3855 {
3856 const QString data =
3857 "<svg width=\"30px\" height=\"30px\""
3858 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
3859
3860 // start
3861 "<marker id=\"SimpleRectMarker1\""
3862 " orient=\"45deg\" refY=\"12.5\" refX=\"12.5\" >"
3863
3864 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3865 " fill=\"red\" stroke=\"none\"/>"
3866 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3867 " fill=\"yellow\" stroke=\"none\"/>"
3868 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3869 " fill=\"white\" stroke=\"none\"/>"
3870 "</marker>"
3871
3872 // end
3873 "<marker id=\"SimpleRectMarker2\""
3874 " orient=\"200grad\" refY=\"12.5\" refX=\"12.5\" >"
3875
3876 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3877 " fill=\"green\" stroke=\"none\"/>"
3878 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3879 " fill=\"yellow\" stroke=\"none\"/>"
3880 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3881 " fill=\"white\" stroke=\"none\"/>"
3882 "</marker>"
3883
3884 // mid
3885 "<marker id=\"SimpleRectMarker3\""
3886 " orient=\"-1.57rad\" refY=\"12.5\" refX=\"12.5\" >"
3887
3888 " <rect id=\"markerRect\" x=\"10\" y=\"10\" width=\"5\" height=\"5\""
3889 " fill=\"blue\" stroke=\"none\"/>"
3890 " <rect id=\"markerRect\" x=\"14\" y=\"12\" width=\"1\" height=\"1\""
3891 " fill=\"yellow\" stroke=\"none\"/>"
3892 " <rect id=\"markerRect\" x=\"12\" y=\"12\" width=\"1\" height=\"1\""
3893 " fill=\"white\" stroke=\"none\"/>"
3894 "</marker>"
3895
3896 "<path id=\"testRect\""
3897 " style=\"fill:none;stroke:#000000;stroke-width:1px;marker-start:url(#SimpleRectMarker1);marker-end:url(#SimpleRectMarker2);marker-mid:url(#SimpleRectMarker3)\""
3898 " d=\"M5,15 C5,5 25,5 25,15 L15,25\"/>"
3899
3900 "</svg>";
3901
3902 SvgRenderTester t (data);
3903
3904 t.test_standard_30px_72ppi("markers_angular_units", false);
3905 }
3906
3907 #include "KoParameterShape.h"
3908
testSodipodiArcShape()3909 void TestSvgParser::testSodipodiArcShape()
3910 {
3911 const QString data =
3912 "<svg width=\"30px\" height=\"30px\""
3913 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\""
3914 " xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\""
3915 ">"
3916
3917 "<path"
3918 " fill=\"red\" stroke=\"black\""
3919 " id=\"testRect\""
3920
3921 " sodipodi:type=\"arc\""
3922 " sodipodi:cx=\"15.464287\""
3923 " sodipodi:cy=\"14.517863\""
3924 " sodipodi:rx=\"6.25\""
3925 " sodipodi:ry=\"8.5\""
3926 " sodipodi:start=\"5.5346039\""
3927 " sodipodi:end=\"4.0381334\""
3928 //" d=\"m 20.043381,8.7327624 a 6.25,8.5 0 0 1 1.053863,9.4677386 6.25,8.5 0 0 1 -6.094908,4.794113 6.25,8.5 0 0 1 -5.5086474,-5.963709 6.25,8.5 0 0 1 2.0686234,-9.1530031 l 3.901975,6.6399611 z\" />"
3929 " d=\" some weird unparsable text \" />"
3930
3931 "</svg>";
3932
3933 SvgRenderTester t (data);
3934
3935 t.test_standard_30px_72ppi("sodipodi_closed_arc", false);
3936
3937 KoShape *shape = t.findShape("testRect");
3938 QVERIFY(dynamic_cast<KoParameterShape*>(shape));
3939 }
3940
testSodipodiArcShapeOpen()3941 void TestSvgParser::testSodipodiArcShapeOpen()
3942 {
3943 const QString data =
3944 "<svg width=\"30px\" height=\"30px\""
3945 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\""
3946 " xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\""
3947 ">"
3948
3949 "<path"
3950 " fill=\"red\" stroke=\"black\""
3951 " id=\"testRect\""
3952
3953 " sodipodi:type=\"arc\""
3954 " sodipodi:open=\"true\""
3955 " sodipodi:cx=\"15.464287\""
3956 " sodipodi:cy=\"14.517863\""
3957 " sodipodi:rx=\"6.25\""
3958 " sodipodi:ry=\"8.5\""
3959 " sodipodi:start=\"5.5346039\""
3960 " sodipodi:end=\"4.0381334\""
3961 //" d=\"m 20.043381,8.7327624 a 6.25,8.5 0 0 1 1.053863,9.4677386 6.25,8.5 0 0 1 -6.094908,4.794113 6.25,8.5 0 0 1 -5.5086474,-5.963709 6.25,8.5 0 0 1 2.0686234,-9.1530031 l 3.901975,6.6399611 z\" />"
3962 " d=\" some weird unparsable text \" />"
3963
3964 "</svg>";
3965
3966 SvgRenderTester t (data);
3967
3968 t.test_standard_30px_72ppi("sodipodi_open_arc", false);
3969
3970 KoShape *shape = t.findShape("testRect");
3971 QVERIFY(dynamic_cast<KoParameterShape*>(shape));
3972 }
3973
testKritaChordShape()3974 void TestSvgParser::testKritaChordShape()
3975 {
3976 const QString data =
3977 "<svg width=\"30px\" height=\"30px\""
3978 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\""
3979 " xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\""
3980 ">"
3981
3982 "<path"
3983 " fill=\"red\" stroke=\"black\""
3984 " id=\"testRect\""
3985
3986 " krita:type=\"arc\""
3987 " krita:arcType=\"chord\""
3988 " krita:cx=\"15.464287\""
3989 " krita:cy=\"14.517863\""
3990 " krita:rx=\"6.25\""
3991 " krita:ry=\"8.5\""
3992 " krita:start=\"5.5346039\""
3993 " krita:end=\"4.0381334\""
3994 //" d=\"m 20.043381,8.7327624 a 6.25,8.5 0 0 1 1.053863,9.4677386 6.25,8.5 0 0 1 -6.094908,4.794113 6.25,8.5 0 0 1 -5.5086474,-5.963709 6.25,8.5 0 0 1 2.0686234,-9.1530031 l 3.901975,6.6399611 z\" />"
3995 " d=\" some weird unparsable text \" />"
3996
3997 "</svg>";
3998
3999 SvgRenderTester t (data);
4000
4001 t.test_standard_30px_72ppi("sodipodi_chord_arc", false);
4002
4003 KoShape *shape = t.findShape("testRect");
4004 QVERIFY(dynamic_cast<KoParameterShape*>(shape));
4005 }
4006
testSodipodiChordShape()4007 void TestSvgParser::testSodipodiChordShape()
4008 {
4009 const QString data =
4010 "<svg width=\"30px\" height=\"30px\""
4011 " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\""
4012 " xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\""
4013 ">"
4014
4015 "<path"
4016 " fill=\"red\" stroke=\"black\""
4017 " id=\"testRect\""
4018
4019 " sodipodi:type=\"arc\""
4020 " sodipodi:arc-type=\"chord\""
4021 " sodipodi:open=\"true\""
4022 " sodipodi:cx=\"15.464287\""
4023 " sodipodi:cy=\"14.517863\""
4024 " sodipodi:rx=\"6.25\""
4025 " sodipodi:ry=\"8.5\""
4026 " sodipodi:start=\"5.5346039\""
4027 " sodipodi:end=\"4.0381334\""
4028 //" d=\"m 20.043381,8.7327624 a 6.25,8.5 0 0 1 1.053863,9.4677386 6.25,8.5 0 0 1 -6.094908,4.794113 6.25,8.5 0 0 1 -5.5086474,-5.963709 6.25,8.5 0 0 1 2.0686234,-9.1530031 l 3.901975,6.6399611 z\" />"
4029 " d=\" some weird unparsable text \" />"
4030
4031 "</svg>";
4032
4033 SvgRenderTester t (data);
4034
4035 t.test_standard_30px_72ppi("sodipodi_chord_arc", false);
4036
4037 KoShape *shape = t.findShape("testRect");
4038 QVERIFY(dynamic_cast<KoParameterShape*>(shape));
4039 }
4040
4041
4042 QTEST_MAIN(TestSvgParser)
4043