1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31
32#if 0
33#include <private/qpaintengine_svg_p.h>
34#endif
35
36#include <qapplication.h>
37#include <qpainter.h>
38#include <qbuffer.h>
39#include <qimage.h>
40#include <qpicture.h>
41#include <qdrawutil.h>
42#include <qpaintdevice.h>
43
44class tst_QSvgDevice : public QObject
45{
46 Q_OBJECT
47public:
48 tst_QSvgDevice();
49
50private slots:
51 void play_data();
52 void play();
53 void boundingRect();
54
55private:
56 void playPaint( QPainter *p, const QString &type );
57};
58
59tst_QSvgDevice::tst_QSvgDevice()
60{
61}
62
63void tst_QSvgDevice::play_data()
64{
65 QTest::addColumn<QString>(name: "tag name");
66 // we only use the tag name
67 QTest::newRow( dataTag: "lines" );
68 QTest::newRow( dataTag: "font" );
69 QTest::newRow( dataTag: "polyline" );
70 QTest::newRow( dataTag: "translate" );
71 QTest::newRow( dataTag: "scaleRect" );
72 QTest::newRow( dataTag: "ellipseOdd" );
73 QTest::newRow( dataTag: "ellipseEven" );
74 QTest::newRow( dataTag: "ellipseRandom" );
75 QTest::newRow( dataTag: "scaleText" );
76 QTest::newRow( dataTag: "scaleTextWithFont" );
77 QTest::newRow( dataTag: "scaleTextSaveRestore" );
78 QTest::newRow( dataTag: "scaleLineWithPen" );
79 QTest::newRow( dataTag: "task-17637" );
80 QTest::newRow( dataTag: "dashed-lines" );
81 QTest::newRow( dataTag: "dot-lines" );
82 QTest::newRow( dataTag: "dashed-dot-lines" );
83 QTest::newRow( dataTag: "dashed-dot-dot-lines" );
84 QTest::newRow( dataTag: "scaleDashed-lines" );
85 QTest::newRow( dataTag: "thick-dashed-lines" );
86 QTest::newRow( dataTag: "negative-rect" );
87 QTest::newRow( dataTag: "lightText" );
88 QTest::newRow( dataTag: "boldText" );
89 QTest::newRow( dataTag: "demiBoldText" );
90 QTest::newRow( dataTag: "blackText" );
91 QTest::newRow( dataTag: "task-20239" );
92 QTest::newRow( dataTag: "clipRect" );
93 QTest::newRow( dataTag: "multipleClipRects" );
94 QTest::newRow(dataTag: "qsimplerichtext");
95}
96
97#if 0
98
99class SVGDummyDevice : public QPaintDevice
100{
101public:
102 SVGDummyDevice()
103 : QPaintDevice(QInternal::ExternalDevice), eng(0) { }
104 ~SVGDummyDevice() {
105 delete eng;
106 }
107 QPaintEngine *engine() const {
108 if (!eng)
109 const_cast<SVGDummyDevice *>(this)->eng = new QSVGPaintEngine;
110 return eng;
111 }
112
113private:
114 QPaintEngine *eng;
115};
116
117void tst_QSvgDevice::play()
118{
119 // current tag name
120 QString type = data()->dataTag();
121
122 // reference pixmap
123 QPixmap ref( 100, 100 );
124 ref.fill( Qt::white );
125 QPainter pref( &ref );
126 playPaint( &pref, type );
127 pref.end();
128
129 // draw the same into the SVG device
130 SVGDummyDevice dev;
131 QPainter pdev( &dev );
132 playPaint( &pdev, type );
133 pdev.end();
134
135
136 //dev.setBoundingRect( QRect( 0, 0, 100, 100 ) );
137 //dev.save( type + "-res.svg" ); // ### sets bounding rect to 0 !
138
139 // replay on a result pixmap and compare
140 QPixmap res( 100, 100 );
141 res.fill( Qt::white );
142 QPainter pres( &res );
143 static_cast<QSVGPaintEngine *>(dev.engine())->play( &pres );
144
145#if 0
146 // for visual inspection
147 ref.save( type + "-ref.xpm", "XPM" );
148 res.save( type + "-res.xpm", "XPM" );
149#endif
150
151 QVERIFY( res.convertToImage() == ref.convertToImage() );
152}
153
154// helper function for play()
155void tst_QSvgDevice::playPaint( QPainter *p, const QString &type )
156{
157 if ( type == "lines" ) {
158 // line with pen width 0
159 p->setPen( QPen( Qt::black, 0, Qt::SolidLine ) );
160 p->drawLine( 10, 0, 20, 3 );
161
162 // line with pen width 1
163 p->setPen( QPen( Qt::black, 1, Qt::SolidLine ) );
164 p->drawLine( 2, 0, 10, 3 );
165
166 // rect without outline (qt-bugs/arc-17/35556)
167 p->setPen( Qt::NoPen );
168 p->setBrush( Qt::red );
169 p->drawRect( 5, 10, 20, 30 );
170 } else if ( type == "text" ) {
171 QFont f = p->font();
172 f.setItalic( TRUE );
173 f.setBold( TRUE );
174 p->setFont( f );
175 p->drawText( 5, 55, "Text" );
176 } else if ( type == "polyline" ) {
177 // we'll draw 4 triangular polylines. Only two will show up
178 // as the QPainter::drawPolyline() doesn't respect the brush
179 // just the pen setting
180 QPolygon pa( 3 );
181 pa.setPoint( 0, 0, 0 );
182 pa.setPoint( 1, 10, 0 );
183 pa.setPoint( 2, 0, 10 );
184
185 // frame around the following 4 polylines
186 p->setBrush( Qt::NoBrush );
187 p->setPen( Qt::SolidLine );
188 p->drawRect( 46, 3, 19, 60 );
189
190 // polyline with blue brush, no pen
191 p->setPen( Qt::NoPen );
192 p->setBrush( Qt::blue );
193 p->translate( 50, 5 );
194 p->drawPolyline( pa );
195
196 // polyline without brush, no pen
197 p->setBrush( Qt::NoBrush );
198 p->translate( 0, 15 );
199 p->drawPolyline( pa );
200
201 // polyline with green brush, solid pen
202 p->setBrush( Qt::green );
203 p->setPen( Qt::SolidLine );
204 p->translate( 0, 15 );
205 p->drawPolyline( pa );
206
207 // polyline without brush, solid pen
208 p->setBrush( Qt::NoBrush );
209 p->setPen( Qt::SolidLine );
210 p->translate( 0, 15 );
211 p->drawPolyline( pa );
212 } else if ( type == "translate" ) {
213 p->translate(-10,-10);
214 p->save();
215 p->setBrush( Qt::blue );
216 p->drawRect( 20, 30, 50, 20 );
217 p->restore();
218 p->setBrush( Qt::green );
219 p->drawRect( 70, 50, 10, 10 );
220 } else if ( type == "scaleRect" ) {
221 p->scale( 1, 2 );
222 p->setBrush( Qt::blue );
223 p->drawRect( 20, 20, 60, 60 );
224 } else if ( type == "ellipseEven" ) {
225 p->setBrush( Qt::blue );
226 p->drawEllipse( 20, 20, 60, 60 );
227 } else if ( type == "ellipseOdd" ) {
228 p->setBrush( Qt::blue );
229 p->drawEllipse( 20, 20, 59, 59 );
230 } else if ( type == "ellipseRandom" ) {
231 p->setBrush( Qt::blue );
232 p->drawEllipse( 20, 34, 89, 123 );
233 } else if ( type == "scaleText" ) {
234 p->scale(0.25,0.25);
235 p->drawText(200,200,"Hello!");
236 } else if ( type == "scaleTextWithFont" ) {
237 p->setFont(QFont("Helvetica",12));
238 p->scale(0.25,0.25);
239 p->drawText(200,200,"Hello!");
240#ifdef Q_WS_WIN
241 // Only test on Windows for now, visually it looks fine, but
242 // it's failing for some reason on Linux
243 } else if ( type == "scaleTextSaveRestore" ) {
244 p->scale(1,-1);
245 p->save();
246 p->setFont(QFont("Helvetica",12));
247 p->scale(0.5,0.5);
248 p->drawText(0,0,"Hello!");
249 p->restore();
250#endif
251 } else if ( type == "scaleLineWithPen" ) {
252 p->scale(0.1,0.1);
253 p->setPen(QPen(Qt::red,100));
254 p->drawLine(3,3,500,500);
255 } else if ( type == "task-17637" ) {
256 p->translate(0,200);
257 p->scale(0.01,-0.01);
258 p->setBrush(Qt::blue);
259 p->drawEllipse(2000,2000,6000,6000);
260 p->setPen(QPen(Qt::red,100));
261 p->setFont(QFont("Helvetica",12));
262 p->save();
263 p->scale(1,-1);
264 p->drawText(4000,4000,"Hello!");
265 p->restore();
266 p->drawLine(3000,3000,5000,5000);
267 } else if ( type == "dashed-lines" ) {
268 p->setPen(QPen(Qt::red, 1, Qt::DashLine));
269 p->drawLine(10,10,50,50);
270 } else if ( type == "dot-lines" ) {
271 p->setPen(QPen(Qt::red, 1, Qt::DotLine));
272 p->drawLine(10,10,50,50);
273 } else if ( type == "dashed-dot-lines" ) {
274 p->setPen(QPen(Qt::red, 1, Qt::DashDotLine));
275 p->drawLine(10,10,50,50);
276 } else if ( type == "dashed-dot-dot-lines" ) {
277 p->setPen(QPen(Qt::red, 1, Qt::DashDotDotLine));
278 p->drawLine(10,10,50,50);
279 } else if ( type == "scaleDashed-lines" ) {
280 p->scale(0.1,0.1);
281 p->setPen(QPen(Qt::red, 10, Qt::DashLine));
282 p->drawLine(10,10,500,500);
283 } else if ( type == "thick-dashed-lines" ) {
284 p->setPen(QPen(Qt::red, 10, Qt::DashLine));
285 p->drawLine(10,10,50,50);
286 } else if ( type == "negative-rect" ) {
287 p->drawRect(70, 0,-30,30);
288 } else if ( type == "lightText" ) {
289 QFont f("Helvetica",12);
290 f.setWeight( QFont::Light );
291 p->setFont(f);
292 p->drawText(0,0,"Hello!");
293 } else if ( type == "boldText" ) {
294 QFont f("Helvetica",12);
295 f.setWeight( QFont::Bold );
296 p->setFont(f);
297 p->drawText(0,0,"Hello!");
298 } else if ( type == "demiBoldText" ) {
299 QFont f("Helvetica",12);
300 f.setWeight( QFont::DemiBold );
301 p->setFont(f);
302 p->drawText(0,0,"Hello!");
303 } else if ( type == "blackText" ) {
304 QFont f("Helvetica",12);
305 f.setWeight( QFont::Black );
306 p->setFont(f);
307 p->drawText(0,0,"Hello!");
308 } else if ( type == "task-20239" ) {
309 p->translate(0,200);
310 p->scale(0.02,-0.02);
311 p->scale(1,-1);
312 for(int y = 1000; y <=10000; y += 2000) {
313 QBrush br(Qt::green);
314 QPalette palette(Qt::green,Qt::blue);
315 qDrawShadePanel(p,4000,5000,4000,2000,palette.active(),false,200,&br);
316 qDrawShadeRect(p,2000,2000,4000,2000,palette.active(),true,100,0,&br);
317 }
318 } else if (type=="clipRect") {
319 p->setClipRect(15,25,10,10);
320 p->drawEllipse(10,20,50,70);
321 } else if (type=="multipleClipRects") {
322 p->setClipRect(15,25,10,10);
323 p->drawEllipse(10,20,50,70);
324 p->setClipRect(100,200,20,20);
325 p->drawEllipse(110,220,50,70);
326 } else if (type == "qsimplerichtext") {
327 p->setPen(QColor(0,0,0));
328 p->setBrush(Qt::NoBrush);
329 QRect rect1(10, 10, 100, 50);
330 QRect rect2(200, 20, 80, 50);
331 p->drawRect(10, 10, 100, 50);
332 p->drawRect(200, 20, 80, 50);
333
334 QSimpleRichText text1("Text 1", QApplication::font());
335 QSimpleRichText text2("Text 2", QApplication::font());
336
337 QColorGroup cg(Qt::black, Qt::red, Qt::gray, Qt::gray, Qt::gray, Qt::black, Qt::blue, Qt::black, Qt::white);
338 text1.draw(p, rect1.x(), rect1.y(), rect1, cg);
339 text2.draw(p, rect2.x(), rect2.y(), rect2, cg);
340 }
341}
342
343void tst_QSvgDevice::boundingRect()
344{
345 // ### the bounding rect is only calculated/parsed
346 // ### when replaying. Therefore we go through QPicture.
347 QRect r( 10, 20, 30, 40 );
348 // create document
349 QPicture pic;
350 QPainter p( &pic );
351 p.drawRect( r );
352 p.end();
353 pic.save( "tmp.svg", "svg" );
354 // load it
355 QPicture pic2;
356 pic2.load( "tmp.svg", "svg" );
357 QCOMPARE( pic2.boundingRect(), r );
358}
359
360#else
361
362void tst_QSvgDevice::play()
363{
364 QSKIP("This test needs some redoing, this is just a temp measure until I work it out");
365}
366
367void tst_QSvgDevice::boundingRect()
368{
369 QSKIP("This test needs some redoing, this is just a temp measure until I work it out");
370}
371
372#endif
373
374QTEST_MAIN(tst_QSvgDevice)
375#include "tst_qsvgdevice.moc"
376

source code of qtsvg/tests/auto/qsvgdevice/tst_qsvgdevice.cpp