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#include "paintcommands.h"
29
30#include <qdir.h>
31#include <qfile.h>
32#include <qfileinfo.h>
33#include <qpainter.h>
34#include <qpainterpath.h>
35#include <qbitmap.h>
36#include <qtextstream.h>
37#include <qtextlayout.h>
38#include <qdebug.h>
39#include <QStaticText>
40#include <QTextDocument>
41#include <private/qimage_p.h>
42
43#ifndef QT_NO_OPENGL
44#include <QOpenGLFramebufferObjectFormat>
45#include <QOpenGLContext>
46#include <QOpenGLPaintDevice>
47#endif
48
49/*********************************************************************************
50** everything to populate static tables
51**********************************************************************************/
52const char *PaintCommands::brushStyleTable[] = {
53 "NoBrush",
54 "SolidPattern",
55 "Dense1Pattern",
56 "Dense2Pattern",
57 "Dense3Pattern",
58 "Dense4Pattern",
59 "Dense5Pattern",
60 "Dense6Pattern",
61 "Dense7Pattern",
62 "HorPattern",
63 "VerPattern",
64 "CrossPattern",
65 "BDiagPattern",
66 "FDiagPattern",
67 "DiagCrossPattern",
68 "LinearGradientPattern"
69};
70
71const char *PaintCommands::penStyleTable[] = {
72 "NoPen",
73 "SolidLine",
74 "DashLine",
75 "DotLine",
76 "DashDotLine",
77 "DashDotDotLine"
78};
79
80const char *PaintCommands::fontWeightTable[] = {
81 "Light",
82 "Normal",
83 "DemiBold",
84 "Bold",
85 "Black"
86};
87
88const char *PaintCommands::fontHintingTable[] = {
89 "Default",
90 "None",
91 "Vertical",
92 "Full"
93};
94
95const char *PaintCommands::clipOperationTable[] = {
96 "NoClip",
97 "ReplaceClip",
98 "IntersectClip",
99 "UniteClip"
100};
101
102const char *PaintCommands::spreadMethodTable[] = {
103 "PadSpread",
104 "ReflectSpread",
105 "RepeatSpread"
106};
107
108const char *PaintCommands::coordinateMethodTable[] = {
109 "LogicalMode",
110 "StretchToDeviceMode",
111 "ObjectBoundingMode",
112 "ObjectMode"
113};
114
115const char *PaintCommands::sizeModeTable[] = {
116 "AbsoluteSize",
117 "RelativeSize"
118};
119
120const char *PaintCommands::compositionModeTable[] = {
121 "SourceOver",
122 "DestinationOver",
123 "Clear",
124 "Source",
125 "Destination",
126 "SourceIn",
127 "DestinationIn",
128 "SourceOut",
129 "DestinationOut",
130 "SourceAtop",
131 "DestinationAtop",
132 "Xor",
133 "Plus",
134 "Multiply",
135 "Screen",
136 "Overlay",
137 "Darken",
138 "Lighten",
139 "ColorDodge",
140 "ColorBurn",
141 "HardLight",
142 "SoftLight",
143 "Difference",
144 "Exclusion",
145 "SourceOrDestination",
146 "SourceAndDestination",
147 "SourceXorDestination",
148 "NotSourceAndNotDestination",
149 "NotSourceOrNotDestination",
150 "NotSourceXorDestination",
151 "NotSource",
152 "NotSourceAndDestination",
153 "SourceAndNotDestination"
154};
155
156const char *PaintCommands::imageFormatTable[] = {
157 "Invalid",
158 "Mono",
159 "MonoLSB",
160 "Indexed8",
161 "RGB32",
162 "ARGB32",
163 "ARGB32_Premultiplied",
164 "Format_RGB16",
165 "Format_ARGB8565_Premultiplied",
166 "Format_RGB666",
167 "Format_ARGB6666_Premultiplied",
168 "Format_RGB555",
169 "Format_ARGB8555_Premultiplied",
170 "Format_RGB888",
171 "Format_RGB444",
172 "Format_ARGB4444_Premultiplied",
173 "Format_RGBX8888",
174 "Format_RGBA8888",
175 "Format_RGBA8888_Premultiplied",
176 "Format_BGR30",
177 "Format_A2BGR30_Premultiplied",
178 "Format_RGB30",
179 "Format_A2RGB30_Premultiplied",
180 "Alpha8",
181 "Grayscale8",
182 "RGBx64",
183 "RGBA64",
184 "RGBA64_Premultiplied",
185};
186
187int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit)
188{
189 QByteArray p = pattern.toLatin1().toLower();
190 for (int i=0; i<limit; ++i)
191 if (p == QByteArray::fromRawData(table[i], size: qstrlen(str: table[i])).toLower())
192 return i;
193 return -1;
194}
195
196QList<PaintCommands::PaintCommandInfos> PaintCommands::s_commandInfoTable = QList<PaintCommands::PaintCommandInfos>();
197QList<QPair<QString,QStringList> > PaintCommands::s_enumsTable = QList<QPair<QString,QStringList> >();
198QMultiHash<QString, int> PaintCommands::s_commandHash;
199
200#define DECL_PAINTCOMMAND(identifier, method, regexp, syntax, sample) \
201 s_commandInfoTable << PaintCommandInfos(QLatin1String(identifier), &PaintCommands::method, QRegularExpression(regexp), \
202 QLatin1String(syntax), QLatin1String(sample) );
203
204#define DECL_PAINTCOMMANDSECTION(title) \
205 s_commandInfoTable << PaintCommandInfos(QLatin1String(title));
206
207#define ADD_ENUMLIST(listCaption, cStrArray) { \
208 QStringList list; \
209 for (int i=0; i<int(sizeof(cStrArray)/sizeof(char*)); i++) \
210 list << cStrArray[i]; \
211 s_enumsTable << qMakePair(QString(listCaption), list); \
212 }
213
214void PaintCommands::staticInit()
215{
216 // check if already done
217 if (!s_commandInfoTable.isEmpty()) return;
218
219 // populate the command list
220 DECL_PAINTCOMMANDSECTION("misc");
221 DECL_PAINTCOMMAND("comment", command_comment,
222 "^\\s*#",
223 "# this is some comments",
224 "# place your comments here");
225 DECL_PAINTCOMMAND("import", command_import,
226 "^import\\s+\"(.*)\"$",
227 "import <qrcFilename>",
228 "import \"myfile.qrc\"");
229 DECL_PAINTCOMMAND("begin_block", command_begin_block,
230 "^begin_block\\s+(\\w*)$",
231 "begin_block <blockName>",
232 "begin_block blockName");
233 DECL_PAINTCOMMAND("end_block", command_end_block,
234 "^end_block\\s*(\\w*)$",
235 "end_block [blockName]",
236 "end_block blockName");
237 DECL_PAINTCOMMAND("repeat_block", command_repeat_block,
238 "^repeat_block\\s+(\\w*)$",
239 "repeat_block <blockName>",
240 "repeat_block blockName");
241 DECL_PAINTCOMMAND("textlayout_draw", command_textlayout_draw,
242 "^textlayout_draw\\s+\"(.*)\"\\s+([0-9.]*)$",
243 "textlayout_draw <text> <width>",
244 "textlayout_draw \"your text\" 1.0");
245 DECL_PAINTCOMMAND("abort", command_abort,
246 "^abort$",
247 "abort",
248 "abort");
249 DECL_PAINTCOMMAND("noop", command_noop,
250 "^$",
251 "-",
252 "\n");
253
254 DECL_PAINTCOMMANDSECTION("setters");
255 DECL_PAINTCOMMAND("setBackgroundMode", command_setBgMode,
256 "^(setBackgroundMode|setBgMode)\\s+(\\w*)$",
257 "setBackgroundMode <OpaqueMode|TransparentMode>",
258 "setBackgroundMode TransparentMode");
259 DECL_PAINTCOMMAND("setBackground", command_setBackground,
260 "^setBackground\\s+#?(\\w*)\\s*(\\w*)?$",
261 "setBackground <color> [brush style enum]",
262 "setBackground black SolidPattern");
263 DECL_PAINTCOMMAND("setOpacity", command_setOpacity,
264 "^setOpacity\\s+(-?\\d*\\.?\\d*)$",
265 "setOpacity <opacity>\n - opacity is in [0,1]",
266 "setOpacity 1.0");
267 DECL_PAINTCOMMAND("path_setFillRule", command_path_setFillRule,
268 "^path_setFillRule\\s+(\\w*)\\s+(\\w*)$",
269 "path_setFillRule <pathName> [Winding|OddEven]",
270 "path_setFillRule pathName Winding");
271 DECL_PAINTCOMMAND("setBrush", command_setBrush,
272 "^setBrush\\s+(#?[\\w.:\\/]*)\\s*(\\w*)?$",
273 "setBrush <imageFileName>\nsetBrush noBrush\nsetBrush <color> <brush style enum>",
274 "setBrush white SolidPattern");
275 DECL_PAINTCOMMAND("setBrushOrigin", command_setBrushOrigin,
276 "^setBrushOrigin\\s*(-?\\w*)\\s+(-?\\w*)$",
277 "setBrushOrigin <dx> <dy>",
278 "setBrushOrigin 0 0");
279 DECL_PAINTCOMMAND("brushTranslate", command_brushTranslate,
280 "^brushTranslate\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
281 "brushTranslate <tx> <ty>",
282 "brushTranslate 0.0 0.0");
283 DECL_PAINTCOMMAND("brushScale", command_brushScale,
284 "^brushScale\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
285 "brushScale <kx> <ky>",
286 "brushScale 0.0 0.0");
287 DECL_PAINTCOMMAND("brushRotate", command_brushRotate,
288 "^brushRotate\\s+(-?[\\w.]*)$",
289 "brushRotate <angle>\n - angle in degrees",
290 "brushRotate 0.0");
291 DECL_PAINTCOMMAND("brushShear", command_brushShear,
292 "^brushShear\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
293 "brushShear <sx> <sy>",
294 "brushShear 0.0 0.0");
295 DECL_PAINTCOMMAND("setCompositionMode", command_setCompositionMode,
296 "^setCompositionMode\\s+([\\w_0-9]*)$",
297 "setCompositionMode <composition mode enum>",
298 "setCompositionMode SourceOver");
299 DECL_PAINTCOMMAND("setFont", command_setFont,
300 "^setFont\\s+\"([\\w\\s]*)\"\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)$",
301 "setFont <fontFace> [size] [font weight|font weight enum] [italic] [hinting enum]\n - font weight is an integer between 0 and 99",
302 "setFont \"times\" 12");
303 DECL_PAINTCOMMAND("setPen", command_setPen,
304 "^setPen\\s+#?(\\w*)$",
305 "setPen <color>\nsetPen <pen style enum>\nsetPen brush",
306 "setPen black");
307 DECL_PAINTCOMMAND("setPen", command_setPen2,
308 "^setPen\\s+(#?\\w*)\\s+([\\w.]+)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)$",
309 "setPen brush|<color> [width] [pen style enum] [FlatCap|SquareCap|RoundCap] [MiterJoin|BevelJoin|RoundJoin]",
310 "setPen black 1 FlatCap MiterJoin");
311 DECL_PAINTCOMMAND("pen_setDashOffset", command_pen_setDashOffset,
312 "^pen_setDashOffset\\s+(-?[\\w.]+)$",
313 "pen_setDashOffset <offset>\n",
314 "pen_setDashOffset 1.0");
315 DECL_PAINTCOMMAND("pen_setDashPattern", command_pen_setDashPattern,
316 "^pen_setDashPattern\\s+\\[([\\w\\s.]*)\\]$",
317 "pen_setDashPattern <[ <dash_1> <space_1> ... <dash_n> <space_n> ]>",
318 "pen_setDashPattern [ 2 1 4 1 3 3 ]");
319 DECL_PAINTCOMMAND("pen_setCosmetic", command_pen_setCosmetic,
320 "^pen_setCosmetic\\s+(\\w*)$",
321 "pen_setCosmetic <true|false>",
322 "pen_setCosmetic true");
323 DECL_PAINTCOMMAND("setRenderHint", command_setRenderHint,
324 "^setRenderHint\\s+([\\w_0-9]*)\\s*(\\w*)$",
325 "setRenderHint <Antialiasing|SmoothPixmapTransform> <true|false>",
326 "setRenderHint Antialiasing true");
327 DECL_PAINTCOMMAND("clearRenderHint", command_clearRenderHint,
328 "^clearRenderHint$",
329 "clearRenderHint",
330 "clearRenderHint");
331
332 DECL_PAINTCOMMANDSECTION("gradients");
333 DECL_PAINTCOMMAND("gradient_appendStop", command_gradient_appendStop,
334 "^gradient_appendStop\\s+([\\w.]*)\\s+#?(\\w*)$",
335 "gradient_appendStop <pos> <color>",
336 "gradient_appendStop 1.0 red");
337 DECL_PAINTCOMMAND("gradient_clearStops", command_gradient_clearStops,
338 "^gradient_clearStops$",
339 "gradient_clearStops",
340 "gradient_clearStops");
341 DECL_PAINTCOMMAND("gradient_setConical", command_gradient_setConical,
342 "^gradient_setConical\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$",
343 "gradient_setConical <cx> <cy> <angle>\n - angle in degrees",
344 "gradient_setConical 5.0 5.0 45.0");
345 DECL_PAINTCOMMAND("gradient_setLinear", command_gradient_setLinear,
346 "^gradient_setLinear\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$",
347 "gradient_setLinear <x1> <y1> <x2> <y2>",
348 "gradient_setLinear 1.0 1.0 2.0 2.0");
349 DECL_PAINTCOMMAND("gradient_setRadial", command_gradient_setRadial,
350 "^gradient_setRadial\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)$",
351 "gradient_setRadial <cx> <cy> <rad> <fx> <fy>\n - C is the center\n - rad is the radius\n - F is the focal point",
352 "gradient_setRadial 1.0 1.0 45.0 2.0 2.0");
353 DECL_PAINTCOMMAND("gradient_setRadialExtended", command_gradient_setRadialExtended,
354 "^gradient_setRadialExtended\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)$",
355 "gradient_setRadialExtended <cx> <cy> <rad> <fx> <fy> <frad>\n - C is the center\n - rad is the center radius\n - F is the focal point\n - frad is the focal radius",
356 "gradient_setRadialExtended 1.0 1.0 45.0 2.0 2.0 45.0");
357 DECL_PAINTCOMMAND("gradient_setLinearPen", command_gradient_setLinearPen,
358 "^gradient_setLinearPen\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$",
359 "gradient_setLinearPen <x1> <y1> <x2> <y2>",
360 "gradient_setLinearPen 1.0 1.0 2.0 2.0");
361 DECL_PAINTCOMMAND("gradient_setSpread", command_gradient_setSpread,
362 "^gradient_setSpread\\s+(\\w*)$",
363 "gradient_setSpread <spread method enum>",
364 "gradient_setSpread PadSpread");
365 DECL_PAINTCOMMAND("gradient_setCoordinateMode", command_gradient_setCoordinateMode,
366 "^gradient_setCoordinateMode\\s+(\\w*)$",
367 "gradient_setCoordinateMode <coordinate method enum>",
368 "gradient_setCoordinateMode ObjectBoundingMode");
369
370 DECL_PAINTCOMMANDSECTION("drawing ops");
371 DECL_PAINTCOMMAND("drawPoint", command_drawPoint,
372 "^drawPoint\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
373 "drawPoint <x> <y>",
374 "drawPoint 10.0 10.0");
375 DECL_PAINTCOMMAND("drawLine", command_drawLine,
376 "^drawLine\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
377 "drawLine <x1> <y1> <x2> <y2>",
378 "drawLine 10.0 10.0 20.0 20.0");
379 DECL_PAINTCOMMAND("drawLines", command_drawLines,
380 "^drawLines\\s+\\[([\\w\\s\\-.]*)\\]$",
381 "drawLines <[ <l1x1> <l1y1> <l1x2> <l1y2> <l2x1> <l2y1> ... ]>",
382 "drawLines [ 10 10 50 10 50 20 10 20 ]");
383 DECL_PAINTCOMMAND("drawRect", command_drawRect,
384 "^drawRect\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
385 "drawRect <x> <y> <w> <h>",
386 "drawRect 10.0 10.0 20.0 20.0");
387 DECL_PAINTCOMMAND("drawRoundRect", command_drawRoundRect,
388 "^drawRoundRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)?\\s*(-?\\w*)?$",
389 "drawRoundRect <x> <y> <w> <h> [rx] [ry]",
390 "drawRoundRect 10 10 20 20 3 3");
391 DECL_PAINTCOMMAND("drawRoundedRect", command_drawRoundedRect,
392 "^drawRoundedRect\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(\\w*)?$",
393 "drawRoundedRect <x> <y> <w> <h> <rx> <ry> [SizeMode enum]",
394 "drawRoundedRect 10 10 20 20 4 4 AbsoluteSize");
395 DECL_PAINTCOMMAND("drawArc", command_drawArc,
396 "^drawArc\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$",
397 "drawArc <x> <y> <w> <h> <angleStart> <angleArc>\n - angles are expressed in 1/16th of degree",
398 "drawArc 10 10 20 20 0 5760");
399 DECL_PAINTCOMMAND("drawChord", command_drawChord,
400 "^drawChord\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$",
401 "drawChord <x> <y> <w> <h> <angleStart> <angleArc>\n - angles are expressed in 1/16th of degree",
402 "drawChord 10 10 20 20 0 5760");
403 DECL_PAINTCOMMAND("drawEllipse", command_drawEllipse,
404 "^drawEllipse\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
405 "drawEllipse <x> <y> <w> <h>",
406 "drawEllipse 10.0 10.0 20.0 20.0");
407 DECL_PAINTCOMMAND("drawPath", command_drawPath,
408 "^drawPath\\s+(\\w*)$",
409 "drawPath <pathName>",
410 "drawPath mypath");
411 DECL_PAINTCOMMAND("drawPie", command_drawPie,
412 "^drawPie\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$",
413 "drawPie <x> <y> <w> <h> <angleStart> <angleArc>\n - angles are expressed in 1/16th of degree",
414 "drawPie 10 10 20 20 0 5760");
415 DECL_PAINTCOMMAND("drawPixmap", command_drawPixmap,
416 "^drawPixmap\\s+([\\w.:\\-/]*)"
417 "\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?" // target rect
418 "\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?$", // source rect
419 "drawPixmap <filename> <tx> <ty> <tw> <th> <sx> <sy> <sw> <sh>"
420 "\n- where t means target and s means source"
421 "\n- a width or height of -1 means maximum space",
422 "drawPixmap :/images/face.png 0 0 -1 -1 0 0 -1 -1");
423 DECL_PAINTCOMMAND("drawImage", command_drawImage,
424 "^drawImage\\s+([\\w.:\\/]*)"
425 "\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?" // target rect
426 "\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?$", // source rect
427 "drawImage <filename> <tx> <ty> <tw> <th> <sx> <sy> <sw> <sh>"
428 "\n- where t means target and s means source"
429 "\n- a width or height of -1 means maximum space",
430 "drawImage :/images/face.png 0 0 -1 -1 0 0 -1 -1");
431 DECL_PAINTCOMMAND("drawPolygon", command_drawPolygon,
432 "^drawPolygon\\s+\\[([\\w\\s\\-.]*)\\]\\s*(\\w*)$",
433 "drawPolygon <[ <x1> <y1> ... <xn> <yn> ]> <Winding|OddEven>",
434 "drawPolygon [ 1 4 6 8 5 3 ] Winding");
435 DECL_PAINTCOMMAND("drawConvexPolygon", command_drawConvexPolygon,
436 "^drawConvexPolygon\\s+\\[([\\w\\s-.]*)\\]$",
437 "drawConvexPolygon <[ <x1> <y1> ... <xn> <yn> ]>",
438 "drawConvexPolygon [ 1 4 6 8 5 3 ]");
439 DECL_PAINTCOMMAND("drawPolyline", command_drawPolyline,
440 "^drawPolyline\\s+\\[([\\w\\s\\-.]*)\\]$",
441 "drawPolyline <[ <x1> <y1> ... <xn> <yn> ]>",
442 "drawPolyline [ 1 4 6 8 5 3 ]");
443 DECL_PAINTCOMMAND("drawText", command_drawText,
444 "^drawText\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$",
445 "drawText <x> <y> <text>",
446 "drawText 10 10 \"my text\"");
447 DECL_PAINTCOMMAND("drawStaticText", command_drawStaticText,
448 "^drawStaticText\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$",
449 "drawStaticText <x> <y> <text>",
450 "drawStaticText 10 10 \"my text\"");
451 DECL_PAINTCOMMAND("drawTextDocument", command_drawTextDocument,
452 "^drawTextDocument\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$",
453 "drawTextDocument <x> <y> <html>",
454 "drawTextDocument 10 10 \"html\"");
455 DECL_PAINTCOMMAND("drawTiledPixmap", command_drawTiledPixmap,
456 "^drawTiledPixmap\\s+([\\w.:\\/]*)"
457 "\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)\\s*(-?\\w*)"
458 "\\s*(-?\\w*)\\s*(-?\\w*)$",
459 "drawTiledPixmap <tile image filename> <tx> <ty> <tx> <ty> <sx> <sy>"
460 "\n - where t means tile"
461 "\n - and s is an offset in the tile",
462 "drawTiledPixmap :/images/alpha.png ");
463 DECL_PAINTCOMMAND("fillRect", command_fillRect,
464 "^fillRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(\\w*)?$",
465 "fillRect <x> <y> <w> <h> [color]\n - Uses current brush if no color given",
466 "fillRect 10 10 20 20 blue");
467 DECL_PAINTCOMMAND("fillRectF", command_fillRectF,
468 "^fillRectF\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s*(\\w*)?$",
469 "fillRectF <x> <y> <w> <h> [color]\n - Uses current brush if no color given",
470 "fillRectF 10.5 10.5 20.2 20.2 blue");
471
472 DECL_PAINTCOMMANDSECTION("painterPaths");
473 DECL_PAINTCOMMAND("path_moveTo", command_path_moveTo,
474 "^path_moveTo\\s+([.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$",
475 "path_moveTo <pathName> <x> <y>",
476 "path_moveTo mypath 1.0 1.0");
477 DECL_PAINTCOMMAND("path_lineTo", command_path_lineTo,
478 "^path_lineTo\\s+([.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$",
479 "path_lineTo <pathName> <x> <y>",
480 "path_lineTo mypath 1.0 1.0");
481 DECL_PAINTCOMMAND("path_addEllipse", command_path_addEllipse,
482 "^path_addEllipse\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$",
483 "path_addEllipse <pathName> <x1> <y1> <x2> <y2>",
484 "path_addEllipse mypath 10.0 10.0 20.0 20.0");
485 DECL_PAINTCOMMAND("path_addPolygon", command_path_addPolygon,
486 "^path_addPolygon\\s+(\\w*)\\s+\\[([\\w\\s]*)\\]\\s*(\\w*)$",
487 "path_addPolygon <pathName> <[ <x1> <y1> ... <xn> <yn> ]>",
488 "path_addPolygon mypath [ 1 4 6 8 5 3 ]");
489 DECL_PAINTCOMMAND("path_addRect", command_path_addRect,
490 "^path_addRect\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$",
491 "path_addRect <pathName> <x1> <y1> <x2> <y2>",
492 "path_addRect mypath 10.0 10.0 20.0 20.0");
493 DECL_PAINTCOMMAND("path_addText", command_path_addText,
494 "^path_addText\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+\"(.*)\"$",
495 "path_addText <pathName> <x> <y> <text>",
496 "path_addText mypath 10.0 20.0 \"some text\"");
497 DECL_PAINTCOMMAND("path_arcTo", command_path_arcTo,
498 "^path_arcTo\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$",
499 "path_arcTo <pathName> <x> <y> <w> <h> <angleStart> <angleArc>\n - angles are expressed in degrees",
500 "path_arcTo mypath 0.0 0.0 10.0 10.0 0.0 360.0");
501 DECL_PAINTCOMMAND("path_cubicTo", command_path_cubicTo,
502 "^path_cubicTo\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$",
503 "path_cubicTo <pathName> <x1> <y1> <x2> <y2> <x3> <y3>",
504 "path_cubicTo mypath 0.0 0.0 10.0 10.0 20.0 20.0");
505 DECL_PAINTCOMMAND("path_closeSubpath", command_path_closeSubpath,
506 "^path_closeSubpath\\s+(\\w*)$",
507 "path_closeSubpath <pathName>",
508 "path_closeSubpath mypath");
509 DECL_PAINTCOMMAND("path_createOutline", command_path_createOutline,
510 "^path_createOutline\\s+(\\w*)\\s+(\\w*)$",
511 "path_createOutline <pathName> <newName>",
512 "path_createOutline mypath myoutline");
513 DECL_PAINTCOMMAND("path_debugPrint", command_path_debugPrint,
514 "^path_debugPrint\\s+(\\w*)$",
515 "path_debugPrint <pathName>",
516 "path_debugPrint mypath");
517
518 DECL_PAINTCOMMANDSECTION("regions");
519 DECL_PAINTCOMMAND("region_addRect", command_region_addRect,
520 "^region_addRect\\s+(\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$",
521 "region_addRect <regionName> <x1> <y1> <x2> <y2>",
522 "region_addRect myregion 0.0 0.0 10.0 10.0");
523 DECL_PAINTCOMMAND("region_addEllipse", command_region_addEllipse,
524 "^region_addEllipse\\s+(\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$",
525 "region_addEllipse <regionName> <x1> <y1> <x2> <y2>",
526 "region_addEllipse myregion 0.0 0.0 10.0 10.0");
527
528 DECL_PAINTCOMMANDSECTION("clipping");
529 DECL_PAINTCOMMAND("region_getClipRegion", command_region_getClipRegion,
530 "^region_getClipRegion\\s+(\\w*)$",
531 "region_getClipRegion <regionName>",
532 "region_getClipRegion myregion");
533 DECL_PAINTCOMMAND("setClipRegion", command_setClipRegion,
534 "^setClipRegion\\s+(\\w*)\\s*(\\w*)$",
535 "setClipRegion <regionName> <clip operation enum>",
536 "setClipRegion myregion ReplaceClip");
537 DECL_PAINTCOMMAND("path_getClipPath", command_path_getClipPath,
538 "^path_getClipPath\\s+([\\w0-9]*)$",
539 "path_getClipPath <pathName>",
540 "path_getClipPath mypath");
541 DECL_PAINTCOMMAND("setClipPath", command_setClipPath,
542 "^setClipPath\\s+(\\w*)\\s*(\\w*)$",
543 "setClipPath <pathName> <clip operation enum>",
544 "setClipPath mypath ReplaceClip");
545 DECL_PAINTCOMMAND("setClipRect", command_setClipRect,
546 "^setClipRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(\\w*)$",
547 "setClipRect <x1> <y1> <x2> <y2> <clip operation enum>",
548 "setClipRect 0.0 0.0 10.0 10.0 ReplaceClip");
549 DECL_PAINTCOMMAND("setClipping", command_setClipping,
550 "^setClipping\\s+(\\w*)$",
551 "setClipping <true|false>",
552 "setClipping true");
553
554 DECL_PAINTCOMMANDSECTION("surface");
555 DECL_PAINTCOMMAND("surface_begin", command_surface_begin,
556 "^surface_begin\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
557 "surface_begin <x> <y> <w> <h>",
558 "surface_begin 0.0 0.0 10.0 10.0");
559 DECL_PAINTCOMMAND("surface_end", command_surface_end,
560 "^surface_end$",
561 "surface_end",
562 "surface_end");
563
564 DECL_PAINTCOMMANDSECTION("painter states");
565 DECL_PAINTCOMMAND("restore", command_restore,
566 "^restore$",
567 "restore",
568 "restore");
569 DECL_PAINTCOMMAND("save", command_save,
570 "^save$",
571 "save",
572 "save");
573
574 DECL_PAINTCOMMANDSECTION("pixmaps'n'images");
575 DECL_PAINTCOMMAND("pixmap_load", command_pixmap_load,
576 "^pixmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$",
577 "pixmap_load <image filename> <pixmapName>",
578 "pixmap_load :/images/face.png myPixmap");
579 DECL_PAINTCOMMAND("pixmap_setMask", command_pixmap_setMask,
580 "^pixmap_setMask\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]*)$",
581 "pixmap_setMask <pixmapName> <bitmap filename>",
582 "pixmap_setMask myPixmap :/images/bitmap.png");
583 DECL_PAINTCOMMAND("bitmap_load", command_bitmap_load,
584 "^bitmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$",
585 "bitmap_load <bitmap filename> <bitmapName>\n - note that the image is stored as a pixmap",
586 "bitmap_load :/images/bitmap.png myBitmap");
587 DECL_PAINTCOMMAND("pixmap_setDevicePixelRatio", command_pixmap_setDevicePixelRatio,
588 "^pixmap_setDevicePixelRatio\\s+([\\w.:\\/]*)\\s+([.0-9]*)$",
589 "pixmap_setDevicePixelRatio <pixmapName> <dpr>",
590 "pixmap_setDevicePixelRatio myPixmap 2.0");
591 DECL_PAINTCOMMAND("image_convertToFormat", command_image_convertToFormat,
592 "^image_convertToFormat\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]+)\\s+([\\w0-9_]*)$",
593 "image_convertToFormat <sourceImageName> <destImageName> <image format enum>",
594 "image_convertToFormat myImage myNewImage Indexed8");
595 DECL_PAINTCOMMAND("image_load", command_image_load,
596 "^image_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$",
597 "image_load <filename> <imageName>",
598 "image_load :/images/face.png myImage");
599 DECL_PAINTCOMMAND("image_setColor", command_image_setColor,
600 "^image_setColor\\s+([\\w.:\\/]*)\\s+([0-9]*)\\s+#([0-9]*)$",
601 "image_setColor <imageName> <index> <color>",
602 "image_setColor myImage 0 black");
603 DECL_PAINTCOMMAND("image_setColorCount", command_image_setColorCount,
604 "^image_setColorCount\\s+([\\w.:\\/]*)\\s+([0-9]*)$",
605 "image_setColorCount <imageName> <nbColors>",
606 "image_setColorCount myImage 128");
607 DECL_PAINTCOMMAND("image_setDevicePixelRatio", command_image_setDevicePixelRatio,
608 "^image_setDevicePixelRatio\\s+([\\w.:\\/]*)\\s+([.0-9]*)$",
609 "image_setDevicePixelRatio <imageName> <dpr>",
610 "image_setDevicePixelRatio myImage 2.0");
611
612 DECL_PAINTCOMMANDSECTION("transformations");
613 DECL_PAINTCOMMAND("resetMatrix", command_resetMatrix,
614 "^resetMatrix$",
615 "resetMatrix",
616 "resetMatrix");
617 DECL_PAINTCOMMAND("setMatrix", command_setMatrix,
618 "^setMatrix\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$",
619 "setMatrix <m11> <m12> <m13> <m21> <m22> <m23> <m31> <m32> <m33>",
620 "setMatrix 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0");
621 DECL_PAINTCOMMAND("translate", command_translate,
622 "^translate\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
623 "translate <tx> <ty>",
624 "translate 10.0 10.0");
625 DECL_PAINTCOMMAND("rotate", command_rotate,
626 "^rotate\\s+(-?[\\w.]*)$",
627 "rotate <angle>\n - with angle in degrees",
628 "rotate 30.0");
629 DECL_PAINTCOMMAND("rotate_x", command_rotate_x,
630 "^rotate_x\\s+(-?[\\w.]*)$",
631 "rotate_x <angle>\n - with angle in degrees",
632 "rotate_x 30.0");
633 DECL_PAINTCOMMAND("rotate_y", command_rotate_y,
634 "^rotate_y\\s+(-?[\\w.]*)$",
635 "rotate_y <angle>\n - with angle in degrees",
636 "rotate_y 30.0");
637 DECL_PAINTCOMMAND("scale", command_scale,
638 "^scale\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$",
639 "scale <sx> <sy>",
640 "scale 2.0 1.0");
641 DECL_PAINTCOMMAND("mapQuadToQuad", command_mapQuadToQuad,
642 "^mapQuadToQuad\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$",
643 "mapQuadToQuad <x1> <y1> <x2> <y2> <x3> <y3> <x4> <y4> <x5> <y5> <x6> <y6> <x7> <y7> <x8> <y8>"
644 "\n - where vertices 1 to 4 defines the source quad and 5 to 8 the destination quad",
645 "mapQuadToQuad 0.0 0.0 1.0 1.0 0.0 0.0 -1.0 -1.0");
646
647 // populate the command lookup hash
648 for (int i=0; i<s_commandInfoTable.size(); i++) {
649 // and pre-optimize the regexps.
650 s_commandInfoTable.at(i).regExp.optimize();
651 if (s_commandInfoTable.at(i).isSectionHeader() ||
652 s_commandInfoTable.at(i).identifier == QLatin1String("comment") ||
653 s_commandInfoTable.at(i).identifier == QLatin1String("noop"))
654 continue;
655 s_commandHash.insert(akey: s_commandInfoTable.at(i).identifier, avalue: i);
656 }
657
658 // populate the enums list
659 ADD_ENUMLIST("brush styles", brushStyleTable);
660 ADD_ENUMLIST("pen styles", penStyleTable);
661 ADD_ENUMLIST("font weights", fontWeightTable);
662 ADD_ENUMLIST("font hintings", fontHintingTable);
663 ADD_ENUMLIST("clip operations", clipOperationTable);
664 ADD_ENUMLIST("spread methods", spreadMethodTable);
665 ADD_ENUMLIST("composition modes", compositionModeTable);
666 ADD_ENUMLIST("image formats", imageFormatTable);
667 ADD_ENUMLIST("coordinate modes", coordinateMethodTable);
668 ADD_ENUMLIST("size modes", sizeModeTable);
669}
670
671#undef DECL_PAINTCOMMAND
672#undef ADD_ENUMLIST
673/*********************************************************************************
674** utility
675**********************************************************************************/
676template <typename T> T PaintCommands::image_load(const QString &filepath)
677{
678 T t(filepath);
679
680 if (t.isNull())
681 t = T(":images/" + filepath);
682
683 if (t.isNull())
684 t = T("images/" + filepath);
685
686 if (t.isNull()) {
687 QFileInfo fi(filepath);
688 QDir dir = fi.absoluteDir();
689 dir.cdUp();
690 dir.cd(dirName: "images");
691 QString fileName = dir.absolutePath() + QLatin1Char('/') + fi.fileName();
692 t = T(fileName);
693 if (t.isNull() && !fileName.endsWith(s: ".png")) {
694 fileName.append(s: ".png");
695 t = T(fileName);
696 }
697 }
698
699 return t;
700}
701
702/*********************************************************************************
703** setters
704**********************************************************************************/
705void PaintCommands::insertAt(int commandIndex, const QStringList &newCommands)
706{
707 int index = 0;
708 int left = newCommands.size();
709 while (left--)
710 m_commands.insert(i: ++commandIndex, t: newCommands.at(i: index++));
711}
712
713/*********************************************************************************
714** run
715**********************************************************************************/
716void PaintCommands::runCommand(const QString &scriptLine)
717{
718 static QRegularExpression separators("\\s");
719 if (scriptLine.isEmpty()) {
720 command_noop(re: QRegularExpressionMatch());
721 return;
722 }
723 if (scriptLine.startsWith(c: '#')) {
724 command_comment(re: QRegularExpressionMatch());
725 return;
726 }
727 QString firstWord = scriptLine.section(re: separators, start: 0, end: 0);
728 QList<int> indices = s_commandHash.values(akey: firstWord);
729 foreach(int idx, indices) {
730 PaintCommandInfos command = s_commandInfoTable.at(i: idx);
731 Q_ASSERT(command.regExp.isValid());
732 QRegularExpressionMatch match = command.regExp.match(subject: scriptLine);
733 if (match.hasMatch()) {
734 (this->*(command.paintMethod))(match);
735 return;
736 }
737 }
738 qWarning(msg: "ERROR: unknown command or argument syntax error in \"%s\"", qPrintable(scriptLine));
739}
740
741void PaintCommands::runCommands()
742{
743 staticInit();
744 int width = m_painter->window().width();
745 int height = m_painter->window().height();
746
747 if (width <= 0)
748 width = 800;
749 if (height <= 0)
750 height = 800;
751
752 m_pathMap.clear();
753 m_imageMap.clear();
754 m_pixmapMap.clear();
755 m_regionMap.clear();
756 m_gradientStops.clear();
757 m_blockMap.clear();
758
759 // paint background
760 if (m_checkers_background) {
761 QPixmap pm(20, 20);
762 pm.fill(fillColor: Qt::white);
763 QPainter pt(&pm);
764 pt.fillRect(x: 0, y: 0, w: 10, h: 10, b: QColor::fromRgba(rgba: 0xffdfdfdf));
765 pt.fillRect(x: 10, y: 10, w: 10, h: 10, b: QColor::fromRgba(rgba: 0xffdfdfdf));
766 pt.end();
767 m_painter->drawTiledPixmap(x: 0, y: 0, w: width, h: height, pm);
768 } else {
769 m_painter->fillRect(x: 0, y: 0, w: width, h: height, c: Qt::white);
770 }
771
772 // run each command
773 m_abort = false;
774 for (int i=0; i<m_commands.size() && !m_abort; ++i) {
775 const QString &commandNow = m_commands.at(i);
776 m_currentCommand = commandNow;
777 m_currentCommandIndex = i;
778 runCommand(scriptLine: commandNow.trimmed());
779 }
780}
781
782/*********************************************************************************
783** conversions
784**********************************************************************************/
785int PaintCommands::convertToInt(const QString &str)
786{
787 return qRound(d: convertToDouble(str));
788}
789
790float PaintCommands::convertToFloat(const QString &str)
791{
792 return float(convertToDouble(str));
793}
794
795double PaintCommands::convertToDouble(const QString &str)
796{
797 static QRegularExpression re("cp([0-9])([xy])");
798 if (str.toLower() == "width") {
799 if (m_painter->device()->devType() == Qt::Widget)
800 return m_painter->window().width();
801 else
802 return 800;
803 }
804 if (str.toLower() == "height") {
805 if (m_painter->device()->devType() == Qt::Widget)
806 return m_painter->window().height();
807 else
808 return 800;
809 }
810 QRegularExpressionMatch match = re.match(subject: str);
811 if (match.hasMatch()) {
812 int index = match.captured(nth: 1).toInt();
813 bool is_it_x = match.captured(nth: 2) == "x";
814 if (index < 0 || index >= m_controlPoints.size()) {
815 qWarning(msg: "ERROR: control point index=%d is out of bounds", index);
816 return 0;
817 }
818 return is_it_x ? m_controlPoints.at(i: index).x() : m_controlPoints.at(i: index).y();
819 }
820 return str.toDouble();
821}
822
823QColor PaintCommands::convertToColor(const QString &str)
824{
825 static QRegularExpression alphaColorRe("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})");
826 static QRegularExpression opaqueColorRe("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})");
827
828 Q_ASSERT(alphaColorRe.isValid());
829 Q_ASSERT(opaqueColorRe.isValid());
830
831 QRegularExpressionMatch alphaColor = alphaColorRe.match(subject: str);
832 QRegularExpressionMatch opaqueColor = opaqueColorRe.match(subject: str);
833 if (alphaColor.hasMatch()) {
834 return QColor(alphaColor.captured(nth: 2).toInt(ok: 0, base: 16),
835 alphaColor.captured(nth: 3).toInt(ok: 0, base: 16),
836 alphaColor.captured(nth: 4).toInt(ok: 0, base: 16),
837 alphaColor.captured(nth: 1).toInt(ok: 0, base: 16));
838 } else if (opaqueColor.hasMatch()) {
839 return QColor(opaqueColor.captured(nth: 1).toInt(ok: 0, base: 16),
840 opaqueColor.captured(nth: 2).toInt(ok: 0, base: 16),
841 opaqueColor.captured(nth: 3).toInt(ok: 0, base: 16));
842 }
843 return QColor(str);
844}
845
846/*********************************************************************************
847** command implementations
848**********************************************************************************/
849void PaintCommands::command_comment(QRegularExpressionMatch)
850{
851 if (m_verboseMode)
852 printf(format: " -(lance) comment: %s\n", qPrintable(m_currentCommand));
853}
854
855/***************************************************************************************************/
856void PaintCommands::command_import(QRegularExpressionMatch re)
857{
858 QString importFile(re.captured(nth: 1));
859 QFileInfo fi(m_filepath);
860 QDir dir = fi.absoluteDir();
861 QFile *file = new QFile(dir.absolutePath() + QDir::separator() + importFile);
862
863 if (importFile.isEmpty() || !file->exists()) {
864 dir.cdUp();
865 dir.cd(dirName: "data");
866 dir.cd(dirName: "qps");
867 delete file;
868 file = new QFile(dir.absolutePath() + QDir::separator() + importFile);
869 }
870
871 if (importFile.isEmpty() || !file->exists()) {
872 dir.cdUp();
873 dir.cd(dirName: "images");
874 delete file;
875 file = new QFile(dir.absolutePath() + QDir::separator() + importFile);
876 }
877
878 if (importFile.isEmpty() || !file->exists()) {
879 printf(format: " - importing non-existing file at line %d (%s)\n", m_currentCommandIndex,
880 qPrintable(file->fileName()));
881 delete file;
882 return;
883 }
884
885 if (!file->open(flags: QIODevice::ReadOnly)) {
886 printf(format: " - failed to read file: '%s'\n", qPrintable(file->fileName()));
887 delete file;
888 return;
889 }
890 if (m_verboseMode)
891 printf(format: " -(lance) importing file at line %d (%s)\n", m_currentCommandIndex,
892 qPrintable(fi.fileName()));
893
894 QFileInfo fileinfo(*file);
895 m_commands[m_currentCommandIndex] = QLatin1String("# import file (") + fileinfo.fileName()
896 + QLatin1String(") start");
897 QString rawContent = QString::fromUtf8(str: file->readAll());
898 QStringList importedData = rawContent.split(sep: '\n', behavior: Qt::SkipEmptyParts);
899 importedData.append(t: QLatin1String("# import file (") + fileinfo.fileName() + QLatin1String(") end ---"));
900 insertAt(commandIndex: m_currentCommandIndex, newCommands: importedData);
901
902 if (m_verboseMode) {
903 printf(format: " -(lance) Command buffer now looks like:\n");
904 for (int i = 0; i < m_commands.count(); ++i)
905 printf(format: " ---> {%s}\n", qPrintable(m_commands.at(i)));
906 }
907 delete file;
908}
909
910/***************************************************************************************************/
911void PaintCommands::command_begin_block(QRegularExpressionMatch re)
912{
913 const QString &blockName = re.captured(nth: 1);
914 if (m_verboseMode)
915 printf(format: " -(lance) begin_block (%s)\n", qPrintable(blockName));
916 if (m_blockMap.contains(akey: blockName))
917 qFatal(msg: "Two blocks named (%s)", qPrintable(blockName));
918
919 m_commands[m_currentCommandIndex] = QLatin1String("# begin block (") + blockName + QLatin1Char(')');
920 QStringList newBlock;
921 int i = m_currentCommandIndex + 1;
922 for (; i < m_commands.count(); ++i) {
923 const QString &nextCmd = m_commands.at(i);
924 if (nextCmd.startsWith(s: "end_block")) {
925 m_commands[i] = QLatin1String("# end block (") + blockName + QLatin1Char(')');
926 break;
927 }
928 newBlock += nextCmd;
929 }
930
931 if (m_verboseMode)
932 for (int j = 0; j < newBlock.count(); ++j)
933 printf(format: " %d: %s\n", j, qPrintable(newBlock.at(j)));
934
935 if (i >= m_commands.count())
936 printf(format: " - Warning! Block doesn't have an 'end_block' marker!\n");
937
938 m_blockMap.insert(akey: blockName, avalue: newBlock);
939}
940
941/***************************************************************************************************/
942void PaintCommands::command_end_block(QRegularExpressionMatch)
943{
944 printf(format: " - end_block should be consumed by begin_block command.\n");
945 printf(format: " You will never see this if your block markers are in sync\n");
946 printf(format: " (noop)\n");
947}
948
949/***************************************************************************************************/
950void PaintCommands::command_repeat_block(QRegularExpressionMatch re)
951{
952 QString blockName = re.captured(nth: 1);
953 if (m_verboseMode)
954 printf(format: " -(lance) repeating block (%s)\n", qPrintable(blockName));
955
956 QStringList block = m_blockMap.value(akey: blockName);
957 if (block.isEmpty()) {
958 printf(format: " - repeated block (%s) is empty!\n", qPrintable(blockName));
959 return;
960 }
961
962 m_commands[m_currentCommandIndex] = QLatin1String("# repeated block (") + blockName + QLatin1Char(')');
963 insertAt(commandIndex: m_currentCommandIndex, newCommands: block);
964}
965
966/***************************************************************************************************/
967void PaintCommands::command_drawLine(QRegularExpressionMatch re)
968{
969 QStringList caps = re.capturedTexts();
970 double x1 = convertToDouble(str: caps.at(i: 1));
971 double y1 = convertToDouble(str: caps.at(i: 2));
972 double x2 = convertToDouble(str: caps.at(i: 3));
973 double y2 = convertToDouble(str: caps.at(i: 4));
974
975 if (m_verboseMode)
976 printf(format: " -(lance) drawLine((%.2f, %.2f), (%.2f, %.2f))\n", x1, y1, x2, y2);
977
978 m_painter->drawLine(l: QLineF(x1, y1, x2, y2));
979}
980
981/***************************************************************************************************/
982void PaintCommands::command_drawLines(QRegularExpressionMatch re)
983{
984 static QRegularExpression separators("\\s");
985 QStringList numbers = re.captured(nth: 1).split(sep: separators, behavior: Qt::SkipEmptyParts);
986
987 QVector<QLineF> array;
988 for (int i = 0; i + 3 < numbers.size(); i += 4) {
989 QPointF pt1(numbers.at(i).toFloat(), numbers.at(i: i + 1).toFloat());
990 QPointF pt2(numbers.at(i: i + 2).toFloat(), numbers.at(i: i + 3).toFloat());
991 array.append(t: QLineF(pt1, pt2));
992 }
993
994 if (m_verboseMode)
995 printf(format: " -(lance) drawLines(size=%zd)\n", size_t(array.size()));
996
997 m_painter->drawLines(lines: array);
998}
999
1000/***************************************************************************************************/
1001void PaintCommands::command_drawPath(QRegularExpressionMatch re)
1002{
1003 if (m_verboseMode)
1004 printf(format: " -(lance) drawPath(name=%s)\n", qPrintable(re.captured(1)));
1005
1006 QPainterPath &path = m_pathMap[re.captured(nth: 1)];
1007 m_painter->drawPath(path);
1008}
1009
1010/***************************************************************************************************/
1011void PaintCommands::command_drawPixmap(QRegularExpressionMatch re)
1012{
1013 QPixmap pm;
1014 pm = m_pixmapMap[re.captured(nth: 1)]; // try cache first
1015 if (pm.isNull())
1016 pm = image_load<QPixmap>(filepath: re.captured(nth: 1));
1017 if (pm.isNull()) {
1018 QFileInfo fi(m_filepath);
1019 QDir dir = fi.absoluteDir();
1020 dir.cdUp();
1021 dir.cd(dirName: "images");
1022 QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(nth: 1);
1023 pm = QPixmap(fileName);
1024 if (pm.isNull() && !fileName.endsWith(s: ".png")) {
1025 fileName.append(s: ".png");
1026 pm = QPixmap(fileName);
1027 }
1028 }
1029 if (pm.isNull()) {
1030 fprintf(stderr, format: "ERROR(drawPixmap): failed to load pixmap: '%s'\n",
1031 qPrintable(re.captured(1)));
1032 return;
1033 }
1034
1035 qreal tx = convertToFloat(str: re.captured(nth: 2));
1036 qreal ty = convertToFloat(str: re.captured(nth: 3));
1037 qreal tw = convertToFloat(str: re.captured(nth: 4));
1038 qreal th = convertToFloat(str: re.captured(nth: 5));
1039
1040 qreal sx = convertToFloat(str: re.captured(nth: 6));
1041 qreal sy = convertToFloat(str: re.captured(nth: 7));
1042 qreal sw = convertToFloat(str: re.captured(nth: 8));
1043 qreal sh = convertToFloat(str: re.captured(nth: 9));
1044
1045 if (tw == 0) tw = -1;
1046 if (th == 0) th = -1;
1047 if (sw == 0) sw = -1;
1048 if (sh == 0) sh = -1;
1049
1050 if (m_verboseMode)
1051 printf(format: " -(lance) drawPixmap('%s' dim=(%d, %d), depth=%d, (%f, %f, %f, %f), (%f, %f, %f, %f)\n",
1052 qPrintable(re.captured(1)), pm.width(), pm.height(), pm.depth(),
1053 tx, ty, tw, th, sx, sy, sw, sh);
1054
1055 if (!re.capturedLength(nth: 4)) // at most two coordinates specified
1056 m_painter->drawPixmap(p: QPointF(tx, ty), pm);
1057 else
1058 m_painter->drawPixmap(targetRect: QRectF(tx, ty, tw, th), pixmap: pm, sourceRect: QRectF(sx, sy, sw, sh));
1059}
1060
1061/***************************************************************************************************/
1062void PaintCommands::command_drawImage(QRegularExpressionMatch re)
1063{
1064 QImage im;
1065 im = m_imageMap[re.captured(nth: 1)]; // try cache first
1066 if (im.isNull())
1067 im = image_load<QImage>(filepath: re.captured(nth: 1));
1068
1069 if (im.isNull()) {
1070 QFileInfo fi(m_filepath);
1071 QDir dir = fi.absoluteDir();
1072 dir.cdUp();
1073 dir.cd(dirName: "images");
1074 QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(nth: 1);
1075 im = QImage(fileName);
1076 if (im.isNull() && !fileName.endsWith(s: ".png")) {
1077 fileName.append(s: ".png");
1078 im = QImage(fileName);
1079 }
1080 }
1081 if (im.isNull()) {
1082 fprintf(stderr, format: "ERROR(drawImage): failed to load image: '%s'\n", qPrintable(re.captured(1)));
1083 return;
1084 }
1085
1086 qreal tx = convertToFloat(str: re.captured(nth: 2));
1087 qreal ty = convertToFloat(str: re.captured(nth: 3));
1088 qreal tw = convertToFloat(str: re.captured(nth: 4));
1089 qreal th = convertToFloat(str: re.captured(nth: 5));
1090
1091 qreal sx = convertToFloat(str: re.captured(nth: 6));
1092 qreal sy = convertToFloat(str: re.captured(nth: 7));
1093 qreal sw = convertToFloat(str: re.captured(nth: 8));
1094 qreal sh = convertToFloat(str: re.captured(nth: 9));
1095
1096 if (tw == 0) tw = -1;
1097 if (th == 0) th = -1;
1098 if (sw == 0) sw = -1;
1099 if (sh == 0) sh = -1;
1100
1101 if (m_verboseMode)
1102 printf(format: " -(lance) drawImage('%s' dim=(%d, %d), (%f, %f, %f, %f), (%f, %f, %f, %f)\n",
1103 qPrintable(re.captured(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh);
1104
1105 if (!re.capturedLength(nth: 4)) // at most two coordinates specified
1106 m_painter->drawImage(p: QPointF(tx, ty), image: im);
1107 else
1108 m_painter->drawImage(targetRect: QRectF(tx, ty, tw, th), image: im, sourceRect: QRectF(sx, sy, sw, sh));
1109}
1110
1111/***************************************************************************************************/
1112void PaintCommands::command_drawTiledPixmap(QRegularExpressionMatch re)
1113{
1114 QPixmap pm;
1115 pm = m_pixmapMap[re.captured(nth: 1)]; // try cache first
1116 if (pm.isNull())
1117 pm = image_load<QPixmap>(filepath: re.captured(nth: 1));
1118 if (pm.isNull()) {
1119 QFileInfo fi(m_filepath);
1120 QDir dir = fi.absoluteDir();
1121 dir.cdUp();
1122 dir.cd(dirName: "images");
1123 QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(nth: 1);
1124 pm = QPixmap(fileName);
1125 if (pm.isNull() && !fileName.endsWith(s: ".png")) {
1126 fileName.append(s: ".png");
1127 pm = QPixmap(fileName);
1128 }
1129 }
1130 if (pm.isNull()) {
1131 fprintf(stderr, format: "ERROR(drawTiledPixmap): failed to load pixmap: '%s'\n",
1132 qPrintable(re.captured(1)));
1133 return;
1134 }
1135
1136 int tx = convertToInt(str: re.captured(nth: 2));
1137 int ty = convertToInt(str: re.captured(nth: 3));
1138 int tw = convertToInt(str: re.captured(nth: 4));
1139 int th = convertToInt(str: re.captured(nth: 5));
1140
1141 int sx = convertToInt(str: re.captured(nth: 6));
1142 int sy = convertToInt(str: re.captured(nth: 7));
1143
1144 if (tw == 0) tw = -1;
1145 if (th == 0) th = -1;
1146
1147 if (m_verboseMode)
1148 printf(format: " -(lance) drawTiledPixmap('%s' dim=(%d, %d), (%d, %d, %d, %d), (%d, %d)\n",
1149 qPrintable(re.captured(1)), pm.width(), pm.height(), tx, ty, tw, th, sx, sy);
1150
1151 m_painter->drawTiledPixmap(x: tx, y: ty, w: tw, h: th, pm, sx, sy);
1152}
1153
1154/***************************************************************************************************/
1155void PaintCommands::command_drawPoint(QRegularExpressionMatch re)
1156{
1157 QStringList caps = re.capturedTexts();
1158 float x = convertToFloat(str: caps.at(i: 1));
1159 float y = convertToFloat(str: caps.at(i: 2));
1160
1161 if (m_verboseMode)
1162 printf(format: " -(lance) drawPoint(%.2f, %.2f)\n", x, y);
1163
1164 m_painter->drawPoint(p: QPointF(x, y));
1165}
1166
1167/***************************************************************************************************/
1168void PaintCommands::command_drawPolygon(QRegularExpressionMatch re)
1169{
1170 static QRegularExpression separators("\\s");
1171 QStringList caps = re.capturedTexts();
1172 QString cap = caps.at(i: 1);
1173 QStringList numbers = cap.split(sep: separators, behavior: Qt::SkipEmptyParts);
1174
1175 QPolygonF array;
1176 for (int i=0; i + 1<numbers.size(); i+=2)
1177 array.append(t: QPointF(convertToDouble(str: numbers.at(i)), convertToDouble(str: numbers.at(i: i+1))));
1178
1179 if (m_verboseMode)
1180 printf(format: " -(lance) drawPolygon(size=%d)\n", array.size());
1181
1182 m_painter->drawPolygon(polygon: array, fillRule: caps.at(i: 2).toLower() == "winding" ? Qt::WindingFill : Qt::OddEvenFill);
1183}
1184
1185/***************************************************************************************************/
1186void PaintCommands::command_drawPolyline(QRegularExpressionMatch re)
1187{
1188 static QRegularExpression separators("\\s");
1189 QStringList numbers = re.captured(nth: 1).split(sep: separators, behavior: Qt::SkipEmptyParts);
1190
1191 QPolygonF array;
1192 for (int i=0; i + 1<numbers.size(); i+=2)
1193 array.append(t: QPointF(numbers.at(i).toFloat(),numbers.at(i: i+1).toFloat()));
1194
1195 if (m_verboseMode)
1196 printf(format: " -(lance) drawPolyline(size=%d)\n", array.size());
1197
1198 m_painter->drawPolyline(polyline: array.toPolygon());
1199}
1200
1201/***************************************************************************************************/
1202void PaintCommands::command_drawRect(QRegularExpressionMatch re)
1203{
1204 QStringList caps = re.capturedTexts();
1205 float x = convertToFloat(str: caps.at(i: 1));
1206 float y = convertToFloat(str: caps.at(i: 2));
1207 float w = convertToFloat(str: caps.at(i: 3));
1208 float h = convertToFloat(str: caps.at(i: 4));
1209
1210 if (m_verboseMode)
1211 printf(format: " -(lance) drawRect(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h);
1212
1213 m_painter->drawRect(rect: QRectF(x, y, w, h));
1214}
1215
1216/***************************************************************************************************/
1217void PaintCommands::command_drawRoundedRect(QRegularExpressionMatch re)
1218{
1219 QStringList caps = re.capturedTexts();
1220 float x = convertToFloat(str: caps.at(i: 1));
1221 float y = convertToFloat(str: caps.at(i: 2));
1222 float w = convertToFloat(str: caps.at(i: 3));
1223 float h = convertToFloat(str: caps.at(i: 4));
1224 float xr = convertToFloat(str: caps.at(i: 5));
1225 float yr = convertToFloat(str: caps.at(i: 6));
1226
1227 int mode = translateEnum(table: sizeModeTable, pattern: caps.at(i: 7), limit: sizeof(sizeModeTable)/sizeof(char *));
1228 if (mode < 0)
1229 mode = Qt::AbsoluteSize;
1230
1231 if (m_verboseMode)
1232 printf(format: " -(lance) drawRoundRect(%f, %f, %f, %f, %f, %f, %s)\n", x, y, w, h, xr, yr, mode ? "RelativeSize" : "AbsoluteSize");
1233
1234 m_painter->drawRoundedRect(rect: QRectF(x, y, w, h), xRadius: xr, yRadius: yr, mode: Qt::SizeMode(mode));
1235}
1236
1237/***************************************************************************************************/
1238void PaintCommands::command_drawRoundRect(QRegularExpressionMatch re)
1239{
1240 QStringList caps = re.capturedTexts();
1241 int x = convertToInt(str: caps.at(i: 1));
1242 int y = convertToInt(str: caps.at(i: 2));
1243 int w = convertToInt(str: caps.at(i: 3));
1244 int h = convertToInt(str: caps.at(i: 4));
1245 int xs = caps.at(i: 5).isEmpty() ? 50 : convertToInt(str: caps.at(i: 5));
1246 int ys = caps.at(i: 6).isEmpty() ? 50 : convertToInt(str: caps.at(i: 6));
1247
1248 if (m_verboseMode)
1249 printf(format: " -(lance) drawRoundRect(%d, %d, %d, %d, [%d, %d])\n", x, y, w, h, xs, ys);
1250
1251 QT_WARNING_PUSH
1252 QT_WARNING_DISABLE_DEPRECATED
1253 m_painter->drawRoundedRect(x, y, w, h, xRadius: xs, yRadius: ys, mode: Qt::RelativeSize);
1254 QT_WARNING_POP
1255}
1256
1257/***************************************************************************************************/
1258void PaintCommands::command_drawEllipse(QRegularExpressionMatch re)
1259{
1260 QStringList caps = re.capturedTexts();
1261 float x = convertToFloat(str: caps.at(i: 1));
1262 float y = convertToFloat(str: caps.at(i: 2));
1263 float w = convertToFloat(str: caps.at(i: 3));
1264 float h = convertToFloat(str: caps.at(i: 4));
1265
1266 if (m_verboseMode)
1267 printf(format: " -(lance) drawEllipse(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h);
1268
1269 m_painter->drawEllipse(r: QRectF(x, y, w, h));
1270}
1271
1272/***************************************************************************************************/
1273void PaintCommands::command_drawPie(QRegularExpressionMatch re)
1274{
1275 QStringList caps = re.capturedTexts();
1276 int x = convertToInt(str: caps.at(i: 1));
1277 int y = convertToInt(str: caps.at(i: 2));
1278 int w = convertToInt(str: caps.at(i: 3));
1279 int h = convertToInt(str: caps.at(i: 4));
1280 int angle = convertToInt(str: caps.at(i: 5));
1281 int sweep = convertToInt(str: caps.at(i: 6));
1282
1283 if (m_verboseMode)
1284 printf(format: " -(lance) drawPie(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep);
1285
1286 m_painter->drawPie(x, y, w, h, a: angle, alen: sweep);
1287}
1288
1289/***************************************************************************************************/
1290void PaintCommands::command_drawChord(QRegularExpressionMatch re)
1291{
1292 QStringList caps = re.capturedTexts();
1293 int x = convertToInt(str: caps.at(i: 1));
1294 int y = convertToInt(str: caps.at(i: 2));
1295 int w = convertToInt(str: caps.at(i: 3));
1296 int h = convertToInt(str: caps.at(i: 4));
1297 int angle = convertToInt(str: caps.at(i: 5));
1298 int sweep = convertToInt(str: caps.at(i: 6));
1299
1300 if (m_verboseMode)
1301 printf(format: " -(lance) drawChord(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep);
1302
1303 m_painter->drawChord(x, y, w, h, a: angle, alen: sweep);
1304}
1305
1306/***************************************************************************************************/
1307void PaintCommands::command_drawArc(QRegularExpressionMatch re)
1308{
1309 QStringList caps = re.capturedTexts();
1310 int x = convertToInt(str: caps.at(i: 1));
1311 int y = convertToInt(str: caps.at(i: 2));
1312 int w = convertToInt(str: caps.at(i: 3));
1313 int h = convertToInt(str: caps.at(i: 4));
1314 int angle = convertToInt(str: caps.at(i: 5));
1315 int sweep = convertToInt(str: caps.at(i: 6));
1316
1317 if (m_verboseMode)
1318 printf(format: " -(lance) drawArc(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep);
1319
1320 m_painter->drawArc(x, y, w, h, a: angle, alen: sweep);
1321}
1322
1323/***************************************************************************************************/
1324void PaintCommands::command_drawText(QRegularExpressionMatch re)
1325{
1326 if (!m_shouldDrawText)
1327 return;
1328 QStringList caps = re.capturedTexts();
1329 int x = convertToInt(str: caps.at(i: 1));
1330 int y = convertToInt(str: caps.at(i: 2));
1331 QString txt = caps.at(i: 3);
1332
1333 if (m_verboseMode)
1334 printf(format: " -(lance) drawText(%d, %d, %s)\n", x, y, qPrintable(txt));
1335
1336 m_painter->drawText(x, y, s: txt);
1337}
1338
1339void PaintCommands::command_drawStaticText(QRegularExpressionMatch re)
1340{
1341 if (!m_shouldDrawText)
1342 return;
1343 QStringList caps = re.capturedTexts();
1344 int x = convertToInt(str: caps.at(i: 1));
1345 int y = convertToInt(str: caps.at(i: 2));
1346 QString txt = caps.at(i: 3);
1347
1348 if (m_verboseMode)
1349 printf(format: " -(lance) drawStaticText(%d, %d, %s)\n", x, y, qPrintable(txt));
1350
1351 m_painter->drawStaticText(x, y, staticText: QStaticText(txt));
1352}
1353
1354void PaintCommands::command_drawTextDocument(QRegularExpressionMatch re)
1355{
1356 if (!m_shouldDrawText)
1357 return;
1358 QStringList caps = re.capturedTexts();
1359 int x = convertToInt(str: caps.at(i: 1));
1360 int y = convertToInt(str: caps.at(i: 2));
1361 QString txt = caps.at(i: 3);
1362
1363 if (m_verboseMode)
1364 printf(format: " -(lance) drawTextDocument(%d, %d, %s)\n", x, y, qPrintable(txt));
1365
1366 QTextDocument doc;
1367 doc.setBaseUrl(QUrl::fromLocalFile(localfile: QDir::currentPath() + QLatin1String("/")));
1368 doc.setHtml(txt);
1369
1370 m_painter->save();
1371 m_painter->translate(dx: x, dy: y);
1372 doc.drawContents(painter: m_painter);
1373 m_painter->restore();
1374}
1375
1376/***************************************************************************************************/
1377void PaintCommands::command_fillRect(QRegularExpressionMatch re)
1378{
1379 QStringList caps = re.capturedTexts();
1380 int x = convertToInt(str: caps.at(i: 1));
1381 int y = convertToInt(str: caps.at(i: 2));
1382 int w = convertToInt(str: caps.at(i: 3));
1383 int h = convertToInt(str: caps.at(i: 4));
1384
1385 if (!caps.at(i: 5).isEmpty()) {
1386 QColor color = convertToColor(str: caps.at(i: 5));
1387 if (m_verboseMode)
1388 printf(format: " -(lance) fillRect(%d, %d, %d, %d, %s)\n", x, y, w, h, qPrintable(color.name()));
1389 m_painter->fillRect(x, y, w, h, b: color);
1390 } else {
1391 if (m_verboseMode)
1392 printf(format: " -(lance) fillRect(%d, %d, %d, %d)\n", x, y, w, h);
1393 m_painter->fillRect(x, y, w, h, b: m_painter->brush());
1394 }
1395}
1396
1397void PaintCommands::command_fillRectF(QRegularExpressionMatch re)
1398{
1399 QStringList caps = re.capturedTexts();
1400 double x = convertToDouble(str: caps.at(i: 1));
1401 double y = convertToDouble(str: caps.at(i: 2));
1402 double w = convertToDouble(str: caps.at(i: 3));
1403 double h = convertToDouble(str: caps.at(i: 4));
1404
1405 if (!caps.at(i: 5).isEmpty()) {
1406 QColor color = convertToColor(str: caps.at(i: 5));
1407 if (m_verboseMode)
1408 printf(format: " -(lance) fillRectF(%.2f, %.2f, %.2f, %.2f, %s)\n", x, y, w, h, qPrintable(color.name()));
1409 m_painter->fillRect(QRectF(x, y, w, h), color);
1410 } else {
1411 if (m_verboseMode)
1412 printf(format: " -(lance) fillRectF(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h);
1413 m_painter->fillRect(QRectF(x, y, w, h), m_painter->brush());
1414 }
1415}
1416
1417/***************************************************************************************************/
1418void PaintCommands::command_noop(QRegularExpressionMatch)
1419{
1420 if (m_verboseMode)
1421 printf(format: " -(lance) noop: %s\n", qPrintable(m_currentCommand));
1422
1423 if (!m_currentCommand.trimmed().isEmpty()) {
1424 fprintf(stderr, format: "unknown command: '%s'\n", qPrintable(m_currentCommand.trimmed()));
1425 }
1426}
1427
1428/***************************************************************************************************/
1429void PaintCommands::command_path_addText(QRegularExpressionMatch re)
1430{
1431 QStringList caps = re.capturedTexts();
1432 QString name = caps.at(i: 1);
1433 double x = convertToDouble(str: caps.at(i: 2));
1434 double y = convertToDouble(str: caps.at(i: 3));
1435 QString text = caps.at(i: 4);
1436
1437 if (m_verboseMode)
1438 printf(format: " -(lance) path_addText(%s, %.2f, %.2f, text=%s\n", qPrintable(name), x, y, qPrintable(text));
1439
1440 m_pathMap[name].addText(x, y, f: m_painter->font(), text);
1441}
1442
1443/***************************************************************************************************/
1444void PaintCommands::command_path_addEllipse(QRegularExpressionMatch re)
1445{
1446 QStringList caps = re.capturedTexts();
1447 QString name = caps.at(i: 1);
1448 double x = convertToDouble(str: caps.at(i: 2));
1449 double y = convertToDouble(str: caps.at(i: 3));
1450 double w = convertToDouble(str: caps.at(i: 4));
1451 double h = convertToDouble(str: caps.at(i: 5));
1452
1453 if (m_verboseMode)
1454 printf(format: " -(lance) path_addEllipse(%s, %.2f, %.2f, %.2f, %.2f)\n", qPrintable(name), x, y, w, h);
1455
1456 m_pathMap[name].addEllipse(x, y, w, h);
1457}
1458
1459/***************************************************************************************************/
1460void PaintCommands::command_path_addRect(QRegularExpressionMatch re)
1461{
1462 QStringList caps = re.capturedTexts();
1463 QString name = caps.at(i: 1);
1464 double x = convertToDouble(str: caps.at(i: 2));
1465 double y = convertToDouble(str: caps.at(i: 3));
1466 double w = convertToDouble(str: caps.at(i: 4));
1467 double h = convertToDouble(str: caps.at(i: 5));
1468
1469 if (m_verboseMode)
1470 printf(format: " -(lance) path_addRect(%s, %.2f, %.2f, %.2f, %.2f)\n", qPrintable(name), x, y, w, h);
1471
1472 m_pathMap[name].addRect(x, y, w, h);
1473}
1474
1475/***************************************************************************************************/
1476void PaintCommands::command_path_addPolygon(QRegularExpressionMatch re)
1477{
1478 static QRegularExpression separators("\\s");
1479 QStringList caps = re.capturedTexts();
1480 QString name = caps.at(i: 1);
1481 QString cap = caps.at(i: 2);
1482 QStringList numbers = cap.split(sep: separators, behavior: Qt::SkipEmptyParts);
1483
1484 QPolygonF array;
1485 for (int i=0; i + 1<numbers.size(); i+=2)
1486 array.append(t: QPointF(numbers.at(i).toFloat(),numbers.at(i: i+1).toFloat()));
1487
1488 if (m_verboseMode)
1489 printf(format: " -(lance) path_addPolygon(name=%s, size=%d)\n", qPrintable(name), array.size());
1490
1491 m_pathMap[name].addPolygon(polygon: array);
1492}
1493
1494/***************************************************************************************************/
1495void PaintCommands::command_path_arcTo(QRegularExpressionMatch re)
1496{
1497 QStringList caps = re.capturedTexts();
1498 QString name = caps.at(i: 1);
1499 double x = convertToDouble(str: caps.at(i: 2));
1500 double y = convertToDouble(str: caps.at(i: 3));
1501 double w = convertToDouble(str: caps.at(i: 4));
1502 double h = convertToDouble(str: caps.at(i: 5));
1503 double angle = convertToDouble(str: caps.at(i: 6));
1504 double length = convertToDouble(str: caps.at(i: 7));
1505
1506 if (m_verboseMode)
1507 printf(format: " -(lance) path_arcTo(%s, %.2f, %.2f, %.2f, %.2f, angle=%.2f, len=%.2f)\n", qPrintable(name), x, y, w, h, angle, length);
1508
1509 m_pathMap[name].arcTo(x, y, w, h, startAngle: angle, arcLength: length);
1510}
1511
1512/***************************************************************************************************/
1513void PaintCommands::command_path_createOutline(QRegularExpressionMatch re)
1514{
1515 QStringList caps = re.capturedTexts();
1516 QString name = caps.at(i: 1);
1517 QString newName = caps.at(i: 2);
1518 QPen pen = m_painter->pen();
1519
1520 if (m_verboseMode)
1521 printf(format: " -(lance) path_createOutline(%s, name=%s, width=%d)\n",
1522 qPrintable(name), qPrintable(newName), pen.width());
1523
1524 if (!m_pathMap.contains(akey: name)) {
1525 fprintf(stderr, format: "createOutline(), unknown path: %s\n", qPrintable(name));
1526 return;
1527 }
1528 QPainterPathStroker stroker;
1529 stroker.setWidth(pen.widthF());
1530 stroker.setDashPattern(pen.style());
1531 stroker.setCapStyle(pen.capStyle());
1532 stroker.setJoinStyle(pen.joinStyle());
1533 m_pathMap[newName] = stroker.createStroke(path: m_pathMap[name]);
1534}
1535
1536/***************************************************************************************************/
1537void PaintCommands::command_path_cubicTo(QRegularExpressionMatch re)
1538{
1539 QStringList caps = re.capturedTexts();
1540 QString name = caps.at(i: 1);
1541 double x1 = convertToDouble(str: caps.at(i: 2));
1542 double y1 = convertToDouble(str: caps.at(i: 3));
1543 double x2 = convertToDouble(str: caps.at(i: 4));
1544 double y2 = convertToDouble(str: caps.at(i: 5));
1545 double x3 = convertToDouble(str: caps.at(i: 6));
1546 double y3 = convertToDouble(str: caps.at(i: 7));
1547
1548 if (m_verboseMode)
1549 printf(format: " -(lance) path_cubicTo(%s, (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f))\n", qPrintable(name), x1, y1, x2, y2, x3, y3);
1550
1551 m_pathMap[name].cubicTo(ctrlPt1x: x1, ctrlPt1y: y1, ctrlPt2x: x2, ctrlPt2y: y2, endPtx: x3, endPty: y3);
1552}
1553
1554/***************************************************************************************************/
1555void PaintCommands::command_path_moveTo(QRegularExpressionMatch re)
1556{
1557 QStringList caps = re.capturedTexts();
1558 QString name = caps.at(i: 1);
1559 double x1 = convertToDouble(str: caps.at(i: 2));
1560 double y1 = convertToDouble(str: caps.at(i: 3));
1561
1562 if (m_verboseMode)
1563 printf(format: " -(lance) path_moveTo(%s, (%.2f, %.2f))\n", qPrintable(name), x1, y1);
1564
1565 m_pathMap[name].moveTo(x: x1, y: y1);
1566}
1567
1568/***************************************************************************************************/
1569void PaintCommands::command_path_lineTo(QRegularExpressionMatch re)
1570{
1571 QStringList caps = re.capturedTexts();
1572 QString name = caps.at(i: 1);
1573 double x1 = convertToDouble(str: caps.at(i: 2));
1574 double y1 = convertToDouble(str: caps.at(i: 3));
1575
1576 if (m_verboseMode)
1577 printf(format: " -(lance) path_lineTo(%s, (%.2f, %.2f))\n", qPrintable(name), x1, y1);
1578
1579 m_pathMap[name].lineTo(x: x1, y: y1);
1580}
1581
1582/***************************************************************************************************/
1583void PaintCommands::command_path_setFillRule(QRegularExpressionMatch re)
1584{
1585 QStringList caps = re.capturedTexts();
1586 QString name = caps.at(i: 1);
1587 bool winding = caps.at(i: 2).toLower() == "winding";
1588
1589 if (m_verboseMode)
1590 printf(format: " -(lance) path_setFillRule(name=%s, winding=%d)\n", qPrintable(name), winding);
1591
1592 m_pathMap[name].setFillRule(winding ? Qt::WindingFill : Qt::OddEvenFill);
1593}
1594
1595/***************************************************************************************************/
1596void PaintCommands::command_path_closeSubpath(QRegularExpressionMatch re)
1597{
1598 QStringList caps = re.capturedTexts();
1599 QString name = caps.at(i: 1);
1600
1601 if (m_verboseMode)
1602 printf(format: " -(lance) path_closeSubpath(name=%s)\n", qPrintable(name));
1603
1604 m_pathMap[name].closeSubpath();
1605}
1606
1607/***************************************************************************************************/
1608void PaintCommands::command_path_getClipPath(QRegularExpressionMatch re)
1609{
1610 QStringList caps = re.capturedTexts();
1611 QString name = caps.at(i: 1);
1612
1613 if (m_verboseMode)
1614 printf(format: " -(lance) path_closeSubpath(name=%s)\n", qPrintable(name));
1615
1616 m_pathMap[name] = m_painter->clipPath();
1617}
1618
1619/***************************************************************************************************/
1620static void qt_debug_path(const QPainterPath &path, const QString &name)
1621{
1622 const char *names[] = {
1623 "MoveTo ",
1624 "LineTo ",
1625 "CurveTo ",
1626 "CurveToData"
1627 };
1628
1629 printf(format: "\nQPainterPath (%s): elementCount=%d\n", qPrintable(name), path.elementCount());
1630 for (int i=0; i<path.elementCount(); ++i) {
1631 const QPainterPath::Element &e = path.elementAt(i);
1632 Q_ASSERT(e.type >= 0 && e.type <= QPainterPath::CurveToDataElement);
1633 printf(format: " - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y);
1634 }
1635}
1636
1637/***************************************************************************************************/
1638void PaintCommands::command_path_debugPrint(QRegularExpressionMatch re)
1639{
1640 QStringList caps = re.capturedTexts();
1641 QString name = caps.at(i: 1);
1642 qt_debug_path(path: m_pathMap[name], name);
1643}
1644
1645/***************************************************************************************************/
1646void PaintCommands::command_region_addRect(QRegularExpressionMatch re)
1647{
1648 QStringList caps = re.capturedTexts();
1649 QString name = caps.at(i: 1);
1650 int x = convertToInt(str: caps.at(i: 2));
1651 int y = convertToInt(str: caps.at(i: 3));
1652 int w = convertToInt(str: caps.at(i: 4));
1653 int h = convertToInt(str: caps.at(i: 5));
1654
1655 if (m_verboseMode)
1656 printf(format: " -(lance) region_addRect(%s, %d, %d, %d, %d)\n", qPrintable(name), x, y, w, h);
1657
1658 m_regionMap[name] += QRect(x, y, w, h);
1659}
1660
1661/***************************************************************************************************/
1662void PaintCommands::command_region_addEllipse(QRegularExpressionMatch re)
1663{
1664 QStringList caps = re.capturedTexts();
1665 QString name = caps.at(i: 1);
1666 int x = convertToInt(str: caps.at(i: 2));
1667 int y = convertToInt(str: caps.at(i: 3));
1668 int w = convertToInt(str: caps.at(i: 4));
1669 int h = convertToInt(str: caps.at(i: 5));
1670
1671 if (m_verboseMode)
1672 printf(format: " -(lance) region_addEllipse(%s, %d, %d, %d, %d)\n", qPrintable(name), x, y, w, h);
1673
1674 m_regionMap[name] += QRegion(x, y, w, h, QRegion::Ellipse);
1675}
1676
1677/***************************************************************************************************/
1678void PaintCommands::command_region_getClipRegion(QRegularExpressionMatch re)
1679{
1680 QStringList caps = re.capturedTexts();
1681 QString name = caps.at(i: 1);
1682 QRegion region = m_painter->clipRegion();
1683
1684 if (m_verboseMode)
1685 printf(format: " -(lance) region_getClipRegion(name=%s), bounds=[%d, %d, %d, %d]\n", qPrintable(name),
1686 region.boundingRect().x(),
1687 region.boundingRect().y(),
1688 region.boundingRect().width(),
1689 region.boundingRect().height());
1690
1691 m_regionMap[name] = region;
1692}
1693
1694/***************************************************************************************************/
1695void PaintCommands::command_resetMatrix(QRegularExpressionMatch)
1696{
1697 if (m_verboseMode)
1698 printf(format: " -(lance) resetMatrix()\n");
1699
1700 m_painter->resetTransform();
1701}
1702
1703/***************************************************************************************************/
1704void PaintCommands::command_restore(QRegularExpressionMatch)
1705{
1706 if (m_verboseMode)
1707 printf(format: " -(lance) restore()\n");
1708
1709 m_painter->restore();
1710}
1711
1712/***************************************************************************************************/
1713void PaintCommands::command_rotate(QRegularExpressionMatch re)
1714{
1715 QStringList caps = re.capturedTexts();
1716 double angle = convertToDouble(str: caps.at(i: 1));
1717
1718 if (m_verboseMode)
1719 printf(format: " -(lance) rotate(%.2f)\n", angle);
1720
1721 m_painter->rotate(a: angle);
1722}
1723
1724/***************************************************************************************************/
1725void PaintCommands::command_rotate_x(QRegularExpressionMatch re)
1726{
1727 QStringList caps = re.capturedTexts();
1728 double angle = convertToDouble(str: caps.at(i: 1));
1729
1730 if (m_verboseMode)
1731 printf(format: " -(lance) rotate_x(%.2f)\n", angle);
1732
1733 QTransform transform;
1734 transform.rotate(a: angle, axis: Qt::XAxis);
1735 m_painter->setTransform(transform, combine: true);
1736}
1737
1738/***************************************************************************************************/
1739void PaintCommands::command_rotate_y(QRegularExpressionMatch re)
1740{
1741 QStringList caps = re.capturedTexts();
1742 double angle = convertToDouble(str: caps.at(i: 1));
1743
1744 if (m_verboseMode)
1745 printf(format: " -(lance) rotate_y(%.2f)\n", angle);
1746
1747 QTransform transform;
1748 transform.rotate(a: angle, axis: Qt::YAxis);
1749 m_painter->setTransform(transform, combine: true);
1750}
1751
1752/***************************************************************************************************/
1753void PaintCommands::command_save(QRegularExpressionMatch)
1754{
1755 if (m_verboseMode)
1756 printf(format: " -(lance) save()\n");
1757
1758 m_painter->save();
1759}
1760
1761/***************************************************************************************************/
1762void PaintCommands::command_mapQuadToQuad(QRegularExpressionMatch re)
1763{
1764 QStringList caps = re.capturedTexts();
1765 double x1 = convertToDouble(str: caps.at(i: 1));
1766 double y1 = convertToDouble(str: caps.at(i: 2));
1767 double x2 = convertToDouble(str: caps.at(i: 3));
1768 double y2 = convertToDouble(str: caps.at(i: 4));
1769 double x3 = convertToDouble(str: caps.at(i: 5));
1770 double y3 = convertToDouble(str: caps.at(i: 6));
1771 double x4 = convertToDouble(str: caps.at(i: 7));
1772 double y4 = convertToDouble(str: caps.at(i: 8));
1773 QPolygonF poly1(4);
1774 poly1[0] = QPointF(x1, y1);
1775 poly1[1] = QPointF(x2, y2);
1776 poly1[2] = QPointF(x3, y3);
1777 poly1[3] = QPointF(x4, y4);
1778
1779 double x5 = convertToDouble(str: caps.at(i: 9));
1780 double y5 = convertToDouble(str: caps.at(i: 10));
1781 double x6 = convertToDouble(str: caps.at(i: 11));
1782 double y6 = convertToDouble(str: caps.at(i: 12));
1783 double x7 = convertToDouble(str: caps.at(i: 13));
1784 double y7 = convertToDouble(str: caps.at(i: 14));
1785 double x8 = convertToDouble(str: caps.at(i: 15));
1786 double y8 = convertToDouble(str: caps.at(i: 16));
1787 QPolygonF poly2(4);
1788 poly2[0] = QPointF(x5, y5);
1789 poly2[1] = QPointF(x6, y6);
1790 poly2[2] = QPointF(x7, y7);
1791 poly2[3] = QPointF(x8, y8);
1792
1793 if (m_verboseMode)
1794 printf(format: " -(lance) mapQuadToQuad(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f ->\n\t"
1795 ",%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
1796 x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6, x7, y7, x8, y8);
1797
1798 QTransform trans;
1799
1800 if (!QTransform::quadToQuad(one: poly1, two: poly2, result&: trans)) {
1801 qWarning(msg: "Couldn't perform quad to quad transformation!");
1802 }
1803
1804 m_painter->setTransform(transform: trans, combine: true);
1805}
1806
1807/***************************************************************************************************/
1808void PaintCommands::command_setMatrix(QRegularExpressionMatch re)
1809{
1810 QStringList caps = re.capturedTexts();
1811 double m11 = convertToDouble(str: caps.at(i: 1));
1812 double m12 = convertToDouble(str: caps.at(i: 2));
1813 double m13 = convertToDouble(str: caps.at(i: 3));
1814 double m21 = convertToDouble(str: caps.at(i: 4));
1815 double m22 = convertToDouble(str: caps.at(i: 5));
1816 double m23 = convertToDouble(str: caps.at(i: 6));
1817 double m31 = convertToDouble(str: caps.at(i: 7));
1818 double m32 = convertToDouble(str: caps.at(i: 8));
1819 double m33 = convertToDouble(str: caps.at(i: 9));
1820
1821 if (m_verboseMode)
1822 printf(format: " -(lance) setMatrix(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
1823 m11, m12, m13, m21, m22, m23, m31, m32, m33);
1824
1825 QTransform trans;
1826 trans.setMatrix(m11, m12, m13,
1827 m21, m22, m23,
1828 m31, m32, m33);
1829
1830 m_painter->setTransform(transform: trans, combine: true);
1831}
1832
1833/***************************************************************************************************/
1834void PaintCommands::command_scale(QRegularExpressionMatch re)
1835{
1836 QStringList caps = re.capturedTexts();
1837 double sx = convertToDouble(str: caps.at(i: 1));
1838 double sy = convertToDouble(str: caps.at(i: 2));
1839
1840 if (m_verboseMode)
1841 printf(format: " -(lance) scale(%.2f, %.2f)\n", sx, sy);
1842
1843
1844 m_painter->scale(sx, sy);
1845}
1846
1847/***************************************************************************************************/
1848void PaintCommands::command_setBackground(QRegularExpressionMatch re)
1849{
1850 QStringList caps = re.capturedTexts();
1851 QColor color = convertToColor(str: caps.at(i: 1));
1852 QString pattern = caps.at(i: 2);
1853
1854 int style = translateEnum(table: brushStyleTable, pattern, limit: Qt::LinearGradientPattern);
1855 if (style < 0)
1856 style = Qt::SolidPattern;
1857
1858 if (m_verboseMode)
1859 printf(format: " -(lance) setBackground(%s, %s)\n", qPrintable(color.name()), qPrintable(pattern));
1860
1861 m_painter->setBackground(QBrush(color, Qt::BrushStyle(style)));
1862}
1863
1864/***************************************************************************************************/
1865void PaintCommands::command_setOpacity(QRegularExpressionMatch re)
1866{
1867 QStringList caps = re.capturedTexts();
1868 double opacity = convertToDouble(str: caps.at(i: 1));
1869
1870 if (m_verboseMode)
1871 printf(format: " -(lance) setOpacity(%lf)\n", opacity);
1872
1873 m_painter->setOpacity(opacity);
1874}
1875
1876/***************************************************************************************************/
1877void PaintCommands::command_setBgMode(QRegularExpressionMatch re)
1878{
1879 QString cap = re.captured(nth: 2);
1880 Qt::BGMode mode = Qt::TransparentMode;
1881 if (cap.toLower() == QLatin1String("opaquemode") || cap.toLower() == QLatin1String("opaque"))
1882 mode = Qt::OpaqueMode;
1883
1884 if (m_verboseMode)
1885 printf(format: " -(lance) setBackgroundMode(%s)\n", mode == Qt::OpaqueMode ? "OpaqueMode" : "TransparentMode");
1886
1887 m_painter->setBackgroundMode(mode);
1888}
1889
1890/***************************************************************************************************/
1891void PaintCommands::command_setBrush(QRegularExpressionMatch re)
1892{
1893 QStringList caps = re.capturedTexts();
1894
1895 QImage img = m_imageMap[caps.at(i: 1)]; // try cache first
1896 if (img.isNull())
1897 img = image_load<QImage>(filepath: caps.at(i: 1));
1898 if (!img.isNull()) { // Assume image brush
1899 if (m_verboseMode)
1900 printf(format: " -(lance) setBrush(image=%s, width=%d, height=%d)\n",
1901 qPrintable(caps.at(1)), img.width(), img.height());
1902
1903 m_painter->setBrush(QBrush(img));
1904 } else if (caps.at(i: 1).toLower() == "nobrush") {
1905 m_painter->setBrush(Qt::NoBrush);
1906 if (m_verboseMode)
1907 printf(format: " -(lance) setBrush(Qt::NoBrush)\n");
1908 } else {
1909 QColor color = convertToColor(str: caps.at(i: 1));
1910 QString pattern = caps.at(i: 2);
1911
1912 int style = translateEnum(table: brushStyleTable, pattern, limit: Qt::LinearGradientPattern);
1913 if (style < 0)
1914 style = Qt::SolidPattern;
1915
1916 if (m_verboseMode)
1917 printf(format: " -(lance) setBrush(%s, %s (%d))\n", qPrintable(color.name()), qPrintable(pattern), style);
1918
1919 m_painter->setBrush(QBrush(color, Qt::BrushStyle(style)));
1920 }
1921}
1922
1923/***************************************************************************************************/
1924void PaintCommands::command_setBrushOrigin(QRegularExpressionMatch re)
1925{
1926 int x = convertToInt(str: re.captured(nth: 1));
1927 int y = convertToInt(str: re.captured(nth: 2));
1928
1929 if (m_verboseMode)
1930 printf(format: " -(lance) setBrushOrigin(%d, %d)\n", x, y);
1931
1932 m_painter->setBrushOrigin(x, y);
1933}
1934
1935/***************************************************************************************************/
1936void PaintCommands::command_brushTranslate(QRegularExpressionMatch re)
1937{
1938 QStringList caps = re.capturedTexts();
1939 double dx = convertToDouble(str: caps.at(i: 1));
1940 double dy = convertToDouble(str: caps.at(i: 2));
1941
1942 if (m_verboseMode)
1943 printf(format: " -(lance) brushTranslate(%f, %f)\n", dx, dy);
1944
1945 QBrush new_brush = m_painter->brush();
1946 QTransform brush_matrix = new_brush.transform();
1947 brush_matrix.translate(dx, dy);
1948 new_brush.setTransform(brush_matrix);
1949 m_painter->setBrush(new_brush);
1950}
1951
1952/***************************************************************************************************/
1953void PaintCommands::command_brushScale(QRegularExpressionMatch re)
1954{
1955 QStringList caps = re.capturedTexts();
1956 double sx = convertToDouble(str: caps.at(i: 1));
1957 double sy = convertToDouble(str: caps.at(i: 2));
1958
1959 if (m_verboseMode)
1960 printf(format: " -(lance) brushScale(%f, %f)\n", sx, sy);
1961
1962 QBrush new_brush = m_painter->brush();
1963 QTransform brush_matrix = new_brush.transform();
1964 brush_matrix.scale(sx, sy);
1965 new_brush.setTransform(brush_matrix);
1966 m_painter->setBrush(new_brush);
1967}
1968
1969/***************************************************************************************************/
1970void PaintCommands::command_brushRotate(QRegularExpressionMatch re)
1971{
1972 QStringList caps = re.capturedTexts();
1973 double rot = convertToDouble(str: caps.at(i: 1));
1974
1975 if (m_verboseMode)
1976 printf(format: " -(lance) brushScale(%f)\n", rot);
1977
1978 QBrush new_brush = m_painter->brush();
1979 QTransform brush_matrix = new_brush.transform();
1980 brush_matrix.rotate(a: rot);
1981 new_brush.setTransform(brush_matrix);
1982 m_painter->setBrush(new_brush);
1983}
1984
1985/***************************************************************************************************/
1986void PaintCommands::command_brushShear(QRegularExpressionMatch re)
1987{
1988 QStringList caps = re.capturedTexts();
1989 double sx = convertToDouble(str: caps.at(i: 1));
1990 double sy = convertToDouble(str: caps.at(i: 2));
1991
1992 if (m_verboseMode)
1993 printf(format: " -(lance) brushShear(%f, %f)\n", sx, sy);
1994
1995 QBrush new_brush = m_painter->brush();
1996 QTransform brush_matrix = new_brush.transform();
1997 brush_matrix.shear(sh: sx, sv: sy);
1998 new_brush.setTransform(brush_matrix);
1999 m_painter->setBrush(new_brush);
2000}
2001
2002/***************************************************************************************************/
2003void PaintCommands::command_setClipping(QRegularExpressionMatch re)
2004{
2005 bool clipping = re.captured(nth: 1).toLower() == "true";
2006
2007 if (m_verboseMode)
2008 printf(format: " -(lance) setClipping(%d)\n", clipping);
2009
2010 m_painter->setClipping(clipping);
2011}
2012
2013/***************************************************************************************************/
2014void PaintCommands::command_setClipRect(QRegularExpressionMatch re)
2015{
2016 QStringList caps = re.capturedTexts();
2017 int x = convertToInt(str: caps.at(i: 1));
2018 int y = convertToInt(str: caps.at(i: 2));
2019 int w = convertToInt(str: caps.at(i: 3));
2020 int h = convertToInt(str: caps.at(i: 4));
2021
2022 int combine = translateEnum(table: clipOperationTable, pattern: caps.at(i: 5), limit: Qt::IntersectClip + 1);
2023 if (combine == -1)
2024 combine = Qt::ReplaceClip;
2025
2026 if (m_verboseMode)
2027 printf(format: " -(lance) setClipRect(%d, %d, %d, %d), %s\n", x, y, w, h, clipOperationTable[combine]);
2028
2029 m_painter->setClipRect(x, y, w, h, op: Qt::ClipOperation(combine));
2030}
2031
2032/***************************************************************************************************/
2033void PaintCommands::command_setClipPath(QRegularExpressionMatch re)
2034{
2035 int combine = translateEnum(table: clipOperationTable, pattern: re.captured(nth: 2), limit: Qt::IntersectClip + 1);
2036 if (combine == -1)
2037 combine = Qt::ReplaceClip;
2038
2039 if (m_verboseMode)
2040 printf(format: " -(lance) setClipPath(name=%s), %s\n", qPrintable(re.captured(1)), clipOperationTable[combine]);
2041
2042 if (!m_pathMap.contains(akey: re.captured(nth: 1)))
2043 fprintf(stderr, format: " - setClipPath, no such path");
2044 m_painter->setClipPath(path: m_pathMap[re.captured(nth: 1)], op: Qt::ClipOperation(combine));
2045}
2046
2047/***************************************************************************************************/
2048void PaintCommands::command_setClipRegion(QRegularExpressionMatch re)
2049{
2050 int combine = translateEnum(table: clipOperationTable, pattern: re.captured(nth: 2), limit: Qt::IntersectClip + 1);
2051 if (combine == -1)
2052 combine = Qt::ReplaceClip;
2053 QRegion r = m_regionMap[re.captured(nth: 1)];
2054
2055 if (m_verboseMode)
2056 printf(format: " -(lance) setClipRegion(name=%s), bounds=[%d, %d, %d, %d], %s\n",
2057 qPrintable(re.captured(1)),
2058 r.boundingRect().x(),
2059 r.boundingRect().y(),
2060 r.boundingRect().width(),
2061 r.boundingRect().height(),
2062 clipOperationTable[combine]);
2063
2064 m_painter->setClipRegion(m_regionMap[re.captured(nth: 1)], op: Qt::ClipOperation(combine));
2065}
2066
2067/***************************************************************************************************/
2068void PaintCommands::command_setFont(QRegularExpressionMatch re)
2069{
2070 QStringList caps = re.capturedTexts();
2071 QString family = caps.at(i: 1);
2072 int size = convertToInt(str: caps.at(i: 2));
2073
2074 int weight = translateEnum(table: fontWeightTable, pattern: re.captured(nth: 3).toLower(), limit: 5);
2075 if (weight != -1) {
2076 switch (weight) {
2077 case 0: weight = QFont::Light; break;
2078 case 1: weight = QFont::Normal; break;
2079 case 2: weight = QFont::DemiBold; break;
2080 case 3: weight = QFont::Bold; break;
2081 case 4: weight = QFont::Black; break;
2082 }
2083 } else {
2084 weight = convertToInt(str: re.captured(nth: 3));
2085 }
2086
2087 bool italic = caps.at(i: 4).toLower() == "true" || caps.at(i: 4).toLower() == "italic";
2088
2089 QFont font(family, size, weight, italic);
2090
2091 int hinting = translateEnum(table: fontHintingTable, pattern: caps.at(i: 5), limit: 4);
2092 if (hinting == -1)
2093 hinting = 0;
2094 else
2095 font.setHintingPreference(QFont::HintingPreference(hinting));
2096 if (m_verboseMode)
2097 printf(format: " -(lance) setFont(family=%s, size=%d, weight=%d, italic=%d hinting=%s\n",
2098 qPrintable(family), size, weight, italic, fontHintingTable[hinting]);
2099
2100 m_painter->setFont(font);
2101}
2102
2103/***************************************************************************************************/
2104void PaintCommands::command_setPen(QRegularExpressionMatch re)
2105{
2106 QString cap = re.captured(nth: 1);
2107 int style = translateEnum(table: penStyleTable, pattern: cap, limit: Qt::DashDotDotLine + 1);
2108 if (style >= 0) {
2109 if (m_verboseMode)
2110 printf(format: " -(lance) setPen(%s)\n", qPrintable(cap));
2111
2112 m_painter->setPen(Qt::PenStyle(style));
2113 } else if (cap.toLower() == "brush") {
2114 QPen pen(m_painter->brush(), 0);
2115 if (m_verboseMode) {
2116 printf(format: " -(lance) setPen(brush), style=%d, color=%08x\n",
2117 pen.brush().style(), pen.color().rgba());
2118 }
2119 m_painter->setPen(pen);
2120 } else {
2121 QColor color = convertToColor(str: cap);
2122 if (m_verboseMode)
2123 printf(format: " -(lance) setPen(%s)\n", qPrintable(color.name()));
2124
2125 m_painter->setPen(color);
2126 }
2127}
2128
2129/***************************************************************************************************/
2130void PaintCommands::command_setPen2(QRegularExpressionMatch re)
2131{
2132 QStringList caps = re.capturedTexts();
2133
2134 QBrush brush;
2135
2136 if (caps.at(i: 1).toLower() == "brush")
2137 brush = m_painter->brush();
2138 else
2139 brush = convertToColor(str: caps.at(i: 1));
2140
2141 double width = convertToDouble(str: caps.at(i: 2));
2142 int penStyle = translateEnum(table: penStyleTable, pattern: caps.at(i: 3), limit: Qt::DashDotDotLine + 1);
2143 if (penStyle < 0)
2144 penStyle = Qt::SolidLine;
2145
2146 Qt::PenCapStyle capStyle = Qt::SquareCap;
2147 if (caps.at(i: 4).toLower() == "flatcap") capStyle = Qt::FlatCap;
2148 else if (caps.at(i: 4).toLower() == "squarecap") capStyle = Qt::SquareCap;
2149 else if (caps.at(i: 4).toLower() == "roundcap") capStyle = Qt::RoundCap;
2150 else if (!caps.at(i: 4).isEmpty())
2151 fprintf(stderr, format: "ERROR: setPen, unknown capStyle: %s\n", qPrintable(caps.at(4)));
2152
2153 Qt::PenJoinStyle joinStyle = Qt::BevelJoin;
2154 if (caps.at(i: 5).toLower() == "miterjoin") joinStyle = Qt::MiterJoin;
2155 else if (caps.at(i: 5).toLower() == "beveljoin") joinStyle = Qt::BevelJoin;
2156 else if (caps.at(i: 5).toLower() == "roundjoin") joinStyle = Qt::RoundJoin;
2157 else if (!caps.at(i: 5).isEmpty())
2158 fprintf(stderr, format: "ERROR: setPen, unknown joinStyle: %s\n", qPrintable(caps.at(5)));
2159
2160 if (m_verboseMode)
2161 printf(format: " -(lance) setPen(%s, width=%f, style=%d, cap=%d, join=%d)\n",
2162 qPrintable(brush.color().name()), width, penStyle, capStyle, joinStyle);
2163
2164 m_painter->setPen(QPen(brush, width, Qt::PenStyle(penStyle), capStyle, joinStyle));
2165}
2166
2167/***************************************************************************************************/
2168void PaintCommands::command_setRenderHint(QRegularExpressionMatch re)
2169{
2170 QString hintString = re.captured(nth: 1).toLower();
2171 bool on = re.captured(nth: 2).isEmpty() || re.captured(nth: 2).toLower() == "true";
2172 if (hintString.contains(s: "antialiasing")) {
2173 if (m_verboseMode)
2174 printf(format: " -(lance) setRenderHint Antialiasing\n");
2175
2176 m_painter->setRenderHint(hint: QPainter::Antialiasing, on);
2177 } else if (hintString.contains(s: "smoothpixmaptransform")) {
2178 if (m_verboseMode)
2179 printf(format: " -(lance) setRenderHint SmoothPixmapTransform\n");
2180 m_painter->setRenderHint(hint: QPainter::SmoothPixmapTransform, on);
2181 } else {
2182 fprintf(stderr, format: "ERROR(setRenderHint): unknown hint '%s'\n", qPrintable(hintString));
2183 }
2184}
2185
2186/***************************************************************************************************/
2187void PaintCommands::command_clearRenderHint(QRegularExpressionMatch /*re*/)
2188{
2189 m_painter->setRenderHint(hint: QPainter::Antialiasing, on: false);
2190 m_painter->setRenderHint(hint: QPainter::SmoothPixmapTransform, on: false);
2191 if (m_verboseMode)
2192 printf(format: " -(lance) clearRenderHint\n");
2193}
2194
2195/***************************************************************************************************/
2196void PaintCommands::command_setCompositionMode(QRegularExpressionMatch re)
2197{
2198 QString modeString = re.captured(nth: 1).toLower();
2199 int mode = translateEnum(table: compositionModeTable, pattern: modeString, limit: 33);
2200
2201 if (mode < 0 || mode > QPainter::RasterOp_SourceAndNotDestination) {
2202 fprintf(stderr, format: "ERROR: invalid mode: %s\n", qPrintable(modeString));
2203 return;
2204 }
2205
2206 if (m_verboseMode)
2207 printf(format: " -(lance) setCompositionMode: %d: %s\n", mode, qPrintable(modeString));
2208
2209 m_painter->setCompositionMode(QPainter::CompositionMode(mode));
2210}
2211
2212/***************************************************************************************************/
2213void PaintCommands::command_translate(QRegularExpressionMatch re)
2214{
2215 QStringList caps = re.capturedTexts();
2216 double dx = convertToDouble(str: caps.at(i: 1));
2217 double dy = convertToDouble(str: caps.at(i: 2));
2218
2219 if (m_verboseMode)
2220 printf(format: " -(lance) translate(%f, %f)\n", dx, dy);
2221
2222 m_painter->translate(dx, dy);
2223}
2224
2225/***************************************************************************************************/
2226void PaintCommands::command_pixmap_load(QRegularExpressionMatch re)
2227{
2228 QStringList caps = re.capturedTexts();
2229
2230 QString fileName = caps.at(i: 1);
2231 QString name = caps.at(i: 2);
2232
2233 if (name.isEmpty())
2234 name = fileName;
2235
2236 QImage im = image_load<QImage>(filepath: fileName);
2237 QPixmap px = QPixmap::fromImage(image: im, flags: Qt::OrderedDither | Qt::OrderedAlphaDither);
2238
2239 if (m_verboseMode)
2240 printf(format: " -(lance) pixmap_load(%s as %s), size=[%d, %d], depth=%d\n",
2241 qPrintable(fileName), qPrintable(name),
2242 px.width(), px.height(), px.depth());
2243
2244 m_pixmapMap[name] = px;
2245}
2246
2247/***************************************************************************************************/
2248void PaintCommands::command_bitmap_load(QRegularExpressionMatch re)
2249{
2250 QStringList caps = re.capturedTexts();
2251
2252 QString fileName = caps.at(i: 1);
2253 QString name = caps.at(i: 2);
2254
2255 if (name.isEmpty())
2256 name = fileName;
2257
2258 QBitmap bm = image_load<QBitmap>(filepath: fileName);
2259
2260 if (m_verboseMode)
2261 printf(format: " -(lance) bitmap_load(%s as %s), size=[%d, %d], depth=%d\n",
2262 qPrintable(fileName), qPrintable(name),
2263 bm.width(), bm.height(), bm.depth());
2264
2265 m_pixmapMap[name] = bm;
2266}
2267
2268void PaintCommands::command_pixmap_setDevicePixelRatio(QRegularExpressionMatch re)
2269{
2270 QStringList caps = re.capturedTexts();
2271
2272 QString name = caps.at(i: 1);
2273 double dpr = convertToDouble(str: caps.at(i: 2));
2274
2275 if (m_verboseMode)
2276 printf(format: " -(lance) pixmap_setDevicePixelRatio(%s), %.1f -> %.1f\n",
2277 qPrintable(name), m_pixmapMap[name].devicePixelRatioF(), dpr);
2278
2279 m_pixmapMap[name].setDevicePixelRatio(dpr);
2280}
2281
2282/***************************************************************************************************/
2283void PaintCommands::command_pixmap_setMask(QRegularExpressionMatch re)
2284{
2285 QStringList caps = re.capturedTexts();
2286 QBitmap mask = image_load<QBitmap>(filepath: caps.at(i: 2));
2287
2288 if (m_verboseMode)
2289 printf(format: " -(lance) pixmap_setMask(%s, %s)\n", qPrintable(caps.at(1)), qPrintable(caps.at(2)));
2290
2291 if (!m_pixmapMap[caps.at(i: 1)].isNull())
2292 m_pixmapMap[caps.at(i: 1)].setMask(mask);
2293}
2294
2295/***************************************************************************************************/
2296void PaintCommands::command_image_load(QRegularExpressionMatch re)
2297{
2298 QStringList caps = re.capturedTexts();
2299
2300 QString fileName = caps.at(i: 1);
2301 QString name = caps.at(i: 2);
2302
2303 if (name.isEmpty())
2304 name = fileName;
2305
2306 QImage image = image_load<QImage>(filepath: fileName);
2307
2308 if (m_verboseMode)
2309 printf(format: " -(lance) image_load(%s as %s), size=[%d, %d], format=%d\n",
2310 qPrintable(fileName), qPrintable(name),
2311 image.width(), image.height(), image.format());
2312
2313 m_imageMap[name] = image;
2314}
2315
2316/***************************************************************************************************/
2317void PaintCommands::command_image_setColorCount(QRegularExpressionMatch re)
2318{
2319 QStringList caps = re.capturedTexts();
2320
2321 QString name = caps.at(i: 1);
2322 int count = convertToInt(str: caps.at(i: 2));
2323
2324 if (m_verboseMode)
2325 printf(format: " -(lance) image_setColorCount(%s), %d -> %d\n",
2326 qPrintable(name), m_imageMap[name].colorCount(), count);
2327
2328 m_imageMap[name].setColorCount(count);
2329}
2330
2331/***************************************************************************************************/
2332void PaintCommands::command_image_setColor(QRegularExpressionMatch re)
2333{
2334 QStringList caps = re.capturedTexts();
2335
2336 QString name = caps.at(i: 1);
2337 int index = convertToInt(str: caps.at(i: 2));
2338 QColor color = convertToColor(str: caps.at(i: 3));
2339
2340 if (m_verboseMode)
2341 printf(format: " -(lance) image_setColor(%s), %d = %08x\n", qPrintable(name), index, color.rgba());
2342
2343 m_imageMap[name].setColor(i: index, c: color.rgba());
2344}
2345
2346/***************************************************************************************************/
2347void PaintCommands::command_image_setDevicePixelRatio(QRegularExpressionMatch re)
2348{
2349 QStringList caps = re.capturedTexts();
2350
2351 QString name = caps.at(i: 1);
2352 double dpr = convertToDouble(str: caps.at(i: 2));
2353
2354 if (m_verboseMode)
2355 printf(format: " -(lance) image_setDevicePixelRatio(%s), %.1f -> %.1f\n",
2356 qPrintable(name), m_imageMap[name].devicePixelRatioF(), dpr);
2357
2358 m_imageMap[name].setDevicePixelRatio(dpr);
2359}
2360
2361/***************************************************************************************************/
2362void PaintCommands::command_abort(QRegularExpressionMatch)
2363{
2364 m_abort = true;
2365}
2366
2367/***************************************************************************************************/
2368void PaintCommands::command_gradient_clearStops(QRegularExpressionMatch)
2369{
2370 if (m_verboseMode)
2371 printf(format: " -(lance) gradient_clearStops\n");
2372 m_gradientStops.clear();
2373}
2374
2375/***************************************************************************************************/
2376void PaintCommands::command_gradient_appendStop(QRegularExpressionMatch re)
2377{
2378 QStringList caps = re.capturedTexts();
2379 double pos = convertToDouble(str: caps.at(i: 1));
2380 QColor color = convertToColor(str: caps.at(i: 2));
2381
2382 if (m_verboseMode)
2383 printf(format: " -(lance) gradient_appendStop(%.2f, %x)\n", pos, color.rgba());
2384
2385 m_gradientStops << QGradientStop(pos, color);
2386}
2387
2388/***************************************************************************************************/
2389void PaintCommands::command_gradient_setLinear(QRegularExpressionMatch re)
2390{
2391 QStringList caps = re.capturedTexts();
2392 double x1 = convertToDouble(str: caps.at(i: 1));
2393 double y1 = convertToDouble(str: caps.at(i: 2));
2394 double x2 = convertToDouble(str: caps.at(i: 3));
2395 double y2 = convertToDouble(str: caps.at(i: 4));
2396
2397 if (m_verboseMode)
2398 printf(format: " -(lance) gradient_setLinear (%.2f, %.2f), (%.2f, %.2f), spread=%d\n",
2399 x1, y1, x2, y2, m_gradientSpread);
2400
2401 QLinearGradient lg(QPointF(x1, y1), QPointF(x2, y2));
2402 lg.setStops(m_gradientStops);
2403 lg.setSpread(m_gradientSpread);
2404 lg.setCoordinateMode(m_gradientCoordinate);
2405 QBrush brush(lg);
2406 QTransform brush_matrix = m_painter->brush().transform();
2407 brush.setTransform(brush_matrix);
2408 m_painter->setBrush(brush);
2409}
2410
2411/***************************************************************************************************/
2412void PaintCommands::command_gradient_setLinearPen(QRegularExpressionMatch re)
2413{
2414 QStringList caps = re.capturedTexts();
2415 double x1 = convertToDouble(str: caps.at(i: 1));
2416 double y1 = convertToDouble(str: caps.at(i: 2));
2417 double x2 = convertToDouble(str: caps.at(i: 3));
2418 double y2 = convertToDouble(str: caps.at(i: 4));
2419
2420 if (m_verboseMode)
2421 printf(format: " -(lance) gradient_setLinear (%.2f, %.2f), (%.2f, %.2f), spread=%d\n",
2422 x1, y1, x2, y2, m_gradientSpread);
2423
2424 QLinearGradient lg(QPointF(x1, y1), QPointF(x2, y2));
2425 lg.setStops(m_gradientStops);
2426 lg.setSpread(m_gradientSpread);
2427 lg.setCoordinateMode(m_gradientCoordinate);
2428 QPen pen = m_painter->pen();
2429 pen.setBrush(lg);
2430 m_painter->setPen(pen);
2431}
2432
2433/***************************************************************************************************/
2434void PaintCommands::command_gradient_setRadial(QRegularExpressionMatch re)
2435{
2436 QStringList caps = re.capturedTexts();
2437 double cx = convertToDouble(str: caps.at(i: 1));
2438 double cy = convertToDouble(str: caps.at(i: 2));
2439 double rad = convertToDouble(str: caps.at(i: 3));
2440 double fx = convertToDouble(str: caps.at(i: 4));
2441 double fy = convertToDouble(str: caps.at(i: 5));
2442
2443 if (m_verboseMode)
2444 printf(format: " -(lance) gradient_setRadial center=(%.2f, %.2f), radius=%.2f, focal=(%.2f, %.2f), "
2445 "spread=%d\n",
2446 cx, cy, rad, fx, fy, m_gradientSpread);
2447
2448 QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy));
2449 rg.setStops(m_gradientStops);
2450 rg.setSpread(m_gradientSpread);
2451 rg.setCoordinateMode(m_gradientCoordinate);
2452 QBrush brush(rg);
2453 QTransform brush_matrix = m_painter->brush().transform();
2454 brush.setTransform(brush_matrix);
2455 m_painter->setBrush(brush);
2456}
2457
2458/***************************************************************************************************/
2459void PaintCommands::command_gradient_setRadialExtended(QRegularExpressionMatch re)
2460{
2461 QStringList caps = re.capturedTexts();
2462 double cx = convertToDouble(str: caps.at(i: 1));
2463 double cy = convertToDouble(str: caps.at(i: 2));
2464 double rad = convertToDouble(str: caps.at(i: 3));
2465 double fx = convertToDouble(str: caps.at(i: 4));
2466 double fy = convertToDouble(str: caps.at(i: 5));
2467 double frad = convertToDouble(str: caps.at(i: 6));
2468
2469 if (m_verboseMode)
2470 printf(format: " -(lance) gradient_setRadialExtended center=(%.2f, %.2f), radius=%.2f, focal=(%.2f, %.2f), "
2471 "focal radius=%.2f, spread=%d\n",
2472 cx, cy, rad, fx, fy, frad, m_gradientSpread);
2473
2474 QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy), frad);
2475 rg.setStops(m_gradientStops);
2476 rg.setSpread(m_gradientSpread);
2477 rg.setCoordinateMode(m_gradientCoordinate);
2478 QBrush brush(rg);
2479 QTransform brush_matrix = m_painter->brush().transform();
2480 brush.setTransform(brush_matrix);
2481 m_painter->setBrush(brush);
2482}
2483
2484/***************************************************************************************************/
2485void PaintCommands::command_gradient_setConical(QRegularExpressionMatch re)
2486{
2487 QStringList caps = re.capturedTexts();
2488 double cx = convertToDouble(str: caps.at(i: 1));
2489 double cy = convertToDouble(str: caps.at(i: 2));
2490 double angle = convertToDouble(str: caps.at(i: 3));
2491
2492 if (m_verboseMode) {
2493 printf(format: " -(lance) gradient_setConical center=(%.2f, %.2f), angle=%.2f\n, spread=%d",
2494 cx, cy, angle, m_gradientSpread);
2495 }
2496
2497 QConicalGradient cg(QPointF(cx, cy), angle);
2498 cg.setStops(m_gradientStops);
2499 cg.setSpread(m_gradientSpread);
2500 cg.setCoordinateMode(m_gradientCoordinate);
2501 QBrush brush(cg);
2502 QTransform brush_matrix = m_painter->brush().transform();
2503 brush.setTransform(brush_matrix);
2504 m_painter->setBrush(brush);
2505}
2506
2507/***************************************************************************************************/
2508void PaintCommands::command_gradient_setSpread(QRegularExpressionMatch re)
2509{
2510 int spreadMethod = translateEnum(table: spreadMethodTable, pattern: re.captured(nth: 1), limit: 3);
2511
2512 if (m_verboseMode)
2513 printf(format: " -(lance) gradient_setSpread %d=[%s]\n", spreadMethod, spreadMethodTable[spreadMethod]);
2514
2515 m_gradientSpread = QGradient::Spread(spreadMethod);
2516}
2517
2518void PaintCommands::command_gradient_setCoordinateMode(QRegularExpressionMatch re)
2519{
2520 int coord = translateEnum(table: coordinateMethodTable, pattern: re.captured(nth: 1), limit: 4);
2521
2522 if (m_verboseMode)
2523 printf(format: " -(lance) gradient_setCoordinateMode %d=[%s]\n", coord,
2524 coordinateMethodTable[coord]);
2525
2526 m_gradientCoordinate = QGradient::CoordinateMode(coord);
2527}
2528
2529/***************************************************************************************************/
2530void PaintCommands::command_surface_begin(QRegularExpressionMatch re)
2531{
2532 QStringList caps = re.capturedTexts();
2533 double x = convertToDouble(str: caps.at(i: 1));
2534 double y = convertToDouble(str: caps.at(i: 2));
2535 double w = convertToDouble(str: caps.at(i: 3));
2536 double h = convertToDouble(str: caps.at(i: 4));
2537
2538 if (m_surface_painter) {
2539 fprintf(stderr, format: "ERROR: surface already active");
2540 return;
2541 }
2542
2543 if (m_verboseMode)
2544 printf(format: " -(lance) surface_begin, pos=[%.2f, %.2f], size=[%.2f, %.2f]\n", x, y, w, h);
2545
2546 m_surface_painter = m_painter;
2547
2548 if (m_type == OpenGLType || m_type == OpenGLBufferType) {
2549#ifndef QT_NO_OPENGL
2550 m_default_glcontext = QOpenGLContext::currentContext();
2551 m_surface_glcontext = new QOpenGLContext();
2552 // Pick up the format from the current context; this is especially
2553 // important in order to pick the right version/profile to test.
2554 m_surface_glcontext->setFormat(m_default_glcontext->format());
2555 m_surface_glcontext->create();
2556 m_surface_glcontext->makeCurrent(surface: m_default_glcontext->surface());
2557 QOpenGLFramebufferObjectFormat fmt; // ###TBD: get format from caller
2558 fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
2559 fmt.setSamples(4);
2560 m_surface_glbuffer = new QOpenGLFramebufferObject(qRound(d: w), qRound(d: h), fmt);
2561 m_surface_glbuffer->bind();
2562 m_surface_glpaintdevice = new QOpenGLPaintDevice(qRound(d: w), qRound(d: h));
2563 m_painter = new QPainter(m_surface_glpaintdevice);
2564 m_painter->save();
2565 m_painter->setCompositionMode(QPainter::CompositionMode_Clear);
2566 m_painter->fillRect(r: QRect(0, 0, qRound(d: w), qRound(d: h)), c: Qt::transparent);
2567 m_painter->restore();
2568#endif
2569 } else {
2570 QImage::Format surface_format;
2571 if (QImage::toPixelFormat(format: m_format).alphaUsage() != QPixelFormat::UsesAlpha)
2572 surface_format = qt_alphaVersion(format: m_format);
2573 else
2574 surface_format = m_format;
2575
2576 m_surface_image = QImage(qRound(d: w), qRound(d: h), surface_format);
2577 m_surface_image.fill(pixel: 0);
2578 m_painter = new QPainter(&m_surface_image);
2579 }
2580 m_surface_rect = QRectF(x, y, w, h);
2581}
2582
2583/***************************************************************************************************/
2584void PaintCommands::command_surface_end(QRegularExpressionMatch)
2585{
2586 if (!m_surface_painter) {
2587 fprintf(stderr, format: "ERROR: surface not active");
2588 return;
2589 }
2590
2591 if (m_verboseMode)
2592 printf(format: " -(lance) surface_end, pos=[%.2f, %.2f], size=[%.2f, %.2f]\n",
2593 m_surface_rect.x(),
2594 m_surface_rect.y(),
2595 m_surface_rect.width(),
2596 m_surface_rect.height());
2597 m_painter->end();
2598
2599 delete m_painter;
2600 m_painter = m_surface_painter;
2601 m_surface_painter = 0;
2602
2603 if (m_type == OpenGLType || m_type == OpenGLBufferType) {
2604#ifndef QT_NO_OPENGL
2605 QImage new_image = m_surface_glbuffer->toImage().convertToFormat(f: QImage::Format_ARGB32_Premultiplied);
2606
2607 delete m_surface_glpaintdevice;
2608 m_surface_glpaintdevice = 0;
2609 delete m_surface_glbuffer;
2610 m_surface_glbuffer = 0;
2611 delete m_surface_glcontext;
2612 m_surface_glcontext = 0;
2613
2614 m_default_glcontext->makeCurrent(surface: m_default_glcontext->surface());
2615 m_painter->drawImage(r: m_surface_rect, image: new_image);
2616 // Flush the pipeline:
2617 m_painter->beginNativePainting();
2618 m_painter->endNativePainting();
2619#endif
2620 } else {
2621 m_painter->drawImage(r: m_surface_rect, image: m_surface_image);
2622 m_surface_image = QImage();
2623 }
2624 m_surface_rect = QRectF();
2625}
2626
2627/***************************************************************************************************/
2628void PaintCommands::command_image_convertToFormat(QRegularExpressionMatch re)
2629{
2630 QStringList caps = re.capturedTexts();
2631
2632 QString srcName = caps.at(i: 1);
2633 QString destName = caps.at(i: 2);
2634
2635 if (!m_imageMap.contains(akey: srcName)) {
2636 fprintf(stderr, format: "ERROR(convertToFormat): no such image '%s'\n", qPrintable(srcName));
2637 return;
2638 }
2639
2640 int format = translateEnum(table: imageFormatTable, pattern: caps.at(i: 3), limit: QImage::NImageFormats);
2641 if (format < 0 || format >= QImage::NImageFormats) {
2642 fprintf(stderr, format: "ERROR(convertToFormat): invalid format %d = '%s'\n",
2643 format, qPrintable(caps.at(3)));
2644 return;
2645 }
2646
2647 QImage src = m_imageMap[srcName];
2648 QImage dest = src.convertToFormat(f: QImage::Format(format),
2649 flags: Qt::OrderedAlphaDither | Qt::OrderedDither);
2650
2651 if (m_verboseMode) {
2652 printf(format: " -(lance) convertToFormat %s:%d -> %s:%d\n",
2653 qPrintable(srcName), src.format(),
2654 qPrintable(destName), dest.format());
2655 }
2656
2657 m_imageMap[destName] = dest;
2658}
2659
2660/***************************************************************************************************/
2661void PaintCommands::command_textlayout_draw(QRegularExpressionMatch re)
2662{
2663 QStringList caps = re.capturedTexts();
2664
2665 QString text = caps.at(i: 1);
2666 double width = convertToDouble(str: caps.at(i: 2));
2667
2668 if (m_verboseMode)
2669 printf(format: " -(lance) textlayout_draw text='%s', width=%f\n",
2670 qPrintable(text), width);
2671
2672 QFont copy = m_painter->font();
2673 copy.setPointSize(10);
2674
2675 QTextLayout layout(text, copy, m_painter->device());
2676 layout.beginLayout();
2677
2678 double y_offset = 0;
2679
2680 while (true) {
2681 QTextLine line = layout.createLine();
2682 if (!line.isValid())
2683 break;
2684 line.setLineWidth(width);
2685 line.setPosition(QPointF(0, y_offset));
2686
2687 y_offset += line.height();
2688 }
2689
2690 layout.draw(p: m_painter, pos: QPointF(0, 0));
2691}
2692
2693/***************************************************************************************************/
2694void PaintCommands::command_pen_setDashOffset(QRegularExpressionMatch re)
2695{
2696 QStringList caps = re.capturedTexts();
2697 double offset = convertToDouble(str: caps.at(i: 1));
2698
2699 if (m_verboseMode)
2700 printf(format: " -(lance) setDashOffset(%lf)\n", offset);
2701
2702 QPen p = m_painter->pen();
2703 p.setDashOffset(offset);
2704 m_painter->setPen(p);
2705}
2706
2707/***************************************************************************************************/
2708void PaintCommands::command_pen_setDashPattern(QRegularExpressionMatch re)
2709{
2710 static QRegularExpression separators("\\s");
2711 QStringList caps = re.capturedTexts();
2712 QString cap = caps.at(i: 1);
2713 QStringList numbers = cap.split(sep: separators, behavior: Qt::SkipEmptyParts);
2714
2715 QVector<qreal> pattern;
2716 for (int i=0; i<numbers.size(); ++i)
2717 pattern.append(t: convertToDouble(str: numbers.at(i)));
2718
2719 if (m_verboseMode)
2720 printf(format: " -(lance) pen_setDashPattern(size=%d)\n", pattern.size());
2721
2722 QPen p = m_painter->pen();
2723 p.setDashPattern(pattern);
2724 m_painter->setPen(p);
2725}
2726
2727/***************************************************************************************************/
2728void PaintCommands::command_pen_setCosmetic(QRegularExpressionMatch re)
2729{
2730 QString hm = re.capturedTexts().at(i: 1);
2731 bool on = hm == "true" || hm == "yes" || hm == "on";
2732
2733 if (m_verboseMode) {
2734 printf(format: " -(lance) pen_setCosmetic(%s)\n", on ? "true" : "false");
2735 }
2736
2737 QPen p = m_painter->pen();
2738 p.setCosmetic(on);
2739
2740 m_painter->setPen(p);
2741}
2742
2743/***************************************************************************************************/
2744void PaintCommands::command_drawConvexPolygon(QRegularExpressionMatch re)
2745{
2746 static QRegularExpression separators("\\s");
2747 QStringList caps = re.capturedTexts();
2748 QString cap = caps.at(i: 1);
2749 QStringList numbers = cap.split(sep: separators, behavior: Qt::SkipEmptyParts);
2750
2751 QPolygonF array;
2752 for (int i=0; i + 1<numbers.size(); i+=2)
2753 array.append(t: QPointF(convertToDouble(str: numbers.at(i)), convertToDouble(str: numbers.at(i: i+1))));
2754
2755 if (m_verboseMode)
2756 printf(format: " -(lance) drawConvexPolygon(size=%d)\n", array.size());
2757
2758
2759 m_painter->drawConvexPolygon(poly: array);
2760}
2761

source code of qtbase/tests/auto/other/lancelot/paintcommands.cpp