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 | |
44 | class tst_QSvgDevice : public QObject |
45 | { |
46 | Q_OBJECT |
47 | public: |
48 | tst_QSvgDevice(); |
49 | |
50 | private slots: |
51 | void play_data(); |
52 | void play(); |
53 | void boundingRect(); |
54 | |
55 | private: |
56 | void playPaint( QPainter *p, const QString &type ); |
57 | }; |
58 | |
59 | tst_QSvgDevice::tst_QSvgDevice() |
60 | { |
61 | } |
62 | |
63 | void 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 | |
99 | class SVGDummyDevice : public QPaintDevice |
100 | { |
101 | public: |
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 | |
113 | private: |
114 | QPaintEngine *eng; |
115 | }; |
116 | |
117 | void 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() |
155 | void 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 | |
343 | void 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 | |
362 | void tst_QSvgDevice::play() |
363 | { |
364 | QSKIP("This test needs some redoing, this is just a temp measure until I work it out" ); |
365 | } |
366 | |
367 | void 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 | |
374 | QTEST_MAIN(tst_QSvgDevice) |
375 | #include "tst_qsvgdevice.moc" |
376 | |