diff options
Diffstat (limited to 'tests/baseline')
154 files changed, 16905 insertions, 0 deletions
diff --git a/tests/baseline/CMakeLists.txt b/tests/baseline/CMakeLists.txt new file mode 100644 index 0000000000..037ffd9e0e --- /dev/null +++ b/tests/baseline/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(TARGET Qt::Gui AND TARGET Qt::Network AND QT_FEATURE_pdf) + add_subdirectory(painting) +endif() +if(TARGET Qt::Network AND TARGET Qt::Widgets) + add_subdirectory(widgets) + add_subdirectory(stylesheet) + add_subdirectory(text) +endif() diff --git a/tests/baseline/painting/.gitignore b/tests/baseline/painting/.gitignore new file mode 100644 index 0000000000..0a70416d57 --- /dev/null +++ b/tests/baseline/painting/.gitignore @@ -0,0 +1 @@ +tst_lancelot diff --git a/tests/baseline/painting/CMakeLists.txt b/tests/baseline/painting/CMakeLists.txt new file mode 100644 index 0000000000..72e737d227 --- /dev/null +++ b/tests/baseline/painting/CMakeLists.txt @@ -0,0 +1,78 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_baseline_painting Test: +##################################################################### + +# Collect test data +file(GLOB_RECURSE test_data_glob + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + scripts/*) +list(APPEND test_data ${test_data_glob}) + +qt_internal_add_test(tst_baseline_painting + SOURCES + ../shared/baselineprotocol.cpp ../shared/baselineprotocol.h ../shared/lookup3.cpp + ../shared/qbaselinetest.cpp ../shared/qbaselinetest.h + ../shared/paintcommands.cpp ../shared/paintcommands.h + tst_baseline_painting.cpp + NO_PCH_SOURCES + tst_baseline_painting.cpp # undef QT_NO_FOREACH + INCLUDE_DIRECTORIES + ../shared + LIBRARIES + Qt::Gui + Qt::GuiPrivate + Qt::Network + TESTDATA ${test_data} +) + +# Resources: +set(images_resource_files + "images/alpha.png" + "images/alpha2x2.png" + "images/bitmap.png" + "images/border.png" + "images/borderimage.png" + "images/dome_argb32.png" + "images/dome_indexed.png" + "images/dome_indexed_mask.png" + "images/dome_mono.png" + "images/dome_mono_128.png" + "images/dome_mono_palette.png" + "images/dome_rgb32.png" + "images/dot.png" + "images/face.png" + "images/gam030.png" + "images/gam045.png" + "images/gam056.png" + "images/gam100.png" + "images/gam200.png" + "images/image.png" + "images/mask.png" + "images/mask_100.png" + "images/masked.png" + "images/sign.png" + "images/solid.png" + "images/solid2x2.png" + "images/struct-image-01.jpg" + "images/struct-image-01.png" + "images/zebra.png" +) + +qt_internal_add_resource(tst_baseline_painting "images" + PREFIX + "/" + FILES + ${images_resource_files} +) + + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_baseline_painting CONDITION QT_FEATURE_opengl + LIBRARIES + Qt::OpenGL +) diff --git a/tests/baseline/painting/images.qrc b/tests/baseline/painting/images.qrc new file mode 100644 index 0000000000..060b52c85a --- /dev/null +++ b/tests/baseline/painting/images.qrc @@ -0,0 +1,34 @@ +<!DOCTYPE RCC> +<RCC version="1.0"> +<qresource> + <file>images/alpha.png</file> + <file>images/border.png</file> + <file>images/borderimage.png</file> + <file>images/dome_argb32.png</file> + <file>images/dome_indexed.png</file> + <file>images/dome_mono_palette.png</file> + <file>images/dome_rgb32.png</file> + <file>images/face.png</file> + <file>images/gam045.png</file> + <file>images/gam100.png</file> + <file>images/image.png</file> + <file>images/masked.png</file> + <file>images/sign.png</file> + <file>images/struct-image-01.jpg</file> + <file>images/bitmap.png</file> + <file>images/dome_indexed_mask.png</file> + <file>images/dome_mono_128.png</file> + <file>images/dome_mono.png</file> + <file>images/dot.png</file> + <file>images/gam030.png</file> + <file>images/gam056.png</file> + <file>images/gam200.png</file> + <file>images/mask_100.png</file> + <file>images/mask.png</file> + <file>images/solid.png</file> + <file>images/struct-image-01.png</file> + <file>images/zebra.png</file> + <file>images/alpha2x2.png</file> + <file>images/solid2x2.png</file> +</qresource> +</RCC> diff --git a/tests/baseline/painting/images/alpha.png b/tests/baseline/painting/images/alpha.png Binary files differnew file mode 100644 index 0000000000..e465b2586d --- /dev/null +++ b/tests/baseline/painting/images/alpha.png diff --git a/tests/baseline/painting/images/alpha2x2.png b/tests/baseline/painting/images/alpha2x2.png Binary files differnew file mode 100644 index 0000000000..8e99feb4cc --- /dev/null +++ b/tests/baseline/painting/images/alpha2x2.png diff --git a/tests/baseline/painting/images/bitmap.png b/tests/baseline/painting/images/bitmap.png Binary files differnew file mode 100644 index 0000000000..d21f8f51bb --- /dev/null +++ b/tests/baseline/painting/images/bitmap.png diff --git a/tests/baseline/painting/images/border.png b/tests/baseline/painting/images/border.png Binary files differnew file mode 100644 index 0000000000..a3d2fed0a3 --- /dev/null +++ b/tests/baseline/painting/images/border.png diff --git a/tests/baseline/painting/images/borderimage.png b/tests/baseline/painting/images/borderimage.png Binary files differnew file mode 100644 index 0000000000..f7f6b66227 --- /dev/null +++ b/tests/baseline/painting/images/borderimage.png diff --git a/tests/baseline/painting/images/dome_argb32.png b/tests/baseline/painting/images/dome_argb32.png Binary files differnew file mode 100644 index 0000000000..e3ccba0c13 --- /dev/null +++ b/tests/baseline/painting/images/dome_argb32.png diff --git a/tests/baseline/painting/images/dome_indexed.png b/tests/baseline/painting/images/dome_indexed.png Binary files differnew file mode 100644 index 0000000000..beefcd514e --- /dev/null +++ b/tests/baseline/painting/images/dome_indexed.png diff --git a/tests/baseline/painting/images/dome_indexed_mask.png b/tests/baseline/painting/images/dome_indexed_mask.png Binary files differnew file mode 100644 index 0000000000..a62f29f40e --- /dev/null +++ b/tests/baseline/painting/images/dome_indexed_mask.png diff --git a/tests/baseline/painting/images/dome_mono.png b/tests/baseline/painting/images/dome_mono.png Binary files differnew file mode 100644 index 0000000000..950c2a7494 --- /dev/null +++ b/tests/baseline/painting/images/dome_mono.png diff --git a/tests/baseline/painting/images/dome_mono_128.png b/tests/baseline/painting/images/dome_mono_128.png Binary files differnew file mode 100644 index 0000000000..77e48aaab7 --- /dev/null +++ b/tests/baseline/painting/images/dome_mono_128.png diff --git a/tests/baseline/painting/images/dome_mono_palette.png b/tests/baseline/painting/images/dome_mono_palette.png Binary files differnew file mode 100644 index 0000000000..dca3f59245 --- /dev/null +++ b/tests/baseline/painting/images/dome_mono_palette.png diff --git a/tests/baseline/painting/images/dome_rgb32.png b/tests/baseline/painting/images/dome_rgb32.png Binary files differnew file mode 100644 index 0000000000..27bc02a545 --- /dev/null +++ b/tests/baseline/painting/images/dome_rgb32.png diff --git a/tests/baseline/painting/images/dot.png b/tests/baseline/painting/images/dot.png Binary files differnew file mode 100644 index 0000000000..17a7b6a0ba --- /dev/null +++ b/tests/baseline/painting/images/dot.png diff --git a/tests/baseline/painting/images/face.png b/tests/baseline/painting/images/face.png Binary files differnew file mode 100644 index 0000000000..4f6172d83b --- /dev/null +++ b/tests/baseline/painting/images/face.png diff --git a/tests/baseline/painting/images/gam030.png b/tests/baseline/painting/images/gam030.png Binary files differnew file mode 100644 index 0000000000..904c9721bd --- /dev/null +++ b/tests/baseline/painting/images/gam030.png diff --git a/tests/baseline/painting/images/gam045.png b/tests/baseline/painting/images/gam045.png Binary files differnew file mode 100644 index 0000000000..b649a8a54f --- /dev/null +++ b/tests/baseline/painting/images/gam045.png diff --git a/tests/baseline/painting/images/gam056.png b/tests/baseline/painting/images/gam056.png Binary files differnew file mode 100644 index 0000000000..e5f959dc96 --- /dev/null +++ b/tests/baseline/painting/images/gam056.png diff --git a/tests/baseline/painting/images/gam100.png b/tests/baseline/painting/images/gam100.png Binary files differnew file mode 100644 index 0000000000..6c7ba5f1ed --- /dev/null +++ b/tests/baseline/painting/images/gam100.png diff --git a/tests/baseline/painting/images/gam200.png b/tests/baseline/painting/images/gam200.png Binary files differnew file mode 100644 index 0000000000..daa20fcbc4 --- /dev/null +++ b/tests/baseline/painting/images/gam200.png diff --git a/tests/baseline/painting/images/image.png b/tests/baseline/painting/images/image.png Binary files differnew file mode 100644 index 0000000000..85d486a790 --- /dev/null +++ b/tests/baseline/painting/images/image.png diff --git a/tests/baseline/painting/images/mask.png b/tests/baseline/painting/images/mask.png Binary files differnew file mode 100644 index 0000000000..c3f3b1b6ca --- /dev/null +++ b/tests/baseline/painting/images/mask.png diff --git a/tests/baseline/painting/images/mask_100.png b/tests/baseline/painting/images/mask_100.png Binary files differnew file mode 100644 index 0000000000..fc950dc7ed --- /dev/null +++ b/tests/baseline/painting/images/mask_100.png diff --git a/tests/baseline/painting/images/masked.png b/tests/baseline/painting/images/masked.png Binary files differnew file mode 100644 index 0000000000..6debec534d --- /dev/null +++ b/tests/baseline/painting/images/masked.png diff --git a/tests/baseline/painting/images/sign.png b/tests/baseline/painting/images/sign.png Binary files differnew file mode 100644 index 0000000000..6aac7e150a --- /dev/null +++ b/tests/baseline/painting/images/sign.png diff --git a/tests/baseline/painting/images/solid.png b/tests/baseline/painting/images/solid.png Binary files differnew file mode 100644 index 0000000000..371e9c1aee --- /dev/null +++ b/tests/baseline/painting/images/solid.png diff --git a/tests/baseline/painting/images/solid2x2.png b/tests/baseline/painting/images/solid2x2.png Binary files differnew file mode 100644 index 0000000000..f34562f964 --- /dev/null +++ b/tests/baseline/painting/images/solid2x2.png diff --git a/tests/baseline/painting/images/struct-image-01.jpg b/tests/baseline/painting/images/struct-image-01.jpg Binary files differnew file mode 100644 index 0000000000..a74e07223b --- /dev/null +++ b/tests/baseline/painting/images/struct-image-01.jpg diff --git a/tests/baseline/painting/images/struct-image-01.png b/tests/baseline/painting/images/struct-image-01.png Binary files differnew file mode 100644 index 0000000000..4ed08406dc --- /dev/null +++ b/tests/baseline/painting/images/struct-image-01.png diff --git a/tests/baseline/painting/images/zebra.png b/tests/baseline/painting/images/zebra.png Binary files differnew file mode 100644 index 0000000000..ef35f20785 --- /dev/null +++ b/tests/baseline/painting/images/zebra.png diff --git a/tests/baseline/painting/scripts/aliasing.qps b/tests/baseline/painting/scripts/aliasing.qps new file mode 100644 index 0000000000..1fb0113396 --- /dev/null +++ b/tests/baseline/painting/scripts/aliasing.qps @@ -0,0 +1,167 @@ + +path_moveTo convexPath 25 0 +path_lineTo convexPath 50 50 +path_lineTo convexPath 25 25 +path_lineTo convexPath 0 50 +path_closeSubpath convexPath + +pixmap_load border.png pixmap + +setRenderHint LineAntialiasing false +translate 10 10 + +begin_block drawing + setPen black 1 + setBrush 7f7fff + drawPath convexPath + + setFont "monospace" 8 + setPen black + drawText 0 68 "QwErTy@" + + setPen green 1 SolidLine + drawLine 0 75 10 75 + setPen 800000ff 1 + drawPoint 0 75 + drawPoint 10 75 + + setPen green 2 SolidLine + drawLine 20 75 30 75 + setPen 800000ff 2 + drawPoint 20 75 + drawPoint 30 75 + + setPen black 1 + setBrush 7f7fff + drawRect 0 80 10 5 + + setPen black 1 + setBrush noBrush + drawRect 20 80 10 5 + + setPen noPen + setBrush 7f7fff + drawRect 40 80 10 5 + + + setPen black 2 + setBrush 7f7fff + drawRect 0 90 10 5 + + setPen black 2 + setBrush noBrush + drawRect 20 90 10 5 + + setPen noPen + setBrush 7f7fff + drawRect 40 90 10 5 + + + setPen black 3 + setBrush 7f7fff + drawRect 0 100 10 5 + + setPen black 3 + setBrush noBrush + drawRect 20 100 10 5 + + setPen noPen + setBrush 7f7fff + drawRect 40 100 10 5 + + + setPen black 1 + setBrush noBrush + drawLine 10 110 20 120 + drawLine 30 120 40 110 + + setPen black 2 + setBrush noBrush + drawLine 10 120 20 130 + drawLine 30 130 40 120 + + setPen black 3 + setBrush noBrush + drawLine 10 130 20 140 + drawLine 30 140 40 130 + + drawPixmap pixmap 0 150 + + setRenderHint SmoothPixmapTransform false + drawPixmap pixmap 20 150 15 15 0 0 10 10 + +end_block + +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +drawText 15 185 "0.0" + +resetMatrix +translate 70.2 10.2 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.2 -0.2 +drawText 15 185 "0.2" + + +resetMatrix +translate 130.4 10.4 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.4 -0.4 +drawText 15 185 "0.4" + + +resetMatrix +translate 190.5 10.5 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.5 -0.5 +drawText 15 185 "0.5" + + +resetMatrix +translate 250.6 10.6 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.6 -0.6 +drawText 15 185 "0.6" + + +resetMatrix +translate 310.8 10.8 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.8 -0.8 +drawText 15 185 "0.8" + + +resetMatrix +translate 371 11 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +drawText 15 185 "1.0" + + +resetMatrix +drawText 430 95 "Aliased" +drawText 430 275 "Anti-Aliased" diff --git a/tests/baseline/painting/scripts/arcs.qps b/tests/baseline/painting/scripts/arcs.qps new file mode 100644 index 0000000000..8afaf73ff1 --- /dev/null +++ b/tests/baseline/painting/scripts/arcs.qps @@ -0,0 +1,68 @@ +# Version: 1 +# CheckVsReference: 5 + +setRenderHint LineAntialiasing + +setPen red 0 + +drawEllipse 0 0 600 400 + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 0 10 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 20 30 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 60 45 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 115 60 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 180 90 +path_closeSubpath arcs + +path_moveTo arcs 590 200 +path_arcTo arcs 10 10 580 380 0 360 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 0 -10 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 -20 -30 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 -60 -45 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 -115 -60 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 -180 -90 +path_closeSubpath arcs + +setPen black 1 solidline +setBrush #3f00ff00 +drawPath arcs + +# Then again with a matrix set... +translate 200 400 +rotate 10 +scale 0.5 0.5 +setPen red 0 +setBrush nobrush +drawEllipse 0 0 600 400 + +setPen black 1 solidline +setBrush #3f0000ff +drawPath arcs
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/arcs2.qps b/tests/baseline/painting/scripts/arcs2.qps new file mode 100644 index 0000000000..a2739a8c97 --- /dev/null +++ b/tests/baseline/painting/scripts/arcs2.qps @@ -0,0 +1,54 @@ +# Version: 1 +# CheckVsReference: 5 + +drawArc 100 100 100 100 0 1440 +drawArc 100 100 100 100 1440 1440 +drawArc 100 100 100 100 2880 1440 +drawArc 100 100 100 100 4320 1440 + +drawArc 100 200 100 100 0 -1440 +drawArc 100 200 100 100 -1440 -1440 +drawArc 100 200 100 100 -2880 -1440 +drawArc 100 200 100 100 -4320 -1440 + +drawArc 200 100 100 100 720 1440 +drawArc 200 100 100 100 2160 1440 +drawArc 200 100 100 100 3600 1440 +drawArc 200 100 100 100 5040 1440 + +drawArc 200 200 100 100 -720 -1440 +drawArc 200 200 100 100 -2160 -1440 +drawArc 200 200 100 100 -3600 -1440 +drawArc 200 200 100 100 -5040 -1440 + + +drawArc 300 100 100 100 3840 480 +drawArc 300 200 100 100 -3840 -480 + +drawArc 300 100 100 100 1600 1340 + +setPen black +drawArc 400 100 200 200 0 5760 +setPen white +drawArc 400 100 200 200 960 960 +drawArc 400 100 200 200 2880 960 +drawArc 400 100 200 200 4800 960 + +setPen black +drawArc 100 350 300 300 160 5760 +drawArc 100 350 300 300 320 5760 +drawArc 100 350 300 300 1920 5760 +drawArc 100 350 300 300 2080 5760 +drawArc 100 350 300 300 3680 5760 +drawArc 100 350 300 300 3840 5760 +drawArc 100 350 300 300 5440 5760 +drawArc 100 350 300 300 5600 5760 +setPen white +drawArc 100 350 300 300 0 5760 + +translate 400 300 +setRenderHint Antialiasing true +setPen blue 40 +drawArc 100 100 200 200 0 4320 +setPen red 40 +drawArc 60 60 280 280 0 4320 diff --git a/tests/baseline/painting/scripts/background.qps b/tests/baseline/painting/scripts/background.qps new file mode 100644 index 0000000000..d1efe5c178 --- /dev/null +++ b/tests/baseline/painting/scripts/background.qps @@ -0,0 +1,136 @@ +# Version: 1 +# CheckVsReference: 5% + +translate 10 30 +setBackground 7f7fff +setBackgroundMode Transparent +setPen ff7f7f + +path_moveTo path 0 0 +path_lineTo path 25 0 +path_cubicTo path 50 0 25 25 25 50 +path_lineTo path 0 50 + +bitmap_load bitmap.png bitmap + +begin_block drawing + save + drawRect 0 0 50 50 + + translate 60 0 + drawEllipse 0 0 50 50 + + translate 60 0 + drawPolygon [0 0 50 0 25 50 25 25] + + translate 60 0 + drawPath path + + translate 60 0 + drawPie 0 0 50 50 1440 2000 + + translate 60 0 + drawChord 0 0 50 50 1440 2000 + + translate 60 0 + drawLine 0 0 50 0 + drawLine 0 0 50 50 + drawLine 0 0 0 50 + + translate 60 0 + drawPolyline [0 0 50 0 25 50 25 25] + + translate 60 0 + drawArc 0 0 50 50 1440 2000 + + translate 60 0 + drawText 0 10 "Jambi-Bambi" + + translate 80 0 + drawPixmap bitmap 0 0 + restore + + save + setRenderHint Antialiasing + translate 5 55 + drawRect 0 0 50 50 + + translate 60 0 + drawEllipse 0 0 50 50 + + translate 60 0 + drawPolygon [0 0 50 0 25 50 25 25] + + translate 60 0 + drawPath path + + translate 60 0 + drawPie 0 0 50 50 1440 2000 + + translate 60 0 + drawChord 0 0 50 50 1440 2000 + + translate 60 0 + drawLine 0 0 50 0 + drawLine 0 0 50 50 + drawLine 0 0 0 50 + + translate 60 0 + drawPolyline [0 0 50 0 25 50 25 25] + + translate 60 0 + drawArc 0 0 50 50 1440 2000 + + translate 60 0 + drawText 0 10 "Jambi-Bambi" + + translate 80 0 + drawPixmap bitmap 0 0 + restore +end_block + +translate 0 160 +setBackgroundMode Transparent +setPen ff7f7f 0 dotline flatcap beveljoin +repeat_block drawing + +translate 0 160 +setBackgroundMode Opaque +setPen ff7f7f 0 dotline flatcap beveljoin +repeat_block drawing + +translate 0 160 +setBackgroundMode Transparent +setPen ff7f7f 4 dashline flatcap beveljoin +repeat_block drawing + +translate 0 160 +setBackgroundMode OpaqueMode +setPen ff7f7f 4 dashline flatcap beveljoin +repeat_block drawing + +resetMatrix + +translate 5 5 + +setBrush nobrush +setPen black +setBackgroundMode transparent +drawText 10 15 "TransparentMode with solid 0-width pen" +drawRect 0 0 685 135 + +translate 0 160 +drawText 10 15 "TransparentMode with dotted 0-width pen" +drawRect 0 0 685 135 + +translate 0 160 +drawText 10 15 "OpaqueMode with dotted 0-width pen" +drawRect 0 0 685 135 + +translate 0 160 +drawText 10 15 "TransparentMode with dotted 4-width pen" +drawRect 0 0 685 135 + +translate 0 160 +drawText 10 15 "OpaqueMode with solid 4-width pen" +drawRect 0 0 685 135 diff --git a/tests/baseline/painting/scripts/background_brush.qps b/tests/baseline/painting/scripts/background_brush.qps new file mode 100644 index 0000000000..ca1f944964 --- /dev/null +++ b/tests/baseline/painting/scripts/background_brush.qps @@ -0,0 +1,5 @@ +# Version: 1 +# CheckVsReference: 5% + +setBrush #00ff00 crosspattern +import "background.qps"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/beziers.qps b/tests/baseline/painting/scripts/beziers.qps new file mode 100644 index 0000000000..62d9d031a6 --- /dev/null +++ b/tests/baseline/painting/scripts/beziers.qps @@ -0,0 +1,148 @@ +# Version: 1 +# CheckVsReference: 5% + +setRenderHint LineAntialiasing + +setPen green 0 + +translate 20 20 +path_moveTo fullSize 0 0 +path_cubicTo fullSize 200 100 -100 100 100 0 + +path_moveTo fullSize 0 200 +path_cubicTo fullSize 0 100 100 100 100 200 + +path_moveTo fullSize 0 250 +path_cubicTo fullSize 50 200 50 200 100 250 +drawPath fullSize + +translate 110 0 +scale 10 10 +path_moveTo medSize 0 0 +path_cubicTo medSize 20 10 -10 10 10 0 + +path_moveTo medSize 0 20 +path_cubicTo medSize 0 10 10 10 10 20 + +path_moveTo medSize 0 25 +path_cubicTo medSize 5 20 5 20 10 25 +drawPath medSize + +resetMatrix +translate 240 20 +scale 100 100 +path_moveTo smallSize 0 0 +path_cubicTo smallSize 2 1 -1 1 1 0 + +path_moveTo smallSize 0 2 +path_cubicTo smallSize 0 1 1 1 1 2 + +path_moveTo smallSize 0 2.5 +path_cubicTo smallSize 0.5 2 0.5 2 1 2.5 +drawPath smallSize + +resetMatrix +translate 20 300 +drawPath medSize + +resetMatrix +translate 250 -100 +path_moveTo maxSize 0 500 +path_cubicTo maxSize 1000 0 -500 0 500 500 +drawPath maxSize + +setRenderHint Antialiasing off +resetMatrix + +path_moveTo path1 0 0 +path_cubicTo path1 10 10 0 10 10 0 + +path_moveTo path2 0 0 +path_cubicTo path2 15 15 -5 15 10 0 + +path_moveTo path3 0 0 +path_cubicTo path3 20 20 -10 20 10 0 + +path_moveTo path4 0 0 +path_cubicTo path4 0 5 10 10 0 15 + +path_moveTo path5 0 10 +path_cubicTo path5 10 10 -10 20 0 0 + +path_moveTo path6 0 0 +path_cubicTo path6 10 5 -10 10 0 15 + +setPen black 2 +setBrush nobrush + +translate 10 500 +scale 3 3 +begin_block paths +save +drawPath path1 +translate 20 0 +drawPath path2 +translate 20 0 +drawPath path3 +translate 20 0 +drawPath path4 +translate 20 0 +drawPath path5 +translate 20 0 +drawPath path6 +restore +end_block + +setPen nopen +setBrush black + +translate 0 20 +repeat_block paths + +setRenderHint Antialiasing + +setPen black 2 +setBrush nobrush + +translate 120 -20 +repeat_block paths + +setPen nopen +setBrush black + +translate 0 20 +repeat_block paths + +resetMatrix +path_moveTo miterPath 20 0 +path_cubicTo miterPath 20 20 0 0 1 0 +path_lineTo miterPath -1 -0.2 + +setBrush nobrush + +translate 50 660 +scale 5 5 + +setPen black 4 solidline flatcap miterjoin +drawPath miterPath +setPen red 0 +drawPath miterPath + +path_moveTo miterPath2 21 0.2 +path_lineTo miterPath2 19 0 +path_cubicTo miterPath2 20 0 0 20 0 0 + +translate 30 0 +setPen black 4 solidline flatcap miterjoin +drawPath miterPath2 +setPen red 0 +drawPath miterPath2 + +path_moveTo wonkyPath 0 0 +path_cubicTo wonkyPath 5 15 20 0 17 0 + +translate 30 0 +setPen black 4 solidline flatcap miterjoin +drawPath wonkyPath +setPen red 0 +drawPath wonkyPath diff --git a/tests/baseline/painting/scripts/bitmaps.qps b/tests/baseline/painting/scripts/bitmaps.qps new file mode 100644 index 0000000000..4966490337 --- /dev/null +++ b/tests/baseline/painting/scripts/bitmaps.qps @@ -0,0 +1,166 @@ +# Version: 1 +# CheckVsReference: 5% + + +#setRenderHint SmoothPixmapTransform + +translate 10 50 +setBackground ff7f7f +setPen 3f3f9f + +bitmap_load dome_mono.png the_pixmap + +save + # Draw with opaque pen/bg in transparent/opaque mode + setBackgroundMode Transparent + drawPixmap the_pixmap 0 0 + setBackgroundMode Opaque + drawPixmap the_pixmap 110 0 + + translate 220 0 + + # Draw with alpha pen/bg in transparent/opaque mode + save + setBackground 7fff7f7f + setPen 7f3f3f9f + setBackgroundMode Transparent + drawPixmap the_pixmap 0 0 + setBackgroundMode Opaque + drawPixmap the_pixmap 110 0 + restore + + translate 220 0 + + # Draw with rotated opaque pen/bg in transparent/opaque mode + setBackgroundMode Transparent + save + translate 50 50 + rotate 10 + translate -50 -50 + drawPixmap the_pixmap 0 0 + restore + setBackgroundMode Opaque + translate 110 0 + save + translate 50 50 + rotate 10 + translate -50 -50 + drawPixmap the_pixmap 0 0 + restore +restore + +translate 0 150 + +save + setBackgroundMode Transparent + drawTiledPixmap the_pixmap 0 0 200 100 + setBackgroundMode Opaque + drawTiledPixmap the_pixmap 210 0 200 100 + + translate 440 -10 + save + rotate 10 + drawTiledPixmap the_pixmap 0 0 200 100 + restore +restore + +translate 0 150 +save + setBackgroundMode Transparent + drawTiledPixmap the_pixmap 0 0 200 100 10 20 + setBackgroundMode Opaque + drawTiledPixmap the_pixmap 210 0 200 100 10 20 + + translate 440 -10 + save + rotate 10 + drawTiledPixmap the_pixmap 0 0 200 100 10 20 + restore +restore + + +pixmap_setMask the_pixmap mask_100.png +drawPixmap the_pixmap 0 150 +setBackgroundMode Opaque +drawPixmap the_pixmap 110 150 + +translate 220 150 +save + translate 50 50 + rotate 10 + translate -50 -50 + setBackgroundMode Transparent + drawPixmap the_pixmap 0 0 +restore + +translate 110 0 +save + translate 50 50 + rotate 10 + translate -50 -50 + setBackgroundMode Opaque + drawPixmap the_pixmap 0 0 +restore + +resetMatrix +translate 10 650 +bitmap_load dome_mono.png the_bitmap +setBackgroundMode Transparent + +begin_block draw_subrected + drawPixmap the_bitmap 0 0 50 50 0 0 50 50 + drawPixmap the_bitmap 50 0 50 50 50 0 50 50 + drawPixmap the_bitmap 0 50 50 50 0 50 50 50 + drawPixmap the_bitmap 50 50 50 50 50 50 50 50 +end_block + +translate 110 0 +setBackgroundMode Opaque +repeat_block draw_subrected + +translate 110 0 +save + translate 20 -10 + rotate 10 + setBackgroundMode Transparent + repeat_block draw_subrected +restore + +translate 110 0 +save + translate 20 -10 + rotate 10 + setBackgroundMode Opaque + repeat_block draw_subrected +restore + +# Some helpful texts + +resetMatrix +setPen black +drawText 10 40 "Transparent" +drawText 120 40 "Opaque" +drawText 230 40 "Trans w/alpha" +drawText 340 40 "Opaque w/alpha" +drawText 450 40 "Trans w/xform" +drawText 560 40 "Opaque w/xform" + +drawText 10 190 "Transparent tiled" +drawText 220 190 "Opaque tiled" +drawText 440 190 "Opaque w/xform" + +drawText 10 340 "Transparent tiled w/offset" +drawText 220 340 "Opaque tiled w/offset" +drawText 440 340 "Opaque w/xform w/offset" + +drawText 10 490 "Trans masked" +drawText 120 490 "Opaque masked" +drawText 230 490 "masked w/xform" +drawText 340 490 "masked w/xform" + +drawText 10 640 "Subrected" +drawText 110 640 "Subrected opaque" +drawText 220 640 "subrect w/xform" +drawText 330 640 "subrect w/xform opaque" + + diff --git a/tests/baseline/painting/scripts/borderimage.qps b/tests/baseline/painting/scripts/borderimage.qps new file mode 100644 index 0000000000..ebd4f4d249 --- /dev/null +++ b/tests/baseline/painting/scripts/borderimage.qps @@ -0,0 +1,120 @@ +# Version: 1 +# CheckVsReference: 10% + +image_load borderimage.png borderimage +translate -128 -128 +begin_block draw_border +# top +drawImage borderimage 0 0 16 16 0 0 16 16 +drawImage borderimage 16 0 36 16 16 0 32 16 +drawImage borderimage 52 0 16 16 48 0 16 16 +# sides +drawImage borderimage 0 16 16 16 0 16 16 32 +drawImage borderimage 52 16 16 16 48 16 16 32 +#bottom +drawImage borderimage 0 32 16 16 0 48 16 16 +drawImage borderimage 16 32 36 16 16 48 32 16 +drawImage borderimage 52 32 16 16 48 48 16 16 +end_block draw_border +resetMatrix +begin_block draw_column +translate 1 1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +end_block draw_column +setRenderHint Antialiasing +resetMatrix +translate 72 0 +repeat_block draw_column +resetMatrix +scale 1.25 1.25 +translate 144 0 +repeat_block draw_border +resetMatrix +scale 1.25 1.25 +translate 246 0 +rotate 30 +repeat_block draw_border +setRenderHint SmoothPixmapTransform +resetMatrix +scale 1.25 1.25 +translate 144 120 +repeat_block draw_border +resetMatrix +scale 1.25 1.25 +translate 246 120 +rotate 30 +repeat_block draw_border +resetMatrix +translate 215 260 +scale 3.55 3.55 +rotate 30 +repeat_block draw_border +resetMatrix +setRenderHint SmoothPixmapTransform off +setRenderHint Antialiasing off +translate 480 627 +rotate 180 +repeat_block draw_column +resetMatrix +setRenderHint Antialiasing +translate 552 627 +rotate 180 +repeat_block draw_column +resetMatrix +setRenderHint Antialiasing off +translate 200.1 520.1 +begin_block one_pixel_border +drawImage borderimage 0 0 16 16 0 0 16 16 +drawImage borderimage 16 0 64 16 16 0 1 1 +drawImage borderimage 80 0 16 16 48 0 16 16 +drawImage borderimage 0 16 16 64 16 0 1 1 +drawImage borderimage 80 16 16 64 16 0 1 1 +drawImage borderimage 0 80 16 16 0 48 16 16 +drawImage borderimage 16 80 64 16 16 0 1 1 +drawImage borderimage 80 80 16 16 48 48 16 16 +end_block one_pixel_border +resetMatrix +translate 205.1 626.1 +scale 0.4 0.4 +repeat_block one_pixel_border +resetMatrix +translate 255.1 624.1 +scale 0.4 0.4 +rotate 10 +repeat_block one_pixel_border +resetMatrix +setPen red +drawRect 0 0 70 680 +drawText 10 670 "aa off" +drawRect 72 0 70 680 +drawText 80 670 "aa on" +drawRect 409 0 70 680 +drawText 419 650 "rot 180" +drawText 419 670 "aa off" +drawRect 481 0 70 680 +drawText 491 650 "rot 180" +drawText 491 670 "aa on" +drawRect 164 0 224 124 +drawText 174 114 "smoothpixmaptransform off" +drawRect 164 128 224 134 +drawText 174 252 "smoothpixmaptransform on" +drawRect 200 520 97 188 +drawText 210 698 "1x1 edges"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/brush_pens.qps b/tests/baseline/painting/scripts/brush_pens.qps new file mode 100644 index 0000000000..b9a2bc0ada --- /dev/null +++ b/tests/baseline/painting/scripts/brush_pens.qps @@ -0,0 +1,104 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addRect p 0 0 75 75 +path_addEllipse p 25 25 75 75 + +translate 10 10 + +begin_block setup_gradient + gradient_clearStops + gradient_appendStop 0 red + gradient_appendStop 0.1 blue + gradient_appendStop 0.2 yellow + gradient_appendStop 0.3 cyan + gradient_appendStop 0.4 magenta + gradient_appendStop 0.5 green + gradient_appendStop 0.6 black + gradient_appendStop 0.7 indianred + gradient_appendStop 0.8 white + gradient_appendStop 0.9 orange + gradient_appendStop 1 blue + gradient_setLinear 0 0 100 100 +end_block + +setPen brush 0 +setBrush nobrush + +begin_block drawing + save + drawLine 0 0 100 100 + + translate 0 100 + drawPath p + + translate 0 110 + drawRect 0 0 100 100 + + translate 0 110 + drawPolyline [0 0 100 0 50 50] + + drawPoint 40 40 + drawPoint 41 40 + drawPoint 42 40 + drawPoint 43 40 + drawPoint 44 40 + drawPoint 45 40 + drawPoint 46 40 + drawPoint 47 40 + drawPoint 48 40 + drawPoint 49 40 + drawPoint 50 40 + + restore +end_block + +save + translate 110 0 + save + setRenderHint Antialiasing + repeat_block drawing + restore + + setBrush dome_rgb32.png + setPen brush 0 + setBrush nobrush + + translate 110 0 + repeat_block drawing + + translate 110 0 + save + setRenderHint Antialiasing + repeat_block drawing + restore +restore + +translate 0 0 + +save + repeat_block setup_gradient + setPen brush 5 + setBrush nobrush + translate 0 350 + repeat_block drawing + + translate 110 0 + save + setRenderHint Antialiasing + repeat_block drawing + restore + + setBrush dome_rgb32.png + setPen brush 5 + setBrush nobrush + + translate 110 0 + repeat_block drawing + + translate 110 0 + save + setRenderHint Antialiasing + repeat_block drawing + restore +restore
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/brushes.qps b/tests/baseline/painting/scripts/brushes.qps new file mode 100644 index 0000000000..43a7843601 --- /dev/null +++ b/tests/baseline/painting/scripts/brushes.qps @@ -0,0 +1,88 @@ +# Version: 1 +# CheckVsReference: 5% + +# Fill the background +drawRect 0 0 width height + +setRenderHint Antialiasing +setRenderHint SmoothPixmapTransform + +translate 10 10 +# Draw all the pattern types as 40x40 rects using green, transparent background +begin_block drawrects +setBrush green Dense1Pattern +drawRect 0 0 40 40 +setBrush green Dense2Pattern +drawRect 40 0 40 40 +setBrush green Dense3Pattern +drawRect 80 0 40 40 +setBrush green Dense4Pattern +drawRect 120 0 40 40 +setBrush green Dense5Pattern +drawRect 160 0 40 40 +setBrush green Dense6Pattern +drawRect 200 0 40 40 +setBrush green Dense7Pattern +drawRect 240 0 40 40 +setBrush green HorPattern +drawRect 280 0 40 40 +setBrush green VerPattern +drawRect 320 0 40 40 +setBrush green CrossPattern +drawRect 360 0 40 40 +setBrush green BDiagPattern +drawRect 400 0 40 40 +setBrush green FDiagPattern +drawRect 440 0 40 40 +setBrush green DiagCrossPattern +drawRect 480 0 40 40 +setBrush green SolidPattern +drawRect 520 0 40 40 +setBrush green NoBrush +drawRect 560 0 40 40 +gradient_setLinear 0 0 0 40 +drawRect 600 0 40 40 +setBrush face.png +drawRect 640 0 80 40 +end_block + +# Switch to opaque mode +setBackground #7fff7f +setBackgroundMode OpaqueMode +translate 0 50 + +# Draw all the pattern types as 40x40 rects using green, opaque background +repeat_block drawrects + +translate 50 50 +rotate 10 + + +setBackgroundMode TransparentMode +repeat_block drawrects +setBackgroundMode OpaqueMode +translate 0 40 +repeat_block drawrects + + +setBrush dot.png +setPen nopen +resetMatrix +drawRect 0 200 50 50 +drawRect 50 200 50 50 + +setPen red +setBrushOrigin 0 250 +drawRect 0 250 50 50 +setBrushOrigin 50 250 +drawRect 50 250 50 50 + + +setBrush dome_indexed.png +setPen nopen +brushScale 0.7 0.7 +drawRect 20 320 600 200 + +setBrush dome_argb32.png +brushScale 1.5 1.5 +drawRect 20 540 600 200 diff --git a/tests/baseline/painting/scripts/clippath_antialiasing.qps b/tests/baseline/painting/scripts/clippath_antialiasing.qps new file mode 100644 index 0000000000..193ce8b7ed --- /dev/null +++ b/tests/baseline/painting/scripts/clippath_antialiasing.qps @@ -0,0 +1,76 @@ +# There was no serration in either case +save +setBrush black SolidPattern +drawRect 0.0 0.0 500.0 300.0 +restore + +save +setRenderHint Antialiasing true +path_addEllipse mypath1 10.0 10.0 200.0 200.0 +path_addRect mypath1 10.0 210.0 200.0 40.0 +path_addPolygon mypath1 [ 10 250 50 280 90 300 130 300 170 280 210 250] + +setClipPath mypath1 ReplaceClip +setPen NoPen +setBrush cyan SolidPattern +drawRect 10.0 10.0 400.0 400.0 +restore +save +setRenderHint Antialiasing false +path_addEllipse mypath2 220.0 10.0 200.0 200.0 +path_addRect mypath2 220.0 210.0 200.0 40.0 +path_addPolygon mypath2 [ 220 250 270 280 300 300 340 300 380 280 420 250] +setClipPath mypath2 ReplaceClip +setRenderHint Antialiasing true +setPen NoPen +setBrush cyan SolidPattern +drawRect 220.0 10.0 300.0 300.0 +restore + +setPen red +setBrush NoBrush +drawText 20 250 "Antialiasing before setClipPath" +drawText 240 250 "Antialiasing after setClipPath" + +# Test that the clipping region is not abnormal after some transformations +translate 100 300 + +save +path_addEllipse mypath3 10.0 10.0 200.0 200.0 +path_addRect mypath3 10.0 210.0 200.0 40.0 +setPen black SolidLine +setBrush NoBrush +setRenderHint Antialiasing true +drawPath mypath3 +setClipPath mypath3 ReplaceClip +rotate 60 +setFont "times" 10 Bold +drawText 10 70 "Antialiasing before setClipPath - Transformation" +drawText 10 40 "Antialiasing before setClipPath - Transformation" +drawText 10 10 "Antialiasing before setClipPath - Transformation" +drawText 10 -20 "Antialiasing before setClipPath - Transformation" +drawText 10 -50 "Antialiasing before setClipPath - Transformation" +drawText 10 -80 "Antialiasing before setClipPath - Transformation" +restore + +translate 0 250 + +save +path_addEllipse mypath4 10.0 10.0 200.0 200.0 +path_addRect mypath4 10.0 210.0 200.0 40.0 +setPen black SolidLine +setBrush NoBrush +drawPath mypath4 +setClipPath mypath4 ReplaceClip +setRenderHint Antialiasing true +rotate 60 +setFont "times" 10 Bold +drawText 10 70 "Antialiasing after setClipPath - Transformation" +drawText 10 40 "Antialiasing after setClipPath - Transformation" +drawText 10 10 "Antialiasing after setClipPath - Transformation" +drawText 10 -20 "Antialiasing after setClipPath - Transformation" +drawText 10 -50 "Antialiasing after setClipPath - Transformation" +drawText 10 -80 "Antialiasing after setClipPath - Transformation" +restore + + diff --git a/tests/baseline/painting/scripts/clippaths.qps b/tests/baseline/painting/scripts/clippaths.qps new file mode 100644 index 0000000000..fe8e198a17 --- /dev/null +++ b/tests/baseline/painting/scripts/clippaths.qps @@ -0,0 +1,60 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addRect hor 0 0 50 10 +path_addRect ver 0 0 10 50 + +translate 10 10 +setPen NoPen + +begin_block clipping +save + + setBrush 0x7f7fff + save + setClipPath hor + drawRect 0 0 100 100 + + setClipPath ver IntersectClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + + translate 100 0 + save + setClipPath hor + drawRect 0 0 100 100 + + setClipPath ver ReplaceClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + + translate 100 0 + save + setClipPath hor + drawRect 0 0 100 100 + + setClipPath ver UniteClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + +restore +end_block + +translate 300 0 +setRenderHint Antialiasing +repeat_block clipping + +translate -300 100 +setRenderHint Antialiasing false +scale 1.2 1.2 +repeat_block clipping + +translate 300 0 +setRenderHint Antialiasing +setRenderHint SmoothPixmapTransform +repeat_block clipping + + diff --git a/tests/baseline/painting/scripts/clipping.qps b/tests/baseline/painting/scripts/clipping.qps new file mode 100644 index 0000000000..3694ff2ba7 --- /dev/null +++ b/tests/baseline/painting/scripts/clipping.qps @@ -0,0 +1,182 @@ +# Version: 1 +# CheckVsReference: 5% + +region_addRect clip 50 0 90 190 +region_addRect clip 0 50 180 90 + +region_addRect clip2 30 30 60 60 + +region_addRect clip3 10 10 60 60 + +path_cubicTo path 90 0 50 50 90 90 +path_cubicTo path 0 90 50 50 0 0 + +path_addRect path2 0 0 90 90 +path_moveTo path2 90 45 +path_arcTo path2 0 0 90 90 0 -360 + +path_addRect emptypath 0 0 0 0 +region_addRect emptyregion 0 0 0 0 + +# Normal clip rect +setClipRect 0 0 50 150 +begin_block repaint +save +setBrush red +setPen nopen +resetMatrix +region_getClipRegion tmpclip +path_getClipPath tmpclippath +drawRect 0 0 width height +setBrush #3f0000ff +setClipRegion tmpclip +drawRect 0 0 width height +setClipPath tmpclippath +setBrush #3f00ff00 +drawRect 0 0 width height +restore +end_block + +# Rotated clip rect +translate 100 0 +rotate 10 +setClipRect 0 0 50 150 +repeat_block repaint + +# simple clip region +resetMatrix +translate 0 200 +setClipRegion clip +repeat_block repaint + +# simle rotated clip region +translate 250 -10 +rotate 10 +setClipRegion clip +repeat_block repaint + +# verify that clip is not xformed with painter +resetMatrix +translate 200 0 +setClipRegion clip +rotate 30 +setBrush red +setPen nopen +drawRect 0 0 width height + +resetMatrix +translate 0 400 +save +setClipRegion clip +setClipRegion clip2 IntersectClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipRegion clip +setClipRegion clip2 IntersectClip +restore + +translate 100 0 +save +setClipRegion clip3 +setClipRegion clip2 UniteClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipRegion clip3 +setClipRegion clip2 UniteClip +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +repeat_block repaint +translate 50 100 +rotate 45 +setClipPath path +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +setClipPath path2 IntersectClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipPath path +setClipPath path2 IntersectClip +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +setClipPath path2 UniteClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipPath path +setClipPath path2 UniteClip +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +setClipRegion clip3 IntersectClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipRegion clip3 +setClipPath path IntersectClip +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +setClipRegion clip3 UniteClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipRegion clip3 +setClipPath path UniteClip +repeat_block repaint +restore + +# test that an empty region is not drawn. +resetMatrix +setClipRegion emptyregion +setBrush #3f00ff00 +drawRect 0 0 300 300 +drawText 50 50 "Text should be clipped away by region" +setClipping false + +setClipPath emptypath +setBrush #3fffff00 +drawRect 50 50 300 300 +drawText 70 80 "Text should be clipped away by path" + +# Test that we can extract a clipregion when a matrix is set too +resetMatrix +translate 500 10 +scale 2 1 +setBrush blue +setClipping false +rotate 5 +drawRect 0 0 100 100 +setClipRect 0 0 100 100 +resetMatrix +rotate 10 +region_getClipRegion xclip +setClipRegion xclip +resetMatrix +setBrush #7f00ff00 +drawRect 0 0 width height + +# the below used to assert in debug mode +setClipRect 10 10 20 20 +setClipping false +setClipping true
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/clipping_state.qps b/tests/baseline/painting/scripts/clipping_state.qps new file mode 100644 index 0000000000..a29d3738c8 --- /dev/null +++ b/tests/baseline/painting/scripts/clipping_state.qps @@ -0,0 +1,47 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addRect path1 10 10 50 50 +path_addRect path2 30 30 50 50 +# enable/disable a clip path +setPen nopen +setBrush red +setClipPath path1 +setClipPath path2 UniteClip +drawRect 0 0 100 100 +setClipping false +setBrush #630000ff +drawRect 0 0 100 100 +setClipping true +setBrush #6300ff00 +drawRect 0 0 100 100 +# enable/disable noclip +translate 150 0 +setClipPath path1 NoClip +setClipping false +setBrush #630000ff +drawRect 0 0 100 100 +setClipping true +setBrush #6300ff00 +drawRect 25 25 50 50 +# enable/disable full clipping +translate 150 0 +path_addRect path3 0 0 10 10 +path_addRect path4 20 20 10 10 +setClipPath path3 +setClipPath path4 IntersectClip +setClipping false +setBrush #630000ff +drawRect 0 0 100 100 +setClipping true +setBrush #6300ff00 +drawRect 25 25 50 50 +# disable clipping followed by setClipRect +translate 150 0 +setClipRect 0 0 50 50 ReplaceClip +setClipping false +setBrush #630000ff +drawRect 0 0 100 100 +setClipRect 25 25 75 75 IntersectClip +setBrush #6300ff00 +drawRect 25 25 50 50
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/cliprects.qps b/tests/baseline/painting/scripts/cliprects.qps new file mode 100644 index 0000000000..cbc2a90055 --- /dev/null +++ b/tests/baseline/painting/scripts/cliprects.qps @@ -0,0 +1,352 @@ +# Version: 1 +# CheckVsReference: 5% + +save + +translate 10 10 +setPen NoPen + +begin_block clipping +save + + setBrush 0x7f7fff + save + setClipRect 0 0 50 10 + drawRect 0 0 100 100 + + setClipRect 0 0 10 50 IntersectClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + + translate 100 0 + save + setClipRect 0 0 50 10 + drawRect 0 0 100 100 + + setClipRect 0 0 10 50 ReplaceClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + + translate 100 0 + save + setClipRect 0 0 50 10 + drawRect 0 0 100 100 + + setClipRect 0 0 10 50 UniteClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + +restore +end_block + +translate 300 0 +setRenderHint Antialiasing +repeat_block clipping + +translate -300 100 +setRenderHint Antialiasing false +scale 1.2 1.2 +repeat_block clipping + +translate 300 0 +setRenderHint Antialiasing +setRenderHint SmoothPixmapTransform +repeat_block clipping + +restore + +# Excercise combining different clips + +translate 0 250 +scale 0.9 0.9 +setFont "times" 10 bold +region_addRect dummyRegion 1000 1000 10 10 +region_addRect realRegion 20 10 60 30 +path_addRect dummyPath 1000 1000 10 10 +path_addRect realPath 20 10 60 30 +begin_block paintstuff +fillRect 0 0 100 50 orange +drawText 0 5 "Should be clipped" +drawText 0 15 "Should be clipped" +drawText 0 25 "Should be clipped" +drawText 0 35 "Should be clipped" +drawText 0 45 "Should be clipped" +drawText 0 55 "Should be clipped" +end_block + +translate 0 100 + +# rect replaced by x +save +setClipRect 1000 1000 10 10 ReplaceClip +setClipRect 20 10 60 30 ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRect 1000 1000 10 10 ReplaceClip +setClipRectF 20 10 60 30 ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRect 1000 1000 10 10 ReplaceClip +setClipRegion realRegion ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRect 1000 1000 10 10 ReplaceClip +setClipPath realPath ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +# rectF replaced by x +save +setClipRectF 1000 1000 10 10 ReplaceClip +setClipRect 20 10 60 30 ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRectF 1000 1000 10 10 ReplaceClip +setClipRectF 20 10 60 30 ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRectF 1000 1000 10 10 ReplaceClip +setClipRegion realRegion ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRectF 1000 1000 10 10 ReplaceClip +setClipPath realPath ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +translate -800 100 + +# region replaced by x +save +setClipRegion dummyRegion ReplaceClip +setClipRect 20 10 60 30 ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRegion dummyRegion ReplaceClip +setClipRectF 20 10 60 30 ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRegion dummyRegion ReplaceClip +setClipRegion realRegion ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRegion dummyRegion ReplaceClip +setClipPath realPath ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +# path replaced by x +save +setClipPath dummyPath ReplaceClip +setClipRect 20 10 60 30 ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipPath dummyPath ReplaceClip +setClipRectF 20 10 60 30 ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipPath dummyPath ReplaceClip +setClipRegion realRegion ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +save +setClipPath dummyPath ReplaceClip +setClipPath realPath ReplaceClip +repeat_block paintstuff +restore +translate 100 0 + +region_addRect intregion 0 10 60 30 +path_addRect intpath 0 10 60 30 + +translate -800 100 +# rect & x +save +setClipRect 0 10 60 30 ReplaceClip +translate 40 0 +setClipRect 0 10 60 30 IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRect 0 10 60 30 ReplaceClip +translate 40 0 +setClipRectF 0 10 60 30 IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRect 0 10 60 30 ReplaceClip +translate 40 0 +setClipRegion intregion IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRect 0 10 60 30 ReplaceClip +translate 40 0 +setClipPath intpath IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +# rectF & x +save +setClipRectF 0 10 60 30 ReplaceClip +translate 40 0 +setClipRect 0 10 60 30 IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRectF 0 10 60 30 ReplaceClip +translate 40 0 +setClipRectF 0 10 60 30 IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRectF 0 10 60 30 ReplaceClip +translate 40 0 +setClipRegion intregion IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRectF 0 10 60 30 ReplaceClip +translate 40 0 +setClipPath intpath IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +translate -800 100 + +# region & x +save +setClipRegion intregion ReplaceClip +translate 40 0 +setClipRect 0 10 60 30 IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRegion intregion ReplaceClip +translate 40 0 +setClipRectF 0 10 60 30 IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRegion intregion ReplaceClip +translate 40 0 +setClipRegion intregion IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipRegion intregion ReplaceClip +translate 40 0 +setClipPath intpath IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +# path & x +save +setClipPath intpath ReplaceClip +translate 40 0 +setClipRect 0 10 60 30 IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipPath intpath ReplaceClip +translate 40 0 +setClipRectF 0 10 60 30 IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipPath intpath ReplaceClip +translate 40 0 +setClipRegion intregion IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 + +save +setClipPath intpath ReplaceClip +translate 40 0 +setClipPath intpath IntersectClip +translate -40 0 +repeat_block paintstuff +restore +translate 100 0 diff --git a/tests/baseline/painting/scripts/conical_gradients.qps b/tests/baseline/painting/scripts/conical_gradients.qps new file mode 100644 index 0000000000..d6eb860f3f --- /dev/null +++ b/tests/baseline/painting/scripts/conical_gradients.qps @@ -0,0 +1,85 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addRect path 300 0 80 80 +path_addEllipse path 340 40 60 60 + +setRenderHint Antialiasing + +setPen black + +begin_block gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setConical 40 40 50 +drawRect 0 0 100 100 + +gradient_setConical 140 40 230 +drawEllipse 100 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setConical 240 40 50 +drawPolygon [200 0 290 0 250 99] + +gradient_setConical 340 40 230 +drawPath path + +end_block + +translate 0 100 +scale 1 2 +repeat_block gradients + +resetMatrix +translate 0 300 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block gradients + +# Some helpful info perhaps? +resetMatrix +setPen black + +drawText 410 50 "No XForm" +drawText 410 200 "scale 1x2" +drawText 410 300 "brush transform" +drawText 10 450 "50 deg" +drawText 110 450 "230 deg" +drawText 210 450 "50 deg w/alpha " +drawText 310 450 "230 deg w/alpha" + +setPen 3f000000 +setBrush nobrush + +begin_block ellipse_draw + setClipRect 0 0 100 100 + drawEllipse 35 35 11 11 + save + translate 40 40 + rotate -50 + drawLine -100 0 100 0 + restore + translate 100 0 +end_block + +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw + +resetMatrix +translate 0 100 +scale 1 2 +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/conical_gradients_perspectives.qps b/tests/baseline/painting/scripts/conical_gradients_perspectives.qps new file mode 100644 index 0000000000..a9c14f1ce7 --- /dev/null +++ b/tests/baseline/painting/scripts/conical_gradients_perspectives.qps @@ -0,0 +1,64 @@ +# Version: 1 +# CheckVsReference: 5% + + +setRenderHint Antialiasing + +setPen #00ff00 + +translate 10 10 +# standard draw +begin_block gradient +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 0.9 cyan +gradient_appendStop 1 red + +gradient_setSpread PadSpread +gradient_setConical 140 140 100 +drawRect 0 0 300 300 +end_block gradient + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + repeat_block gradient +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + repeat_block gradient +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + repeat_block gradient +restore +restore + + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/cosmetic.qps b/tests/baseline/painting/scripts/cosmetic.qps new file mode 100644 index 0000000000..3c730cf26f --- /dev/null +++ b/tests/baseline/painting/scripts/cosmetic.qps @@ -0,0 +1,55 @@ +drawRect 0 0 800 800 + +setRenderHint Antialiasing true +image_load dome_argb32.png img + +save +setBrush springgreen SolidPattern + +begin_block primitives + +setPen black 2 DashLine +pen_setCosmetic true +drawLine 10 60 60 10 +drawRect 80 10.0 30 50 +drawText 130 50 "Foo" +drawImage img 160 10 50 50 + +pen_setCosmetic false +drawLine 10 160 60 110 +drawRect 80 110.0 30 50 +drawText 130 150 "Foo" +drawImage img 160 110 50 50 + +setPen NoPen +drawLine 10 260 60 210 +drawRect 80 210.0 30 50 +drawText 130 250 "Foo" +drawImage img 160 210 50 50 + +end_block primitives + + +translate 250 0 +rotate 10 +scale 2.5 1 +repeat_block primitives + +resetMatrix +# Force non-simple pen in Pdf +setOpacity 0.5 +translate 0 400 +repeat_block primitives + +translate 250 0 +rotate 10 +scale 2.5 1 +repeat_block primitives + +restore +setPen blue 4 DotLine +setBrush olive SolidPattern +pen_setCosmetic true +translate 50 720 +scale 2 2 +drawRect 0 0 30 30 diff --git a/tests/baseline/painting/scripts/dashes.qps b/tests/baseline/painting/scripts/dashes.qps new file mode 100644 index 0000000000..185443a292 --- /dev/null +++ b/tests/baseline/painting/scripts/dashes.qps @@ -0,0 +1,268 @@ +# Version: 1 +# CheckVsReference: 5% + +translate 20 20 + +begin_block draw +save + save + setPen black 1 SolidLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 SolidLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 SolidLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 SolidLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 SolidLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 SolidLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 6 SolidLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 SolidLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 SolidLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + + translate 100 0 + save + setPen black 1 DotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 DotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 6 DotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + translate 100 0 + save + setPen black 1 DashLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 DashLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 6 DashLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DashLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DashLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + translate 100 0 + + save + setPen black 1 DashDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 DashDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 6 DashDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DashDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DashDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + translate 100 0 + + save + setPen black 1 DashDotDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashDotDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashDotDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 DashDotDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashDotDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashDotDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 4 DashDotDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 4 DashDotDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 4 DashDotDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + translate 100 0 + + save + setPen black 1 SolidLine FlatCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 SolidLine SquareCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 SolidLine RoundCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 SolidLine FlatCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 SolidLine SquareCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 SolidLine RoundCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 4 SolidLine FlatCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 4 SolidLine SquareCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 4 SolidLine RoundCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + +restore +end_block + +translate 0 400 +setRenderHint Antialiasing +repeat_block draw + +translate 0 -20 +drawText 30 0 "Solid" + +translate 100 0 +drawText 20 0 "DotLine" + +translate 100 0 +drawText 10 0 "DashLine" + +translate 100 0 +drawText 0 0 "DashDotLine" + +translate 100 0 +drawText 0 0 "DashDotDotLine" + +translate 100 0 +drawText 0 0 "CustomDashLine" + +resetMatrix + +translate 620 40 + +begin_block width_and_caps_texts + drawText 0 0 "Width=1, FlatCap" + translate 0 40 + drawText 0 0 "Width=1, SquareCap" + translate 0 40 + drawText 0 0 "Width=1, RoundCap" + translate 0 40 + drawText 0 0 "Width=2, FlatCap" + translate 0 40 + drawText 0 0 "Width=2, SquareCap" + translate 0 40 + drawText 0 0 "Width=2, RoundCap" + translate 0 40 + drawText 0 0 "Width=6, FlatCap" + translate 0 40 + drawText 0 0 "Width=6, SqareCap" + translate 0 40 + drawText 0 0 "Width=6, RoundCap" +end_block + +translate 0 80 +repeat_block width_and_caps_texts
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/degeneratebeziers.qps b/tests/baseline/painting/scripts/degeneratebeziers.qps new file mode 100644 index 0000000000..948968b0cd --- /dev/null +++ b/tests/baseline/painting/scripts/degeneratebeziers.qps @@ -0,0 +1,47 @@ +# Version: 1 +# CheckVsReference: 5% + +path_moveTo degenerate 3427.0918499999997948 3872.1318999999998596 +path_cubicTo degenerate 3427.0918499999997948 3872.1318999999994048 4729.4590867905308187 5176.8613451144155988 5389.9325499999995372 5837.8072499999998399 + +scale 0.05 0.05 +translate -2500 -3000 +setPen black 800 +drawPath degenerate + +resetMatrix +path_moveTo revbez 0 20 +path_cubicTo revbez 0 0 120 0 120 -20 + +path_moveTo revbez 0 80 +path_cubicTo revbez 0 100 120 100 120 120 + +translate 50 250 + +setPen blue 40 solidline flatcap +drawPath revbez +setPen red 0 +drawPath revbez + +translate 200 0 +setPen blue 40 solidline squarecap +drawPath revbez +setPen red 0 +drawPath revbez + +translate 200 0 +setPen blue 40 solidline roundcap +drawPath revbez +setPen red 0 +drawPath revbez + +resetMatrix +path_lineTo tightJoin 60 10 +path_cubicTo tightJoin 50 0 100 0 100 50 + +translate 50 500 + +setPen green 40 solidline roundcap roundjoin +drawPath tightJoin +setPen red 0 +drawPath tightJoin diff --git a/tests/baseline/painting/scripts/deviceclipping.qps b/tests/baseline/painting/scripts/deviceclipping.qps new file mode 100644 index 0000000000..8608a50994 --- /dev/null +++ b/tests/baseline/painting/scripts/deviceclipping.qps @@ -0,0 +1,48 @@ +# Version: 1 +# CheckVsReference: 5% + +setBrush 0xff7f7f +setPen 0x7f0000 + +path_moveTo path -1000000 10000 +path_cubicTo path 100 100 100 150 150 400 +path_closeSubpath path + +begin_block drawing + + drawPath ellipse + + drawLine -1000000 200 200 200 + drawLine 200 -1000000 200 200 + drawLine 200 200 1000000 200 + drawLine 200 200 200 1000000 + drawLine -1000000 -1000000 200 200 + + drawPolygon [-1000000 100 100 -1000000 100 100] + drawRect 300 -500000 1000000 1000000 + + drawPath path + +end_block + +save +translate 20 20 +setBrush #0x7f7f7fff +setPen #0x7f00007f +repeat_block drawing + +translate 20 20 +setRenderHint Antialiasing +setBrush #0x7f7fff7f +setPen #0x7f007f00 +repeat_block drawing +restore + +setPen 0x00007f 2 +setRenderHint Antialiasing + +drawLine 0 -200 200 200 + +setPen 0x007f00 10 + +drawLine 0 -200 200 0
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/drawpoints.qps b/tests/baseline/painting/scripts/drawpoints.qps new file mode 100644 index 0000000000..c02cd85737 --- /dev/null +++ b/tests/baseline/painting/scripts/drawpoints.qps @@ -0,0 +1,101 @@ +# Version: 1 +# CheckVsReference: 5% + +#setRenderHint Antialiasing + +setPen red 0 solidline +begin_block points +drawPoint 00 00 +drawPoint 10 00 +drawPoint 20 00 +drawPoint 30 00 +drawPoint 40 00 +drawPoint 50 00 +drawPoint 00 10 +drawPoint 10 10 +drawPoint 20 10 +drawPoint 30 10 +drawPoint 40 10 +drawPoint 50 10 +drawPoint 00 20 +drawPoint 10 20 +drawPoint 20 20 +drawPoint 30 20 +drawPoint 40 20 +drawPoint 50 20 +drawPoint 00 30 +drawPoint 10 30 +drawPoint 20 30 +drawPoint 30 30 +drawPoint 40 30 +drawPoint 50 30 +drawPoint 00 40 +drawPoint 10 40 +drawPoint 20 40 +drawPoint 30 40 +drawPoint 40 40 +drawPoint 50 40 +drawPoint 00 50 +drawPoint 10 50 +drawPoint 20 50 +drawPoint 30 50 +drawPoint 40 50 +drawPoint 50 50 +end_block points + +translate 100 0 +setPen blue 1 solidline +repeat_block points + +translate 100 0 +setPen green 5 solidline roundcap +repeat_block points + +resetMatrix + +translate 0 100 +scale 3 3 +setPen red 0 solidline roundcap +repeat_block points + +translate 60 0 +setPen blue 1 solidline roundcap +repeat_block points + +translate 60 0 +setPen green 5 solidline roundcap +repeat_block points + +resetMatrix + +translate 0 300 +scale 3 3 +setPen red 0 solidline flatcap +repeat_block points + +translate 60 0 +setPen blue 1 solidline flatcap +repeat_block points + +translate 60 0 +setPen green 5 solidline flatcap +repeat_block points + +resetMatrix +translate 10 500 +setPen black 1 solidline flatcap +drawPoint 0 0 +setPen black 2 solidline flatcap +drawPoint 3 0 +setPen black 3 solidline flatcap +drawPoint 8 0 +setPen black 4 solidline flatcap +drawPoint 15 0 +setPen black 5 solidline flatcap +drawPoint 24 0 +setPen black 6 solidline flatcap +drawPoint 35 0 +setPen black 7 solidline flatcap +drawPoint 48 0 +setPen black 8 solidline flatcap +drawPoint 63 0
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/ellipses.qps b/tests/baseline/painting/scripts/ellipses.qps new file mode 100644 index 0000000000..e2cffd7f27 --- /dev/null +++ b/tests/baseline/painting/scripts/ellipses.qps @@ -0,0 +1,86 @@ +# Version: 1 +# CheckVsReference: 5% + + +surface_begin 0 0 600 600 +translate 0 50 + +setPen nopen +setBrush 0x7f000000 +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setRadial 20 20 220 200 + +drawEllipse 10 10 80 80 +drawEllipse 50 50 120 90 + +translate 100 0 +brushTranslate 40 20 +brushScale 0.25 0.25 + +setPen black + +drawEllipse 10 10 80 80 +setOpacity 0.5 +setCompositionMode SourceIn +drawEllipse 50 50 120 90 +setOpacity 1.0 +setRenderHint Antialiasing +setCompositionMode Xor +brushTranslate 70 0 +translate 100 0 +drawEllipse 10 10 80 80 + +setPen nopen +drawEllipse 50 50 120 90 + +setOpacity 0.7 +setBrush red +translate 100 0 +setCompositionMode SourceOver + +drawEllipse 10 10 80 80 + +setOpacity 0.6 +setPen black 5.0 +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 20 20 120 100 +drawEllipse 50 50 120 90 + + +translate 100 0 + +setOpacity 1.0 +drawEllipse 10 10 80 80 + +setCompositionMode SourceIn +setOpacity 0.7 +setPen black 3.0 +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 50 50 80 90 +drawEllipse 50 50 120 90 + +surface_end + +drawText 200 220 "Testing Ellipse drawing with varios combinations" +drawText 200 240 "of features such as brushes, pens and composition modes"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/fillrect.qps b/tests/baseline/painting/scripts/fillrect.qps new file mode 100644 index 0000000000..103ef2646a --- /dev/null +++ b/tests/baseline/painting/scripts/fillrect.qps @@ -0,0 +1,121 @@ +setRenderHint Antialiasing false + +# offscreen +translate 0 -200 + +begin_block rects +# int API +fillRect 10 10 20 20 green +fillRect 40 10 20 20 +drawRect 70 10 20 20 + +# float API, int values +fillRectF 10.0 40.0 20.0 20.0 green +fillRectF 40.0 40.0 20.0 20.0 +drawRect 70.0 40.0 20.0 20.0 + +# float API, float values +fillRectF 10.0 70.0 20.5 20.5 green +fillRectF 40.0 70.0 20.5 20.5 +drawRect 70.0 70.0 20.5 20.5 + +# alignment, int api, color +fillRect 10 100 10 10 green +fillRect 20 100 10 10 green +fillRect 10 110 10 10 green +fillRect 20 110 10 10 green + +# alignment, int api, brush +fillRect 40 100 10 10 +fillRect 50 100 10 10 +fillRect 40 110 10 10 +fillRect 50 110 10 10 + +# alignment comparison +drawRect 70 100 10 10 +drawRect 80 100 10 10 +drawRect 70 110 10 10 +drawRect 80 110 10 10 + +# alignment, float api, color +fillRectF 10.0 130.0 10.0 10.0 green +fillRectF 20.0 130.0 10.0 10.0 green +fillRectF 10.0 140.0 10.0 10.0 green +fillRectF 20.0 140.0 10.0 10.0 green + +# alignment, float api, brush +fillRectF 40.0 130.0 10.0 10.0 +fillRectF 50.0 130.0 10.0 10.0 +fillRectF 40.0 140.0 10.0 10.0 +fillRectF 50.0 140.0 10.0 10.0 + +# alignment comparison +drawRect 70.0 130.0 10.0 10.0 +drawRect 80.0 130.0 10.0 10.0 +drawRect 70.0 140.0 10.0 10.0 +drawRect 80.0 140.0 10.0 10.0 + +end_block + +begin_block row + +repeat_block rects + +save +translate 100.2 0.2 +repeat_block rects +restore + +save +translate 200.5 0.5 +repeat_block rects +restore + +save +translate 300.7 0.7 +repeat_block rects +restore + +end_block + +# end of block defs + +resetMatrix + +setPen NoPen +setBrush green +repeat_block row + +save +translate 500 50 +scale 0.42 0.42 +repeat_block row +restore + +save +translate 0 160 +scale 1.8 0.8 +repeat_block row +restore + +save +translate 650 320 +rotate 80 +repeat_block row +restore + +save +setBrush green Dense2Pattern +translate 0 400 +repeat_block row +restore + +save +gradient_clearStops +gradient_appendStop 0 green +gradient_appendStop 1 blue +gradient_setCoordinateMode ObjectBoundingMode +gradient_setLinear 0.0 0.0 1.0 1.0 +translate 0 600 +repeat_block row +restore diff --git a/tests/baseline/painting/scripts/fillrect_aa.qps b/tests/baseline/painting/scripts/fillrect_aa.qps new file mode 100644 index 0000000000..3232899661 --- /dev/null +++ b/tests/baseline/painting/scripts/fillrect_aa.qps @@ -0,0 +1,121 @@ +setRenderHint Antialiasing true + +# offscreen +translate 0 -200 + +begin_block rects +# int API +fillRect 10 10 20 20 green +fillRect 40 10 20 20 +drawRect 70 10 20 20 + +# float API, int values +fillRectF 10.0 40.0 20.0 20.0 green +fillRectF 40.0 40.0 20.0 20.0 +drawRect 70.0 40.0 20.0 20.0 + +# float API, float values +fillRectF 10.0 70.0 20.5 20.5 green +fillRectF 40.0 70.0 20.5 20.5 +drawRect 70.0 70.0 20.5 20.5 + +# alignment, int api, color +fillRect 10 100 10 10 green +fillRect 20 100 10 10 green +fillRect 10 110 10 10 green +fillRect 20 110 10 10 green + +# alignment, int api, brush +fillRect 40 100 10 10 +fillRect 50 100 10 10 +fillRect 40 110 10 10 +fillRect 50 110 10 10 + +# alignment comparison +drawRect 70 100 10 10 +drawRect 80 100 10 10 +drawRect 70 110 10 10 +drawRect 80 110 10 10 + +# alignment, float api, color +fillRectF 10.0 130.0 10.0 10.0 green +fillRectF 20.0 130.0 10.0 10.0 green +fillRectF 10.0 140.0 10.0 10.0 green +fillRectF 20.0 140.0 10.0 10.0 green + +# alignment, float api, brush +fillRectF 40.0 130.0 10.0 10.0 +fillRectF 50.0 130.0 10.0 10.0 +fillRectF 40.0 140.0 10.0 10.0 +fillRectF 50.0 140.0 10.0 10.0 + +# alignment comparison +drawRect 70.0 130.0 10.0 10.0 +drawRect 80.0 130.0 10.0 10.0 +drawRect 70.0 140.0 10.0 10.0 +drawRect 80.0 140.0 10.0 10.0 + +end_block + +begin_block row + +repeat_block rects + +save +translate 100.2 0.2 +repeat_block rects +restore + +save +translate 200.5 0.5 +repeat_block rects +restore + +save +translate 300.7 0.7 +repeat_block rects +restore + +end_block + +# end of block defs + +resetMatrix + +setPen NoPen +setBrush green +repeat_block row + +save +translate 500 50 +scale 0.42 0.42 +repeat_block row +restore + +save +translate 0 160 +scale 1.8 0.8 +repeat_block row +restore + +save +translate 650 320 +rotate 80 +repeat_block row +restore + +save +setBrush green Dense2Pattern +translate 0 400 +repeat_block row +restore + +save +gradient_clearStops +gradient_appendStop 0 green +gradient_appendStop 1 blue +gradient_setCoordinateMode ObjectBoundingMode +gradient_setLinear 0.0 0.0 1.0 1.0 +translate 0 600 +repeat_block row +restore diff --git a/tests/baseline/painting/scripts/filltest.qps b/tests/baseline/painting/scripts/filltest.qps new file mode 100644 index 0000000000..112ffc85be --- /dev/null +++ b/tests/baseline/painting/scripts/filltest.qps @@ -0,0 +1,413 @@ +# Version: 1 +# CheckVsReference: 5% + +setPen nopen +setBrush red +translate 0 4 +begin_block polys +drawPolygon [0 0 2 -2 4 0] +drawPolygon [0 2 2 4 4 2] +end_block polys +translate 6 .5 +repeat_block polys +translate 6.5 0 +repeat_block polys +translate 6 .5 +repeat_block polys + +resetMatrix + +translate 0 12 +setPen black +drawPolygon [0 0 5 0 5 5 0 5] + +translate 10 0 +setPen nopen +drawPolygon [0 0 5 0 5 5 0 5] + +translate 10 0 +drawPolygon [0 0 5 0 5 5 0 5] + +setBrush black +path_addRect stroke -.5 -.5 6 6 +path_addRect stroke .5 .5 4 4 +drawPath stroke + +resetMatrix + +translate 0 65 + +setPen red +drawText 0 0 "path" +drawText 40 0 "rect" +drawText 80 0 "img" +drawText 120 0 "pix" +drawText 160 0 "brush" +setPen nopen + +translate 0 5 + +image_load border.png img +pixmap_load border.png pix + +path_addRect rect 0 0 10 10 +begin_block rects +drawPath rect +drawRect 40 0 10 10 +drawImage img 80 0 +drawPixmap pix 120 0 +setBrush border.png +drawRect 160 0 10 10 +setBrush black +end_block rects + +setPen red +drawText 180 10 "0.0" +setPen nopen + +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.1" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.2" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.3" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.4" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.5" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.6" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.7" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.8" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.9" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "1.0" +setPen nopen + +resetMatrix + +translate 0 400 + +setPen red +drawText 0 10 "path" +drawText 0 30 "rect" +drawText 0 50 "img" +drawText 0 70 "pix" +drawText 0 90 "brush" +drawText 0 110 "stroke" +drawText 0 130 "scale" +drawText 0 170 "rotate" +setPen nopen + +translate 50 0 + +begin_block rects2 +drawPath rect +drawRect 0 20 10 10 +drawImage img 0 40 +drawPixmap pix 0 60 +save +setBrush border.png +drawRect 0 80 10 10 +translate 0 100 +setBrush red +setPen black +drawRect 0 0 10 10 +setBrush border.png +setPen nopen +translate 0 20 +scale 2 2 +drawRect 0 0 10 10 +translate 10 20 +rotate 90 +drawRect 0 0 10 10 +restore +end_block rects2 + +setPen red +drawText -5 -10 "0.0" +setPen nopen + +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.1" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.2" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.3" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.4" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.5" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.6" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.7" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.8" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "0.9" +setPen nopen +translate 40 0.1 +repeat_block rects2 +setPen red +drawText -5 -10 "1.0" +setPen nopen + +resetMatrix + +translate 0 620 + +setPen red +drawText 0 10 "path" +setPen nopen + +path_addRect rect2 -5 -5 10 10 + +translate 55 5 +drawPath rect2 + +translate 20 0 +rotate 10 +drawPath rect2 +rotate -10 +translate 20 0 +rotate 20 +drawPath rect2 +rotate -20 +translate 20 0 +rotate 30 +drawPath rect2 +rotate -30 +translate 20 0 +rotate 40 +drawPath rect2 +rotate -40 +translate 20 0 +rotate 50 +drawPath rect2 +rotate -50 +translate 20 0 +rotate 60 +drawPath rect2 +rotate -60 +translate 20 0 +rotate 70 +drawPath rect2 +rotate -70 +translate 20 0 +rotate 80 +drawPath rect2 +rotate -80 +translate 20 0 +rotate 90 +drawPath rect2 +rotate -90 + +resetMatrix + +translate 0 600 + +setPen red +drawText 0 10 "rect" +setPen nopen + +translate 55 5 +drawRect -5 -5 10 10 + +translate 20 0 +rotate 10 +drawRect -5 -5 10 10 +rotate -10 +translate 20 0 +rotate 20 +drawRect -5 -5 10 10 +rotate -20 +translate 20 0 +rotate 30 +drawRect -5 -5 10 10 +rotate -30 +translate 20 0 +rotate 40 +drawRect -5 -5 10 10 +rotate -40 +translate 20 0 +rotate 50 +drawRect -5 -5 10 10 +rotate -50 +translate 20 0 +rotate 60 +drawRect -5 -5 10 10 +rotate -60 +translate 20 0 +rotate 70 +drawRect -5 -5 10 10 +rotate -70 +translate 20 0 +rotate 80 +drawRect -5 -5 10 10 +rotate -80 +translate 20 0 +rotate 90 +drawRect -5 -5 10 10 +rotate -90 + +resetMatrix +path_addRect vertical 0.1 0.1 0.2 10 + +translate 0 320 +drawPath vertical +translate 2.2 0 +drawPath vertical +translate 2.2 0 +drawPath vertical +translate 2.2 0 +drawPath vertical +translate 2.2 0 +drawPath vertical + +resetMatrix +path_addRect horizontal 0.1 0.1 10 0.2 + +translate 0 340 +drawPath horizontal +translate 0 2.2 +drawPath horizontal +translate 0 2.2 +drawPath horizontal +translate 0 2.2 +drawPath horizontal +translate 0 2.2 +drawPath horizontal + +setOpacity 0.8 +resetMatrix + +translate 0.1 24.7 +translate 400 0 +#rotate 88.8 +rotate 89.9 +setBrush red +drawPolygon [0 0 300 0 0 173] +setBrush green +drawPolygon [0 173 300 0 300 173] + +resetMatrix + +translate 410 24 +path_lineTo left 0 273 +path_lineTo left 300 273 +path_cubicTo left 50 273 250 0 0 0 + +path_cubicTo right 250 0 50 273 300 273 +path_lineTo right 300 0 + +translate 310 0 +rotate 90 +setBrush red +drawPath left +setBrush green +drawPath right + +resetMatrix +translate 0.1 680.1 +setPen red +setOpacity 1 +drawText 115 -20 "0.1" +drawText 0 0 "pixmap w/ opacity" +setOpacity 0.6 +drawPixmap pix 120 -10 +translate 0 20 +setOpacity 1 +drawText 0 0 "image w/ opacity" +setOpacity 0.6 +drawImage img 120 -10 + +resetMatrix +path_lineTo fillpath 0 50 +path_lineTo fillpath 50 50 +path_moveTo fillpath 70 50 +path_lineTo fillpath 70 100 +path_lineTo fillpath 40 100 +translate 500 400 +drawPath fillpath + +resetMatrix +path_moveTo vectorarne 50 10 +path_lineTo vectorarne 50 50 +path_lineTo vectorarne 100 50 +path_addEllipse vectorarne 350 20 230 230 +path_moveTo vectorarne 500 500 +path_cubicTo vectorarne 20 20 250 30 50 150 +translate 500 550 +scale 0.4 0.4 +setRenderHint antialiasing +drawPath vectorarne + +resetMatrix +translate 200 730 +setRenderHint antialiasing off +setOpacity 1 +setPen red +drawText 0 0 "outline/fill consistency" +setPen red +setBrush green +translate 80 -30 +drawPolygon [13.6965 -99.1837 -71.4767 13.823 32.4596 -33.1847] diff --git a/tests/baseline/painting/scripts/glyphruns.qps b/tests/baseline/painting/scripts/glyphruns.qps new file mode 100644 index 0000000000..2b70c72610 --- /dev/null +++ b/tests/baseline/painting/scripts/glyphruns.qps @@ -0,0 +1,175 @@ +drawGlyphRun -5 5 "Text that is drawn outside the bounds..." + +translate 20 20 +begin_block text_drawing +save + setFont "sansserif" 10 normal + drawGlyphRun 0 20 "sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawGlyphRun 0 40 "sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawGlyphRun 0 60 "sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawGlyphRun 0 80 "sansserif 10pt, bold italic" + + + translate 0 100 + setPen #7fff0000 + + setFont "sansserif" 10 normal + drawGlyphRun 0 20 "alpha sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawGlyphRun 0 40 "alpha sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawGlyphRun 0 60 "alpha sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawGlyphRun 0 80 "alpha sansserif 10pt, bold italic" + + + translate 0 100 + setPen black + save + scale 0.9 0.9 + + setFont "sansserif" 10 normal + drawGlyphRun 0 20 "scaled sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawGlyphRun 0 40 "scaled sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawGlyphRun 0 60 "scaled sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawGlyphRun 0 80 "scaled sansserif 10pt, bold italic" + restore + + translate 200 200 + setPen black + save + scale -1 -1 + + setFont "sansserif" 10 normal + drawGlyphRun 0 20 "flipped sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawGlyphRun 0 40 "flipped sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawGlyphRun 0 60 "flipped sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawGlyphRun 0 80 "flipped sansserif 10pt, bold italic" + restore + + translate -200 20 + setPen black + save + translate 200 90 + rotate 185 + + setFont "sansserif" 10 normal + drawGlyphRun 0 20 "rotated sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawGlyphRun 0 40 "rotated sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawGlyphRun 0 60 "rotated sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawGlyphRun 0 80 "rotated sansserif 10pt, bold italic" + restore + + translate 0 100 + gradient_appendStop 0 red + gradient_appendStop 0.5 #00ff00 + gradient_appendStop 1 blue + gradient_setLinear 0 0 200 0 + setPen brush + + setFont "sansserif" 10 normal + drawGlyphRun 0 0 "gradient sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawGlyphRun 0 20 "gradient sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawGlyphRun 0 40 "gradient sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawGlyphRun 0 60 "gradient sansserif 10pt, bold italic" +restore +end_block + +translate 250 0 +drawGlyphRun 25 640 "clipped to rectangle" +save + setPen #3f000000 + setBrush nobrush + drawRect 20 0 100 620 + setClipRect 20 0 100 620 + setPen black + repeat_block text_drawing +restore + +translate 150 0 +drawGlyphRun 25 640 "clipped to path" +save + path_moveTo clip 20 0 + path_cubicTo clip 0 200 40 400 20 400 + path_lineTo clip 30 620 + path_lineTo clip 30 0 + path_lineTo clip 40 0 + path_lineTo clip 40 620 + path_lineTo clip 120 620 + path_lineTo clip 120 0 + path_lineTo clip 20 0 + setPen #3f000000 + setBrush nobrush + drawPath clip + setClipPath clip + setPen black + repeat_block text_drawing +restore + +translate 150 0 +save + setPen black + setFont "sansserif" 16 normal + drawGlyphRun 0 40 "e😃m😇o😍j😜i😸!" +restore + +translate 0 55 +save + setPen black + setFont "sansserif" 12 normal normal default underline + drawGlyphRun 0 20 "Underlined text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default normal strikeout + drawGlyphRun 0 20 "Struck out text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default normal normal overline + drawGlyphRun 0 20 "Overlined text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default underline strikeout overline + drawGlyphRun 0 20 "All the effects text drawing" +restore diff --git a/tests/baseline/painting/scripts/gradients.qps b/tests/baseline/painting/scripts/gradients.qps new file mode 100644 index 0000000000..eb3cda9cad --- /dev/null +++ b/tests/baseline/painting/scripts/gradients.qps @@ -0,0 +1,44 @@ +# Version: 1 +# CheckVsReference: 5% + +drawText 75 20 "Linear" +drawText 176 20 "Radial" +drawText 277 20 "Conical" +translate 0 30 +drawText 0 50 "AA off" +drawText 0 151 "AA on" + +setPen nopen + +gradient_clearStops +gradient_appendStop 0 0x00000000 +gradient_appendStop 0.001 red +gradient_appendStop 0.2 blue +gradient_appendStop 0.4 yellow +gradient_appendStop 0.6 cyan +gradient_appendStop 0.8 green +gradient_appendStop 0.999 red +gradient_appendStop 1 0x00000000 + +gradient_setSpread PadSpread +gradient_setCoordinateMode ObjectBoundingMode + +begin_block row +save +gradient_setLinear 0.1 0.0 0.9 0.0 +drawRect 50 0 100 100 + +gradient_setRadial 0.5 0.5 0.5 0.5 0.5 +translate 101 0 +drawRect 50 0 100 100 + +gradient_setConical 0.5 0.5 45 +translate 101 0 +drawRect 50 0 100 100 +restore +end_block row + +setRenderHint Antialiasing + +translate 0 101 +repeat_block row
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/gradientxform_device.qps b/tests/baseline/painting/scripts/gradientxform_device.qps new file mode 100644 index 0000000000..cd8b55d5b6 --- /dev/null +++ b/tests/baseline/painting/scripts/gradientxform_device.qps @@ -0,0 +1,67 @@ +# Version: 1 +# CheckVsReference: 5% + +gradient_clearStops +gradient_appendStop 0 black +gradient_appendStop 0.4 yellow +gradient_appendStop 1 gray + +gradient_setSpread PadSpread + +gradient_setCoordinateMode StretchToDeviceMode + +# first run is dummy, make it offscreen +save +translate -500 -500 + +begin_block row +save + +setPen nopen +drawRect 50 0 100 100 + +setPen brush 30 +setBrush lightblue +drawRect 175 15 70 70 + +setFont "times" 110 1000 +drawText 270 100 "X" + +restore +end_block row + +restore + +drawText 160 20 "PLAIN" +drawText 560 20 "BRUSH XFORM" +translate 0 20 + +begin_block block +save + +drawText 75 20 "Brush Fill" +drawText 176 20 "Pen Stroke" +drawText 277 20 "Text Stroke" +translate 0 30 +drawText 0 50 "Linear" +drawText 0 160 "Radial" +drawText 0 270 "Conical" + +gradient_setLinear 0.0 0.0 0.4 0.0 +repeat_block row + +translate 0 110 +gradient_setRadial 0.04 0.08 0.3 0.3 0.05 +repeat_block row + +translate 0 110 +gradient_setConical 0.25 0.1 45 +repeat_block row +restore +end_block block + +translate 400 0 +brushRotate 30.0 +brushScale 1.5 .5 +brushTranslate 0 -80 +repeat_block block diff --git a/tests/baseline/painting/scripts/gradientxform_logical.qps b/tests/baseline/painting/scripts/gradientxform_logical.qps new file mode 100644 index 0000000000..1bba63a929 --- /dev/null +++ b/tests/baseline/painting/scripts/gradientxform_logical.qps @@ -0,0 +1,67 @@ +# Version: 1 +# CheckVsReference: 5% + +gradient_clearStops +gradient_appendStop 0 black +gradient_appendStop 0.4 yellow +gradient_appendStop 1 gray + +gradient_setSpread PadSpread + +gradient_setCoordinateMode LogicalMode + +# first run is dummy, make it offscreen +save +translate -500 -500 + +begin_block row +save + +setPen nopen +drawRect 50 0 100 100 + +setPen brush 30 +setBrush lightblue +drawRect 175 15 70 70 + +setFont "times" 110 1000 +drawText 270 100 "X" + +restore +end_block row + +restore + +drawText 160 20 "PLAIN" +drawText 560 20 "BRUSH XFORM" +translate 0 20 + +begin_block block +save + +drawText 75 20 "Brush Fill" +drawText 176 20 "Pen Stroke" +drawText 277 20 "Text Stroke" +translate 0 30 +drawText 0 50 "Linear" +drawText 0 160 "Radial" +drawText 0 270 "Conical" + +gradient_setLinear 0 0 400 0 +repeat_block row + +translate 0 110 +gradient_setRadial 200 50 140 70 20 +repeat_block row + +translate 0 110 +gradient_setConical 220 60 45 +repeat_block row +restore +end_block block + +translate 400 0 +brushRotate 30.0 +brushScale 1.5 .5 +brushTranslate 0 -80 +repeat_block block diff --git a/tests/baseline/painting/scripts/gradientxform_object.qps b/tests/baseline/painting/scripts/gradientxform_object.qps new file mode 100644 index 0000000000..e34da24d46 --- /dev/null +++ b/tests/baseline/painting/scripts/gradientxform_object.qps @@ -0,0 +1,83 @@ +# Version: 1 +# CheckVsReference: 5% + +gradient_clearStops +gradient_appendStop 0 black +gradient_appendStop 0.4 yellow +gradient_appendStop 1 gray + +gradient_setSpread PadSpread + +gradient_setCoordinateMode ObjectBoundingMode + +# first run is dummy, make it offscreen +save +translate -500 -500 + +begin_block row +save + +setPen nopen +drawRect 50 0 100 100 + +setPen brush 30 +setBrush lightblue +translate 110 0 +drawRect 65 15 70 70 + +translate 110 0 +setFont "times" 110 1000 +drawText 50 100 "X" + +restore +end_block row + +restore + +drawText 160 20 "PLAIN" +drawText 560 20 "BRUSH XFORM" +translate 0 20 + +begin_block block +save + +drawText 75 20 "Brush Fill" +drawText 176 20 "Pen Stroke" +drawText 277 20 "Text Stroke" +translate 0 30 +drawText 0 50 "Linear" +drawText 0 160 "Radial" +drawText 0 270 "Conical" + +gradient_setLinear 0.1 0.0 0.5 0.0 +repeat_block row + +translate 0 110 +gradient_setRadial 0.3 0.2 0.5 0.4 0.5 +repeat_block row + +translate 0 110 +gradient_setConical 0.5 0.7 45 +repeat_block row +restore +end_block block + +save +translate 400 0 +brushRotate 30.0 +brushScale 1.5 .5 +repeat_block block +restore + +drawText 80 400 "BRUSH XFORM, OBJECT BOUNDING MODE" +drawText 500 400 "BRUSH XFORM, OBJECT MODE" + +translate 0 400 +brushTranslate 0.5 0.5 +brushRotate 180.0 +brushTranslate -0.5 -0.5 +repeat_block block + +translate 400 0 +gradient_setCoordinateMode ObjectMode +repeat_block block diff --git a/tests/baseline/painting/scripts/hinting.qps b/tests/baseline/painting/scripts/hinting.qps new file mode 100644 index 0000000000..7ce21b287a --- /dev/null +++ b/tests/baseline/painting/scripts/hinting.qps @@ -0,0 +1,26 @@ +translate 10 50 +setFont "sansserif" 10 +drawText 0 0 "Default hinting:" +setFont "times" 12 normal normal default +drawText 0 20 "The quick brown fox jumps over the lazy dog" + +translate 0 50 +setFont "sansserif" 10 +drawText 0 0 "No hinting:" +setFont "times" 12 normal normal none +drawText 0 20 "The quick brown fox jumps over the lazy dog" + +translate 0 50 +setFont "sansserif" 10 +drawText 0 0 "Vertical hinting:" +setFont "times" 12 normal normal vertical +drawText 0 20 "The quick brown fox jumps over the lazy dog" + +translate 0 50 +setFont "sansserif" 10 +drawText 0 0 "Full hinting:" +setFont "times" 12 normal normal full +drawText 0 20 "The quick brown fox jumps over the lazy dog" + + +# Note: there is also the textlayout_draw command which might be interesting here. diff --git a/tests/baseline/painting/scripts/image_dpr.qps b/tests/baseline/painting/scripts/image_dpr.qps new file mode 100644 index 0000000000..7d3ca3099c --- /dev/null +++ b/tests/baseline/painting/scripts/image_dpr.qps @@ -0,0 +1,43 @@ + +setRenderHint Antialiasing true +setRenderHint SmoothPixmapTransform true + +image_load sign.png img1 +pixmap_load sign.png pix1 + +begin_block drawIt +save + +drawImage img1 20 20 -1 -1 +drawRect 17.5 17.5 85 85 + +setBrush img1 +setPen NoPen +drawRect 20 120 120 120 + +brushRotate 45 +drawRect 20 260 120 120 + +setBrush NoBrush +drawTiledPixmap pix1 20 400 120 120 + +restore +end_block + +save +translate 150 0 +rotate -5 +repeat_block drawIt +restore + +image_setDevicePixelRatio img1 2.0 +pixmap_setDevicePixelRatio pix1 2.0 +translate 400 0 +repeat_block drawIt + +save +translate 150 0 +rotate -5 +repeat_block drawIt +restore + diff --git a/tests/baseline/painting/scripts/image_formats.qps b/tests/baseline/painting/scripts/image_formats.qps new file mode 100644 index 0000000000..d817d04bf8 --- /dev/null +++ b/tests/baseline/painting/scripts/image_formats.qps @@ -0,0 +1,81 @@ +# Version: 1 +# CheckVsReference: 5% + + +image_load dome_argb32.png the_pixmap +image_convertToFormat the_pixmap the_pixmap ARGB32_Premultiplied + +begin_block draw_stuff + save + image_convertToFormat the_pixmap converted ARGB32_Premultiplied + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted ARGB32 + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted RGB32 + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted Indexed8 + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted MonoLSB + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted Mono + drawImage converted 0 0 + translate 0 110 + restore +end_block + + +image_load dome_argb32.png the_pixmap +translate 110 0 +repeat_block draw_stuff + + +image_load dome_rgb32.png the_pixmap +translate 110 0 +repeat_block draw_stuff + +image_load dome_indexed.png the_pixmap +translate 110 0 +repeat_block draw_stuff + + +image_load dome_mono.png the_pixmap +translate 110 0 +repeat_block draw_stuff + +image_load dome_mono_palette.png the_pixmap +translate 110 0 +repeat_block draw_stuff + +image_load dome_indexed_mask.png the_pixmap +translate 110 0 +repeat_block draw_stuff + + +# helpful texts +resetMatrix +setPen black + +drawText 10 670 "ARGB32_PM" +drawText 120 670 "ARGB32" +drawText 230 670 "RGB32" +drawText 340 670 "Indexed" +drawText 450 670 "Mono" +drawText 560 670 "Mono w/lut" +drawText 670 670 "Indexed w/mask" + +drawText 770 50 "ARGB32_PM" +drawText 770 160 "ARGB32" +drawText 770 270 "RGB32" +drawText 770 380 "Indexed" +drawText 770 490 "MonoLSB" +drawText 770 600 "Mono"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/images.qps b/tests/baseline/painting/scripts/images.qps new file mode 100644 index 0000000000..3f892400e2 --- /dev/null +++ b/tests/baseline/painting/scripts/images.qps @@ -0,0 +1,106 @@ +# Version: 1 +# CheckVsReference: 5% + + +setRenderHint Antialiasing + +setPen #00ff00 + +image_load dome_argb32.png the_image +begin_block draw_stuff + +save + + # standard draw + drawImage the_image 0 0 + + # sub recting + translate 120 0 + drawImage the_image 0 0 40 40 0 0 40 40 + drawImage the_image 60 0 40 40 60 0 40 40 + drawImage the_image 0 60 40 40 0 60 40 40 + drawImage the_image 60 60 40 40 60 60 40 40 + drawImage the_image 0 40 40 20 0 40 40 20 + drawImage the_image 60 40 40 20 60 40 40 20 + drawImage the_image 40 0 20 100 40 0 20 100 + + # subrecting w/scale + translate 120 0 + drawImage the_image 0 0 50 50 0 0 25 25 + drawImage the_image 50 0 50 50 25 0 25 25 + drawImage the_image 0 50 50 50 0 25 25 25 + drawImage the_image 50 50 50 50 25 25 25 25 + + # subrecting w/scale & smooth xform + translate 120 0 + setRenderHint SmoothPixmapTransformation + drawImage the_image 0 0 50 50 0 0 25 25 + drawImage the_image 50 0 50 50 25 0 25 25 + drawImage the_image 0 50 50 50 0 25 25 25 + drawImage the_image 50 50 50 50 25 25 25 25 + + + # Rotation w/o smooth xform + translate 120 0 + save + setRenderHint SmoothPixmapTransform off + rotate 10 + drawImage the_image 0 0 + restore + + # Rotation w smooth xform + translate 120 0 + save + setRenderHint SmoothPixmapTransform + rotate 10 + drawImage the_image 0 0 + restore + +restore + +end_block + + +translate 0 120 +image_load dome_rgb32.png the_image +repeat_block draw_stuff + +translate 0 120 +image_load dome_indexed.png the_image +repeat_block draw_stuff + +translate 0 120 +image_load dome_indexed_mask.png the_image +repeat_block draw_stuff + +translate 0 120 +image_load dome_mono.png the_image +repeat_block draw_stuff + + +resetMatrix +translate 700 60 +setPen black +drawText 0 0 "32 bit w/alpha" +translate 0 120 +drawText 0 0 "32 bit w/o alpha" +translate 0 120 +drawText 0 0 "8 bit indexed" +translate 0 120 +drawText 0 0 "8 bit indexed w/mask" +translate 0 120 +drawText 0 0 "1 bit" +resetMatrix +translate 0 600 +drawText 0 0 "normal" +translate 120 0 +drawText 0 0 "subrect" +translate 120 0 +drawText 0 0 "subrect scale" +translate 120 0 +drawText 0 0 "subrect scale smooth" +translate 120 0 +drawText 0 0 "xform" +translate 120 0 +drawText 0 0 "smooth xform" +translate 120 0
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/images2.qps b/tests/baseline/painting/scripts/images2.qps new file mode 100644 index 0000000000..5159abc928 --- /dev/null +++ b/tests/baseline/painting/scripts/images2.qps @@ -0,0 +1,145 @@ +# Version: 1 +# CheckVsReference: 5% + +image_load dome_argb32.png the_image +begin_block draw_stuff + +save + # standard draw + drawImage the_image 0 0 + + # flip x + translate 220 0 + scale -1 1 + drawImage the_image 0 0 + scale -1 1 + + # flip y + translate 20 100 + scale 1 -1 + drawImage the_image 0 0 + scale 1 -1 + + # flip x and y + translate 220 0 + scale -1 -1 + drawImage the_image 0 0 + scale -1 -1 + + # flip y and scale + translate 20 10 + save + scale 1 -1.1 + drawImage the_image 0 0 + restore + + # flip y and scale + translate 220 -110 + save + scale -1.1 0.9 + drawImage the_image 0 0 + restore +restore +end_block + +setRenderHint Antialiasing + +resetMatrix +translate 0 120 +repeat_block draw_stuff + +resetMatrix +translate 720 60 +setPen black +drawText 0 0 "aliased" +translate 0 120 +drawText 0 0 "antialiased" +resetMatrix +translate 0 260 +drawText 0 0 "normal" +translate 120 0 +drawText 0 0 "flip x" +translate 120 0 +drawText 0 0 "flip y" +translate 120 0 +drawText 0 0 "flip x and y" +translate 120 0 +drawText 0 0 "flip y and scale" +translate 120 0 +drawText 0 0 "flip x and scale" +translate 120 0 + +setRenderHint SmoothPixmapTransform + +resetMatrix +translate 20 300 +drawImage border.png 0 0 100 100 1 1 8 8 +drawText 0 -5 "subrect color bleeding" +translate 0 120 +drawImage border.png 0 0 100 100 0 0 10 10 + +image_load sign.png the_image +resetMatrix +drawText 240 300 "drawImage() with varying sx/sy offsets" +translate 0 10 +drawRect 240 300 50 50 +drawImage the_image 240 300 50 50 20 0 80 80 +drawRect 300 300 50 50 +drawImage the_image 300 300 50 50 -20 0 80 80 +drawRect 240 370 50 50 +drawImage the_image 240 370 50 50 0 20 80 80 +drawRect 300 370 50 50 +drawImage the_image 300 370 50 50 0 -20 80 80 + +pixmap_load sign.png the_pixmap +translate 220 0 +translate 0 -10 +drawText 240 300 "drawPixmap() with varying sx/sy offsets" +translate 0 10 +drawRect 240 300 50 50 +drawPixmap the_pixmap 240 300 50 50 20 0 80 80 +drawRect 300 300 50 50 +drawPixmap the_pixmap 300 300 50 50 -20 0 80 80 +drawRect 240 370 50 50 +drawPixmap the_pixmap 240 370 50 50 0 20 80 80 +drawRect 300 370 50 50 +drawPixmap the_pixmap 300 370 50 50 0 -20 80 80 + + +resetMatrix +translate 0 170 +drawText 240 300 "drawImage() with varying sx/sy offsets" +translate 0 10 +drawRect 240 300 50 50 +drawImage the_image 240 300 50 50 50 0 50 50 +drawRect 300 300 50 50 +drawImage the_image 300 300 50 50 -20 0 50 50 +drawRect 240 370 50 50 +drawImage the_image 240 370 50 50 0 50 50 50 +drawRect 300 370 50 50 +drawImage the_image 300 370 50 50 0 -20 50 50 + +resetMatrix +translate 220 170 +drawText 240 300 "drawPixmap() with varying sx/sy offsets" +translate 0 10 +drawRect 240 300 50 50 +drawPixmap the_pixmap 240 300 50 50 50 0 50 50 +drawRect 300 300 50 50 +drawPixmap the_pixmap 300 300 50 50 -20 0 50 50 +drawRect 240 370 50 50 +drawPixmap the_pixmap 240 370 50 50 0 50 50 50 +drawRect 300 370 50 50 +drawPixmap the_pixmap 300 370 50 50 0 -20 50 50 + +resetMatrix +drawText 10 620 "drawImage/Pixmap() with negative x/y and sx/sy" +setPen red + +translate 20 640 +drawImage the_image -10 -10 -1 -1 -10 -10 0 0 +drawRect 0 0 80 80 + +translate 100 0 +drawPixmap the_pixmap -10 -10 -1 -1 -10 -10 0 0 +drawRect 0 0 80 80 diff --git a/tests/baseline/painting/scripts/join_cap_styles.qps b/tests/baseline/painting/scripts/join_cap_styles.qps new file mode 100644 index 0000000000..ed823f53f5 --- /dev/null +++ b/tests/baseline/painting/scripts/join_cap_styles.qps @@ -0,0 +1,63 @@ +# Version: 1 +# CheckVsReference: 5% + + +setRenderHint Antialiasing + +path_moveTo p 20 20 +path_cubicTo p 100 20 100 180 180 100 +path_lineTo p 20 180 +path_lineTo p 180 20 + +setPen black 20 solidline roundcap roundjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline roundcap miterjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline roundcap beveljoin +drawPath p +setPen red +drawPath p + +translate -400 200 +setPen black 20 solidline squarecap roundjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline squarecap miterjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline squarecap beveljoin +drawPath p +setPen red +drawPath p + +translate -400 200 +setPen black 20 solidline flatcap roundjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline flatcap miterjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline flatcap beveljoin +drawPath p +setPen red +drawPath p
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/join_cap_styles_duplicate_control_points.qps b/tests/baseline/painting/scripts/join_cap_styles_duplicate_control_points.qps new file mode 100644 index 0000000000..96405ceae7 --- /dev/null +++ b/tests/baseline/painting/scripts/join_cap_styles_duplicate_control_points.qps @@ -0,0 +1,68 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 600 650) + + +setRenderHint Antialiasing + +path_moveTo p 40 70 +path_lineTo p 20 70 +path_cubicTo p 20 70 40 20 80 80 + +path_moveTo p 20 120 +path_cubicTo p 50 60 80 110 80 110 +path_lineTo p 60 110 + +scale 2 2 + +setPen black 10 solidline roundcap roundjoin +drawPath p +setPen red 0 +drawPath p + +translate 100 0 +setPen black 10 solidline roundcap miterjoin +drawPath p +setPen red 0 +drawPath p + +translate 100 0 +setPen black 10 solidline roundcap beveljoin +drawPath p +setPen red 0 +drawPath p + +translate -200 100 +setPen black 10 solidline squarecap roundjoin +drawPath p +setPen red 0 +drawPath p + +translate 100 0 +setPen black 10 solidline squarecap miterjoin +drawPath p +setPen red 0 +drawPath p + +translate 100 0 +setPen black 10 solidline squarecap beveljoin +drawPath p +setPen red 0 +drawPath p + +translate -200 100 +setPen black 10 solidline flatcap roundjoin +drawPath p +setPen red 0 +drawPath p + +translate 100 0 +setPen black 10 solidline flatcap miterjoin +drawPath p +setPen red 0 +drawPath p + +translate 100 0 +setPen black 10 solidline flatcap beveljoin +drawPath p +setPen red 0 +drawPath p
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/linear_gradients.qps b/tests/baseline/painting/scripts/linear_gradients.qps new file mode 100644 index 0000000000..b1b8dd69e7 --- /dev/null +++ b/tests/baseline/painting/scripts/linear_gradients.qps @@ -0,0 +1,144 @@ +# Version: 1 +# CheckVsReference: 2% (0 0 600 750) + +path_addRect path 400 0 80 80 +path_addEllipse path 440 40 60 60 + +setRenderHint Antialiasing + +setPen black + +begin_block gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 20 20 70 70 +drawRect 0 0 100 100 + +gradient_setSpread ReflectSpread +gradient_setLinear 120 20 170 70 +drawEllipse 100 0 100 100 + +gradient_setSpread RepeatSpread +gradient_setLinear 220 20 270 70 +drawRoundRect 200 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setSpread PadSpread +gradient_setLinear 320 20 340 40 +drawPolygon [300 0 390 0 350 99] + +gradient_setSpread ReflectSpread +gradient_setLinear 420 20 440 40 +drawPath path + +gradient_setSpread RepeatSpread +gradient_setLinear 520 20 540 40 +drawPie 500 0 100 100 720 4320 +end_block + +translate 0 100 +scale 1 2 +repeat_block gradients + +resetMatrix +translate 0 300 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block gradients + +# Vertical gradient tests +resetMatrix +setBrush noBrush +translate 0 400 + +begin_block vertical_gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 20 20 20 70 +drawRect 0 0 100 100 + +gradient_setSpread ReflectSpread +gradient_setLinear 120 20 120 70 +drawEllipse 100 0 100 100 + +gradient_setSpread RepeatSpread +gradient_setLinear 220 20 220 70 +drawRoundRect 200 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setSpread PadSpread +gradient_setLinear 320 20 320 40 +drawPolygon [300 0 390 0 350 99] + +gradient_setSpread ReflectSpread +gradient_setLinear 420 20 420 40 +drawPath path + +gradient_setSpread RepeatSpread +gradient_setLinear 520 20 520 40 +drawPie 500 0 100 100 720 4320 +end_block + +translate 0 100 +scale 1 1.5 +repeat_block vertical_gradients + +resetMatrix +translate 0 650 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block vertical_gradients + +# Some helpful info perhaps? +resetMatrix +setPen black +# gradient line indicators +drawLine 20 20 70 70 +drawLine 120 20 170 70 +drawLine 220 20 270 70 +drawLine 320 20 340 40 +drawLine 420 20 440 40 +drawLine 520 20 540 40 + +drawLine 20 140 70 240 +drawLine 120 140 170 240 +drawLine 220 140 270 240 +drawLine 320 140 340 180 +drawLine 420 140 440 180 +drawLine 520 140 540 180 + +drawText 610 50 "No XForm" +drawText 610 200 "scale 1x2" +drawText 610 350 "brush transform" +drawText 610 450 "vertical brush" +drawText 610 570 "vertical brush scale 1x1.5" +drawText 610 700 "vertical brush transform" + +drawText 10 780 "Pad" +drawText 110 780 "Reflect" +drawText 210 780 "Repeat" +drawText 310 780 "Pad w/alpha" +drawText 410 780 "Reflect w/alpha" +drawText 510 780 "Repeat w/alpha"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/linear_gradients_perspectives.qps b/tests/baseline/painting/scripts/linear_gradients_perspectives.qps new file mode 100644 index 0000000000..3ea39fbe46 --- /dev/null +++ b/tests/baseline/painting/scripts/linear_gradients_perspectives.qps @@ -0,0 +1,62 @@ +# Version: 1 + + +setRenderHint Antialiasing + +setPen #00ff00 + +translate 10 10 +# standard draw +begin_block gradient +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 10 10 290 290 +drawRect 0 0 300 300 +end_block gradient + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + repeat_block gradient +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + repeat_block gradient +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + repeat_block gradient +restore +restore + + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/linear_resolving_gradients.qps b/tests/baseline/painting/scripts/linear_resolving_gradients.qps new file mode 100644 index 0000000000..779760cb9a --- /dev/null +++ b/tests/baseline/painting/scripts/linear_resolving_gradients.qps @@ -0,0 +1,66 @@ +# Version: 2 +# CheckVsReference: 2% (0 0 500 400) + +setRenderHint Antialiasing + +setPen black + +begin_block gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setCoordinateMode ObjectBoundingMode +gradient_setLinear 0.2 0.2 0.7 0.7 +drawRect 0 0 100 100 + +gradient_setSpread ReflectSpread +gradient_setLinear 0.2 0.2 0.7 0.7 +drawEllipse 100 0 100 100 + +gradient_setSpread RepeatSpread +gradient_setLinear 0.2 0.2 0.7 0.7 +drawRoundRect 200 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setSpread PadSpread +gradient_setLinear 0.2 0.2 0.8 0.4 +drawPolygon [300 0 400 0 350 100] + +gradient_setSpread RepeatSpread +gradient_setLinear 0.2 0.2 0.4 0.4 +drawPie 400 0 100 100 0 4320 +end_block + +translate 0 100 +scale 1 2 +repeat_block gradients + +resetMatrix +translate 0 300 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block gradients + +# Some helpful info perhaps? +resetMatrix +setPen black + +drawText 510 50 "No XForm" +drawText 510 200 "scale 1x2" +drawText 510 350 "brush transform" + +drawText 10 450 "Pad" +drawText 110 450 "Reflect" +drawText 210 450 "Repeat" +drawText 310 450 "Pad w/alpha" +drawText 410 450 "Repeat w/alpha"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/lineconsistency.qps b/tests/baseline/painting/scripts/lineconsistency.qps new file mode 100644 index 0000000000..0b40577659 --- /dev/null +++ b/tests/baseline/painting/scripts/lineconsistency.qps @@ -0,0 +1,72 @@ +# Version: 1 + +begin_block draw +setPen red +drawPolygon [1.1 1 3.3 30.6 23.1 39.2 38.9 6.5] +setPen black +drawLine 1.1 1 3.3 30.6 +drawLine 3.3 30.6 23.1 39.2 +drawLine 23.1 39.2 38.9 6.5 +drawLine 38.9 6.5 1.1 1 +end_block draw +drawText 0 60 "0.0 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.1 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.2 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.3 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.4 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.5 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.6 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.7 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.8 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.9 aligned" + +resetMatrix +translate 100 0 +setPen black +drawText 0 20 "Line and text, 0.0 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.1 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.2 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.3 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.4 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.5 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.6 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.7 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.8 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.9 aligned" +drawLine 0 21 160 21
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/linedashes.qps b/tests/baseline/painting/scripts/linedashes.qps new file mode 100644 index 0000000000..78c791e68b --- /dev/null +++ b/tests/baseline/painting/scripts/linedashes.qps @@ -0,0 +1,132 @@ +# Version: 1 + +translate 10 10 + +setPen 0xffff0000 0 solidline squarecap +translate 50 50 +begin_block draw_lines + save + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + restore +end_block + +setPen 0xffff0000 0 dotline squarecap +translate 100 0 +repeat_block draw_lines +setPen 0xffff0000 0 dashdotline squarecap +translate 100 0 +repeat_block draw_lines +setPen 0xffff0000 0 dashdotdotline squarecap +translate 100 0 +repeat_block draw_lines +setPen 0xffff0000 0 dashline squarecap +translate 100 0 +repeat_block draw_lines + +path_moveTo mypath 10 10 +path_lineTo mypath 87 10 +path_moveTo mypath 10 30 +path_lineTo mypath 87 30 +path_moveTo mypath 10 50 +path_lineTo mypath 87 50 + +resetMatrix +translate 0 150 + +begin_block distinctLines + +setPen black 0 SolidLine SquareCap +pen_setDashPattern [ 3 3 ] +drawPath mypath + +translate 100 0 +setPen black 5 SolidLine SquareCap +pen_setDashPattern [ 3 3 ] +drawPath mypath + +translate 100 0 +setPen black 0 SolidLine RoundCap +pen_setDashPattern [ 3 3 ] +drawPath mypath + +translate 100 0 +setPen black 5 SolidLine RoundCap +pen_setDashPattern [ 3 3 ] +drawPath mypath + +end_block distinctLines + +resetMatrix +translate 0 220 +setRenderHint Antialiasing true +repeat_block distinctLines diff --git a/tests/baseline/painting/scripts/linedashes2.qps b/tests/baseline/painting/scripts/linedashes2.qps new file mode 100644 index 0000000000..b9a4cb9566 --- /dev/null +++ b/tests/baseline/painting/scripts/linedashes2.qps @@ -0,0 +1,196 @@ +# Version: 1 +# CheckVsReference: 5% (0 0 800 800) + +translate -30 10 + +setPen 0xffff0000 0 dashline squarecap +pen_setDashPattern [10 5] + +save +translate 100 100 +begin_block lines +drawLine 100 100 200 100 +drawLine 100 100 200 200 +drawLine 100 100 100 200 +end_block + +setPen 0xffff0000 2 dashline squarecap +translate 150 0 +repeat_block lines +restore + +save +save +begin_block horizontal +drawLine 0 0 50 0 +drawLine 3 10 53 10 +drawLine 6 20 56 20 +drawLine 9 30 59 30 + +translate 0 50 + +drawLine 0 0 50 5 +drawLine 3 10 53 15 +drawLine 6 20 56 25 +drawLine 9 30 59 35 + +translate 0 50 + +drawLine 0 0 50 -5 +drawLine 3 10 53 5 +drawLine 6 20 56 15 +drawLine 9 30 59 25 +end_block +restore + +save +translate 80 0 +repeat_block horizontal +restore +save +translate 800 0 +repeat_block horizontal +restore + +translate 180 -40 +save +begin_block vertical +drawLine 0 0 0 50 +drawLine 10 3 10 53 +drawLine 20 6 20 56 +drawLine 30 9 30 59 + +translate 50 0 + +drawLine 0 0 5 50 +drawLine 10 3 15 53 +drawLine 20 6 25 56 +drawLine 30 9 35 59 + +translate 50 0 + +drawLine 0 0 -5 50 +drawLine 10 3 5 53 +drawLine 20 6 15 56 +drawLine 30 9 25 59 +end_block +restore + +save +translate 0 80 +repeat_block vertical +restore +translate 0 800 +repeat_block vertical +restore + +translate 0 200 + +setPen 0xffff0000 2 dashline squarecap +save +repeat_block horizontal +restore +save +translate 80 0 +repeat_block horizontal +restore +save +translate 780 0 +repeat_block horizontal +restore + +translate 360 -240 +save +repeat_block vertical +restore +save +translate 0 80 +repeat_block vertical +restore +translate 0 780 +repeat_block vertical + +resetMatrix +translate 20 380 +setPen 0xffff00ff 5 dashdotline flatcap +begin_block offset +pen_setDashPattern [1 1 4 1 1 4] +pen_setDashOffset -4 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset -2 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 0 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 2 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 4 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 6 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 8 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 10 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 12 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 14 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 16 +drawLine 0 0 300 0 +end_block offset + +resetMatrix +translate 420 380 +setPen 0xffff00ff 5 dashdotline roundcap +repeat_block offset + +resetMatrix +setPen black 3 dashdotline +pen_setCosmetic true +translate 0 -150 +drawLine 500 160 500 410 + +resetMatrix +translate 300 480 +setPen blue 0 + +begin_block clip_lines +pen_setDashPattern [ 20 4 5 4 1 4 ] +pen_setDashOffset 26.0 +drawLines [0 0 1000000 10 1000000 10 -1000000 20 -1000000 20 0 30] +end_block clip_lines + +translate 0 45 +setPen blue 5 +repeat_block clip_lines + +translate 0 45 +setPen blue 5 SolidLine RoundCap +repeat_block clip_lines + +translate 0 45 +setPen green 0 + +begin_block clip_poly +pen_setDashPattern [ 20 4 5 4 1 4 ] +pen_setDashOffset 26.0 +drawPolyline [0 0 1000000 10 -1000000 20 0 30] +end_block clip_poly + +translate 0 45 +setPen green 5 +repeat_block clip_poly + +translate 0 45 +setPen green 5 SolidLine RoundCap +repeat_block clip_poly diff --git a/tests/baseline/painting/scripts/linedashes2_aa.qps b/tests/baseline/painting/scripts/linedashes2_aa.qps new file mode 100644 index 0000000000..c818ab62fe --- /dev/null +++ b/tests/baseline/painting/scripts/linedashes2_aa.qps @@ -0,0 +1,5 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 800 800) + +setRenderHint LineAntialiasing +import "linedashes2.qps"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/lines.qps b/tests/baseline/painting/scripts/lines.qps new file mode 100644 index 0000000000..274a7f31ec --- /dev/null +++ b/tests/baseline/painting/scripts/lines.qps @@ -0,0 +1,433 @@ +# Version: 1 +# CheckVsReference: 5% (0 0 310 425) + +translate 10 10 + +begin_block draw_lines + save + translate 50 50 + + save + setPen 0x7fff0000 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + restore + + # and then draw the lines the other direction + save + setPen 0x7f0000ff + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + restore + + # and now with a clip + save + setClipRect -30 -30 60 60 + setPen 0x7f00ff00 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + restore + + restore +end_block + +save + translate 100 0 + scale 2 2 + repeat_block draw_lines +restore + +translate 0 10 + +save + translate 0 200 + setRenderHint Antialiasing + repeat_block draw_lines +restore + +save + translate 100 200 + scale 2 2 + setRenderHint Antialiasing + repeat_block draw_lines +restore + +setPen 0x000000 8 +translate 350 240 +drawText 0 0 "Steep slopes:" + +translate 0 10 + +drawLine 0 0 -8 400 +translate 20 0 +drawLine 0 0 -7 400 +translate 20 0 +drawLine 0 0 -6 400 +translate 20 0 +drawLine 0 0 -5 400 +translate 20 0 +drawLine 0 0 -4 400 +translate 20 0 +drawLine 0 0 -3 400 +translate 20 0 +drawLine 0 0 -2 400 +translate 20 0 +drawLine 0 0 -1 400 +translate 20 0 +drawLine 0 0 0 400 +translate 20 0 +drawLine 0 0 1 400 +translate 20 0 +drawLine 0 0 2 400 +translate 20 0 +drawLine 0 0 3 400 +translate 20 0 +drawLine 0 0 4 400 +translate 20 0 +drawLine 0 0 5 400 +translate 20 0 +drawLine 0 0 6 400 +translate 20 0 +drawLine 0 0 7 400 +translate 20 0 +drawLine 0 0 8 400 + +resetMatrix + +translate 20 450 + +drawText 0 0 "Zero length lines:" + +translate 0 20 +drawText 100 10 "Square cap" +save +begin_block points +setPen 0x000000 1 solidline squarecap +drawLine 0 0 0 0 +setPen 0x000000 2 solidline squarecap +drawLine 8 0 8 0 +setPen 0x000000 3 solidline squarecap +drawLine 16 0 16 0 +setPen 0x000000 4 solidline squarecap +drawLine 24 0 24 0 +setPen 0x000000 5 solidline squarecap +drawLine 32 0 32 0 +setPen 0x000000 6 solidline squarecap +drawLine 40 0 40 0 +setPen 0x000000 7 solidline squarecap +drawLine 48 0 48 0 +setPen 0x000000 8 solidline squarecap +drawLine 57 0 57 0 +setPen 0x000000 9 solidline squarecap +drawLine 67 0 67 0 +setPen 0x000000 10 solidline squarecap +drawLine 78 0 78 0 +end_block points +restore + +translate 0 12 +setRenderHint Antialiasing off +repeat_block points +setRenderHint Antialiasing + +translate 0 20 +drawText 100 10 "Round cap" +save +begin_block points2 +setPen 0x000000 1 solidline roundcap +drawLine 0 0 0 0 +setPen 0x000000 2 solidline roundcap +drawLine 8 0 8 0 +setPen 0x000000 3 solidline roundcap +drawLine 16 0 16 0 +setPen 0x000000 4 solidline roundcap +drawLine 24 0 24 0 +setPen 0x000000 5 solidline roundcap +drawLine 32 0 32 0 +setPen 0x000000 6 solidline roundcap +drawLine 40 0 40 0 +setPen 0x000000 7 solidline roundcap +drawLine 48 0 48 0 +setPen 0x000000 8 solidline roundcap +drawLine 57 0 57 0 +setPen 0x000000 9 solidline roundcap +drawLine 67 0 67 0 +setPen 0x000000 10 solidline roundcap +drawLine 78 0 78 0 +end_block points2 +restore + +translate 0 12 +setRenderHint Antialiasing off +repeat_block points2 +setRenderHint Antialiasing + +translate 0 20 +drawText 100 10 "Flat cap" +save +begin_block points3 +setPen 0x000000 1 solidline flatcap +drawLine 0 0 0 0 +setPen 0x000000 2 solidline flatcap +drawLine 8 0 8 0 +setPen 0x000000 3 solidline flatcap +drawLine 16 0 16 0 +setPen 0x000000 4 solidline flatcap +drawLine 24 0 24 0 +setPen 0x000000 5 solidline flatcap +drawLine 32 0 32 0 +setPen 0x000000 6 solidline flatcap +drawLine 40 0 40 0 +setPen 0x000000 7 solidline flatcap +drawLine 48 0 48 0 +setPen 0x000000 8 solidline flatcap +drawLine 57 0 57 0 +setPen 0x000000 9 solidline flatcap +drawLine 67 0 67 0 +setPen 0x000000 10 solidline flatcap +drawLine 78 0 78 0 +end_block points3 +restore + +translate 0 12 +setRenderHint Antialiasing off +repeat_block points3 + +resetMatrix +translate -220 667.226 +drawText 230 -80 "Task 194266 (should see only one line):" +setPen black +drawRect 230.5 -70.5 122 12 +setRenderHint Antialiasing +setPen red +drawLine 236.842105263 -63.775117299 247.368421053 -63.775437504 + +setRenderHint Antialiasing off +resetMatrix +translate 10 640 +setPen black +drawText 0 -10 "Task 207147 (should see two lines):" +drawRect 0.5 0.5 64 64 +setRenderHint Antialiasing +setPen red + +drawLine 4.5 4.5 4.5001 60.5 +drawLine 4.5 4.5 60.5 4.5001 + +setRenderHint Antialiasing off +resetMatrix +translate 10 730 +setPen black +drawText 0 -10 "Task 229459 (should see one diagonal line):" +drawRect 0.5 0.5 64 64 +setPen red 2 solidline flatcap + +setClipRect 2 2 63 63 +drawLine 1.5 1.5 33560000 33560000 diff --git a/tests/baseline/painting/scripts/lines2.qps b/tests/baseline/painting/scripts/lines2.qps new file mode 100644 index 0000000000..af6ad65939 --- /dev/null +++ b/tests/baseline/painting/scripts/lines2.qps @@ -0,0 +1,179 @@ +# Version: 1 +# CheckVsReference: 5% + +translate 10 20 +drawText 0 0 "Thin lines" + +translate 60 70 + +save +begin_block lines +translate 0 -60 +translate 0 5 +setPen 0x000000 0.05 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.1 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.15 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.2 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.25 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.3 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.35 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.2 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.25 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.5 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.55 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.6 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.65 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.7 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.75 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.8 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.85 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.9 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.95 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.05 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.1 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.15 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.2 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.25 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.3 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.35 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.2 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.25 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.5 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.55 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.6 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.65 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.7 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.75 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.8 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.85 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.9 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.95 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 2 +drawLine -60 -2 60 2 +end_block +restore + +save +translate 150 0 +scale -1 1 +repeat_block lines +restore + +save +translate 80 220 +rotate 90 +repeat_block lines +restore + +save +translate 80 370 +rotate 90 +scale -1 1 +repeat_block lines +restore + +setRenderHint Antialiasing + +translate 300 0 + +save +repeat_block lines +restore + +save +translate 150 0 +scale -1 1 +repeat_block lines +restore + +save +translate 80 220 +rotate 90 +repeat_block lines +restore + +save +translate 80 370 +rotate 90 +scale -1 1 +repeat_block lines +restore
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/lines3.qps b/tests/baseline/painting/scripts/lines3.qps new file mode 100644 index 0000000000..676235e652 --- /dev/null +++ b/tests/baseline/painting/scripts/lines3.qps @@ -0,0 +1,171 @@ + +clearRenderHint +setPen black 0 solidline squarecap + +save +translate 20 20 + +begin_block lines + +# 0 -> 45 degress +drawLine 100 100 200 90 +drawLine 100 100 200 80 +drawLine 100 100 200 70 +drawLine 100 100 200 60 +drawLine 100 100 200 50 +drawLine 100 100 200 40 +drawLine 100 100 200 30 +drawLine 100 100 200 20 +drawLine 100 100 200 10 + +# 45 +drawLine 100 100 200 0 + +# 45 -> 90 +drawLine 100 100 190 0 +drawLine 100 100 180 0 +drawLine 100 100 170 0 +drawLine 100 100 160 0 +drawLine 100 100 150 0 +drawLine 100 100 140 0 +drawLine 100 100 130 0 +drawLine 100 100 120 0 +drawLine 100 100 110 0 + +# 90 +drawLine 100 100 100 0 + +# 90 -> 135 +drawLine 100 100 90 0 +drawLine 100 100 80 0 +drawLine 100 100 70 0 +drawLine 100 100 60 0 +drawLine 100 100 50 0 +drawLine 100 100 40 0 +drawLine 100 100 30 0 +drawLine 100 100 20 0 +drawLine 100 100 10 0 + +# 135 +drawLine 100 100 0 0 + +# 135 -> 180 degress +drawLine 100 100 0 10 +drawLine 100 100 0 20 +drawLine 100 100 0 30 +drawLine 100 100 0 40 +drawLine 100 100 0 50 +drawLine 100 100 0 60 +drawLine 100 100 0 70 +drawLine 100 100 0 80 +drawLine 100 100 0 90 + +# 180 +drawLine 100 100 0 100 + +# 180 -> 225 +drawLine 100 100 0 110 +drawLine 100 100 0 120 +drawLine 100 100 0 130 +drawLine 100 100 0 140 +drawLine 100 100 0 150 +drawLine 100 100 0 160 +drawLine 100 100 0 170 +drawLine 100 100 0 180 +drawLine 100 100 0 190 + +# 225 +drawLine 100 100 0 200 + +# 225 -> 270 +drawLine 100 100 10 200 +drawLine 100 100 20 200 +drawLine 100 100 30 200 +drawLine 100 100 40 200 +drawLine 100 100 50 200 +drawLine 100 100 60 200 +drawLine 100 100 70 200 +drawLine 100 100 80 200 +drawLine 100 100 90 200 + +# 270 +drawLine 100 100 100 200 + +# 270 -> 315 degrees +drawLine 100 100 110 200 +drawLine 100 100 120 200 +drawLine 100 100 130 200 +drawLine 100 100 140 200 +drawLine 100 100 150 200 +drawLine 100 100 160 200 +drawLine 100 100 170 200 +drawLine 100 100 180 200 +drawLine 100 100 190 200 + +# 315 +drawLine 100 100 200 200 + +# 315 -> 360 degress +drawLine 100 100 200 100 +drawLine 100 100 200 110 +drawLine 100 100 200 120 +drawLine 100 100 200 130 +drawLine 100 100 200 140 +drawLine 100 100 200 150 +drawLine 100 100 200 160 +drawLine 100 100 200 170 +drawLine 100 100 200 180 +drawLine 100 100 200 190 + +end_block + +setRenderHint Antialiasing +setPen 0x7fff0000 0 solidline squarecap +repeat_block lines + +translate 250.5 0.5 +clearRenderHint +setPen black 0 solidline squarecap +repeat_block lines +setRenderHint Antialiasing +setPen 0x7fff0000 0 solidline squarecap +repeat_block lines + +restore + +save + +translate 20 250 +clearRenderHint +setPen black 1 solidline squarecap +repeat_block lines +setRenderHint Antialiasing +setPen 0x7fff0000 1 solidline squarecap +repeat_block lines + +translate 250.5 0.5 +clearRenderHint +setPen black 1 soslidline squarecap +repeat_block lines +setRenderHint Antialiasing +setPen 0x7fff0000 0 solidline squarecap +repeat_block lines + +restore + +translate 20 500 +scale 1.5 1.5 +clearRenderHint +setPen black 1 solidline squarecap +repeat_block lines +setRenderHint Antialiasing +setPen 0x7fff0000 1 solidline squarecap +repeat_block lines + +translate 250.5 0.5 +clearRenderHint +setPen black 1 soslidline squarecap +repeat_block lines +setRenderHint Antialiasing +setPen 0x7fff0000 0 solidline squarecap +repeat_block lines diff --git a/tests/baseline/painting/scripts/pathfill.qps b/tests/baseline/painting/scripts/pathfill.qps new file mode 100644 index 0000000000..821b4684c9 --- /dev/null +++ b/tests/baseline/painting/scripts/pathfill.qps @@ -0,0 +1,38 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 850 420) + +setPen afff0000 4 + +setBrush dome_rgb32.png +drawEllipse 10 10 200 200 + +setBrush dome_argb32.png +drawEllipse 220 10 200 200 + +setPen NoPen + +setBrush dome_rgb32.png +drawEllipse 10 220 200 200 + +setBrush dome_argb32.png +drawEllipse 220 220 200 200 + +setBrushOrigin -30 -30 + +setPen afff0000 4 +setBrush dome_rgb32.png +drawEllipse 430 10 200 200 + +setBrush dome_argb32.png +drawEllipse 640 10 200 200 + +setPen NoPen +setBrush dome_rgb32.png +drawEllipse 430 220 200 200 + +setBrush dome_argb32.png +drawEllipse 640 220 200 200 + +setPen black +drawText 150 450 "No offset RGB/ARGB" +drawText 550 450 "-30 offset RGB/ARGB"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/paths.qps b/tests/baseline/painting/scripts/paths.qps new file mode 100644 index 0000000000..454b2a039d --- /dev/null +++ b/tests/baseline/painting/scripts/paths.qps @@ -0,0 +1,49 @@ +# Version: 1 + +setPen black 1 +setBrush 7f7fff + +setFont "arial" 12 +drawText 10 330 "Non-Cosmetic" +drawText 10 730 "Cosmetic" + +path_moveTo star 50 0 +path_lineTo star 30 90 +path_lineTo star 100 60 +path_lineTo star 0 20 +path_lineTo star 80 100 + +setFont "times" 50 +path_addText text 0 50 "ABCD, 1234, abcd, #¤%&" + +path_addRect rectncircle 0 0 75 75 +path_addEllipse rectncircle 25 25 75 75 +path_setFillRule rectncircle winding + +path_moveTo curve 100 0 +path_cubicTo curve 100 100 50 50 0 100 + +begin_block drawing +drawPath star +translate 100 0 +drawPath rectncircle +translate 100 0 +drawPath curve +translate -200 100 +drawPath text +end_block + +begin_block xform +save +translate 50 60 +rotate 10 +scale 1.0 0.7 +repeat_block drawing +restore +end_block xform + +setPen black 0 +setBrush ff7f7f +translate 0 300 +repeat_block drawing +repeat_block xform diff --git a/tests/baseline/painting/scripts/paths_aa.qps b/tests/baseline/painting/scripts/paths_aa.qps new file mode 100644 index 0000000000..4812e2fa5f --- /dev/null +++ b/tests/baseline/painting/scripts/paths_aa.qps @@ -0,0 +1,4 @@ +# Version: 1 + +setRenderHint LineAntialiasing +import "paths.qps" diff --git a/tests/baseline/painting/scripts/pattern_xform.qps b/tests/baseline/painting/scripts/pattern_xform.qps new file mode 100644 index 0000000000..224969f1c7 --- /dev/null +++ b/tests/baseline/painting/scripts/pattern_xform.qps @@ -0,0 +1,79 @@ +# Version: 1 +# CheckVsReference: 5% + +#define basic block off screen +save +translate -1000 -1000 +begin_block drawrects +setBrush green Dense4Pattern +drawRect 0 0 40 40 +setBrush green DiagCrossPattern +drawRect 40 0 40 40 +setBrush green HorPattern +brushRotate 30 +drawRect 80 0 40 40 +fillRect 120 0 40 40 +save +setPen brush 40 SolidLine FlatCap +setBrush NoBrush +drawLine 160 20 200 20 +restore +end_block +restore + +begin_block hintsuite +save +setRenderHint NonCosmeticBrushPatterns false +setRenderHint SmoothPixmapTransform false +translate 10 10 +repeat_block drawrects + +setRenderHint NonCosmeticBrushPatterns false +setRenderHint SmoothPixmapTransform true +translate 0 50 +repeat_block drawrects + +setRenderHint NonCosmeticBrushPatterns true +setRenderHint SmoothPixmapTransform false +translate 0 50 +repeat_block drawrects + +setRenderHint NonCosmeticBrushPatterns true +setRenderHint SmoothPixmapTransform true +translate 0 50 +repeat_block drawrects +restore +end_block + +save +translate 0 200 +scale 2 2 +repeat_block hintsuite +restore + +save +translate 500 0 +scale 1.5 2.5 +rotate_y 60 +repeat_block hintsuite +restore + + +translate 0 650 +setBrush blue CrossPattern +setPen red +setRenderHint NonCosmeticBrushPatterns false + +begin_block dots +save +drawRect 0 0 50 50 +setBrushOrigin 12 0 +drawRect 50 0 50 50 +scale 2 1 +drawRect 50 0 50 50 +restore +end_block dots + +setRenderHint NonCosmeticBrushPatterns true +translate 0 60 +repeat_block dots diff --git a/tests/baseline/painting/scripts/pattern_xform2.qps b/tests/baseline/painting/scripts/pattern_xform2.qps new file mode 100644 index 0000000000..4f9314272d --- /dev/null +++ b/tests/baseline/painting/scripts/pattern_xform2.qps @@ -0,0 +1,81 @@ +# Version: 1 +# CheckVsReference: 5% + +# 1: Check brush origin vs (non)cosmetic brush patterns + +setBrush blue CrossPattern +begin_block blockName +save +setBrushOrigin 0 0 +fillRect 0 0 32 32 +translate 0 32 +setBrushOrigin 1 0 +fillRect 0 0 32 32 +translate 0 32 +setBrushOrigin 2 0 +fillRect 0 0 32 32 +translate 0 32 +setBrushOrigin 3 0 +fillRect 0 0 32 32 +translate 0 32 +setBrushOrigin 4 0 +fillRect 0 0 32 32 +translate 0 32 +setBrushOrigin 5 0 +fillRect 0 0 32 32 +translate 0 32 +setBrushOrigin 6 0 +fillRect 0 0 32 32 +translate 0 32 +setBrushOrigin 7 0 +fillRect 0 0 32 32 +translate 0 32 +setBrushOrigin 8 0 +fillRect 0 0 32 32 +restore +end_block blockName + +save +setBrush red CrossPattern +scale 2 1 +repeat_block blockName +restore + +save +translate 0 300 +setRenderHint NonCosmeticBrushPatterns true +setBrush blue CrossPattern +repeat_block blockName +setBrush red CrossPattern +scale 2 1 +repeat_block blockName +restore + +# 2: Check brush update after only xform or hint change +translate 100 0 + +save +setPen NoPen +setBrush blue DiagCrossPattern +setRenderHint NonCosmeticBrushPatterns true +drawRect 10 10 200 100 +scale 10 10 +drawRect 22 1 20 10 +drawRect 22 12 20 10 +setRenderHint NonCosmeticBrushPatterns false +drawRect 1 12 20 10 +restore + +setBrush green DiagCrossPattern +setPen brush 100 SolidLine FlatCap +pen_setCosmetic true +setBrush NoBrush +translate 0 250 +setRenderHint NonCosmeticBrushPatterns true +drawLine 10 60 210 60 +scale 10 10 +drawLine 22 6 42 6 +drawLine 22 17 42 17 +setRenderHint NonCosmeticBrushPatterns false +drawLine 1 17 21 17 + diff --git a/tests/baseline/painting/scripts/pens.qps b/tests/baseline/painting/scripts/pens.qps new file mode 100644 index 0000000000..c72636dcef --- /dev/null +++ b/tests/baseline/painting/scripts/pens.qps @@ -0,0 +1,133 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 800 800) + + +translate 10 10 + +begin_block penstyles +setPen black 0 solidline flatcap +drawLine 0 0 100 0 +setPen black 0 dashline flatcap +drawLine 100 0 100 40 +setPen black 0 dotline flatcap +drawLine 100 40 200 0 +setPen black 0 dashdotline flatcap +drawLine 200 0 300 0 +setPen black 0 dashdotdotline flatcap +drawLine 300 0 400 40 + +translate 0 50 +setPen blue 2 solidline flatcap +drawLine 0 0 100 0 +setPen blue 2 dashline flatcap +drawLine 100 0 100 40 +setPen blue 2 dotline flatcap +drawLine 100 40 200 0 +setPen blue 2 dashdotline flatcap +drawLine 200 0 300 0 +setPen blue 2 dashdotdotline flatcap +drawLine 300 0 400 40 + +translate 0 50 +setPen red 5 solidline flatcap +drawLine 0 0 100 0 +setPen red 5 dashline flatcap +drawLine 100 0 100 40 +setPen red 5 dotline flatcap +drawLine 100 40 200 0 +setPen red 5 dashdotline flatcap +drawLine 200 0 300 0 +setPen red 5 dashdotdotline flatcap +drawLine 300 0 400 40 +end_block + +translate 0 50 +scale 1 2 +repeat_block penstyles + + +# Test cap styles +resetMatrix +translate 420 10 +setPen green 5 dashdotline flatcap +drawLine 0 0 200 0 +setPen green 5 dashdotline roundcap +drawLine 0 20 200 20 +setPen green 5 dashdotline squarecap +drawLine 0 40 200 40 + + +# Test join styles +resetMatrix +translate 420 80 +setBrush nobrush +begin_block joinstyles +setPen orange 10 solidline flatcap miterjoin +drawPolyline [ 0 0 80 0 80 80 0 80 ] + +translate 0 100 +setPen aquamarine 10 solidline squarecap beveljoin +drawPolyline [ 0 0 80 0 80 80 0 80 ] + +translate 0 100 +setPen purple 10 solidline roundcap roundjoin +drawPolyline [ 0 0 80 0 80 80 0 80 ] +end_block + +translate 130 -200 +scale 2 1 +rotate 1 +repeat_block joinstyles + +# transparent lines +resetMatrix +translate 10 400 +setPen #7f000000 +drawLine 0 0 50 0 +setPen #7f000000 1 SolidLine +drawLine 0 10 50 10 +setPen #7f000000 5 SolidLine +drawLine 0 20 50 20 +setPen #7f000000 10 SolidLine +drawLine 0 30 50 30 +setPen #7f000000 +drawLine 0 0 0 50 +setPen #7f000000 1 SolidLine +drawLine 10 0 10 50 +setPen #7f000000 5 SolidLine +drawLine 20 0 20 50 +setPen #7f000000 10 SolidLine +drawLine 30 0 30 50 + +# pen styles +resetMatrix +translate 0 500 +setPen black 0 DashLine +drawLine 20 20 100 20 +translate 0 10 +setPen black 0 DotLine +drawLine 20 20 100 20 +translate 0 10 +setPen black 0 DashDotLine +drawLine 20 20 100 20 +translate 0 10 +setPen black 0 DashDotDotLine +drawLine 20 20 100 20 + +# scaling ellipse +resetMatrix +setPen black 0.008 DashLine +translate 250 550 +rotate 30 +scale 250 250 +drawEllipse -0.4 -0.4 0.8 0.8 + +# scaling path +path_addEllipse star -0.3 -0.3 0.6 0.6 + +resetMatrix +setPen black 0.008 DashLine +translate 250 550 +rotate 30 +scale 250 250 +drawPath star diff --git a/tests/baseline/painting/scripts/pens_aa.qps b/tests/baseline/painting/scripts/pens_aa.qps new file mode 100644 index 0000000000..066cac365f --- /dev/null +++ b/tests/baseline/painting/scripts/pens_aa.qps @@ -0,0 +1,6 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 800 800) + +setRenderHint LineAntialiasing + +import "pens.qps"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/pens_cosmetic.qps b/tests/baseline/painting/scripts/pens_cosmetic.qps new file mode 100644 index 0000000000..9120290462 --- /dev/null +++ b/tests/baseline/painting/scripts/pens_cosmetic.qps @@ -0,0 +1,116 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 585 470) + +path_addEllipse path 22 0 7 7 +path_addRect path 25 5 4 4 + +translate 20 20 + +setPen black 0 +pen_setCosmetic false + +begin_block lines + save + drawLine 0 0 10 10 + drawLine 2 0 10 0 + drawLine 0 2 0 10 + drawPolygon [12 0 20 0 15 10] + drawPath path + drawEllipse 32 0 8 8 + drawPoint 36 4 + + translate 100 0 + save + scale 4 1 + drawLine 0 0 10 10 + drawLine 2 0 10 0 + drawLine 0 2 0 10 + drawPolygon [12 0 20 0 15 10] + drawPath path + drawEllipse 32 0 8 8 + drawPoint 36 4 + restore + + translate 200 0 + save + scale 1 4 + drawLine 0 0 10 10 + drawLine 2 0 10 0 + drawLine 0 2 0 10 + drawPolygon [12 0 20 0 15 10] + drawPath path + drawEllipse 32 0 8 8 + drawPoint 36 4 + restore + + translate 100 0 + save + scale 4 4 + drawLine 0 0 10 10 + drawLine 2 0 10 0 + drawLine 0 2 0 10 + drawPolygon [12 0 20 0 15 10] + drawPath path + drawEllipse 32 0 8 8 + drawPoint 36 4 + restore + restore +end_block + +drawText 580 15 "non-cosmetic, 0-width" +translate 0 50 + +setPen black 2 +pen_setCosmetic false +repeat_block lines +drawText 580 15 "non-cosmetic, 2-width" + +translate 0 20 +translate 0 50 +setPen black 0 +pen_setCosmetic true +repeat_block lines +drawText 580 15 "cosmetic, 0-width" + +translate 0 50 +setPen black 2 +pen_setCosmetic true +repeat_block lines +drawText 580 15 "cosmetic, 2-width" + + +setRenderHint Antialiasing +translate 0 20 + +translate 0 50 +setPen black 0 +pen_setCosmetic false +repeat_block lines +drawText 580 15 "non-cosmetic, 0-width" + +translate 0 50 + +setPen black 2 +pen_setCosmetic false +repeat_block lines +drawText 580 15 "non-cosmetic, 2-width" + +translate 0 20 +translate 0 50 +setPen black 0 +pen_setCosmetic true +repeat_block lines +drawText 580 15 "cosmetic, 0-width" + +translate 0 50 +setPen black 2 +pen_setCosmetic true +repeat_block lines +drawText 580 15 "cosmetic, 2-width" + + +translate 0 70 +drawText 0 0 "scale(1, 1)" +drawText 150 0 "scale(4, 1)" +drawText 300 0 "scale(1, 4)" +drawText 450 0 "scale(4, 4)"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/perspectives.qps b/tests/baseline/painting/scripts/perspectives.qps new file mode 100644 index 0000000000..0b903e5260 --- /dev/null +++ b/tests/baseline/painting/scripts/perspectives.qps @@ -0,0 +1,72 @@ +# Version: 1 + + +setRenderHint Antialiasing + +setPen #00ff00 + +image_load image.png the_image + +translate 10 10 +# standard draw +drawImage the_image 0 0 + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + drawImage the_image 0 0 +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + drawImage the_image 0 0 +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + drawImage the_image 0 0 +restore +restore + +setRenderHint SmoothPixmapTransform on +setBrush red +setPen black +resetMatrix +translate 100 720 +rotate_y 85 +scale 7 0.01 +drawRect -150 -150 300 300 + +resetMatrix +setBrush gam030.png +setPen black 30 +translate 700 700 +rotate_y -85 +scale 7 0.01 +drawRect -150 -150 300 300 + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0 +resetMatrix +translate 300 760 +drawText 0 0 "Perspective Clipping"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/perspectives2.qps b/tests/baseline/painting/scripts/perspectives2.qps new file mode 100644 index 0000000000..6762e21af4 --- /dev/null +++ b/tests/baseline/painting/scripts/perspectives2.qps @@ -0,0 +1,309 @@ +# Version: 1 + +setRenderHint Antialiasing + +image_load zebra.png zebra_png + +image_convertToFormat zebra_png zebra ARGB32_Premultiplied + +translate 75 100 +# standard draw +begin_block row1 +drawImage zebra -50 -50 + +translate 90 0 +save +rotate_y 50 +drawImage zebra -50 -50 +restore + +translate 65 0 +save +rotate_y 60 +drawImage zebra -50 -50 +restore + +translate 50 0 +save +rotate_y 70 +drawImage zebra -50 -50 +restore + +translate 30 0 +save +rotate_y 80 +drawImage zebra -50 -50 +restore + +translate 24 0 +save +rotate_y 82 +drawImage zebra -50 -50 +restore + +translate 20 0 +save +rotate_y 84 +drawImage zebra -50 -50 +restore + +translate 16 0 +save +rotate_y 86 +drawImage zebra -50 -50 +restore + +translate 12 0 +save +rotate_y 87 +drawImage zebra -50 -50 +restore + +translate 8 0 +save +rotate_y 88 +drawImage zebra -50 -50 +restore + +translate 6 0 +save +rotate_y 89 +drawImage zebra -50 -50 +restore + +translate 6 0 +save +rotate_y 91 +drawImage zebra -50 -50 +restore + +translate 6 0 +save +rotate_y 92 +drawImage zebra -50 -50 +restore + +translate 8 0 +save +rotate_y 93 +drawImage zebra -50 -50 +restore + +translate 12 0 +save +rotate_y 94 +drawImage zebra -50 -50 +restore + +translate 16 0 +save +rotate_y 96 +drawImage zebra -50 -50 +restore + +translate 20 0 +save +rotate_y 98 +drawImage zebra -50 -50 +restore + +translate 24 0 +save +rotate_y 100 +drawImage zebra -50 -50 +restore + +translate 30 0 +save +rotate_y 110 +drawImage zebra -50 -50 +restore + +translate 50 0 +save +rotate_y 120 +drawImage zebra -50 -50 +restore + +translate 65 0 +save +rotate_y 130 +drawImage zebra -50 -50 +restore + +translate 90 0 +save +rotate_y 180 +drawImage zebra -50 -50 +restore +end_block row1 + +resetMatrix +translate 75 280 +setRenderHint SmoothPixmapTransform +repeat_block row1 + +resetMatrix +setPen black +translate 300 20 +drawText 0 0 "Fast Pixmap Transform" +resetMatrix +translate 300 210 +drawText 0 0 "Smooth Pixmap Transform" + +resetMatrix +translate 0 400 + +image_load dome_argb32.png the_pixmap + +image_convertToFormat the_pixmap dome ARGB32 + +setRenderHint SmoothPixmapTransform false + +translate 75 100 +# standard draw +begin_block row2 +drawImage dome -50 -50 + +translate 90 0 +save +rotate_y 50 +drawImage dome -50 -50 +restore + +translate 65 0 +save +rotate_y 60 +drawImage dome -50 -50 +restore + +translate 50 0 +save +rotate_y 70 +drawImage dome -50 -50 +restore + +translate 30 0 +save +rotate_y 80 +drawImage dome -50 -50 +restore + +translate 24 0 +save +rotate_y 82 +drawImage dome -50 -50 +restore + +translate 20 0 +save +rotate_y 84 +drawImage dome -50 -50 +restore + +translate 16 0 +save +rotate_y 86 +drawImage dome -50 -50 +restore + +translate 12 0 +save +rotate_y 87 +drawImage dome -50 -50 +restore + +translate 8 0 +save +rotate_y 88 +drawImage dome -50 -50 +restore + +translate 6 0 +save +rotate_y 89 +drawImage dome -50 -50 +restore + +translate 6 0 +save +rotate_y 91 +drawImage dome -50 -50 +restore + +translate 6 0 +save +rotate_y 92 +drawImage dome -50 -50 +restore + +translate 8 0 +save +rotate_y 93 +drawImage dome -50 -50 +restore + +translate 12 0 +save +rotate_y 94 +drawImage dome -50 -50 +restore + +translate 16 0 +save +rotate_y 96 +drawImage dome -50 -50 +restore + +translate 20 0 +save +rotate_y 98 +drawImage dome -50 -50 +restore + +translate 24 0 +save +rotate_y 100 +drawImage dome -50 -50 +restore + +translate 30 0 +save +rotate_y 110 +drawImage dome -50 -50 +restore + +translate 50 0 +save +rotate_y 120 +drawImage dome -50 -50 +restore + +translate 65 0 +save +rotate_y 130 +drawImage dome -50 -50 +restore + +translate 90 0 +save +rotate_y 180 +drawImage dome -50 -50 +restore +end_block row2 + +resetMatrix +translate 0 400 +translate 75 280 +setRenderHint SmoothPixmapTransform +repeat_block row2 + +resetMatrix +setPen black +translate 0 400 +translate 300 20 +drawText 0 0 "Fast Pixmap Transform" +resetMatrix +translate 0 400 +translate 300 210 +drawText 0 0 "Smooth Pixmap Transform" diff --git a/tests/baseline/painting/scripts/pixmap_rotation.qps b/tests/baseline/painting/scripts/pixmap_rotation.qps new file mode 100644 index 0000000000..8427af85af --- /dev/null +++ b/tests/baseline/painting/scripts/pixmap_rotation.qps @@ -0,0 +1,31 @@ +# Version: 1 +# CheckVsReference: 0% (0 0 440 220) + +translate 120 120 + +begin_block drawing +save + rotate 90 + drawPixmap solid.png 0 0 + + rotate 90 + drawPixmap solid.png 0 0 + + rotate 90 + drawPixmap solid.png 0 0 + + rotate 90 + drawPixmap solid.png 0 0 +restore +end_block + +resetMatrix + +translate 340 120 +setRenderHint SmoothPixmapTransformation +repeat_block drawing + +resetMatrix + +drawText 50 240 "Normal Xform" +drawText 270 240 "Smooth Xform" diff --git a/tests/baseline/painting/scripts/pixmap_rotation2.qps b/tests/baseline/painting/scripts/pixmap_rotation2.qps new file mode 100644 index 0000000000..dfb93fe09c --- /dev/null +++ b/tests/baseline/painting/scripts/pixmap_rotation2.qps @@ -0,0 +1,8 @@ +# Version: 1 +# CheckVsReference: 1% + +setRenderHint SmoothPixmapTransformation +translate 400 -120 +rotate 45 +scale 400 400 +drawImage solid2x2.png 0 0 diff --git a/tests/baseline/painting/scripts/pixmap_scaling.qps b/tests/baseline/painting/scripts/pixmap_scaling.qps new file mode 100644 index 0000000000..8a5ab2c60e --- /dev/null +++ b/tests/baseline/painting/scripts/pixmap_scaling.qps @@ -0,0 +1,224 @@ +# Version: 1 +# CheckVsReference: 0% (0 30 600 70) +# CheckVsReference: 0% (290 130 280 60) +# CheckVsReference: 0% (0 180 250 90) + +# Hurra! Force line endings (?) + +translate 5 25 +setFont "arial" 8 + +save + drawText 15 0 "opaque image" + translate 50 50 + save + translate 1 1 + scale 20 20 + drawImage solid2x2.png 0 0 + restore + save + translate -1 1 + scale -20 20 + drawImage solid2x2.png 0 0 + restore + save + translate 1 -1 + scale 20 -20 + drawImage solid2x2.png 0 0 + restore + save + translate -1 -1 + scale -20 -20 + drawImage solid2x2.png 0 0 + restore + + +restore + +save + translate 150 0 + drawText 15 0 "alpha image" + translate 50 50 + save + translate 1 1 + scale 20 20 + drawImage alpha2x2.png 0 0 + restore + save + translate -1 1 + scale -20 20 + drawImage alpha2x2.png 0 0 + restore + save + translate 1 -1 + scale 20 -20 + drawImage alpha2x2.png 0 0 + restore + save + translate -1 -1 + scale -20 -20 + drawImage alpha2x2.png 0 0 + restore +restore + + +save + translate 0 150 + drawText 15 0 "solid pixmap" + translate 50 50 + save + translate 1 1 + scale 20 20 + drawPixmap solid2x2.png 0 0 + restore + save + translate -1 1 + scale -20 20 + drawPixmap solid2x2.png 0 0 + restore + save + translate 1 -1 + scale 20 -20 + drawPixmap solid2x2.png 0 0 + restore + save + translate -1 -1 + scale -20 -20 + drawPixmap solid2x2.png 0 0 + restore +restore + + +save + translate 150 150 + drawText 15 0 "alpha pixmap" + translate 50 50 + save + translate 1 1 + scale 20 20 + drawPixmap alpha2x2.png 0 0 + restore + save + translate -1 1 + scale -20 20 + drawPixmap alpha2x2.png 0 0 + restore + save + translate 1 -1 + scale 20 -20 + drawPixmap alpha2x2.png 0 0 + restore + save + translate -1 -1 + scale -20 -20 + drawPixmap alpha2x2.png 0 0 + restore +restore + + +save + translate 300 10 + save + drawText 0 -10 "subrect solid image" + drawImage solid2x2.png 0 0 50 5 0 0.0 2 0.2 + drawImage solid2x2.png 0 5 50 5 0 0.2 2 0.2 + drawImage solid2x2.png 0 10 50 5 0 0.4 2 0.2 + drawImage solid2x2.png 0 15 50 5 0 0.6 2 0.2 + drawImage solid2x2.png 0 20 50 5 0 0.8 2 0.2 + drawImage solid2x2.png 0 25 50 5 0 1.0 2 0.2 + drawImage solid2x2.png 0 30 50 5 0 1.2 2 0.2 + drawImage solid2x2.png 0 35 50 5 0 1.4 2 0.2 + drawImage solid2x2.png 0 40 50 5 0 1.6 2 0.2 + drawImage solid2x2.png 0 45 50 5 0 1.8 2 0.2 + translate 60 0 + drawImage solid2x2.png 0 0 5 50 0.0 0 0.2 2 + drawImage solid2x2.png 5 0 5 50 0.2 0 0.2 2 + drawImage solid2x2.png 10 0 5 50 0.4 0 0.2 2 + drawImage solid2x2.png 15 0 5 50 0.6 0 0.2 2 + drawImage solid2x2.png 20 0 5 50 0.8 0 0.2 2 + drawImage solid2x2.png 25 0 5 50 1.0 0 0.2 2 + drawImage solid2x2.png 30 0 5 50 1.2 0 0.2 2 + drawImage solid2x2.png 35 0 5 50 1.4 0 0.2 2 + drawImage solid2x2.png 40 0 5 50 1.6 0 0.2 2 + drawImage solid2x2.png 45 0 5 50 1.8 0 0.2 2 + restore + + save + translate 150 0 + drawText 0 -10 "subrect solid image" + drawImage alpha2x2.png 0 0 50 5 0 0.0 2 0.2 + drawImage alpha2x2.png 0 5 50 5 0 0.2 2 0.2 + drawImage alpha2x2.png 0 10 50 5 0 0.4 2 0.2 + drawImage alpha2x2.png 0 15 50 5 0 0.6 2 0.2 + drawImage alpha2x2.png 0 20 50 5 0 0.8 2 0.2 + drawImage alpha2x2.png 0 25 50 5 0 1.0 2 0.2 + drawImage alpha2x2.png 0 30 50 5 0 1.2 2 0.2 + drawImage alpha2x2.png 0 35 50 5 0 1.4 2 0.2 + drawImage alpha2x2.png 0 40 50 5 0 1.6 2 0.2 + drawImage alpha2x2.png 0 45 50 5 0 1.8 2 0.2 + translate 60 0 + drawImage alpha2x2.png 0 0 5 50 0.0 0 0.2 2 + drawImage alpha2x2.png 5 0 5 50 0.2 0 0.2 2 + drawImage alpha2x2.png 10 0 5 50 0.4 0 0.2 2 + drawImage alpha2x2.png 15 0 5 50 0.6 0 0.2 2 + drawImage alpha2x2.png 20 0 5 50 0.8 0 0.2 2 + drawImage alpha2x2.png 25 0 5 50 1.0 0 0.2 2 + drawImage alpha2x2.png 30 0 5 50 1.2 0 0.2 2 + drawImage alpha2x2.png 35 0 5 50 1.4 0 0.2 2 + drawImage alpha2x2.png 40 0 5 50 1.6 0 0.2 2 + drawImage alpha2x2.png 45 0 5 50 1.8 0 0.2 2 + restore + + save + translate 0 100 + drawText 0 -10 "subrect alpha pixmap" + drawPixmap solid2x2.png 0 0 50 5 0 0.0 2 0.2 + drawPixmap solid2x2.png 0 5 50 5 0 0.2 2 0.2 + drawPixmap solid2x2.png 0 10 50 5 0 0.4 2 0.2 + drawPixmap solid2x2.png 0 15 50 5 0 0.6 2 0.2 + drawPixmap solid2x2.png 0 20 50 5 0 0.8 2 0.2 + drawPixmap solid2x2.png 0 25 50 5 0 1.0 2 0.2 + drawPixmap solid2x2.png 0 30 50 5 0 1.2 2 0.2 + drawPixmap solid2x2.png 0 35 50 5 0 1.4 2 0.2 + drawPixmap solid2x2.png 0 40 50 5 0 1.6 2 0.2 + drawPixmap solid2x2.png 0 45 50 5 0 1.8 2 0.2 + translate 60 0 + drawPixmap solid2x2.png 0 0 5 50 0.0 0 0.2 2 + drawPixmap solid2x2.png 5 0 5 50 0.2 0 0.2 2 + drawPixmap solid2x2.png 10 0 5 50 0.4 0 0.2 2 + drawPixmap solid2x2.png 15 0 5 50 0.6 0 0.2 2 + drawPixmap solid2x2.png 20 0 5 50 0.8 0 0.2 2 + drawPixmap solid2x2.png 25 0 5 50 1.0 0 0.2 2 + drawPixmap solid2x2.png 30 0 5 50 1.2 0 0.2 2 + drawPixmap solid2x2.png 35 0 5 50 1.4 0 0.2 2 + drawPixmap solid2x2.png 40 0 5 50 1.6 0 0.2 2 + drawPixmap solid2x2.png 45 0 5 50 1.8 0 0.2 2 + restore + + save + translate 150 100 + drawText 0 -10 "subrect alpha pixmap" + drawPixmap alpha2x2.png 0 0 50 5 0 0.0 2 0.2 + drawPixmap alpha2x2.png 0 5 50 5 0 0.2 2 0.2 + drawPixmap alpha2x2.png 0 10 50 5 0 0.4 2 0.2 + drawPixmap alpha2x2.png 0 15 50 5 0 0.6 2 0.2 + drawPixmap alpha2x2.png 0 20 50 5 0 0.8 2 0.2 + drawPixmap alpha2x2.png 0 25 50 5 0 1.0 2 0.2 + drawPixmap alpha2x2.png 0 30 50 5 0 1.2 2 0.2 + drawPixmap alpha2x2.png 0 35 50 5 0 1.4 2 0.2 + drawPixmap alpha2x2.png 0 40 50 5 0 1.6 2 0.2 + drawPixmap alpha2x2.png 0 45 50 5 0 1.8 2 0.2 + translate 60 0 + drawPixmap alpha2x2.png 0 0 5 50 0.0 0 0.2 2 + drawPixmap alpha2x2.png 5 0 5 50 0.2 0 0.2 2 + drawPixmap alpha2x2.png 10 0 5 50 0.4 0 0.2 2 + drawPixmap alpha2x2.png 15 0 5 50 0.6 0 0.2 2 + drawPixmap alpha2x2.png 20 0 5 50 0.8 0 0.2 2 + drawPixmap alpha2x2.png 25 0 5 50 1.0 0 0.2 2 + drawPixmap alpha2x2.png 30 0 5 50 1.2 0 0.2 2 + drawPixmap alpha2x2.png 35 0 5 50 1.4 0 0.2 2 + drawPixmap alpha2x2.png 40 0 5 50 1.6 0 0.2 2 + drawPixmap alpha2x2.png 45 0 5 50 1.8 0 0.2 2 + restore + +restore
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/pixmap_subpixel.qps b/tests/baseline/painting/scripts/pixmap_subpixel.qps new file mode 100644 index 0000000000..d5b7b92fc9 --- /dev/null +++ b/tests/baseline/painting/scripts/pixmap_subpixel.qps @@ -0,0 +1,117 @@ +# Version: 1 +# CheckVsReference: 5% + + +translate 50 50 + +# Pixmaps at 0.1 offset, unclipped +begin_block draw_pixmaps +save + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 +restore +end_block + +# Tiled pixmaps at 0.1 offsets, unclipped +translate 0 50 +begin_block draw_tiled +save + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 +restore +end_block + + +path_moveTo clip 0 0 +path_lineTo clip width 0 +path_lineTo clip width 400 +path_lineTo clip 0 height +setClipPath clip + +translate 0 50 +# Pixmaps at 0.1 offset, clipped +repeat_block draw_pixmaps + + +# Tiled pixmaps at 0.1 offsets... +translate 0 50 +repeat_block draw_tiled + diff --git a/tests/baseline/painting/scripts/pixmapfragments.qps b/tests/baseline/painting/scripts/pixmapfragments.qps new file mode 100644 index 0000000000..4c837b760f --- /dev/null +++ b/tests/baseline/painting/scripts/pixmapfragments.qps @@ -0,0 +1,65 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 690 580) + + +setRenderHint Antialiasing + +setPen #00ff00 + +pixmap_load dome_argb32.png the_pixmap +begin_block draw_stuff +save + drawPixmapFragments the_pixmap 1 50 50 25 25 60 60 1 1 0 1 + drawPixmapFragments the_pixmap 1 150 50 25 25 60 60 1 1 0 0.5 + drawPixmapFragments the_pixmap 1 250 50 25 25 60 60 1 1 30 1 + drawPixmapFragments the_pixmap 1 350 50 25 25 60 60 1.5 1 0 1 + drawPixmapFragments the_pixmap 1 450 50 25 25 60 60 1 1.5 0 1 + drawPixmapFragments the_pixmap 2 550 50 25 25 40 40 0.5 0.5 -45 1 600 50 25 25 40 40 0.7 0.7 45 1 +restore +end_block + + +translate 0 120 +pixmap_load dome_rgb32.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_indexed.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_indexed_mask.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_mono.png the_pixmap +repeat_block draw_stuff + + +resetMatrix +translate 700 60 +setPen black +drawText 0 0 "32 bit w/alpha" +translate 0 120 +drawText 0 0 "32 bit w/o alpha" +translate 0 120 +drawText 0 0 "8 bit indexed" +translate 0 120 +drawText 0 0 "8 bit indexed w/mask" +translate 0 120 +drawText 0 0 "1 bit" + +resetMatrix +translate 25 600 +drawText 0 0 "simple" +translate 100 0 +drawText 0 0 "opacity" +translate 100 0 +drawText 0 0 "rotation" +translate 100 0 +drawText 0 0 "scale x" +translate 100 0 +drawText 0 0 "scale y" +translate 100 0 +drawText 0 0 "two fragments" +translate 100 0 diff --git a/tests/baseline/painting/scripts/pixmaps.qps b/tests/baseline/painting/scripts/pixmaps.qps new file mode 100644 index 0000000000..0b4ba2c4fb --- /dev/null +++ b/tests/baseline/painting/scripts/pixmaps.qps @@ -0,0 +1,106 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 690 580) + + +setRenderHint Antialiasing + +setPen #00ff00 + +pixmap_load dome_argb32.png the_pixmap +begin_block draw_stuff + +save + + # standard draw + drawPixmap the_pixmap 0 0 + + # sub recting + translate 120 0 + drawPixmap the_pixmap 0 0 40 40 0 0 40 40 + drawPixmap the_pixmap 60 0 40 40 60 0 40 40 + drawPixmap the_pixmap 0 60 40 40 0 60 40 40 + drawPixmap the_pixmap 60 60 40 40 60 60 40 40 + drawPixmap the_pixmap 0 40 40 20 0 40 40 20 + drawPixmap the_pixmap 60 40 40 20 60 40 40 20 + drawPixmap the_pixmap 40 0 20 100 40 0 20 100 + + # subrecting w/scale + translate 120 0 + drawPixmap the_pixmap 0 0 50 50 0 0 25 25 + drawPixmap the_pixmap 50 0 50 50 25 0 25 25 + drawPixmap the_pixmap 0 50 50 50 0 25 25 25 + drawPixmap the_pixmap 50 50 50 50 25 25 25 25 + + # subrecting w/scale & smooth xform + translate 120 0 + setRenderHint SmoothPixmapTransformation + drawPixmap the_pixmap 0 0 50 50 0 0 25 25 + drawPixmap the_pixmap 50 0 50 50 25 0 25 25 + drawPixmap the_pixmap 0 50 50 50 0 25 25 25 + drawPixmap the_pixmap 50 50 50 50 25 25 25 25 + + + # Rotation w/o smooth xform + translate 120 0 + save + setRenderHint SmoothPixmapTransform off + rotate 10 + drawPixmap the_pixmap 0 0 + restore + + # Rotation w smooth xform + translate 120 0 + save + setRenderHint SmoothPixmapTransform + rotate 10 + drawPixmap the_pixmap 0 0 + restore + +restore + +end_block + + +translate 0 120 +pixmap_load dome_rgb32.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_indexed.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_indexed_mask.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_mono.png the_pixmap +repeat_block draw_stuff + + +resetMatrix +translate 700 60 +setPen black +drawText 0 0 "32 bit w/alpha" +translate 0 120 +drawText 0 0 "32 bit w/o alpha" +translate 0 120 +drawText 0 0 "8 bit indexed" +translate 0 120 +drawText 0 0 "8 bit indexed w/mask" +translate 0 120 +drawText 0 0 "1 bit" +resetMatrix +translate 0 600 +drawText 0 0 "normal" +translate 120 0 +drawText 0 0 "subrect" +translate 120 0 +drawText 0 0 "subrect scale" +translate 120 0 +drawText 0 0 "subrect scale smooth" +translate 120 0 +drawText 0 0 "xform" +translate 120 0 +drawText 0 0 "smooth xform" +translate 120 0
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/porter_duff.qps b/tests/baseline/painting/scripts/porter_duff.qps new file mode 100644 index 0000000000..94e9c68522 --- /dev/null +++ b/tests/baseline/painting/scripts/porter_duff.qps @@ -0,0 +1,251 @@ +# Version: 1 +# CheckVsReference: 5% + + +translate 0 50 + +surface_begin 0 0 100 100 + +begin_block predraw +setRenderHint Antialiasing +setPen nopen +setBrush 0x7f000000 +drawEllipse 10 10 80 80 +end_block + +setCompositionMode SourceOver + +begin_block postdraw + + +setBrush 0x1fff0000 +drawRect 0 0 50 50 + +setBrush 0xdf00ff00 +drawRect 50 50 50 50 + +setBrush 0x7f0000ff +drawEllipse 30 30 40 40 + +# a black rectangle around +setCompositionMode SourceOver +setPen black +setBrush nobrush +drawRect 0.5 0.5 99 99 + +end_block +surface_end + + +# Destination over +surface_begin 100 0 100 100 +repeat_block predraw +setCompositionMode DestinationOver +repeat_block postdraw +surface_end + + +# Clear +surface_begin 200 0 100 100 +repeat_block predraw +setCompositionMode Clear +repeat_block postdraw +surface_end + + +# Source +surface_begin 300 0 100 100 +repeat_block predraw +setCompositionMode Source +repeat_block postdraw +surface_end + + +# Destination +surface_begin 400 0 100 100 +repeat_block predraw +setCompositionMode Destination +repeat_block postdraw +surface_end + + +# Source In +surface_begin 500 0 100 100 +repeat_block predraw +setCompositionMode SourceIn +repeat_block postdraw +surface_end + +translate 0 50 + +# Destination In +surface_begin 0 100 100 100 +repeat_block predraw +setCompositionMode DestinationIn +repeat_block postdraw +surface_end + + +# Source Out +surface_begin 100 100 100 100 +repeat_block predraw +setCompositionMode SourceOut +repeat_block postdraw +surface_end + + +# Destination Out +surface_begin 200 100 100 100 +repeat_block predraw +setCompositionMode DestinationOut +repeat_block postdraw +surface_end + + +# SourceAtop +surface_begin 300 100 100 100 +repeat_block predraw +setCompositionMode SourceAtop +repeat_block postdraw +surface_end + + +# DestinationAtop +surface_begin 400 100 100 100 +repeat_block predraw +setCompositionMode DestinationAtop +repeat_block postdraw +surface_end + + +# Xor +surface_begin 500 100 100 100 +repeat_block predraw +setCompositionMode Xor +repeat_block postdraw +surface_end + +translate 0 50 + +# Plus +surface_begin 0 200 100 100 +repeat_block predraw +setCompositionMode Plus +repeat_block postdraw +surface_end + + +# Multiply +surface_begin 100 200 100 100 +repeat_block predraw +setCompositionMode Multiply +repeat_block postdraw +surface_end + + +# Screen +surface_begin 200 200 100 100 +repeat_block predraw +setCompositionMode Screen +repeat_block postdraw +surface_end + + +# Overlay +surface_begin 300 200 100 100 +repeat_block predraw +setCompositionMode Overlay +repeat_block postdraw +surface_end + + +# Darken +surface_begin 400 200 100 100 +repeat_block predraw +setCompositionMode Darken +repeat_block postdraw +surface_end + + +# Lighten +surface_begin 500 200 100 100 +repeat_block predraw +setCompositionMode Lighten +repeat_block postdraw +surface_end + +translate 0 50 + +# ColorDodge +surface_begin 0 300 100 100 +repeat_block predraw +setCompositionMode ColorDodge +repeat_block postdraw +surface_end + + +# ColorBurn +surface_begin 100 300 100 100 +repeat_block predraw +setCompositionMode ColorBurn +repeat_block postdraw +surface_end + + +# HardLight +surface_begin 200 300 100 100 +repeat_block predraw +setCompositionMode HardLight +repeat_block postdraw +surface_end + + +# SoftLight +surface_begin 300 300 100 100 +repeat_block predraw +setCompositionMode SoftLight +repeat_block postdraw +surface_end + + +# Difference +surface_begin 400 300 100 100 +repeat_block predraw +setCompositionMode Difference +repeat_block postdraw +surface_end + + +# Exclusion +surface_begin 500 300 100 100 +repeat_block predraw +setCompositionMode Exclusion +repeat_block postdraw +surface_end + +resetMatrix + +drawText 0 50 "SourceOver" +drawText 100 50 "DestinationOver" +drawText 200 50 "Clear" +drawText 300 50 "Source" +drawText 400 50 "Destination" +drawText 500 50 "SourceIn" +drawText 0 200 "DestinationIn" +drawText 100 200 "SourceOut" +drawText 200 200 "DestinationOut" +drawText 300 200 "SourceAtop" +drawText 400 200 "DestinationAtop" +drawText 500 200 "Xor" +drawText 0 350 "Plus" +drawText 100 350 "Multiply" +drawText 200 350 "Screen" +drawText 300 350 "Overlay" +drawText 400 350 "Darken" +drawText 500 350 "Lighten" +drawText 0 500 "ColorDodge" +drawText 100 500 "ColorBurn" +drawText 200 500 "HardLight" +drawText 300 500 "SoftLight" +drawText 400 500 "Difference" +drawText 500 500 "Exclusion" diff --git a/tests/baseline/painting/scripts/porter_duff2.qps b/tests/baseline/painting/scripts/porter_duff2.qps new file mode 100644 index 0000000000..f538371ca1 --- /dev/null +++ b/tests/baseline/painting/scripts/porter_duff2.qps @@ -0,0 +1,261 @@ +# Version: 1 +# CheckVsReference: 1% (0 50 600 100) +# CheckVsReference: 1% (0 200 600 100) +# CheckVsReference: 1% (0 350 600 100) +# CheckVsReference: 1% (0 500 600 100) + +translate 0 50 + +surface_begin 0 0 100 100 + +begin_block predraw +setRenderHint Antialiasing +setPen nopen +gradient_clearStops +gradient_appendStop 0 efff0000 +gradient_appendStop 0.5 dfffff00 +gradient_appendStop 1 ef00ff00 + +gradient_setSpread PadSpread +gradient_setLinear 10 10 90 90 +drawEllipse 10 10 80 80 +end_block + +setCompositionMode SourceOver + +begin_block postdraw + +gradient_clearStops +gradient_appendStop 0 afff0000 +gradient_appendStop 0.5 cf0000ff +gradient_appendStop 1 bf00ff00 + +gradient_setSpread PadSpread +gradient_setLinear 0 0 100 0 +drawEllipse 10 10 30 30 +drawEllipse 10 60 30 30 +drawEllipse 60 60 30 30 +drawEllipse 60 10 30 30 +drawEllipse 35 35 30 30 + +# a black rectangle around +setCompositionMode SourceOver +setPen black +setBrush nobrush +drawRect 0.5 0.5 99 99 + +end_block +surface_end + +# Destination over +surface_begin 100 0 100 100 +repeat_block predraw +setCompositionMode DestinationOver +repeat_block postdraw +surface_end + + +# Clear +surface_begin 200 0 100 100 +repeat_block predraw +setCompositionMode Clear +repeat_block postdraw +surface_end + + +# Source +surface_begin 300 0 100 100 +repeat_block predraw +setCompositionMode Source +repeat_block postdraw +surface_end + + +# Destination +surface_begin 400 0 100 100 +repeat_block predraw +setCompositionMode Destination +repeat_block postdraw +surface_end + + +# Source In +surface_begin 500 0 100 100 +repeat_block predraw +setCompositionMode SourceIn +repeat_block postdraw +surface_end + +translate 0 50 + +# Destination In +surface_begin 0 100 100 100 +repeat_block predraw +setCompositionMode DestinationIn +repeat_block postdraw +surface_end + + +# Source Out +surface_begin 100 100 100 100 +repeat_block predraw +setCompositionMode SourceOut +repeat_block postdraw +surface_end + + +# Destination Out +surface_begin 200 100 100 100 +repeat_block predraw +setCompositionMode DestinationOut +repeat_block postdraw +surface_end + + +# SourceAtop +surface_begin 300 100 100 100 +repeat_block predraw +setCompositionMode SourceAtop +repeat_block postdraw +surface_end + + +# DestinationAtop +surface_begin 400 100 100 100 +repeat_block predraw +setCompositionMode DestinationAtop +repeat_block postdraw +surface_end + + +# Xor +surface_begin 500 100 100 100 +repeat_block predraw +setCompositionMode Xor +repeat_block postdraw +surface_end + +translate 0 50 + +# Plus +surface_begin 0 200 100 100 +repeat_block predraw +setCompositionMode Plus +repeat_block postdraw +surface_end + + +# Multiply +surface_begin 100 200 100 100 +repeat_block predraw +setCompositionMode Multiply +repeat_block postdraw +surface_end + + +# Screen +surface_begin 200 200 100 100 +repeat_block predraw +setCompositionMode Screen +repeat_block postdraw +surface_end + + +# Overlay +surface_begin 300 200 100 100 +repeat_block predraw +setCompositionMode Overlay +repeat_block postdraw +surface_end + + +# Darken +surface_begin 400 200 100 100 +repeat_block predraw +setCompositionMode Darken +repeat_block postdraw +surface_end + + +# Lighten +surface_begin 500 200 100 100 +repeat_block predraw +setCompositionMode Lighten +repeat_block postdraw +surface_end + +translate 0 50 + +# ColorDodge +surface_begin 0 300 100 100 +repeat_block predraw +setCompositionMode ColorDodge +repeat_block postdraw +surface_end + + +# ColorBurn +surface_begin 100 300 100 100 +repeat_block predraw +setCompositionMode ColorBurn +repeat_block postdraw +surface_end + + +# HardLight +surface_begin 200 300 100 100 +repeat_block predraw +setCompositionMode HardLight +repeat_block postdraw +surface_end + + +# SoftLight +surface_begin 300 300 100 100 +repeat_block predraw +setCompositionMode SoftLight +repeat_block postdraw +surface_end + + +# Difference +surface_begin 400 300 100 100 +repeat_block predraw +setCompositionMode Difference +repeat_block postdraw +surface_end + + +# Exclusion +surface_begin 500 300 100 100 +repeat_block predraw +setCompositionMode Exclusion +repeat_block postdraw +surface_end + +resetMatrix + +drawText 0 50 "SourceOver" +drawText 100 50 "DestinationOver" +drawText 200 50 "Clear" +drawText 300 50 "Source" +drawText 400 50 "Destination" +drawText 500 50 "SourceIn" +drawText 0 200 "DestinationIn" +drawText 100 200 "SourceOut" +drawText 200 200 "DestinationOut" +drawText 300 200 "SourceAtop" +drawText 400 200 "DestinationAtop" +drawText 500 200 "Xor" +drawText 0 350 "Plus" +drawText 100 350 "Multiply" +drawText 200 350 "Screen" +drawText 300 350 "Overlay" +drawText 400 350 "Darken" +drawText 500 350 "Lighten" +drawText 0 500 "ColorDodge" +drawText 100 500 "ColorBurn" +drawText 200 500 "HardLight" +drawText 300 500 "SoftLight" +drawText 400 500 "Difference" +drawText 500 500 "Exclusion" diff --git a/tests/baseline/painting/scripts/primitives.qps b/tests/baseline/painting/scripts/primitives.qps new file mode 100644 index 0000000000..f44ba27566 --- /dev/null +++ b/tests/baseline/painting/scripts/primitives.qps @@ -0,0 +1,184 @@ +# Version: 1#Version: 1 +# CheckVsReference: 5% + + +# CheckVsReference: 5% + +setBrush #ff7f7fff +setPen black 1 solidline +translate 20 20 +begin_block testblock +save +drawRect 0 0 10 10 +drawRect 20 0 20 10 +drawRect 0 20 10 20 +drawRect 20 20 20 20 +translate 50 0 +setPen NoPen +drawRect 0 0 10 10 +drawRect 20 0 20 10 +drawRect 0 20 10 20 +drawRect 20 20 20 20 +restore +save +translate 0 50 +drawEllipse 0 0 10 10 +drawEllipse 20 0 20 10 +drawEllipse 0 20 10 20 +drawEllipse 20 20 20 20 +translate 50 0 +setPen NoPen +drawEllipse 0 0 10 10 +drawEllipse 20 0 20 10 +drawEllipse 0 20 10 20 +drawEllipse 20 20 20 20 +restore +save +translate 0 100 +drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] +save +translate 0 50 +drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] Winding +translate 0 45 +drawPolyline [ 0 0 50 0 25 25 ] +restore +setPen NoPen +translate 50 0 +drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] +save +translate 0 50 +drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] Winding +restore +save +translate -20 100 +drawPie 0 0 50 50 0 1500 +restore +restore +end_block +setPen black 1 SolidLine FlatCap +translate 200 0 +scale 2 1 +rotate 10 +repeat_block testblock +resetMatrix +translate 0 250 +setBrush 7f7f7fff +translate 20 20 +repeat_block testblock +setPen black 1 SolidLine FlatCap +translate 200 0 +scale 2 1 +rotate 10 +repeat_block testblock +resetMatrix +save +setRenderHint LineAntialiasing +setBrush 7f7fff +translate 20 500 +repeat_block testblock +translate 200 0 +scale 2 1 +rotate 10 +repeat_block testblock +restore +setRenderHint LineAntialiasing false +translate 420 20 +begin_block lines +drawLine 0 0 100 0 +drawLine 0 0 100 10 +drawLine 0 0 100 20 +drawLine 0 0 100 30 +drawLine 0 0 100 40 +drawLine 0 0 100 50 +drawLine 0 0 100 60 +drawLine 0 0 100 70 +drawLine 0 0 100 80 +drawLine 0 0 100 90 +drawLine 0 0 100 100 +drawLine 0 0 90 100 +drawLine 0 0 80 100 +drawLine 0 0 70 100 +drawLine 0 0 60 100 +drawLine 0 0 50 100 +drawLine 0 0 40 100 +drawLine 0 0 30 100 +drawLine 0 0 20 100 +drawLine 0 0 10 100 +drawLine 0 0 0 100 +end_block +setRenderHint LineAntialiasing +translate 0 120 +repeat_block lines +translate 0 120 +scale 5 2 +repeat_block lines +resetMatrix +translate 420 500 +begin_block roundedrects +save +drawRoundedRect 0 0 50 30 5 5 +translate 60 0 +drawRoundedRect 0 0 50 30 7.5 7.5 +translate 60 0 +drawRoundedRect 0 0 50 30 10 10 +translate 60 0 +drawRoundedRect 0 0 50 30 12.5 12.5 +translate 60 0 +drawRoundedRect 0 0 50 30 15 15 +restore +save +translate 0 40 +drawRoundedRect 0 0 50 30 20 20 RelativeSize +translate 60 0 +drawRoundedRect 0 0 50 30 40 40 RelativeSize +translate 60 0 +drawRoundedRect 0 0 50 30 60 60 RelativeSize +translate 60 0 +drawRoundedRect 0 0 50 30 80 80 RelativeSize +translate 60 0 +drawRoundedRect 0 0 50 30 100 100 RelativeSize +restore +end_block +translate 0.5 80.5 +repeat_block roundedrects +translate -0.5 79.5 +setRenderHint Antialiasing off +repeat_block roundedrects +resetMatrix +setRenderHint Antialiasing off +setPen black 1 +begin_block drawShapes +translate 550.5 25 +rotate 45 +setBrush nobrush +drawEllipse -10 -10 20 20 +drawLine 10 0 50 0 +drawRect 50 -7 14 14 +resetMatrix +end_block +setPen black 2 +translate 25 0 +repeat_block drawShapes +setPen black 3 +translate 50 0 +repeat_block drawShapes +setPen black 4 +translate 75 0 +repeat_block drawShapes +resetMatrix +setRenderHint Antialiasing off +setPen nopen +translate 550 100 +setBrush #7f7f7fff +drawRect -0.5 -0.5 21 21 +setBrush red +drawEllipse 0 0 20 20 +setBrush nobrush +setPen black +drawEllipse 0 0 20 20 +translate 25 0 +setPen nopen +setBrush #7f7f7fff +drawRect 0 0 20 20 +setBrush red +drawEllipse 0 0 20 20
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/radial_gradients.qps b/tests/baseline/painting/scripts/radial_gradients.qps new file mode 100644 index 0000000000..b55df8bde6 --- /dev/null +++ b/tests/baseline/painting/scripts/radial_gradients.qps @@ -0,0 +1,99 @@ +# Version: 1 +# CheckVsReference: 5% (0 0 600 400) + +path_addRect path 400 0 80 80 +path_addEllipse path 440 40 60 60 + +setRenderHint Antialiasing + +setPen black + +begin_block gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setRadial 20 20 50 40 40 +drawRect 0 0 100 100 + +gradient_setSpread ReflectSpread +gradient_setRadial 120 20 50 140 40 +drawEllipse 100 0 100 100 + +gradient_setSpread RepeatSpread +gradient_setRadial 220 20 50 240 40 +drawRoundRect 200 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setSpread PadSpread +gradient_setRadial 320 20 50 340 40 +drawPolygon [300 0 390 0 350 99] + +gradient_setSpread ReflectSpread +gradient_setRadial 420 20 50 440 40 +drawPath path + +gradient_setSpread RepeatSpread +gradient_setRadial 520 20 50 540 40 +drawPie 500 0 100 100 720 4320 +end_block + +translate 0 100 +scale 1 2 +repeat_block gradients + +resetMatrix +translate 0 300 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block gradients + +# Some helpful info perhaps? +resetMatrix +setPen black + +drawText 610 50 "No XForm" +drawText 610 200 "scale 1x2" +drawText 610 300 "brush transform" +drawText 10 450 "Pad" +drawText 110 450 "Reflect" +drawText 210 450 "Repeat" +drawText 310 450 "Pad w/alpha" +drawText 410 450 "Reflect w/alpha" +drawText 510 450 "Repeat w/alpha" + +# Radius and focal indicators +setPen 3f000000 +setBrush nobrush + +begin_block ellipse_draw +setClipRect 0 0 100 100 +drawEllipse -30 -30 100 100 +drawEllipse 35 35 11 11 +translate 100 0 +end_block + +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw + +resetMatrix +translate 0 100 +scale 1 2 +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/radial_gradients_perspectives.qps b/tests/baseline/painting/scripts/radial_gradients_perspectives.qps new file mode 100644 index 0000000000..4557354dce --- /dev/null +++ b/tests/baseline/painting/scripts/radial_gradients_perspectives.qps @@ -0,0 +1,62 @@ +# Version: 1 + + +setRenderHint Antialiasing + +setPen #00ff00 + +translate 10 10 +# standard draw +begin_block gradient +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setRadial 110 100 230 230 240 +drawRect 0 0 300 300 +end_block gradient + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + repeat_block gradient +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + repeat_block gradient +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + repeat_block gradient +restore +restore + + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/rasterops.qps b/tests/baseline/painting/scripts/rasterops.qps new file mode 100644 index 0000000000..d0f2da42df --- /dev/null +++ b/tests/baseline/painting/scripts/rasterops.qps @@ -0,0 +1,87 @@ +# Version: 1 +# CheckVsReference: 5% + +setPen NoPen + +setBrush black +drawRect 10 10 60 500 + +setCompositionMode SourceOrDestination +translate 20 20 + +begin_block drawShape + setBrush 0xffff0000 + drawEllipse 5 5 30 30 + setBrush 0xff00ff00 + drawRect 0 0 20 20 + setBrush 0xff0000ff + drawRect 20 20 20 20 +end_block + +begin_block loop + setCompositionMode SourceAndDestination + translate 0 50 +repeat_block drawShape + +setCompositionMode SourceXorDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSourceAndNotDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSourceOrNotDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSourceXorDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSource +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSourceAndDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode SourceAndNotDestination +translate 0 50 +repeat_block drawShape +end_block + +resetMatrix +setCompositionMode Source +setBrush white +drawRect 100 10 60 500 +translate 110 20 +repeat_block loop + +resetMatrix +setCompositionMode Source +translate 190 20 +repeat_block loop + +resetMatrix +setPen black +setCompositionMode SourceOver +translate 250 45 +drawText 20 0 "Or ROP" +translate 0 50 +drawText 20 0 "And ROP" +translate 0 50 +drawText 20 0 "Xor ROP" +translate 0 50 +drawText 20 0 "Nor ROP" +translate 0 50 +drawText 20 0 "Nand ROP" +translate 0 50 +drawText 0 0 "NSrcXorDst ROP" +translate 0 50 +drawText 20 0 "NSrc ROP" +translate 0 50 +drawText 0 0 "NSrcAndDst ROP" +translate 0 50 +drawText 0 0 "SrcAndNDst ROP"
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/richtext.qps b/tests/baseline/painting/scripts/richtext.qps new file mode 100644 index 0000000000..787c97421b --- /dev/null +++ b/tests/baseline/painting/scripts/richtext.qps @@ -0,0 +1,9 @@ +drawTextDocument 10 10 "<img height=50 width=50 align=top src=:/images/border.png /><img height=10 width=10 valign=bottom src=:/images/border.png /><span style='font-size: 100px'>Xy</span>" +drawTextDocument 10 210 "<img height=50 width=50 align=top src=:/images/border.png /><img height=10 width=10 valign=bottom src=:/images/border.png /><span style='font-size: 25px'>Xy</span>" +drawTextDocument 310 210 "<img height=10 width=10 align=top src=:/images/border.png /><img height=50 width=50 valign=bottom src=:/images/border.png /><span style='font-size: 25px'>Xy</span>" +drawTextDocument 10 310 "<img height=50 width=50 align=top src=:/images/border.png /><img height=50 width=50 valign=bottom src=:/images/border.png /><span style='font-size: 25px'>Xy</span>" + +drawTextDocument 10 410 "<img height=10 width=10 align=top src=:/images/border.png /><img height=50 width=50 src=:/images/border.png /><span style='font-size: 25px'>Xy</span>" +drawTextDocument 10 510 "<img height=10 width=10 valign=bottom src=:/images/border.png /><img height=50 width=50 src=:/images/border.png /><span style='font-size: 25px'>Xy</span>" +drawTextDocument 310 410 "<img height=50 width=50 align=top src=:/images/border.png /><img height=10 width=10 src=:/images/border.png /><span style='font-size: 25px'>Xy</span>" +drawTextDocument 310 510 "<img height=50 width=50 valign=bottom src=:/images/border.png /><img height=10 width=10 src=:/images/border.png /><span style='font-size: 25px'>Xy</span>" diff --git a/tests/baseline/painting/scripts/sizes.qps b/tests/baseline/painting/scripts/sizes.qps new file mode 100644 index 0000000000..12b0f4af1e --- /dev/null +++ b/tests/baseline/painting/scripts/sizes.qps @@ -0,0 +1,90 @@ +# Version: 1 +# CheckVsReference: 5% + +setPen NoPen +setBrush black + +translate 10 10 + +begin_block testblock +drawRect 0 0 10 10 +drawRect 20 0 11 11 +drawRect 40 0 12 12 +drawRect 60 0 13 13 +drawRect 80 0 14 14 +drawRect 100 0 15 15 +drawRect 120 0 16 16 +drawRect 140 0 17 17 +drawRect 160 0 18 18 +drawRect 180 0 19 19 + +drawEllipse 0 20 10 10 +drawEllipse 20 20 11 11 +drawEllipse 40 20 12 12 +drawEllipse 60 20 13 13 +drawEllipse 80 20 14 14 +drawEllipse 100 20 15 15 +drawEllipse 120 20 16 16 +drawEllipse 140 20 17 17 +drawEllipse 160 20 18 18 +drawEllipse 180 20 19 19 + +drawRoundRect 0 40 10 10 +drawRoundRect 20 40 11 11 +drawRoundRect 40 40 12 12 +drawRoundRect 60 40 13 13 +drawRoundRect 80 40 14 14 +drawRoundRect 100 40 15 15 +drawRoundRect 120 40 16 16 +drawRoundRect 140 40 17 17 +drawRoundRect 160 40 18 18 +drawRoundRect 180 40 19 19 + +drawPie 0 60 10 10 0 4320 +drawPie 20 60 11 11 0 4320 +drawPie 40 60 12 12 0 4320 +drawPie 60 60 13 13 0 4320 +drawPie 80 60 14 14 0 4320 +drawPie 100 60 15 15 0 4320 +drawPie 120 60 16 16 0 4320 +drawPie 140 60 17 17 0 4320 +drawPie 160 60 18 18 0 4320 +drawPie 180 60 19 19 0 4320 + +drawArc 0 80 10 10 0 4320 +drawArc 20 80 11 11 0 4320 +drawArc 40 80 12 12 0 4320 +drawArc 60 80 13 13 0 4320 +drawArc 80 80 14 14 0 4320 +drawArc 100 80 15 15 0 4320 +drawArc 120 80 16 16 0 4320 +drawArc 140 80 17 17 0 4320 +drawArc 160 80 18 18 0 4320 +drawArc 180 80 19 19 0 4320 + +drawChord 0 100 10 10 0 4320 +drawChord 20 100 11 11 0 4320 +drawChord 40 100 12 12 0 4320 +drawChord 60 100 13 13 0 4320 +drawChord 80 100 14 14 0 4320 +drawChord 100 100 15 15 0 4320 +drawChord 120 100 16 16 0 4320 +drawChord 140 100 17 17 0 4320 +drawChord 160 100 18 18 0 4320 +drawChord 180 100 19 19 0 4320 + +end_block + +setPen red +translate 0 150 +repeat_block testblock + +setRenderHint LineAntialiasing + +setPen nopen +translate 0 150 +repeat_block testblock + +setPen red +translate 0 150 +repeat_block testblock diff --git a/tests/baseline/painting/scripts/smallcaps_path.qps b/tests/baseline/painting/scripts/smallcaps_path.qps new file mode 100644 index 0000000000..4e89b50d96 --- /dev/null +++ b/tests/baseline/painting/scripts/smallcaps_path.qps @@ -0,0 +1,9 @@ +# Version: 1 + +setPen black 1 +setBrush 7f7fff + +setFont "times" 50 Light false Default false false false SmallCaps +path_addText text 0 50 "Hello Qt" + +drawPath text diff --git a/tests/baseline/painting/scripts/statictext.qps b/tests/baseline/painting/scripts/statictext.qps new file mode 100644 index 0000000000..c2a30d0864 --- /dev/null +++ b/tests/baseline/painting/scripts/statictext.qps @@ -0,0 +1,175 @@ +drawStaticText -5 5 "Text that is drawn outside the bounds..." + +translate 20 20 +begin_block text_drawing +save + setFont "sansserif" 10 normal + drawStaticText 0 20 "sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawStaticText 0 60 "sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "sansserif 10pt, bold italic" + + + translate 0 100 + setPen #7fff0000 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "alpha sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "alpha sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawStaticText 0 60 "alpha sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "alpha sansserif 10pt, bold italic" + + + translate 0 100 + setPen black + save + scale 0.9 0.9 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "scaled sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "scaled sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawStaticText 0 60 "scaled sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "scaled sansserif 10pt, bold italic" + restore + + translate 200 200 + setPen black + save + scale -1 -1 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "flipped sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "flipped sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawStaticText 0 60 "flipped sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "flipped sansserif 10pt, bold italic" + restore + + translate -200 20 + setPen black + save + translate 200 90 + rotate 185 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "rotated sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "rotated sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawStaticText 0 60 "rotated sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "rotated sansserif 10pt, bold italic" + restore + + translate 0 100 + gradient_appendStop 0 red + gradient_appendStop 0.5 #00ff00 + gradient_appendStop 1 blue + gradient_setLinear 0 0 200 0 + setPen brush + + setFont "sansserif" 10 normal + drawStaticText 0 0 "gradient sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 20 "gradient sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawStaticText 0 40 "gradient sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 60 "gradient sansserif 10pt, bold italic" +restore +end_block + +translate 250 0 +drawStaticText 25 640 "clipped to rectangle" +save + setPen #3f000000 + setBrush nobrush + drawRect 20 0 100 620 + setClipRect 20 0 100 620 + setPen black + repeat_block text_drawing +restore + +translate 150 0 +drawStaticText 25 640 "clipped to path" +save + path_moveTo clip 20 0 + path_cubicTo clip 0 200 40 400 20 400 + path_lineTo clip 30 620 + path_lineTo clip 30 0 + path_lineTo clip 40 0 + path_lineTo clip 40 620 + path_lineTo clip 120 620 + path_lineTo clip 120 0 + path_lineTo clip 20 0 + setPen #3f000000 + setBrush nobrush + drawPath clip + setClipPath clip + setPen black + repeat_block text_drawing +restore + +translate 150 0 +save + setPen black + setFont "sansserif" 16 normal + drawStaticText 0 40 "e😃m😇o😍j😜i😸!" +restore + +translate 0 55 +save + setPen black + setFont "sansserif" 12 normal normal default underline + drawStaticText 0 20 "Underlined text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default normal strikeout + drawStaticText 0 20 "Struck out text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default normal normal overline + drawStaticText 0 20 "Overlined text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default underline strikeout overline + drawStaticText 0 20 "All the effects text drawing" +restore diff --git a/tests/baseline/painting/scripts/text.qps b/tests/baseline/painting/scripts/text.qps new file mode 100644 index 0000000000..6bacdfd5e6 --- /dev/null +++ b/tests/baseline/painting/scripts/text.qps @@ -0,0 +1,199 @@ +# Version: 1 + +drawText -5 5 "Text that is drawn outside the bounds..." + +translate 20 20 +begin_block text_drawing +save + setFont "sansserif" 10 normal + drawText 0 20 "sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 40 "sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawText 0 60 "sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 80 "sansserif 10pt, bold italic" + + + translate 0 100 + setPen #7fff0000 + + setFont "sansserif" 10 normal + drawText 0 20 "alpha sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 40 "alpha sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawText 0 60 "alpha sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 80 "alpha sansserif 10pt, bold italic" + + + translate 0 100 + setPen black + save + scale 0.9 0.9 + + setFont "sansserif" 10 normal + drawText 0 20 "scaled sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 40 "scaled sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawText 0 60 "scaled sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 80 "scaled sansserif 10pt, bold italic" + restore + + translate 200 200 + setPen black + save + scale -1 -1 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "flipped sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "flipped sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawStaticText 0 60 "flipped sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "flipped sansserif 10pt, bold italic" + restore + + translate -200 20 + setPen black + save + translate 200 90 + rotate 185 + + setFont "sansserif" 10 normal + drawText 0 20 "rotated sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 40 "rotated sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawText 0 60 "rotated sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 80 "rotated sansserif 10pt, bold italic" + restore + + translate 0 100 + gradient_appendStop 0 red + gradient_appendStop 0.5 #00ff00 + gradient_appendStop 1 blue + gradient_setLinear 0 0 200 0 + setPen brush + + setFont "sansserif" 10 normal + drawText 0 0 "gradient sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 20 "gradient sansserif 12pt, normal" + + setFont "sansserif" 12 bold + drawText 0 40 "gradient sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 60 "gradient sansserif 10pt, bold italic" +restore +end_block + +translate 250 0 +drawText 25 640 "clipped to rectangle" +save + setPen #3f000000 + setBrush nobrush + drawRect 20 0 100 620 + setClipRect 20 0 100 620 + setPen black + repeat_block text_drawing +restore + +translate 150 0 +drawText 25 640 "clipped to path" +save + path_moveTo clip 20 0 + path_cubicTo clip 0 200 40 400 20 400 + path_lineTo clip 30 620 + path_lineTo clip 30 0 + path_lineTo clip 40 0 + path_lineTo clip 40 620 + path_lineTo clip 120 620 + path_lineTo clip 120 0 + path_lineTo clip 20 0 + setPen #3f000000 + setBrush nobrush + drawPath clip + setClipPath clip + setPen black + repeat_block text_drawing +restore + +translate 150 0 +save + setPen black + setFont "sansserif" 10 normal + drawText 0 20 "testing glyph cache textures" + + # Important that this gradient doesn't match any earlier + # gradients, so that it's not cached from before. + gradient_clearStops + gradient_appendStop 0 blue + gradient_appendStop 0.5 #00ff00 + gradient_appendStop 1 red + gradient_setLinear 0 0 100 0 + setPen nopen + drawRect 0 30 100 20 + + setPen black + drawText 0 70 "testing glyph cache textures" +restore + +translate 0 75 +save + setPen black + setFont "sansserif" 16 normal + drawText 0 40 "e😃m😇o😍j😜i😸!✈️" +restore + +translate 0 75 +save + setPen black + setFont "sansserif" 12 normal normal default underline + drawText 0 20 "Underlined text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default normal strikeout + drawText 0 20 "Struck out text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default normal normal overline + drawText 0 20 "Overlined text drawing" +restore + +translate 0 35 +save + setPen black + setFont "sansserif" 12 normal normal default underline strikeout overline + drawText 0 20 "All the effects text drawing" +restore + + diff --git a/tests/baseline/painting/scripts/text_perspectives.qps b/tests/baseline/painting/scripts/text_perspectives.qps new file mode 100644 index 0000000000..4c74306265 --- /dev/null +++ b/tests/baseline/painting/scripts/text_perspectives.qps @@ -0,0 +1,102 @@ +# Version: 1 + + +setRenderHint Antialiasing + +setPen black + +translate 10 10 +# standard draw +begin_block text +setBrush gray +drawRect 0 0 300 300 + +setFont "times" 3 +drawText 10 10 "Hello World...." + +setFont "times" 4 +drawText 10 20 "Hello World...." + +setFont "times" 5 +drawText 10 30 "Hello World...." + +setFont "times" 6 +drawText 10 40 "Hello World...." + +setFont "times" 7 +drawText 10 50 "Hello World...." + +setFont "times" 8 +drawText 10 60 "Hello World...." + +setFont "times" 9 +drawText 10 70 "Hello World...." + +setFont "times" 10 +drawText 10 80 "Hello World...." + +setFont "times" 16 +drawText 10 100 "Hello World...." + +setFont "times" 17 +drawText 10 120 "Hello World...." + +setFont "times" 18 +drawText 10 140 "Hello World...." + +setFont "times" 20 +drawText 10 160 "Hello World...." + +setFont "times" 22 +drawText 10 180 "Hello World...." + +setFont "times" 24 +drawText 10 205 "Hello World...." + +setFont "times" 26 +drawText 10 230 "Hello World...." + +setFont "times" 32 +drawText 10 260 "Hello World...." +end_block text + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + repeat_block text +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + repeat_block text +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + repeat_block text +restore +restore + + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0
\ No newline at end of file diff --git a/tests/baseline/painting/scripts/thinlines.qps b/tests/baseline/painting/scripts/thinlines.qps new file mode 100644 index 0000000000..dddfff4538 --- /dev/null +++ b/tests/baseline/painting/scripts/thinlines.qps @@ -0,0 +1,79 @@ +# Version: 1 +# CheckVsReference: 5% + +drawRect 0 0 800 800 + +path_addRect p 0 0 75 75 +path_addEllipse p 25 25 75 75 + +translate -500 -500 + +begin_block drawing + save + drawLine 0 0 100 100 + + translate 0 100 + drawPath p + + translate 0 110 + drawRect 0 0 100 100 + + translate 0 110 + drawPolyline [0 0 100 0 50 50] + + drawPoint 40 40 + drawPoint 41 40 + drawPoint 42 40 + drawPoint 43 40 + drawPoint 44 40 + drawPoint 45 40 + drawPoint 46 40 + drawPoint 47 40 + drawPoint 48 40 + drawPoint 49 40 + drawPoint 50 40 + + restore +end_block + +begin_block univsnonuni + save + + save + scale 0.7 0.7 + repeat_block drawing + restore + + translate 100 0 + save + scale 0.7 0.8 + repeat_block drawing + restore + + restore +end_block + +resetMatrix +translate 20.5 20.5 + +begin_block row +save + repeat_block univsnonuni + + translate 240 0 + save + rotate 10 + repeat_block univsnonuni + restore + + translate 220 0 + save + rotate_y 30 + repeat_block univsnonuni + restore +restore +end_block + +translate 0 320 +setRenderHint AntiAliasing +repeat_block row diff --git a/tests/baseline/painting/scripts/tiled_pixmap.qps b/tests/baseline/painting/scripts/tiled_pixmap.qps new file mode 100644 index 0000000000..0ce3a7834c --- /dev/null +++ b/tests/baseline/painting/scripts/tiled_pixmap.qps @@ -0,0 +1,84 @@ +# Version: 1 +# CheckVsReference: 5% (0 0 639 638) + + +translate 0 10 +setRenderHint Antialiasing + +pixmap_load dome_argb32 the_pixmap + +begin_block draw_stuff +save + + # Standard draw + drawTiledPixmap the_pixmap 0 0 150 100 0 0 + + # Standard draw with offset + translate 160 0 + drawTiledPixmap the_pixmap 0 0 150 100 25 25 + + # xformed + translate 160 0 + save + translate 10 -10 + rotate 10 + setRenderHint SmoothPixmapTransform false + drawTiledPixmap the_pixmap 0 0 150 100 25 25 + restore + + # xformed with smooth xform + translate 160 0 + save + translate 10 -10 + rotate 10 + setRenderHint SmoothPixmapTransform + drawTiledPixmap the_pixmap 0 0 150 100 25 25 + restore +restore +end_block + +translate 0 120 +pixmap_load dome_rgb32 the_pixmap +repeat_block draw_stuff + + +translate 0 120 +pixmap_load dome_indexed the_pixmap +repeat_block draw_stuff + + +translate 0 120 +pixmap_load dome_indexed_mask the_pixmap +repeat_block draw_stuff + + +translate 0 120 +pixmap_load dome_mono the_pixmap +repeat_block draw_stuff + + +################################################################################ +# Some helpful text... +# + +resetMatrix +translate 650 80 +drawText 0 0 "32 bit w/alpha" +translate 0 120 +drawText 0 0 "32 bit w/o alpha" +translate 0 120 +drawText 0 0 "8 bit indexed" +translate 0 120 +drawText 0 0 "8 bit indexed w/mask" +translate 0 120 +drawText 0 0 "1 bit" + +resetMatrix +translate 10 630 +drawText 0 0 "normal" +translate 160 0 +drawText 0 0 "offset" +translate 160 0 +drawText 0 0 "xformed" +translate 160 0 +drawText 0 0 "smooth xformed" diff --git a/tests/baseline/painting/scripts/tinydashes.qps b/tests/baseline/painting/scripts/tinydashes.qps new file mode 100644 index 0000000000..d41ced7f5f --- /dev/null +++ b/tests/baseline/painting/scripts/tinydashes.qps @@ -0,0 +1,34 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addEllipse mypath 20.0 20.0 200.0 200.0 + +save +setPen blue 20 SolidLine FlatCap +pen_setCosmetic true +pen_setDashPattern [ 0.0004 0.0004 ] +setBrush yellow + +drawPath mypath +translate 300 0 +setRenderHint Antialiasing true +drawPath mypath +restore + +path_addEllipse bigpath 200000.0 200000.0 2000000.0 2000000.0 + +setPen blue 20 DotLine FlatCap +setBrush yellow + +save +translate 0 300 +scale 0.0001 0.00011 +drawPath bigpath +restore + +save +translate 300 300 +setRenderHint Antialiasing true +scale 0.0001 0.00011 +drawPath bigpath +restore diff --git a/tests/baseline/painting/tst_baseline_painting.cpp b/tests/baseline/painting/tst_baseline_painting.cpp new file mode 100644 index 0000000000..f486b33430 --- /dev/null +++ b/tests/baseline/painting/tst_baseline_painting.cpp @@ -0,0 +1,489 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses + +#include "paintcommands.h" +#include <qbaselinetest.h> +#include <QDir> +#include <QPainter> +#include <QPdfWriter> +#include <QTemporaryFile> +#if QT_CONFIG(process) +#include <QProcess> +#endif + +#ifndef QT_NO_OPENGL +#include <QOpenGLFramebufferObjectFormat> +#include <QOpenGLContext> +#include <QOpenGLPaintDevice> +#endif + +#include <algorithm> + +#ifndef GL_RGB10 +#define GL_RGB10 0x8052 +#endif +#ifndef GL_RGB10_A2 +#define GL_RGB10_A2 0x8059 +#endif + +class tst_Lancelot : public QObject +{ +Q_OBJECT + +public: + tst_Lancelot(); + +private: + enum GraphicsEngine { + Raster = 0, + OpenGL = 1, + Pdf = 2 + }; + + void setupTestSuite(const QStringList& blacklist = QStringList()); + void runTestSuite(GraphicsEngine engine, QImage::Format format, + const QSurfaceFormat &contextFormat = QSurfaceFormat::defaultFormat()); + void paint(QPaintDevice *device, GraphicsEngine engine, QImage::Format format, const QStringList &script, const QString &filePath); + + QStringList qpsFiles; + QHash<QString, QStringList> scripts; + QHash<QString, quint16> scriptChecksums; + QString scriptsDir; + +private slots: + void initTestCase(); + void init(); + + void testRasterARGB32PM_data(); + void testRasterARGB32PM(); + void testRasterRGB32_data(); + void testRasterRGB32(); + void testRasterARGB32_data(); + void testRasterARGB32(); + void testRasterRGB16_data(); + void testRasterRGB16(); + void testRasterA2RGB30PM_data(); + void testRasterA2RGB30PM(); + void testRasterBGR30_data(); + void testRasterBGR30(); + void testRasterARGB8565PM_data(); + void testRasterARGB8565PM(); + void testRasterGrayscale8_data(); + void testRasterGrayscale8(); + void testRasterRGBA64PM_data(); + void testRasterRGBA64PM(); + void testRasterRGBA16F_data(); + void testRasterRGBA16F(); + void testRasterRGBA32FPM_data(); + void testRasterRGBA32FPM(); + + void testPdf_data(); + void testPdf(); + +#ifndef QT_NO_OPENGL + void testOpenGL_data(); + void testOpenGL(); + void testOpenGLBGR30_data(); + void testOpenGLBGR30(); + void testCoreOpenGL_data(); + void testCoreOpenGL(); +private: + void initOpenGL(); + bool checkSystemGLSupport(); + bool checkSystemCoreGLSupport(); +#endif +}; + +tst_Lancelot::tst_Lancelot() +{ +} + +void tst_Lancelot::initTestCase() +{ + // Check and setup the environment. We treat failures because of test environment + // (e.g. script files not found) as just warnings, and not QFAILs, to avoid false negatives + // caused by environment or server instability + + QByteArray msg; + if (!QBaselineTest::connectToBaselineServer(&msg)) + QSKIP(msg); + + QString baseDir = QFINDTESTDATA("scripts/text.qps"); + scriptsDir = baseDir.left(baseDir.lastIndexOf('/')) + '/'; + QDir qpsDir(scriptsDir); + qpsFiles = qpsDir.entryList(QStringList() << QLatin1String("*.qps"), QDir::Files | QDir::Readable); + if (qpsFiles.isEmpty()) { + qWarning() << "No qps script files found in" << qpsDir.path(); + QSKIP("Aborted due to errors."); + } + + std::sort(qpsFiles.begin(), qpsFiles.end()); + foreach (const QString& fileName, qpsFiles) { + QFile file(scriptsDir + fileName); + QVERIFY(file.open(QFile::ReadOnly)); + QByteArray cont = file.readAll(); + scripts.insert(fileName, QString::fromUtf8(cont).split(QLatin1Char('\n'), Qt::SkipEmptyParts)); + scriptChecksums.insert(fileName, qChecksum(cont)); + } + +#ifndef QT_NO_OPENGL + initOpenGL(); +#endif +} + +void tst_Lancelot::init() +{ + // This gets called for every row. QSKIP if current item is blacklisted on the baseline server: + QBASELINE_SKIP_IF_BLACKLISTED; +} + +void tst_Lancelot::testRasterARGB32PM_data() +{ + setupTestSuite(); +} + + +void tst_Lancelot::testRasterARGB32PM() +{ + runTestSuite(Raster, QImage::Format_ARGB32_Premultiplied); +} + + +void tst_Lancelot::testRasterARGB32_data() +{ + setupTestSuite(); +} + +void tst_Lancelot::testRasterARGB32() +{ + runTestSuite(Raster, QImage::Format_ARGB32); +} + + +void tst_Lancelot::testRasterRGB32_data() +{ + setupTestSuite(); +} + + +void tst_Lancelot::testRasterRGB32() +{ + runTestSuite(Raster, QImage::Format_RGB32); +} + + +void tst_Lancelot::testRasterRGB16_data() +{ + setupTestSuite(); +} + + +void tst_Lancelot::testRasterRGB16() +{ + runTestSuite(Raster, QImage::Format_RGB16); +} + + +void tst_Lancelot::testRasterA2RGB30PM_data() +{ + setupTestSuite(); +} + + +void tst_Lancelot::testRasterA2RGB30PM() +{ + runTestSuite(Raster, QImage::Format_A2RGB30_Premultiplied); +} + + +void tst_Lancelot::testRasterBGR30_data() +{ + setupTestSuite(); +} + + +void tst_Lancelot::testRasterBGR30() +{ + runTestSuite(Raster, QImage::Format_BGR30); +} + + +void tst_Lancelot::testRasterARGB8565PM_data() +{ + setupTestSuite(); +} + +void tst_Lancelot::testRasterARGB8565PM() +{ + runTestSuite(Raster, QImage::Format_ARGB8565_Premultiplied); +} + + +void tst_Lancelot::testRasterGrayscale8_data() +{ + setupTestSuite(); +} + +void tst_Lancelot::testRasterGrayscale8() +{ + runTestSuite(Raster, QImage::Format_Grayscale8); +} + + +void tst_Lancelot::testRasterRGBA64PM_data() +{ + setupTestSuite(); +} + +void tst_Lancelot::testRasterRGBA64PM() +{ + runTestSuite(Raster, QImage::Format_RGBA64_Premultiplied); +} + + +void tst_Lancelot::testRasterRGBA16F_data() +{ + setupTestSuite(); +} + +void tst_Lancelot::testRasterRGBA16F() +{ + runTestSuite(Raster, QImage::Format_RGBA16FPx4); +} + +void tst_Lancelot::testRasterRGBA32FPM_data() +{ + setupTestSuite(); +} + +void tst_Lancelot::testRasterRGBA32FPM() +{ + runTestSuite(Raster, QImage::Format_RGBA32FPx4_Premultiplied); +} + + +void tst_Lancelot::testPdf_data() +{ +#ifdef Q_OS_MACOS + setupTestSuite(); +#else + QSKIP("Pdf testing only implemented for macOS"); +#endif +} + +void tst_Lancelot::testPdf() +{ + runTestSuite(Pdf, QImage::Format_RGB32); +} + + +#ifndef QT_NO_OPENGL +void tst_Lancelot::initOpenGL() +{ + // Stencil buffer is needed for clipping + QSurfaceFormat glFormat; + glFormat.setStencilBufferSize(8); + QSurfaceFormat::setDefaultFormat(glFormat); +} + +bool tst_Lancelot::checkSystemGLSupport() +{ + QWindow win; + win.setSurfaceType(QSurface::OpenGLSurface); + win.create(); + QOpenGLFramebufferObjectFormat fmt; + fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + fmt.setSamples(4); + QOpenGLContext ctx; + if (!ctx.create() || !ctx.makeCurrent(&win)) + return false; + QOpenGLFramebufferObject fbo(800, 800, fmt); + if (!fbo.isValid() || !fbo.bind()) + return false; + + return true; +} + +bool tst_Lancelot::checkSystemCoreGLSupport() +{ + if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) + return false; + + QSurfaceFormat coreFormat(QSurfaceFormat::defaultFormat()); + coreFormat.setVersion(3, 2); + coreFormat.setProfile(QSurfaceFormat::CoreProfile); + QWindow win; + win.setSurfaceType(QSurface::OpenGLSurface); + win.setFormat(coreFormat); + win.create(); + QOpenGLFramebufferObjectFormat fmt; + fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + fmt.setSamples(4); + QOpenGLContext ctx; + ctx.setFormat(coreFormat); + if (!ctx.create() || !ctx.makeCurrent(&win)) + return false; + QOpenGLFramebufferObject fbo(800, 800, fmt); + if (!fbo.isValid() || !fbo.bind()) + return false; + + return true; +} + +void tst_Lancelot::testOpenGL_data() +{ + if (!checkSystemGLSupport()) + QSKIP("System under test does not meet preconditions for GL testing. Skipping."); + QStringList localBlacklist = QStringList() << QLatin1String("rasterops.qps"); + setupTestSuite(localBlacklist); +} + + +void tst_Lancelot::testOpenGL() +{ + runTestSuite(OpenGL, QImage::Format_RGB32); +} + +void tst_Lancelot::testOpenGLBGR30_data() +{ + tst_Lancelot::testOpenGL_data(); +} + +void tst_Lancelot::testOpenGLBGR30() +{ + runTestSuite(OpenGL, QImage::Format_BGR30); +} + +void tst_Lancelot::testCoreOpenGL_data() +{ + if (!checkSystemCoreGLSupport()) + QSKIP("System under test does not meet preconditions for Core Profile GL testing. Skipping."); + QStringList localBlacklist = QStringList() << QLatin1String("rasterops.qps"); + setupTestSuite(localBlacklist); +} + +void tst_Lancelot::testCoreOpenGL() +{ + QSurfaceFormat coreFormat(QSurfaceFormat::defaultFormat()); + coreFormat.setVersion(3, 2); + coreFormat.setProfile(QSurfaceFormat::CoreProfile); + runTestSuite(OpenGL, QImage::Format_RGB32, coreFormat); +} +#endif + + +void tst_Lancelot::setupTestSuite(const QStringList& blacklist) +{ + QTest::addColumn<QString>("qpsFile"); + foreach (const QString &fileName, qpsFiles) { + if (blacklist.contains(fileName)) + continue; + QBaselineTest::newRow(fileName.toLatin1(), scriptChecksums.value(fileName)) << fileName; + } +} + + +void tst_Lancelot::runTestSuite(GraphicsEngine engine, QImage::Format format, const QSurfaceFormat &contextFormat) +{ + QFETCH(QString, qpsFile); + + QString filePath = scriptsDir + qpsFile; + QStringList script = scripts.value(qpsFile); + QImage rendered; + + if (engine == Raster) { + QImage img(800, 800, format); + paint(&img, engine, format, script, QFileInfo(filePath).absoluteFilePath()); + rendered = img; +#ifndef QT_NO_OPENGL + } else if (engine == OpenGL) { + QWindow win; + win.setSurfaceType(QSurface::OpenGLSurface); + win.setFormat(contextFormat); + win.create(); + QOpenGLContext ctx; + ctx.setFormat(contextFormat); + QVERIFY(ctx.create()); + QVERIFY(ctx.makeCurrent(&win)); + QOpenGLFramebufferObjectFormat fmt; + fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + fmt.setSamples(4); + if (format == QImage::Format_BGR30) + fmt.setInternalTextureFormat(ctx.isOpenGLES() ? GL_RGB10_A2 : GL_RGB10); + QOpenGLFramebufferObject fbo(800, 800, fmt); + fbo.bind(); + QOpenGLPaintDevice pdv(800, 800); + paint(&pdv, engine, format, script, QFileInfo(filePath).absoluteFilePath()); + rendered = fbo.toImage().convertToFormat(format); +#endif + } else if (engine == Pdf) { +#if QT_CONFIG(process) + QString tempStem(QDir::tempPath() + QLatin1String("/lancelot_XXXXXX_") + qpsFile.chopped(4)); + + QTemporaryFile pdfFile(tempStem + QLatin1String(".pdf")); + QVERIFY(pdfFile.open()); + QPdfWriter writer(&pdfFile); + writer.setPdfVersion(QPdfWriter::PdfVersion_1_6); + QPageSize pageSize(QSize(800, 800), QStringLiteral("LancePage"), QPageSize::ExactMatch); + writer.setPageSize(pageSize); + writer.setPageMargins(QMarginsF()); + writer.setResolution(72); + paint(&writer, engine, format, script, QFileInfo(filePath).absoluteFilePath()); + pdfFile.close(); + + // Convert pdf to something we can read into a QImage, using macOS' sips utility + QTemporaryFile pngFile(tempStem + QLatin1String(".png")); + QVERIFY(pngFile.open()); // Just create the file name + pngFile.close(); + QProcess proc; + const char *rawArgs = "-s format png -o"; + QStringList argList = QString::fromLatin1(rawArgs).split(QLatin1Char(' ')); + proc.start(QLatin1String("sips"), argList << pngFile.fileName() << pdfFile.fileName()); + proc.waitForFinished(2 * 60 * 1000); // May need some time + + rendered = QImage(pngFile.fileName()); +#endif + } + + QBASELINE_TEST(rendered); +} + +void tst_Lancelot::paint(QPaintDevice *device, GraphicsEngine engine, QImage::Format format, const QStringList &script, const QString &filePath) +{ + QPainter p(device); + PaintCommands pcmd(script, 800, 800, format); + //pcmd.setShouldDrawText(false); + switch (engine) { + case OpenGL: + pcmd.setType(OpenGLBufferType); // version/profile is communicated through the context's format() + break; + case Pdf: + pcmd.setType(PdfType); + break; + case Raster: // fallthrough + default: + pcmd.setType(ImageType); + break; + } + pcmd.setPainter(&p); + pcmd.setFilePath(filePath); + pcmd.runCommands(); + p.end(); +} + +#define main _realmain +QTEST_MAIN(tst_Lancelot) +#undef main + +int main(int argc, char *argv[]) +{ + // Avoid rendering variations caused by QHash randomization + QHashSeed::setDeterministicGlobalSeed(); + + QBaselineTest::handleCmdLineArgs(&argc, &argv); + return _realmain(argc, argv); +} + +#include "tst_baseline_painting.moc" diff --git a/tests/baseline/shared/baselineprotocol.cpp b/tests/baseline/shared/baselineprotocol.cpp new file mode 100644 index 0000000000..6a38e71831 --- /dev/null +++ b/tests/baseline/shared/baselineprotocol.cpp @@ -0,0 +1,456 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "baselineprotocol.h" +#include <QLibraryInfo> +#include <QImage> +#include <QBuffer> +#include <QHostInfo> +#include <QSysInfo> +#if QT_CONFIG(process) +# include <QProcess> +#endif +#include <QFileInfo> +#include <QDir> +#include <QThread> +#include <QTime> +#include <QPointer> +#include <QRegularExpression> + +const QString PI_Project(QLS("Project")); +const QString PI_ProjectImageKeys(QLS("ProjectImageKeys")); +const QString PI_TestCase(QLS("TestCase")); +const QString PI_HostName(QLS("HostName")); +const QString PI_HostAddress(QLS("HostAddress")); +const QString PI_OSName(QLS("OSName")); +const QString PI_OSVersion(QLS("OSVersion")); +const QString PI_QtVersion(QLS("QtVersion")); +const QString PI_QtBuildMode(QLS("QtBuildMode")); +const QString PI_GitCommit(QLS("GitCommit")); +const QString PI_GitBranch(QLS("GitBranch")); + +PlatformInfo PlatformInfo::localHostInfo() +{ + PlatformInfo pi; + pi.insert(PI_HostName, QHostInfo::localHostName()); + pi.insert(PI_QtVersion, QLS(qVersion())); + pi.insert(PI_QtBuildMode, QLibraryInfo::isDebugBuild() ? QLS("QtDebug") : QLS("QtRelease")); +#if defined(Q_OS_LINUX) && QT_CONFIG(process) + pi.insert(PI_OSName, QLS("Linux")); +#elif defined(Q_OS_WIN) + pi.insert(PI_OSName, QLS("Windows")); +#elif defined(Q_OS_DARWIN) + pi.insert(PI_OSName, QLS("Darwin")); +#else + pi.insert(PI_OSName, QLS("Other")); +#endif + pi.insert(PI_OSVersion, QSysInfo::kernelVersion()); + + QString gc = qEnvironmentVariable("BASELINE_GIT_COMMIT"); +#if QT_CONFIG(process) + if (gc.isEmpty()) { + QProcess git; + QString cmd; + QStringList args; + #if defined(Q_OS_WIN) + cmd = QLS("cmd.exe"); + args << QLS("/c") << QLS("git"); + #else + cmd = QLS("git"); + #endif + args << QLS("log") << QLS("--max-count=1") << QLS("--pretty=%H [%an] [%ad] %s"); + git.start(cmd, args); + git.waitForFinished(3000); + if (!git.exitCode()) + gc = QString::fromLocal8Bit(git.readAllStandardOutput().constData()).simplified(); + } +#endif // QT_CONFIG(process) + pi.insert(PI_GitCommit, gc.isEmpty() ? QLS("Unknown") : gc); + + if (qEnvironmentVariableIsSet("JENKINS_HOME")) + pi.setAdHocRun(false); + + QString gb = qEnvironmentVariable("GIT_BRANCH"); + if (!gb.isEmpty()) + pi.insert(PI_GitBranch, gb); + + return pi; +} + + +void PlatformInfo::addOverride(const QString& key, const QString& value) +{ + orides.append(key); + orides.append(value); +} + + +QStringList PlatformInfo::overrides() const +{ + return orides; +} + + +void PlatformInfo::setAdHocRun(bool isAdHoc) +{ + adHoc = isAdHoc; +} + + +bool PlatformInfo::isAdHocRun() const +{ + return adHoc; +} + + +QDataStream & operator<< (QDataStream &stream, const PlatformInfo &pi) +{ + stream << static_cast<const QMap<QString, QString>&>(pi); + stream << pi.orides << pi.adHoc; + return stream; +} + + +QDataStream & operator>> (QDataStream &stream, PlatformInfo &pi) +{ + stream >> static_cast<QMap<QString, QString>&>(pi); + stream >> pi.orides >> pi.adHoc; + return stream; +} + + +// Defined in lookup3.c: +void hashword2 ( +const quint32 *k, /* the key, an array of quint32 values */ +size_t length, /* the length of the key, in quint32s */ +quint32 *pc, /* IN: seed OUT: primary hash value */ +quint32 *pb); /* IN: more seed OUT: secondary hash value */ + +quint64 ImageItem::computeChecksum(const QImage &image) +{ + QImage img(image); + const qsizetype bpl = img.bytesPerLine(); + const int padBytes = bpl - (qsizetype(img.width()) * img.depth() / 8); + if (padBytes) { + uchar *p = img.bits() + bpl - padBytes; + const int h = img.height(); + for (int y = 0; y < h; ++y) { + memset(p, 0, padBytes); + p += bpl; + } + } + + quint32 h1 = 0xfeedbacc; + quint32 h2 = 0x21604894; + hashword2((const quint32 *)img.constBits(), img.sizeInBytes()/4, &h1, &h2); + return (quint64(h1) << 32) | h2; +} + +#if 0 +QString ImageItem::engineAsString() const +{ + switch (engine) { + case Raster: + return QLS("Raster"); + break; + case OpenGL: + return QLS("OpenGL"); + break; + default: + break; + } + return QLS("Unknown"); +} + +QString ImageItem::formatAsString() const +{ + static const int numFormats = 16; + static const char *formatNames[numFormats] = { + "Invalid", + "Mono", + "MonoLSB", + "Indexed8", + "RGB32", + "ARGB32", + "ARGB32-Premult", + "RGB16", + "ARGB8565-Premult", + "RGB666", + "ARGB6666-Premult", + "RGB555", + "ARGB8555-Premult", + "RGB888", + "RGB444", + "ARGB4444-Premult" + }; + if (renderFormat < 0 || renderFormat >= numFormats) + return QLS("UnknownFormat"); + return QLS(formatNames[renderFormat]); +} +#endif + +void ImageItem::writeImageToStream(QDataStream &out) const +{ + if (image.isNull() || image.format() == QImage::Format_Invalid) { + out << quint8(0); + return; + } + out << quint8('Q') << quint8(image.format()); + out << quint8(QSysInfo::ByteOrder) << quint8(0); // pad to multiple of 4 bytes + out << quint32(image.width()) << quint32(image.height()) << quint32(image.bytesPerLine()); + out << qCompress(reinterpret_cast<const uchar *>(image.constBits()), image.sizeInBytes()); + //# can be followed by colormap for formats that use it +} + +void ImageItem::readImageFromStream(QDataStream &in) +{ + quint8 hdr, fmt, endian, pad; + quint32 width, height, bpl; + QByteArray data; + + in >> hdr; + if (hdr != 'Q') { + image = QImage(); + return; + } + in >> fmt >> endian >> pad; + if (!fmt || fmt >= QImage::NImageFormats) { + image = QImage(); + return; + } + if (endian != QSysInfo::ByteOrder) { + qWarning("ImageItem cannot read streamed image with different endianness"); + image = QImage(); + return; + } + in >> width >> height >> bpl; + in >> data; + data = qUncompress(data); + QImage res((const uchar *)data.constData(), width, height, bpl, QImage::Format(fmt)); + image = res.copy(); //# yuck, seems there is currently no way to avoid data copy +} + +QDataStream & operator<< (QDataStream &stream, const ImageItem &ii) +{ + stream << ii.testFunction << ii.itemName << ii.itemChecksum << quint8(ii.status) << ii.imageChecksums << ii.misc; + ii.writeImageToStream(stream); + return stream; +} + +QDataStream & operator>> (QDataStream &stream, ImageItem &ii) +{ + quint8 encStatus; + stream >> ii.testFunction >> ii.itemName >> ii.itemChecksum >> encStatus >> ii.imageChecksums >> ii.misc; + ii.status = ImageItem::ItemStatus(encStatus); + ii.readImageFromStream(stream); + return stream; +} + +BaselineProtocol::BaselineProtocol() +{ +} + +BaselineProtocol::~BaselineProtocol() +{ + disconnect(); +} + +bool BaselineProtocol::disconnect() +{ + socket.close(); + return (socket.state() == QTcpSocket::UnconnectedState) ? true : socket.waitForDisconnected(Timeout); +} + + +bool BaselineProtocol::connect(const QString &testCase, bool *dryrun, const PlatformInfo& clientInfo) +{ + errMsg.clear(); + QByteArray serverName(qgetenv("QT_LANCELOT_SERVER")); + if (serverName.isNull()) + serverName = "lancelot.test.qt-project.org"; + + socket.connectToHost(serverName, ServerPort); + if (!socket.waitForConnected(Timeout)) { + QThread::sleep(std::chrono::seconds{3}); // Wait a bit and try again, the server might just be restarting + if (!socket.waitForConnected(Timeout)) { + errMsg += QLS("TCP connectToHost failed. Host:") + QLS(serverName) + QLS(" port:") + QString::number(ServerPort); + return false; + } + } + + PlatformInfo pi = clientInfo.isEmpty() ? PlatformInfo::localHostInfo() : clientInfo; + pi.insert(PI_TestCase, testCase); + QByteArray block; + QDataStream ds(&block, QIODevice::ReadWrite); + ds << pi; + if (!sendBlock(AcceptPlatformInfo, block)) { + errMsg += QLS("Failed to send data to server."); + return false; + } + + Command cmd = UnknownError; + if (!receiveBlock(&cmd, &block)) { + errMsg.prepend(QLS("Failed to get response from server. ")); + return false; + } + + if (cmd == Abort) { + errMsg += QLS("Server rejected connection. Reason: ") + QString::fromLatin1(block); + return false; + } + + if (dryrun) + *dryrun = (cmd == DoDryRun); + + if (cmd != Ack && cmd != DoDryRun) { + errMsg += QLS("Unexpected response from server."); + return false; + } + + return true; +} + + +bool BaselineProtocol::acceptConnection(PlatformInfo *pi) +{ + errMsg.clear(); + + QByteArray block; + Command cmd = AcceptPlatformInfo; + if (!receiveBlock(&cmd, &block) || cmd != AcceptPlatformInfo) + return false; + + if (pi) { + QDataStream ds(block); + ds >> *pi; + pi->insert(PI_HostAddress, socket.peerAddress().toString()); + } + + return true; +} + + +bool BaselineProtocol::requestBaselineChecksums(const QString &testFunction, ImageItemList *itemList) +{ + errMsg.clear(); + if (!itemList) + return false; + + for (ImageItemList::iterator it = itemList->begin(); it != itemList->end(); it++) + it->testFunction = testFunction; + + QByteArray block; + QDataStream ds(&block, QIODevice::WriteOnly); + ds << *itemList; + if (!sendBlock(RequestBaselineChecksums, block)) + return false; + + Command cmd; + QByteArray rcvBlock; + if (!receiveBlock(&cmd, &rcvBlock) || cmd != BaselineProtocol::Ack) + return false; + QDataStream rds(&rcvBlock, QIODevice::ReadOnly); + rds >> *itemList; + return true; +} + + +bool BaselineProtocol::submitMatch(const ImageItem &item, QByteArray *serverMsg) +{ + Command cmd; + ImageItem smallItem = item; + smallItem.image = QImage(); // No need to waste bandwidth sending image (identical to baseline) to server + return (sendItem(AcceptMatch, smallItem) && receiveBlock(&cmd, serverMsg) && cmd == Ack); +} + + +bool BaselineProtocol::submitNewBaseline(const ImageItem &item, QByteArray *serverMsg) +{ + Command cmd; + return (sendItem(AcceptNewBaseline, item) && receiveBlock(&cmd, serverMsg) && cmd == Ack); +} + + +bool BaselineProtocol::submitMismatch(const ImageItem &item, QByteArray *serverMsg, bool *fuzzyMatch) +{ + Command cmd; + if (sendItem(AcceptMismatch, item) && receiveBlock(&cmd, serverMsg) && (cmd == Ack || cmd == FuzzyMatch)) { + if (fuzzyMatch) + *fuzzyMatch = (cmd == FuzzyMatch); + return true; + } + return false; +} + + +bool BaselineProtocol::sendItem(Command cmd, const ImageItem &item) +{ + errMsg.clear(); + QBuffer buf; + buf.open(QIODevice::WriteOnly); + QDataStream ds(&buf); + ds << item; + if (!sendBlock(cmd, buf.data())) { + errMsg.prepend(QLS("Failed to submit image to server. ")); + return false; + } + return true; +} + + +bool BaselineProtocol::sendBlock(Command cmd, const QByteArray &block) +{ + QDataStream s(&socket); + // TBD: set qds version as a constant + s << quint16(ProtocolVersion) << quint16(cmd); + s.writeBytes(block.constData(), block.size()); + return true; +} + + +bool BaselineProtocol::receiveBlock(Command *cmd, QByteArray *block) +{ + while (socket.bytesAvailable() < int(2*sizeof(quint16) + sizeof(quint32))) { + if (!socket.waitForReadyRead(Timeout)) + return false; + } + QDataStream ds(&socket); + quint16 rcvProtocolVersion, rcvCmd; + ds >> rcvProtocolVersion >> rcvCmd; + if (rcvProtocolVersion != ProtocolVersion) { + errMsg = QLS("Baseline protocol version mismatch, received:") + QString::number(rcvProtocolVersion) + + QLS(" expected:") + QString::number(ProtocolVersion); + return false; + } + if (cmd) + *cmd = Command(rcvCmd); + + QByteArray uMsg; + quint32 remaining; + ds >> remaining; + uMsg.resize(remaining); + int got = 0; + char* uMsgBuf = uMsg.data(); + do { + got = ds.readRawData(uMsgBuf, remaining); + remaining -= got; + uMsgBuf += got; + } while (remaining && got >= 0 && socket.waitForReadyRead(Timeout)); + + if (got < 0) + return false; + + if (block) + *block = uMsg; + + return true; +} + + +QString BaselineProtocol::errorMessage() +{ + QString ret = errMsg; + if (socket.error() >= 0) + ret += QLS(" Socket state: ") + socket.errorString(); + return ret; +} + diff --git a/tests/baseline/shared/baselineprotocol.h b/tests/baseline/shared/baselineprotocol.h new file mode 100644 index 0000000000..598a0cd3af --- /dev/null +++ b/tests/baseline/shared/baselineprotocol.h @@ -0,0 +1,144 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef BASELINEPROTOCOL_H +#define BASELINEPROTOCOL_H + +#include <QDataStream> +#include <QTcpSocket> +#include <QImage> +#include <QList> +#include <QMap> +#include <QPointer> +#include <QStringList> + +#define QLS QLatin1String +#define QLC QLatin1Char + +#define FileFormat "png" + +extern const QString PI_Project; +extern const QString PI_ProjectImageKeys; +extern const QString PI_TestCase; +extern const QString PI_HostName; +extern const QString PI_HostAddress; +extern const QString PI_OSName; +extern const QString PI_OSVersion; +extern const QString PI_QtVersion; +extern const QString PI_QtBuildMode; +extern const QString PI_GitCommit; +extern const QString PI_GitBranch; + +class PlatformInfo : public QMap<QString, QString> +{ +public: + static PlatformInfo localHostInfo(); + + void addOverride(const QString& key, const QString& value); + QStringList overrides() const; + bool isAdHocRun() const; + void setAdHocRun(bool isAdHoc); + +private: + QStringList orides; + bool adHoc = true; + friend QDataStream & operator<< (QDataStream &stream, const PlatformInfo &pi); + friend QDataStream & operator>> (QDataStream &stream, PlatformInfo& pi); +}; +QDataStream & operator<< (QDataStream &stream, const PlatformInfo &pi); +QDataStream & operator>> (QDataStream &stream, PlatformInfo& pi); + + +struct ImageItem +{ + static quint64 computeChecksum(const QImage& image); + + enum ItemStatus { + Ok = 0, + BaselineNotFound = 1, + IgnoreItem = 2, + Mismatch = 3, + FuzzyMatch = 4, + Error = 5 + }; + + QString testFunction; + QString itemName; + ItemStatus status = Ok; + QImage image; + QList<quint64> imageChecksums; + quint16 itemChecksum = 0; + QByteArray misc; + + void writeImageToStream(QDataStream &stream) const; + void readImageFromStream(QDataStream &stream); +}; +QDataStream & operator<< (QDataStream &stream, const ImageItem &ii); +QDataStream & operator>> (QDataStream &stream, ImageItem& ii); + +Q_DECLARE_METATYPE(ImageItem); + +typedef QList<ImageItem> ImageItemList; + +class BaselineProtocol +{ +public: + BaselineProtocol(); + ~BaselineProtocol(); + + static BaselineProtocol *instance(QObject *parent = nullptr); + + // **************************************************** + // Important constants here + // **************************************************** + enum Constant { + ProtocolVersion = 5, + ServerPort = 54129, + Timeout = 15000 + }; + + enum Command { + UnknownError = 0, + // Queries + AcceptPlatformInfo = 1, + RequestBaselineChecksums = 2, + AcceptMatch = 3, + AcceptNewBaseline = 4, + AcceptMismatch = 5, + // Responses + Ack = 128, + Abort = 129, + DoDryRun = 130, + FuzzyMatch = 131 + }; + + // For client: + + // For advanced client: + bool connect(const QString &testCase, bool *dryrun = nullptr, const PlatformInfo& clientInfo = PlatformInfo()); + bool disconnect(); + bool requestBaselineChecksums(const QString &testFunction, ImageItemList *itemList); + bool submitMatch(const ImageItem &item, QByteArray *serverMsg); + bool submitNewBaseline(const ImageItem &item, QByteArray *serverMsg); + bool submitMismatch(const ImageItem &item, QByteArray *serverMsg, bool *fuzzyMatch = nullptr); + + // For server: + bool acceptConnection(PlatformInfo *pi); + + QString errorMessage(); + +private: + bool sendItem(Command cmd, const ImageItem &item); + + bool sendBlock(Command cmd, const QByteArray &block); + bool receiveBlock(Command *cmd, QByteArray *block); + + QString errMsg; + QTcpSocket socket; + + friend class BaselineThread; + friend class BaselineHandler; +}; + + +#endif // BASELINEPROTOCOL_H diff --git a/tests/baseline/shared/baselineprotocol.pri b/tests/baseline/shared/baselineprotocol.pri new file mode 100644 index 0000000000..996f9d5a1f --- /dev/null +++ b/tests/baseline/shared/baselineprotocol.pri @@ -0,0 +1,10 @@ +INCLUDEPATH += $$PWD + +QT *= network + +SOURCES += \ + $$PWD/baselineprotocol.cpp \ + $$PWD/lookup3.cpp + +HEADERS += \ + $$PWD/baselineprotocol.h diff --git a/tests/baseline/shared/lookup3.cpp b/tests/baseline/shared/lookup3.cpp new file mode 100644 index 0000000000..7964a184ae --- /dev/null +++ b/tests/baseline/shared/lookup3.cpp @@ -0,0 +1,821 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +/* +These functions are based on: + +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hashword(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ + +#include <QtGlobal> + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#else +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#endif + +#define hashsize(n) ((quint32)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* +-------------------------------------------------------------------- + This works on all machines. To be useful, it requires + -- that the key be an array of quint32's, and + -- that the length be the number of quint32's in the key + + The function hashword() is identical to hashlittle() on little-endian + machines, and identical to hashbig() on big-endian machines, + except that the length has to be measured in quint32s rather than in + bytes. hashlittle() is more complicated than hashword() only because + hashlittle() has to dance around fitting the key bytes into registers. +-------------------------------------------------------------------- +*/ +quint32 hashword( +const quint32 *k, /* the key, an array of quint32 values */ +size_t length, /* the length of the key, in quint32s */ +quint32 initval) /* the previous hash, or an arbitrary value */ +{ + quint32 a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + (((quint32)length)<<2) + initval; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 quint32's */ + switch (length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + Q_FALLTHROUGH(); + case 2 : b+=k[1]; + Q_FALLTHROUGH(); + case 1 : a+=k[0]; + final(a,b,c); + Q_FALLTHROUGH(); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + return c; +} + + +/* +-------------------------------------------------------------------- +hashword2() -- same as hashword(), but take two seeds and return two +32-bit values. pc and pb must both be nonnull, and *pc and *pb must +both be initialized with seeds. If you pass in (*pb)==0, the output +(*pc) will be the same as the return value from hashword(). +-------------------------------------------------------------------- +*/ +void hashword2 ( +const quint32 *k, /* the key, an array of quint32 values */ +size_t length, /* the length of the key, in quint32s */ +quint32 *pc, /* IN: seed OUT: primary hash value */ +quint32 *pb) /* IN: more seed OUT: secondary hash value */ +{ + quint32 a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((quint32)(length<<2)) + *pc; + c += *pb; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 quint32's */ + switch (length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + Q_FALLTHROUGH(); + case 2 : b+=k[1]; + Q_FALLTHROUGH(); + case 1 : a+=k[0]; + final(a,b,c); + Q_FALLTHROUGH(); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + *pc=c; *pb=b; +} + + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (quint8 **)k, do it like this: + for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h); + +By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this +code any way you wish, private, educational, or commercial. It's free. + +Use for hash table lookup, or anything where one collision in 2^^32 is +acceptable. Do NOT use for cryptographic purposes. +------------------------------------------------------------------------------- +*/ + +quint32 hashlittle( const void *key, size_t length, quint32 initval) +{ + quint32 a,b,c; /* internal state */ + union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((quint32)length) + initval; + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const quint32 *k = (const quint32 *)key; /* read 32-bit chunks */ + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticeably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch (length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + const quint8 *k8 = (const quint8 *)k; + switch (length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((quint32)k8[10])<<16; + Q_FALLTHROUGH(); + case 10: c+=((quint32)k8[9])<<8; + Q_FALLTHROUGH(); + case 9 : c+=k8[8]; + Q_FALLTHROUGH(); + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((quint32)k8[6])<<16; + Q_FALLTHROUGH(); + case 6 : b+=((quint32)k8[5])<<8; + Q_FALLTHROUGH(); + case 5 : b+=k8[4]; + Q_FALLTHROUGH(); + case 4 : a+=k[0]; break; + case 3 : a+=((quint32)k8[2])<<16; + Q_FALLTHROUGH(); + case 2 : a+=((quint32)k8[1])<<8; + Q_FALLTHROUGH(); + case 1 : a+=k8[0]; break; + case 0 : return c; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const quint16 *k = (const quint16 *)key; /* read 16-bit chunks */ + const quint8 *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((quint32)k[1])<<16); + b += k[2] + (((quint32)k[3])<<16); + c += k[4] + (((quint32)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const quint8 *)k; + switch (length) + { + case 12: c+=k[4]+(((quint32)k[5])<<16); + b+=k[2]+(((quint32)k[3])<<16); + a+=k[0]+(((quint32)k[1])<<16); + break; + case 11: c+=((quint32)k8[10])<<16; + Q_FALLTHROUGH(); + case 10: c+=k[4]; + b+=k[2]+(((quint32)k[3])<<16); + a+=k[0]+(((quint32)k[1])<<16); + break; + case 9 : c+=k8[8]; + Q_FALLTHROUGH(); + case 8 : b+=k[2]+(((quint32)k[3])<<16); + a+=k[0]+(((quint32)k[1])<<16); + break; + case 7 : b+=((quint32)k8[6])<<16; + Q_FALLTHROUGH(); + case 6 : b+=k[2]; + a+=k[0]+(((quint32)k[1])<<16); + break; + case 5 : b+=k8[4]; + Q_FALLTHROUGH(); + case 4 : a+=k[0]+(((quint32)k[1])<<16); + break; + case 3 : a+=((quint32)k8[2])<<16; + Q_FALLTHROUGH(); + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const quint8 *k = (const quint8 *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((quint32)k[1])<<8; + a += ((quint32)k[2])<<16; + a += ((quint32)k[3])<<24; + b += k[4]; + b += ((quint32)k[5])<<8; + b += ((quint32)k[6])<<16; + b += ((quint32)k[7])<<24; + c += k[8]; + c += ((quint32)k[9])<<8; + c += ((quint32)k[10])<<16; + c += ((quint32)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch (length) /* all the case statements fall through */ + { + case 12: c+=((quint32)k[11])<<24; + Q_FALLTHROUGH(); + case 11: c+=((quint32)k[10])<<16; + Q_FALLTHROUGH(); + case 10: c+=((quint32)k[9])<<8; + Q_FALLTHROUGH(); + case 9 : c+=k[8]; + Q_FALLTHROUGH(); + case 8 : b+=((quint32)k[7])<<24; + Q_FALLTHROUGH(); + case 7 : b+=((quint32)k[6])<<16; + Q_FALLTHROUGH(); + case 6 : b+=((quint32)k[5])<<8; + Q_FALLTHROUGH(); + case 5 : b+=k[4]; + Q_FALLTHROUGH(); + case 4 : a+=((quint32)k[3])<<24; + Q_FALLTHROUGH(); + case 3 : a+=((quint32)k[2])<<16; + Q_FALLTHROUGH(); + case 2 : a+=((quint32)k[1])<<8; + Q_FALLTHROUGH(); + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + + +/* + * hashlittle2: return 2 32-bit hash values + * + * This is identical to hashlittle(), except it returns two 32-bit hash + * values instead of just one. This is good enough for hash table + * lookup with 2^^64 buckets, or if you want a second hash if you're not + * happy with the first, or if you want a probably-unique 64-bit ID for + * the key. *pc is better mixed than *pb, so use *pc first. If you want + * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". + */ +void hashlittle2( + const void *key, /* the key to hash */ + size_t length, /* length of the key */ + quint32 *pc, /* IN: primary initval, OUT: primary hash */ + quint32 *pb) /* IN: secondary initval, OUT: secondary hash */ +{ + quint32 a,b,c; /* internal state */ + union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((quint32)length) + *pc; + c += *pb; + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const quint32 *k = (const quint32 *)key; /* read 32-bit chunks */ + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticeably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch (length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + const quint8 *k8 = (const quint8 *)k; + switch (length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((quint32)k8[10])<<16; + Q_FALLTHROUGH(); + case 10: c+=((quint32)k8[9])<<8; + Q_FALLTHROUGH(); + case 9 : c+=k8[8]; + Q_FALLTHROUGH(); + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((quint32)k8[6])<<16; + Q_FALLTHROUGH(); + case 6 : b+=((quint32)k8[5])<<8; + Q_FALLTHROUGH(); + case 5 : b+=k8[4]; + Q_FALLTHROUGH(); + case 4 : a+=k[0]; break; + case 3 : a+=((quint32)k8[2])<<16; + Q_FALLTHROUGH(); + case 2 : a+=((quint32)k8[1])<<8; + Q_FALLTHROUGH(); + case 1 : a+=k8[0]; break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const quint16 *k = (const quint16 *)key; /* read 16-bit chunks */ + const quint8 *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((quint32)k[1])<<16); + b += k[2] + (((quint32)k[3])<<16); + c += k[4] + (((quint32)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const quint8 *)k; + switch (length) + { + case 12: c+=k[4]+(((quint32)k[5])<<16); + b+=k[2]+(((quint32)k[3])<<16); + a+=k[0]+(((quint32)k[1])<<16); + break; + case 11: c+=((quint32)k8[10])<<16; + Q_FALLTHROUGH(); + case 10: c+=k[4]; + b+=k[2]+(((quint32)k[3])<<16); + a+=k[0]+(((quint32)k[1])<<16); + break; + case 9 : c+=k8[8]; + Q_FALLTHROUGH(); + case 8 : b+=k[2]+(((quint32)k[3])<<16); + a+=k[0]+(((quint32)k[1])<<16); + break; + case 7 : b+=((quint32)k8[6])<<16; + Q_FALLTHROUGH(); + case 6 : b+=k[2]; + a+=k[0]+(((quint32)k[1])<<16); + break; + case 5 : b+=k8[4]; + Q_FALLTHROUGH(); + case 4 : a+=k[0]+(((quint32)k[1])<<16); + break; + case 3 : a+=((quint32)k8[2])<<16; + Q_FALLTHROUGH(); + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const quint8 *k = (const quint8 *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((quint32)k[1])<<8; + a += ((quint32)k[2])<<16; + a += ((quint32)k[3])<<24; + b += k[4]; + b += ((quint32)k[5])<<8; + b += ((quint32)k[6])<<16; + b += ((quint32)k[7])<<24; + c += k[8]; + c += ((quint32)k[9])<<8; + c += ((quint32)k[10])<<16; + c += ((quint32)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch (length) /* all the case statements fall through */ + { + case 12: c+=((quint32)k[11])<<24; + Q_FALLTHROUGH(); + case 11: c+=((quint32)k[10])<<16; + Q_FALLTHROUGH(); + case 10: c+=((quint32)k[9])<<8; + Q_FALLTHROUGH(); + case 9 : c+=k[8]; + Q_FALLTHROUGH(); + case 8 : b+=((quint32)k[7])<<24; + Q_FALLTHROUGH(); + case 7 : b+=((quint32)k[6])<<16; + Q_FALLTHROUGH(); + case 6 : b+=((quint32)k[5])<<8; + Q_FALLTHROUGH(); + case 5 : b+=k[4]; + Q_FALLTHROUGH(); + case 4 : a+=((quint32)k[3])<<24; + Q_FALLTHROUGH(); + case 3 : a+=((quint32)k[2])<<16; + Q_FALLTHROUGH(); + case 2 : a+=((quint32)k[1])<<8; + Q_FALLTHROUGH(); + case 1 : a+=k[0]; + break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + } + + final(a,b,c); + *pc=c; *pb=b; +} + + + +/* + * hashbig(): + * This is the same as hashword() on big-endian machines. It is different + * from hashlittle() on all machines. hashbig() takes advantage of + * big-endian byte ordering. + */ +quint32 hashbig( const void *key, size_t length, quint32 initval) +{ + quint32 a,b,c; + union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((quint32)length) + initval; + + u.ptr = key; + if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { + const quint32 *k = (const quint32 *)key; /* read 32-bit chunks */ + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]<<8" actually reads beyond the end of the string, but + * then shifts out the part it's not allowed to read. Because the + * string is aligned, the illegal read is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticeably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch (length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; + case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; + case 5 : b+=k[1]&0xff000000; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff00; break; + case 2 : a+=k[0]&0xffff0000; break; + case 1 : a+=k[0]&0xff000000; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + const quint8 *k8 = (const quint8 *)k; + switch (length) /* all the case statements fall through */ + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((quint32)k8[10])<<8; + Q_FALLTHROUGH(); + case 10: c+=((quint32)k8[9])<<16; + Q_FALLTHROUGH(); + case 9 : c+=((quint32)k8[8])<<24; + Q_FALLTHROUGH(); + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((quint32)k8[6])<<8; + Q_FALLTHROUGH(); + case 6 : b+=((quint32)k8[5])<<16; + Q_FALLTHROUGH(); + case 5 : b+=((quint32)k8[4])<<24; + Q_FALLTHROUGH(); + case 4 : a+=k[0]; break; + case 3 : a+=((quint32)k8[2])<<8; + Q_FALLTHROUGH(); + case 2 : a+=((quint32)k8[1])<<16; + Q_FALLTHROUGH(); + case 1 : a+=((quint32)k8[0])<<24; break; + case 0 : return c; + } + +#endif /* !VALGRIND */ + + } else { /* need to read the key one byte at a time */ + const quint8 *k = (const quint8 *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += ((quint32)k[0])<<24; + a += ((quint32)k[1])<<16; + a += ((quint32)k[2])<<8; + a += ((quint32)k[3]); + b += ((quint32)k[4])<<24; + b += ((quint32)k[5])<<16; + b += ((quint32)k[6])<<8; + b += ((quint32)k[7]); + c += ((quint32)k[8])<<24; + c += ((quint32)k[9])<<16; + c += ((quint32)k[10])<<8; + c += ((quint32)k[11]); + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch (length) /* all the case statements fall through */ + { + case 12: c+=k[11]; + Q_FALLTHROUGH(); + case 11: c+=((quint32)k[10])<<8; + Q_FALLTHROUGH(); + case 10: c+=((quint32)k[9])<<16; + Q_FALLTHROUGH(); + case 9 : c+=((quint32)k[8])<<24; + Q_FALLTHROUGH(); + case 8 : b+=k[7]; + Q_FALLTHROUGH(); + case 7 : b+=((quint32)k[6])<<8; + Q_FALLTHROUGH(); + case 6 : b+=((quint32)k[5])<<16; + Q_FALLTHROUGH(); + case 5 : b+=((quint32)k[4])<<24; + Q_FALLTHROUGH(); + case 4 : a+=k[3]; + Q_FALLTHROUGH(); + case 3 : a+=((quint32)k[2])<<8; + Q_FALLTHROUGH(); + case 2 : a+=((quint32)k[1])<<16; + Q_FALLTHROUGH(); + case 1 : a+=((quint32)k[0])<<24; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} diff --git a/tests/baseline/shared/paintcommands.cpp b/tests/baseline/shared/paintcommands.cpp new file mode 100644 index 0000000000..20201b66b0 --- /dev/null +++ b/tests/baseline/shared/paintcommands.cpp @@ -0,0 +1,2951 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "paintcommands.h" + +#include <qdir.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qpainter.h> +#include <qpainterpath.h> +#include <qbitmap.h> +#include <qtextstream.h> +#include <qtextlayout.h> +#include <qdebug.h> +#include <QStaticText> +#include <QTextDocument> +#include <private/qimage_p.h> + +#ifndef QT_NO_OPENGL +#include <QOpenGLFramebufferObjectFormat> +#include <QOpenGLContext> +#include <QOpenGLPaintDevice> +#endif + +/********************************************************************************* +** everything to populate static tables +**********************************************************************************/ +const char *PaintCommands::brushStyleTable[] = { + "NoBrush", + "SolidPattern", + "Dense1Pattern", + "Dense2Pattern", + "Dense3Pattern", + "Dense4Pattern", + "Dense5Pattern", + "Dense6Pattern", + "Dense7Pattern", + "HorPattern", + "VerPattern", + "CrossPattern", + "BDiagPattern", + "FDiagPattern", + "DiagCrossPattern", + "LinearGradientPattern" +}; + +const char *PaintCommands::penStyleTable[] = { + "NoPen", + "SolidLine", + "DashLine", + "DotLine", + "DashDotLine", + "DashDotDotLine" +}; + +const char *PaintCommands::fontWeightTable[] = { + "Light", + "Normal", + "DemiBold", + "Bold", + "Black" +}; + +const char *PaintCommands::fontHintingTable[] = { + "Default", + "None", + "Vertical", + "Full" +}; + +const char *PaintCommands::fontCapitalizationTable[] = { + "MixedCase", + "AllUppercase", + "AllLowercase", + "SmallCaps", + "Capitalize" +}; + +const char *PaintCommands::clipOperationTable[] = { + "NoClip", + "ReplaceClip", + "IntersectClip", + "UniteClip" +}; + +const char *PaintCommands::spreadMethodTable[] = { + "PadSpread", + "ReflectSpread", + "RepeatSpread" +}; + +const char *PaintCommands::coordinateMethodTable[] = { + "LogicalMode", + "StretchToDeviceMode", + "ObjectBoundingMode", + "ObjectMode" +}; + +const char *PaintCommands::sizeModeTable[] = { + "AbsoluteSize", + "RelativeSize" +}; + +const char *PaintCommands::compositionModeTable[] = { + "SourceOver", + "DestinationOver", + "Clear", + "Source", + "Destination", + "SourceIn", + "DestinationIn", + "SourceOut", + "DestinationOut", + "SourceAtop", + "DestinationAtop", + "Xor", + "Plus", + "Multiply", + "Screen", + "Overlay", + "Darken", + "Lighten", + "ColorDodge", + "ColorBurn", + "HardLight", + "SoftLight", + "Difference", + "Exclusion", + "SourceOrDestination", + "SourceAndDestination", + "SourceXorDestination", + "NotSourceAndNotDestination", + "NotSourceOrNotDestination", + "NotSourceXorDestination", + "NotSource", + "NotSourceAndDestination", + "SourceAndNotDestination" +}; + +const char *PaintCommands::imageFormatTable[] = { + "Invalid", + "Mono", + "MonoLSB", + "Indexed8", + "RGB32", + "ARGB32", + "ARGB32_Premultiplied", + "Format_RGB16", + "Format_ARGB8565_Premultiplied", + "Format_RGB666", + "Format_ARGB6666_Premultiplied", + "Format_RGB555", + "Format_ARGB8555_Premultiplied", + "Format_RGB888", + "Format_RGB444", + "Format_ARGB4444_Premultiplied", + "Format_RGBX8888", + "Format_RGBA8888", + "Format_RGBA8888_Premultiplied", + "Format_BGR30", + "Format_A2BGR30_Premultiplied", + "Format_RGB30", + "Format_A2RGB30_Premultiplied", + "Alpha8", + "Grayscale8", + "RGBx64", + "RGBA64", + "RGBA64_Premultiplied", + "Grayscale16", + "BGR888", + "RGBx16FPx4", + "RGBA16FPx4", + "RGBA16FPx4_Premultiplied", + "RGBx32FPx4", + "RGBA32FPx4", + "RGBA32FPx4_Premultiplied", + "CMYK32", +}; + +const char *PaintCommands::renderHintTable[] = { + "Antialiasing", + "SmoothPixmapTransform", + "NonCosmeticBrushPatterns" +}; + +int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit) +{ + QByteArray p = pattern.toLatin1().toLower(); + for (int i=0; i<limit; ++i) + if (p == QByteArray::fromRawData(table[i], qstrlen(table[i])).toLower()) + return i; + return -1; +} + +QList<PaintCommands::PaintCommandInfos> PaintCommands::s_commandInfoTable = QList<PaintCommands::PaintCommandInfos>(); +QList<QPair<QString,QStringList> > PaintCommands::s_enumsTable = QList<QPair<QString,QStringList> >(); +QMultiHash<QString, int> PaintCommands::s_commandHash; + +#define DECL_PAINTCOMMAND(identifier, method, regexp, syntax, sample) \ + s_commandInfoTable << PaintCommandInfos(QLatin1String(identifier), &PaintCommands::method, QRegularExpression(regexp), \ + QLatin1String(syntax), QLatin1String(sample) ); + +#define DECL_PAINTCOMMANDSECTION(title) \ + s_commandInfoTable << PaintCommandInfos(QLatin1String(title)); + +#define ADD_ENUMLIST(listCaption, cStrArray) { \ + QStringList list; \ + for (int i=0; i<int(sizeof(cStrArray)/sizeof(char*)); i++) \ + list << cStrArray[i]; \ + s_enumsTable << qMakePair(QString(listCaption), list); \ + } + +void PaintCommands::staticInit() +{ + // check if already done + if (!s_commandInfoTable.isEmpty()) return; + + // populate the command list + DECL_PAINTCOMMANDSECTION("misc"); + DECL_PAINTCOMMAND("comment", command_comment, + "^\\s*#", + "# this is some comments", + "# place your comments here"); + DECL_PAINTCOMMAND("import", command_import, + "^import\\s+\"(.*)\"$", + "import <qrcFilename>", + "import \"myfile.qrc\""); + DECL_PAINTCOMMAND("begin_block", command_begin_block, + "^begin_block\\s+(\\w*)$", + "begin_block <blockName>", + "begin_block blockName"); + DECL_PAINTCOMMAND("end_block", command_end_block, + "^end_block\\s*(\\w*)$", + "end_block [blockName]", + "end_block blockName"); + DECL_PAINTCOMMAND("repeat_block", command_repeat_block, + "^repeat_block\\s+(\\w*)$", + "repeat_block <blockName>", + "repeat_block blockName"); + DECL_PAINTCOMMAND("textlayout_draw", command_textlayout_draw, + "^textlayout_draw\\s+\"(.*)\"\\s+([0-9.]*)$", + "textlayout_draw <text> <width>", + "textlayout_draw \"your text\" 1.0"); + DECL_PAINTCOMMAND("abort", command_abort, + "^abort$", + "abort", + "abort"); + DECL_PAINTCOMMAND("noop", command_noop, + "^$", + "-", + "\n"); + + DECL_PAINTCOMMANDSECTION("setters"); + DECL_PAINTCOMMAND("setBackgroundMode", command_setBgMode, + "^(setBackgroundMode|setBgMode)\\s+(\\w*)$", + "setBackgroundMode <OpaqueMode|TransparentMode>", + "setBackgroundMode TransparentMode"); + DECL_PAINTCOMMAND("setBackground", command_setBackground, + "^setBackground\\s+#?(\\w*)\\s*(\\w*)?$", + "setBackground <color> [brush style enum]", + "setBackground black SolidPattern"); + DECL_PAINTCOMMAND("setOpacity", command_setOpacity, + "^setOpacity\\s+(-?\\d*\\.?\\d*)$", + "setOpacity <opacity>\n - opacity is in [0,1]", + "setOpacity 1.0"); + DECL_PAINTCOMMAND("path_setFillRule", command_path_setFillRule, + "^path_setFillRule\\s+(\\w*)\\s+(\\w*)$", + "path_setFillRule <pathName> [Winding|OddEven]", + "path_setFillRule pathName Winding"); + DECL_PAINTCOMMAND("setBrush", command_setBrush, + "^setBrush\\s+(#?[\\w.:\\/]*)\\s*(\\w*)?$", + "setBrush <imageFileName>\nsetBrush noBrush\nsetBrush <color> <brush style enum>", + "setBrush white SolidPattern"); + DECL_PAINTCOMMAND("setBrushOrigin", command_setBrushOrigin, + "^setBrushOrigin\\s*(-?\\w*)\\s+(-?\\w*)$", + "setBrushOrigin <dx> <dy>", + "setBrushOrigin 0 0"); + DECL_PAINTCOMMAND("brushTranslate", command_brushTranslate, + "^brushTranslate\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "brushTranslate <tx> <ty>", + "brushTranslate 0.0 0.0"); + DECL_PAINTCOMMAND("brushScale", command_brushScale, + "^brushScale\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "brushScale <kx> <ky>", + "brushScale 0.0 0.0"); + DECL_PAINTCOMMAND("brushRotate", command_brushRotate, + "^brushRotate\\s+(-?[\\w.]*)$", + "brushRotate <angle>\n - angle in degrees", + "brushRotate 0.0"); + DECL_PAINTCOMMAND("brushShear", command_brushShear, + "^brushShear\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "brushShear <sx> <sy>", + "brushShear 0.0 0.0"); + DECL_PAINTCOMMAND("setCompositionMode", command_setCompositionMode, + "^setCompositionMode\\s+([\\w_0-9]*)$", + "setCompositionMode <composition mode enum>", + "setCompositionMode SourceOver"); + DECL_PAINTCOMMAND("setFont", command_setFont, + "^setFont\\s+\"([\\w\\s]*)\"\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)$", + "setFont <fontFace> [size] [font weight|font weight enum] [italic] [hinting enum] [underline] [strikeout] [overline] [capitalization enum]\n - font weight is an integer between 0 and 99", + "setFont \"times\" 12"); + DECL_PAINTCOMMAND("setPen", command_setPen, + "^setPen\\s+#?(\\w*)$", + "setPen <color>\nsetPen <pen style enum>\nsetPen brush", + "setPen black"); + DECL_PAINTCOMMAND("setPen", command_setPen2, + "^setPen\\s+(#?\\w*)\\s+([\\w.]+)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)$", + "setPen brush|<color> [width] [pen style enum] [FlatCap|SquareCap|RoundCap] [MiterJoin|BevelJoin|RoundJoin]", + "setPen black 1 FlatCap MiterJoin"); + DECL_PAINTCOMMAND("pen_setDashOffset", command_pen_setDashOffset, + "^pen_setDashOffset\\s+(-?[\\w.]+)$", + "pen_setDashOffset <offset>\n", + "pen_setDashOffset 1.0"); + DECL_PAINTCOMMAND("pen_setDashPattern", command_pen_setDashPattern, + "^pen_setDashPattern\\s+\\[([\\w\\s.]*)\\]$", + "pen_setDashPattern <[ <dash_1> <space_1> ... <dash_n> <space_n> ]>", + "pen_setDashPattern [ 2 1 4 1 3 3 ]"); + DECL_PAINTCOMMAND("pen_setCosmetic", command_pen_setCosmetic, + "^pen_setCosmetic\\s+(\\w*)$", + "pen_setCosmetic <true|false>", + "pen_setCosmetic true"); + DECL_PAINTCOMMAND("setRenderHint", command_setRenderHint, + "^setRenderHint\\s+([\\w_0-9]*)\\s*(\\w*)$", + "setRenderHint <hint> <true|false>", + "setRenderHint Antialiasing true"); + DECL_PAINTCOMMAND("clearRenderHint", command_clearRenderHint, + "^clearRenderHint$", + "clearRenderHint", + "clearRenderHint"); + + DECL_PAINTCOMMANDSECTION("gradients"); + DECL_PAINTCOMMAND("gradient_appendStop", command_gradient_appendStop, + "^gradient_appendStop\\s+([\\w.]*)\\s+#?(\\w*)$", + "gradient_appendStop <pos> <color>", + "gradient_appendStop 1.0 red"); + DECL_PAINTCOMMAND("gradient_clearStops", command_gradient_clearStops, + "^gradient_clearStops$", + "gradient_clearStops", + "gradient_clearStops"); + DECL_PAINTCOMMAND("gradient_setConical", command_gradient_setConical, + "^gradient_setConical\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", + "gradient_setConical <cx> <cy> <angle>\n - angle in degrees", + "gradient_setConical 5.0 5.0 45.0"); + DECL_PAINTCOMMAND("gradient_setLinear", command_gradient_setLinear, + "^gradient_setLinear\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", + "gradient_setLinear <x1> <y1> <x2> <y2>", + "gradient_setLinear 1.0 1.0 2.0 2.0"); + DECL_PAINTCOMMAND("gradient_setRadial", command_gradient_setRadial, + "^gradient_setRadial\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)$", + "gradient_setRadial <cx> <cy> <rad> <fx> <fy>\n - C is the center\n - rad is the radius\n - F is the focal point", + "gradient_setRadial 1.0 1.0 45.0 2.0 2.0"); + DECL_PAINTCOMMAND("gradient_setRadialExtended", command_gradient_setRadialExtended, + "^gradient_setRadialExtended\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)$", + "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", + "gradient_setRadialExtended 1.0 1.0 45.0 2.0 2.0 45.0"); + DECL_PAINTCOMMAND("gradient_setLinearPen", command_gradient_setLinearPen, + "^gradient_setLinearPen\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", + "gradient_setLinearPen <x1> <y1> <x2> <y2>", + "gradient_setLinearPen 1.0 1.0 2.0 2.0"); + DECL_PAINTCOMMAND("gradient_setSpread", command_gradient_setSpread, + "^gradient_setSpread\\s+(\\w*)$", + "gradient_setSpread <spread method enum>", + "gradient_setSpread PadSpread"); + DECL_PAINTCOMMAND("gradient_setCoordinateMode", command_gradient_setCoordinateMode, + "^gradient_setCoordinateMode\\s+(\\w*)$", + "gradient_setCoordinateMode <coordinate method enum>", + "gradient_setCoordinateMode ObjectBoundingMode"); + + DECL_PAINTCOMMANDSECTION("drawing ops"); + DECL_PAINTCOMMAND("drawPoint", command_drawPoint, + "^drawPoint\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "drawPoint <x> <y>", + "drawPoint 10.0 10.0"); + DECL_PAINTCOMMAND("drawLine", command_drawLine, + "^drawLine\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "drawLine <x1> <y1> <x2> <y2>", + "drawLine 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("drawLines", command_drawLines, + "^drawLines\\s+\\[([\\w\\s\\-.]*)\\]$", + "drawLines <[ <l1x1> <l1y1> <l1x2> <l1y2> <l2x1> <l2y1> ... ]>", + "drawLines [ 10 10 50 10 50 20 10 20 ]"); + DECL_PAINTCOMMAND("drawRect", command_drawRect, + "^drawRect\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "drawRect <x> <y> <w> <h>", + "drawRect 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("drawRoundRect", command_drawRoundRect, + "^drawRoundRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)?\\s*(-?\\w*)?$", + "drawRoundRect <x> <y> <w> <h> [rx] [ry]", + "drawRoundRect 10 10 20 20 3 3"); + DECL_PAINTCOMMAND("drawRoundedRect", command_drawRoundedRect, + "^drawRoundedRect\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(\\w*)?$", + "drawRoundedRect <x> <y> <w> <h> <rx> <ry> [SizeMode enum]", + "drawRoundedRect 10 10 20 20 4 4 AbsoluteSize"); + DECL_PAINTCOMMAND("drawArc", command_drawArc, + "^drawArc\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "drawArc <x> <y> <w> <h> <angleStart> <angleArc>\n - angles are expressed in 1/16th of degree", + "drawArc 10 10 20 20 0 5760"); + DECL_PAINTCOMMAND("drawChord", command_drawChord, + "^drawChord\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "drawChord <x> <y> <w> <h> <angleStart> <angleArc>\n - angles are expressed in 1/16th of degree", + "drawChord 10 10 20 20 0 5760"); + DECL_PAINTCOMMAND("drawEllipse", command_drawEllipse, + "^drawEllipse\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "drawEllipse <x> <y> <w> <h>", + "drawEllipse 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("drawPath", command_drawPath, + "^drawPath\\s+(\\w*)$", + "drawPath <pathName>", + "drawPath mypath"); + DECL_PAINTCOMMAND("drawPie", command_drawPie, + "^drawPie\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "drawPie <x> <y> <w> <h> <angleStart> <angleArc>\n - angles are expressed in 1/16th of degree", + "drawPie 10 10 20 20 0 5760"); + DECL_PAINTCOMMAND("drawPixmap", command_drawPixmap, + "^drawPixmap\\s+([\\w.:\\-/]*)" + "\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?" // target rect + "\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?$", // source rect + "drawPixmap <filename> <tx> <ty> <tw> <th> <sx> <sy> <sw> <sh>" + "\n- where t means target and s means source" + "\n- a width or height of -1 means maximum space", + "drawPixmap :/images/face.png 0 0 -1 -1 0 0 -1 -1"); + DECL_PAINTCOMMAND("drawImage", command_drawImage, + "^drawImage\\s+([\\w.:\\/]*)" + "\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?" // target rect + "\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?$", // source rect + "drawImage <filename> <tx> <ty> <tw> <th> <sx> <sy> <sw> <sh>" + "\n- where t means target and s means source" + "\n- a width or height of -1 means maximum space", + "drawImage :/images/face.png 0 0 -1 -1 0 0 -1 -1"); + DECL_PAINTCOMMAND("drawPolygon", command_drawPolygon, + "^drawPolygon\\s+\\[([\\w\\s\\-.]*)\\]\\s*(\\w*)$", + "drawPolygon <[ <x1> <y1> ... <xn> <yn> ]> <Winding|OddEven>", + "drawPolygon [ 1 4 6 8 5 3 ] Winding"); + DECL_PAINTCOMMAND("drawConvexPolygon", command_drawConvexPolygon, + "^drawConvexPolygon\\s+\\[([\\w\\s-.]*)\\]$", + "drawConvexPolygon <[ <x1> <y1> ... <xn> <yn> ]>", + "drawConvexPolygon [ 1 4 6 8 5 3 ]"); + DECL_PAINTCOMMAND("drawPolyline", command_drawPolyline, + "^drawPolyline\\s+\\[([\\w\\s\\-.]*)\\]$", + "drawPolyline <[ <x1> <y1> ... <xn> <yn> ]>", + "drawPolyline [ 1 4 6 8 5 3 ]"); + DECL_PAINTCOMMAND("drawText", command_drawText, + "^drawText\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", + "drawText <x> <y> <text>", + "drawText 10 10 \"my text\""); + DECL_PAINTCOMMAND("drawStaticText", command_drawStaticText, + "^drawStaticText\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", + "drawStaticText <x> <y> <text>", + "drawStaticText 10 10 \"my text\""); + DECL_PAINTCOMMAND("drawGlyphRun", command_drawGlyphRun, + "^drawGlyphRun\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", + "drawGlyphRun <x> <y> <text> - Will create glyph run using QTextLayout and draw this", + "drawGlyphRun 10 10 \"my text\""); + DECL_PAINTCOMMAND("drawTextDocument", command_drawTextDocument, + "^drawTextDocument\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", + "drawTextDocument <x> <y> <html>", + "drawTextDocument 10 10 \"html\""); + DECL_PAINTCOMMAND("drawTiledPixmap", command_drawTiledPixmap, + "^drawTiledPixmap\\s+([\\w.:\\/]*)" + "\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)\\s*(-?\\w*)" + "\\s*(-?\\w*)\\s*(-?\\w*)$", + "drawTiledPixmap <tile image filename> <tx> <ty> <tx> <ty> <sx> <sy>" + "\n - where t means tile" + "\n - and s is an offset in the tile", + "drawTiledPixmap :/images/alpha.png "); + DECL_PAINTCOMMAND("fillRect", command_fillRect, + "^fillRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(\\w*)?$", + "fillRect <x> <y> <w> <h> [color]\n - Uses current brush if no color given", + "fillRect 10 10 20 20 blue"); + DECL_PAINTCOMMAND("fillRectF", command_fillRectF, + "^fillRectF\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s*(\\w*)?$", + "fillRectF <x> <y> <w> <h> [color]\n - Uses current brush if no color given", + "fillRectF 10.5 10.5 20.2 20.2 blue"); + DECL_PAINTCOMMAND("drawPixmapFragments", command_drawPixmapFragments, + "^drawPixmapFragments\\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]*)?\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)?" + "\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)?$", + "drawPixmapFragments <image filename> <count>" + " <centerx0> <centery0> <x0> <y0> <w0> <h0> <sx0> <sy0> <r0> <o0>" + " <centerx1> <centery1> <x1> <y1> <w1> ..." + "\n - where count is 1 or 2, and followed by centerPos, sourceRect, scaleX, scaleY, rotation, opacity <count> times", + "drawPixmapFragments :/images/sign.png 1 50 50 10 10 60 60 10 10 30 1"); + + DECL_PAINTCOMMANDSECTION("painterPaths"); + DECL_PAINTCOMMAND("path_moveTo", command_path_moveTo, + "^path_moveTo\\s+([.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_moveTo <pathName> <x> <y>", + "path_moveTo mypath 1.0 1.0"); + DECL_PAINTCOMMAND("path_lineTo", command_path_lineTo, + "^path_lineTo\\s+([.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_lineTo <pathName> <x> <y>", + "path_lineTo mypath 1.0 1.0"); + DECL_PAINTCOMMAND("path_addEllipse", command_path_addEllipse, + "^path_addEllipse\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_addEllipse <pathName> <x1> <y1> <x2> <y2>", + "path_addEllipse mypath 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("path_addPolygon", command_path_addPolygon, + "^path_addPolygon\\s+(\\w*)\\s+\\[([\\w\\s]*)\\]\\s*(\\w*)$", + "path_addPolygon <pathName> <[ <x1> <y1> ... <xn> <yn> ]>", + "path_addPolygon mypath [ 1 4 6 8 5 3 ]"); + DECL_PAINTCOMMAND("path_addRect", command_path_addRect, + "^path_addRect\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_addRect <pathName> <x1> <y1> <x2> <y2>", + "path_addRect mypath 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("path_addText", command_path_addText, + "^path_addText\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+\"(.*)\"$", + "path_addText <pathName> <x> <y> <text>", + "path_addText mypath 10.0 20.0 \"some text\""); + DECL_PAINTCOMMAND("path_arcTo", command_path_arcTo, + "^path_arcTo\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_arcTo <pathName> <x> <y> <w> <h> <angleStart> <angleArc>\n - angles are expressed in degrees", + "path_arcTo mypath 0.0 0.0 10.0 10.0 0.0 360.0"); + DECL_PAINTCOMMAND("path_cubicTo", command_path_cubicTo, + "^path_cubicTo\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_cubicTo <pathName> <x1> <y1> <x2> <y2> <x3> <y3>", + "path_cubicTo mypath 0.0 0.0 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("path_closeSubpath", command_path_closeSubpath, + "^path_closeSubpath\\s+(\\w*)$", + "path_closeSubpath <pathName>", + "path_closeSubpath mypath"); + DECL_PAINTCOMMAND("path_createOutline", command_path_createOutline, + "^path_createOutline\\s+(\\w*)\\s+(\\w*)$", + "path_createOutline <pathName> <newName>", + "path_createOutline mypath myoutline"); + DECL_PAINTCOMMAND("path_debugPrint", command_path_debugPrint, + "^path_debugPrint\\s+(\\w*)$", + "path_debugPrint <pathName>", + "path_debugPrint mypath"); + + DECL_PAINTCOMMANDSECTION("regions"); + DECL_PAINTCOMMAND("region_addRect", command_region_addRect, + "^region_addRect\\s+(\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "region_addRect <regionName> <x1> <y1> <x2> <y2>", + "region_addRect myregion 0.0 0.0 10.0 10.0"); + DECL_PAINTCOMMAND("region_addEllipse", command_region_addEllipse, + "^region_addEllipse\\s+(\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "region_addEllipse <regionName> <x1> <y1> <x2> <y2>", + "region_addEllipse myregion 0.0 0.0 10.0 10.0"); + + DECL_PAINTCOMMANDSECTION("clipping"); + DECL_PAINTCOMMAND("region_getClipRegion", command_region_getClipRegion, + "^region_getClipRegion\\s+(\\w*)$", + "region_getClipRegion <regionName>", + "region_getClipRegion myregion"); + DECL_PAINTCOMMAND("setClipRegion", command_setClipRegion, + "^setClipRegion\\s+(\\w*)\\s*(\\w*)$", + "setClipRegion <regionName> <clip operation enum>", + "setClipRegion myregion ReplaceClip"); + DECL_PAINTCOMMAND("path_getClipPath", command_path_getClipPath, + "^path_getClipPath\\s+([\\w0-9]*)$", + "path_getClipPath <pathName>", + "path_getClipPath mypath"); + DECL_PAINTCOMMAND("setClipPath", command_setClipPath, + "^setClipPath\\s+(\\w*)\\s*(\\w*)$", + "setClipPath <pathName> <clip operation enum>", + "setClipPath mypath ReplaceClip"); + DECL_PAINTCOMMAND("setClipRect", command_setClipRect, + "^setClipRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(\\w*)$", + "setClipRect <x> <y> <w> <h> <clip operation enum>", + "setClipRect 0 0 10 10 ReplaceClip"); + DECL_PAINTCOMMAND("setClipRectF", command_setClipRectF, + "^setClipRectF\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s*(\\w.*)$", + "setClipRectF <x> <y> <w> <h> <clip operation enum>", + "setClipRectF 0.1 0.2 10.3 10.4 ReplaceClip"); + DECL_PAINTCOMMAND("setClipping", command_setClipping, + "^setClipping\\s+(\\w*)$", + "setClipping <true|false>", + "setClipping true"); + + DECL_PAINTCOMMANDSECTION("surface"); + DECL_PAINTCOMMAND("surface_begin", command_surface_begin, + "^surface_begin\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "surface_begin <x> <y> <w> <h>", + "surface_begin 0.0 0.0 10.0 10.0"); + DECL_PAINTCOMMAND("surface_end", command_surface_end, + "^surface_end$", + "surface_end", + "surface_end"); + + DECL_PAINTCOMMANDSECTION("painter states"); + DECL_PAINTCOMMAND("restore", command_restore, + "^restore$", + "restore", + "restore"); + DECL_PAINTCOMMAND("save", command_save, + "^save$", + "save", + "save"); + + DECL_PAINTCOMMANDSECTION("pixmaps'n'images"); + DECL_PAINTCOMMAND("pixmap_load", command_pixmap_load, + "^pixmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", + "pixmap_load <image filename> <pixmapName>", + "pixmap_load :/images/face.png myPixmap"); + DECL_PAINTCOMMAND("pixmap_setMask", command_pixmap_setMask, + "^pixmap_setMask\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]*)$", + "pixmap_setMask <pixmapName> <bitmap filename>", + "pixmap_setMask myPixmap :/images/bitmap.png"); + DECL_PAINTCOMMAND("bitmap_load", command_bitmap_load, + "^bitmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", + "bitmap_load <bitmap filename> <bitmapName>\n - note that the image is stored as a pixmap", + "bitmap_load :/images/bitmap.png myBitmap"); + DECL_PAINTCOMMAND("pixmap_setDevicePixelRatio", command_pixmap_setDevicePixelRatio, + "^pixmap_setDevicePixelRatio\\s+([\\w.:\\/]*)\\s+([.0-9]*)$", + "pixmap_setDevicePixelRatio <pixmapName> <dpr>", + "pixmap_setDevicePixelRatio myPixmap 2.0"); + DECL_PAINTCOMMAND("image_convertToFormat", command_image_convertToFormat, + "^image_convertToFormat\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]+)\\s+([\\w0-9_]*)$", + "image_convertToFormat <sourceImageName> <destImageName> <image format enum>", + "image_convertToFormat myImage myNewImage Indexed8"); + DECL_PAINTCOMMAND("image_load", command_image_load, + "^image_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", + "image_load <filename> <imageName>", + "image_load :/images/face.png myImage"); + DECL_PAINTCOMMAND("image_setColor", command_image_setColor, + "^image_setColor\\s+([\\w.:\\/]*)\\s+([0-9]*)\\s+#([0-9]*)$", + "image_setColor <imageName> <index> <color>", + "image_setColor myImage 0 black"); + DECL_PAINTCOMMAND("image_setColorCount", command_image_setColorCount, + "^image_setColorCount\\s+([\\w.:\\/]*)\\s+([0-9]*)$", + "image_setColorCount <imageName> <nbColors>", + "image_setColorCount myImage 128"); + DECL_PAINTCOMMAND("image_setDevicePixelRatio", command_image_setDevicePixelRatio, + "^image_setDevicePixelRatio\\s+([\\w.:\\/]*)\\s+([.0-9]*)$", + "image_setDevicePixelRatio <imageName> <dpr>", + "image_setDevicePixelRatio myImage 2.0"); + + DECL_PAINTCOMMANDSECTION("transformations"); + DECL_PAINTCOMMAND("resetMatrix", command_resetMatrix, + "^resetMatrix$", + "resetMatrix", + "resetMatrix"); + DECL_PAINTCOMMAND("setMatrix", command_setMatrix, + "^setMatrix\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "setMatrix <m11> <m12> <m13> <m21> <m22> <m23> <m31> <m32> <m33>", + "setMatrix 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"); + DECL_PAINTCOMMAND("translate", command_translate, + "^translate\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "translate <tx> <ty>", + "translate 10.0 10.0"); + DECL_PAINTCOMMAND("rotate", command_rotate, + "^rotate\\s+(-?[\\w.]*)$", + "rotate <angle>\n - with angle in degrees", + "rotate 30.0"); + DECL_PAINTCOMMAND("rotate_x", command_rotate_x, + "^rotate_x\\s+(-?[\\w.]*)$", + "rotate_x <angle>\n - with angle in degrees", + "rotate_x 30.0"); + DECL_PAINTCOMMAND("rotate_y", command_rotate_y, + "^rotate_y\\s+(-?[\\w.]*)$", + "rotate_y <angle>\n - with angle in degrees", + "rotate_y 30.0"); + DECL_PAINTCOMMAND("scale", command_scale, + "^scale\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "scale <sx> <sy>", + "scale 2.0 1.0"); + DECL_PAINTCOMMAND("mapQuadToQuad", command_mapQuadToQuad, + "^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]*)$", + "mapQuadToQuad <x1> <y1> <x2> <y2> <x3> <y3> <x4> <y4> <x5> <y5> <x6> <y6> <x7> <y7> <x8> <y8>" + "\n - where vertices 1 to 4 defines the source quad and 5 to 8 the destination quad", + "mapQuadToQuad 0.0 0.0 1.0 1.0 0.0 0.0 -1.0 -1.0"); + + // populate the command lookup hash + for (int i=0; i<s_commandInfoTable.size(); i++) { + // and pre-optimize the regexps. + s_commandInfoTable.at(i).regExp.optimize(); + if (s_commandInfoTable.at(i).isSectionHeader() || + s_commandInfoTable.at(i).identifier == QLatin1String("comment") || + s_commandInfoTable.at(i).identifier == QLatin1String("noop")) + continue; + s_commandHash.insert(s_commandInfoTable.at(i).identifier, i); + } + + // populate the enums list + ADD_ENUMLIST("brush styles", brushStyleTable); + ADD_ENUMLIST("pen styles", penStyleTable); + ADD_ENUMLIST("font weights", fontWeightTable); + ADD_ENUMLIST("font hintings", fontHintingTable); + ADD_ENUMLIST("clip operations", clipOperationTable); + ADD_ENUMLIST("spread methods", spreadMethodTable); + ADD_ENUMLIST("composition modes", compositionModeTable); + ADD_ENUMLIST("image formats", imageFormatTable); + ADD_ENUMLIST("coordinate modes", coordinateMethodTable); + ADD_ENUMLIST("size modes", sizeModeTable); + ADD_ENUMLIST("render hints", renderHintTable); +} + +#undef DECL_PAINTCOMMAND +#undef ADD_ENUMLIST +/********************************************************************************* +** utility +**********************************************************************************/ +template <typename T> T PaintCommands::image_load(const QString &filepath) +{ + T t(filepath); + + if (t.isNull()) + t = T(":images/" + filepath); + + if (t.isNull()) + t = T("images/" + filepath); + + if (t.isNull()) { + QFileInfo fi(filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = dir.absolutePath() + QLatin1Char('/') + fi.fileName(); + t = T(fileName); + if (t.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + t = T(fileName); + } + } + + return t; +} + +/********************************************************************************* +** setters +**********************************************************************************/ +void PaintCommands::insertAt(int commandIndex, const QStringList &newCommands) +{ + int index = 0; + int left = newCommands.size(); + while (left--) + m_commands.insert(++commandIndex, newCommands.at(index++)); +} + +/********************************************************************************* +** run +**********************************************************************************/ +void PaintCommands::runCommand(const QString &scriptLine) +{ + static QRegularExpression separators("\\s"); + if (scriptLine.isEmpty()) { + command_noop(QRegularExpressionMatch()); + return; + } + if (scriptLine.startsWith('#')) { + command_comment(QRegularExpressionMatch()); + return; + } + QString firstWord = scriptLine.section(separators, 0, 0); + const QList<int> indices = s_commandHash.values(firstWord); + for (int idx : indices) { + PaintCommandInfos command = s_commandInfoTable.at(idx); + Q_ASSERT(command.regExp.isValid()); + QRegularExpressionMatch match = command.regExp.match(scriptLine); + if (match.hasMatch()) { + (this->*(command.paintMethod))(match); + return; + } + } + qWarning("ERROR: unknown command or argument syntax error in \"%s\"", qPrintable(scriptLine)); +} + +void PaintCommands::runCommands() +{ + staticInit(); + int width = m_painter->window().width(); + int height = m_painter->window().height(); + + if (width <= 0) + width = 800; + if (height <= 0) + height = 800; + + m_pathMap.clear(); + m_imageMap.clear(); + m_pixmapMap.clear(); + m_regionMap.clear(); + m_gradientStops.clear(); + m_blockMap.clear(); + + // paint background + if (m_checkers_background) { + QPixmap pm(20, 20); + pm.fill(Qt::white); + QPainter pt(&pm); + pt.fillRect(0, 0, 10, 10, QColor::fromRgba(0xffdfdfdf)); + pt.fillRect(10, 10, 10, 10, QColor::fromRgba(0xffdfdfdf)); + pt.end(); + m_painter->drawTiledPixmap(0, 0, width, height, pm); + } else { + m_painter->fillRect(0, 0, width, height, Qt::white); + } + + // run each command + m_abort = false; + for (int i=0; i<m_commands.size() && !m_abort; ++i) { + const QString &commandNow = m_commands.at(i); + m_currentCommand = commandNow; + m_currentCommandIndex = i; + runCommand(commandNow.trimmed()); + } +} + +/********************************************************************************* +** conversions +**********************************************************************************/ +int PaintCommands::convertToInt(const QString &str) +{ + return qRound(convertToDouble(str)); +} + +float PaintCommands::convertToFloat(const QString &str) +{ + return float(convertToDouble(str)); +} + +double PaintCommands::convertToDouble(const QString &str) +{ + static QRegularExpression re("cp([0-9])([xy])"); + if (str.toLower() == "width") { + if (m_painter->device()->devType() == Qt::Widget) + return m_painter->window().width(); + else + return 800; + } + if (str.toLower() == "height") { + if (m_painter->device()->devType() == Qt::Widget) + return m_painter->window().height(); + else + return 800; + } + QRegularExpressionMatch match = re.match(str); + if (match.hasMatch()) { + int index = match.captured(1).toInt(); + bool is_it_x = match.captured(2) == "x"; + if (index < 0 || index >= m_controlPoints.size()) { + qWarning("ERROR: control point index=%d is out of bounds", index); + return 0; + } + return is_it_x ? m_controlPoints.at(index).x() : m_controlPoints.at(index).y(); + } + return str.toDouble(); +} + +QColor PaintCommands::convertToColor(const QString &str) +{ + static QRegularExpression alphaColorRe("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})"); + static QRegularExpression opaqueColorRe("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})"); + + Q_ASSERT(alphaColorRe.isValid()); + Q_ASSERT(opaqueColorRe.isValid()); + + QRegularExpressionMatch alphaColor = alphaColorRe.match(str); + QRegularExpressionMatch opaqueColor = opaqueColorRe.match(str); + if (alphaColor.hasMatch()) { + return QColor(alphaColor.captured(2).toInt(0, 16), + alphaColor.captured(3).toInt(0, 16), + alphaColor.captured(4).toInt(0, 16), + alphaColor.captured(1).toInt(0, 16)); + } else if (opaqueColor.hasMatch()) { + return QColor(opaqueColor.captured(1).toInt(0, 16), + opaqueColor.captured(2).toInt(0, 16), + opaqueColor.captured(3).toInt(0, 16)); + } + return QColor(str); +} + +/********************************************************************************* +** command implementations +**********************************************************************************/ +void PaintCommands::command_comment(QRegularExpressionMatch) +{ + if (m_verboseMode) + printf(" -(lance) comment: %s\n", qPrintable(m_currentCommand)); +} + +/***************************************************************************************************/ +void PaintCommands::command_import(QRegularExpressionMatch re) +{ + QString importFile(re.captured(1)); + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + QFile *file = new QFile(dir.absolutePath() + QDir::separator() + importFile); + + if (importFile.isEmpty() || !file->exists()) { + dir.cdUp(); + dir.cd("data"); + dir.cd("qps"); + delete file; + file = new QFile(dir.absolutePath() + QDir::separator() + importFile); + } + + if (importFile.isEmpty() || !file->exists()) { + dir.cdUp(); + dir.cd("images"); + delete file; + file = new QFile(dir.absolutePath() + QDir::separator() + importFile); + } + + if (importFile.isEmpty() || !file->exists()) { + printf(" - importing non-existing file at line %d (%s)\n", m_currentCommandIndex, + qPrintable(file->fileName())); + delete file; + return; + } + + if (!file->open(QIODevice::ReadOnly)) { + printf(" - failed to read file: '%s'\n", qPrintable(file->fileName())); + delete file; + return; + } + if (m_verboseMode) + printf(" -(lance) importing file at line %d (%s)\n", m_currentCommandIndex, + qPrintable(fi.fileName())); + + QFileInfo fileinfo(*file); + m_commands[m_currentCommandIndex] = QLatin1String("# import file (") + fileinfo.fileName() + + QLatin1String(") start"); + QString rawContent = QString::fromUtf8(file->readAll()); + QStringList importedData = rawContent.split('\n', Qt::SkipEmptyParts); + importedData.append(QLatin1String("# import file (") + fileinfo.fileName() + QLatin1String(") end ---")); + insertAt(m_currentCommandIndex, importedData); + + if (m_verboseMode) { + printf(" -(lance) Command buffer now looks like:\n"); + for (int i = 0; i < m_commands.size(); ++i) + printf(" ---> {%s}\n", qPrintable(m_commands.at(i))); + } + delete file; +} + +/***************************************************************************************************/ +void PaintCommands::command_begin_block(QRegularExpressionMatch re) +{ + const QString &blockName = re.captured(1); + if (m_verboseMode) + printf(" -(lance) begin_block (%s)\n", qPrintable(blockName)); + if (m_blockMap.contains(blockName)) + qFatal("Two blocks named (%s)", qPrintable(blockName)); + + m_commands[m_currentCommandIndex] = QLatin1String("# begin block (") + blockName + QLatin1Char(')'); + QStringList newBlock; + int i = m_currentCommandIndex + 1; + for (; i < m_commands.size(); ++i) { + const QString &nextCmd = m_commands.at(i); + if (nextCmd.startsWith("end_block")) { + m_commands[i] = QLatin1String("# end block (") + blockName + QLatin1Char(')'); + break; + } + newBlock += nextCmd; + } + + if (m_verboseMode) + for (int j = 0; j < newBlock.size(); ++j) + printf(" %d: %s\n", j, qPrintable(newBlock.at(j))); + + if (i >= m_commands.size()) + printf(" - Warning! Block doesn't have an 'end_block' marker!\n"); + + m_blockMap.insert(blockName, newBlock); +} + +/***************************************************************************************************/ +void PaintCommands::command_end_block(QRegularExpressionMatch) +{ + printf(" - end_block should be consumed by begin_block command.\n"); + printf(" You will never see this if your block markers are in sync\n"); + printf(" (noop)\n"); +} + +/***************************************************************************************************/ +void PaintCommands::command_repeat_block(QRegularExpressionMatch re) +{ + QString blockName = re.captured(1); + if (m_verboseMode) + printf(" -(lance) repeating block (%s)\n", qPrintable(blockName)); + + QStringList block = m_blockMap.value(blockName); + if (block.isEmpty()) { + printf(" - repeated block (%s) is empty!\n", qPrintable(blockName)); + return; + } + + m_commands[m_currentCommandIndex] = QLatin1String("# repeated block (") + blockName + QLatin1Char(')'); + insertAt(m_currentCommandIndex, block); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawLine(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double x1 = convertToDouble(caps.at(1)); + double y1 = convertToDouble(caps.at(2)); + double x2 = convertToDouble(caps.at(3)); + double y2 = convertToDouble(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) drawLine((%.2f, %.2f), (%.2f, %.2f))\n", x1, y1, x2, y2); + + m_painter->drawLine(QLineF(x1, y1, x2, y2)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawLines(QRegularExpressionMatch re) +{ + static QRegularExpression separators("\\s"); + QStringList numbers = re.captured(1).split(separators, Qt::SkipEmptyParts); + + QList<QLineF> array; + for (int i = 0; i + 3 < numbers.size(); i += 4) { + QPointF pt1(numbers.at(i).toFloat(), numbers.at(i + 1).toFloat()); + QPointF pt2(numbers.at(i + 2).toFloat(), numbers.at(i + 3).toFloat()); + array.append(QLineF(pt1, pt2)); + } + + if (m_verboseMode) + printf(" -(lance) drawLines(size=%zd)\n", size_t(array.size())); + + m_painter->drawLines(array); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPath(QRegularExpressionMatch re) +{ + if (m_verboseMode) + printf(" -(lance) drawPath(name=%s)\n", qPrintable(re.captured(1))); + + QPainterPath &path = m_pathMap[re.captured(1)]; + m_painter->drawPath(path); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPixmap(QRegularExpressionMatch re) +{ + QPixmap pm; + pm = m_pixmapMap[re.captured(1)]; // try cache first + if (pm.isNull()) + pm = image_load<QPixmap>(re.captured(1)); + if (pm.isNull()) { + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(1); + pm = QPixmap(fileName); + if (pm.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + pm = QPixmap(fileName); + } + } + if (pm.isNull()) { + fprintf(stderr, "ERROR(drawPixmap): failed to load pixmap: '%s'\n", + qPrintable(re.captured(1))); + return; + } + + qreal tx = convertToFloat(re.captured(2)); + qreal ty = convertToFloat(re.captured(3)); + qreal tw = convertToFloat(re.captured(4)); + qreal th = convertToFloat(re.captured(5)); + + qreal sx = convertToFloat(re.captured(6)); + qreal sy = convertToFloat(re.captured(7)); + qreal sw = convertToFloat(re.captured(8)); + qreal sh = convertToFloat(re.captured(9)); + + if (tw == 0) tw = -1; + if (th == 0) th = -1; + if (sw == 0) sw = -1; + if (sh == 0) sh = -1; + + if (m_verboseMode) + printf(" -(lance) drawPixmap('%s' dim=(%d, %d), depth=%d, (%f, %f, %f, %f), (%f, %f, %f, %f)\n", + qPrintable(re.captured(1)), pm.width(), pm.height(), pm.depth(), + tx, ty, tw, th, sx, sy, sw, sh); + + if (!re.capturedLength(4)) // at most two coordinates specified + m_painter->drawPixmap(QPointF(tx, ty), pm); + else + m_painter->drawPixmap(QRectF(tx, ty, tw, th), pm, QRectF(sx, sy, sw, sh)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawImage(QRegularExpressionMatch re) +{ + QImage im; + im = m_imageMap[re.captured(1)]; // try cache first + if (im.isNull()) + im = image_load<QImage>(re.captured(1)); + + if (im.isNull()) { + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(1); + im = QImage(fileName); + if (im.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + im = QImage(fileName); + } + } + if (im.isNull()) { + fprintf(stderr, "ERROR(drawImage): failed to load image: '%s'\n", qPrintable(re.captured(1))); + return; + } + + qreal tx = convertToFloat(re.captured(2)); + qreal ty = convertToFloat(re.captured(3)); + qreal tw = convertToFloat(re.captured(4)); + qreal th = convertToFloat(re.captured(5)); + + qreal sx = convertToFloat(re.captured(6)); + qreal sy = convertToFloat(re.captured(7)); + qreal sw = convertToFloat(re.captured(8)); + qreal sh = convertToFloat(re.captured(9)); + + if (tw == 0) tw = -1; + if (th == 0) th = -1; + if (sw == 0) sw = -1; + if (sh == 0) sh = -1; + + if (m_verboseMode) + printf(" -(lance) drawImage('%s' dim=(%d, %d), (%f, %f, %f, %f), (%f, %f, %f, %f)\n", + qPrintable(re.captured(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh); + + if (!re.capturedLength(4)) // at most two coordinates specified + m_painter->drawImage(QPointF(tx, ty), im); + else + m_painter->drawImage(QRectF(tx, ty, tw, th), im, QRectF(sx, sy, sw, sh)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawTiledPixmap(QRegularExpressionMatch re) +{ + QPixmap pm; + pm = m_pixmapMap[re.captured(1)]; // try cache first + if (pm.isNull()) + pm = image_load<QPixmap>(re.captured(1)); + if (pm.isNull()) { + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(1); + pm = QPixmap(fileName); + if (pm.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + pm = QPixmap(fileName); + } + } + if (pm.isNull()) { + fprintf(stderr, "ERROR(drawTiledPixmap): failed to load pixmap: '%s'\n", + qPrintable(re.captured(1))); + return; + } + + int tx = convertToInt(re.captured(2)); + int ty = convertToInt(re.captured(3)); + int tw = convertToInt(re.captured(4)); + int th = convertToInt(re.captured(5)); + + int sx = convertToInt(re.captured(6)); + int sy = convertToInt(re.captured(7)); + + if (tw == 0) tw = -1; + if (th == 0) th = -1; + + if (m_verboseMode) + printf(" -(lance) drawTiledPixmap('%s' dim=(%d, %d), (%d, %d, %d, %d), (%d, %d)\n", + qPrintable(re.captured(1)), pm.width(), pm.height(), tx, ty, tw, th, sx, sy); + + m_painter->drawTiledPixmap(tx, ty, tw, th, pm, sx, sy); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPoint(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + float x = convertToFloat(caps.at(1)); + float y = convertToFloat(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) drawPoint(%.2f, %.2f)\n", x, y); + + m_painter->drawPoint(QPointF(x, y)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPolygon(QRegularExpressionMatch re) +{ + static QRegularExpression separators("\\s"); + QStringList caps = re.capturedTexts(); + QString cap = caps.at(1); + QStringList numbers = cap.split(separators, Qt::SkipEmptyParts); + + QPolygonF array; + for (int i=0; i + 1<numbers.size(); i+=2) + array.append(QPointF(convertToDouble(numbers.at(i)), convertToDouble(numbers.at(i+1)))); + + if (m_verboseMode) + printf(" -(lance) drawPolygon(size=%zd)\n", size_t(array.size())); + + m_painter->drawPolygon(array, caps.at(2).toLower() == "winding" ? Qt::WindingFill : Qt::OddEvenFill); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPolyline(QRegularExpressionMatch re) +{ + static QRegularExpression separators("\\s"); + QStringList numbers = re.captured(1).split(separators, Qt::SkipEmptyParts); + + QPolygonF array; + for (int i=0; i + 1<numbers.size(); i+=2) + array.append(QPointF(numbers.at(i).toFloat(),numbers.at(i+1).toFloat())); + + if (m_verboseMode) + printf(" -(lance) drawPolyline(size=%zd)\n", size_t(array.size())); + + m_painter->drawPolyline(array.toPolygon()); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawRect(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + float x = convertToFloat(caps.at(1)); + float y = convertToFloat(caps.at(2)); + float w = convertToFloat(caps.at(3)); + float h = convertToFloat(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) drawRect(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h); + + m_painter->drawRect(QRectF(x, y, w, h)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawRoundedRect(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + float x = convertToFloat(caps.at(1)); + float y = convertToFloat(caps.at(2)); + float w = convertToFloat(caps.at(3)); + float h = convertToFloat(caps.at(4)); + float xr = convertToFloat(caps.at(5)); + float yr = convertToFloat(caps.at(6)); + + int mode = translateEnum(sizeModeTable, caps.at(7), sizeof(sizeModeTable)/sizeof(char *)); + if (mode < 0) + mode = Qt::AbsoluteSize; + + if (m_verboseMode) + printf(" -(lance) drawRoundRect(%f, %f, %f, %f, %f, %f, %s)\n", x, y, w, h, xr, yr, mode ? "RelativeSize" : "AbsoluteSize"); + + m_painter->drawRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::SizeMode(mode)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawRoundRect(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + int xs = caps.at(5).isEmpty() ? 50 : convertToInt(caps.at(5)); + int ys = caps.at(6).isEmpty() ? 50 : convertToInt(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) drawRoundRect(%d, %d, %d, %d, [%d, %d])\n", x, y, w, h, xs, ys); + + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + m_painter->drawRoundedRect(x, y, w, h, xs, ys, Qt::RelativeSize); + QT_WARNING_POP +} + +/***************************************************************************************************/ +void PaintCommands::command_drawEllipse(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + float x = convertToFloat(caps.at(1)); + float y = convertToFloat(caps.at(2)); + float w = convertToFloat(caps.at(3)); + float h = convertToFloat(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) drawEllipse(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h); + + m_painter->drawEllipse(QRectF(x, y, w, h)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPie(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + int angle = convertToInt(caps.at(5)); + int sweep = convertToInt(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) drawPie(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); + + m_painter->drawPie(x, y, w, h, angle, sweep); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawChord(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + int angle = convertToInt(caps.at(5)); + int sweep = convertToInt(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) drawChord(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); + + m_painter->drawChord(x, y, w, h, angle, sweep); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawArc(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + int angle = convertToInt(caps.at(5)); + int sweep = convertToInt(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) drawArc(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); + + m_painter->drawArc(x, y, w, h, angle, sweep); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawText(QRegularExpressionMatch re) +{ + if (!m_shouldDrawText) + return; + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + QString txt = caps.at(3); + + if (m_verboseMode) + printf(" -(lance) drawText(%d, %d, %s)\n", x, y, qPrintable(txt)); + + m_painter->drawText(x, y, txt); +} + +void PaintCommands::command_drawStaticText(QRegularExpressionMatch re) +{ + if (!m_shouldDrawText) + return; + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + QString txt = caps.at(3); + + if (m_verboseMode) + printf(" -(lance) drawStaticText(%d, %d, %s)\n", x, y, qPrintable(txt)); + + m_painter->drawStaticText(x, y, QStaticText(txt)); +} + +void PaintCommands::command_drawGlyphRun(QRegularExpressionMatch re) +{ + if (!m_shouldDrawText) + return; + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + QString txt = caps.at(3); + + if (m_verboseMode) + printf(" -(lance) drawGlyphRun(%d, %d, %s)\n", x, y, qPrintable(txt)); + + QTextLayout layout; + layout.setFont(m_painter->font()); + layout.setText(txt); + layout.beginLayout(); + qreal lineY = 0.0; + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + line.setPosition(QPointF(0.0, lineY)); + lineY += line.height(); + } + layout.endLayout(); + + QList<QGlyphRun> glyphRuns = layout.glyphRuns(); + + for (const QGlyphRun &glyphRun : glyphRuns) + m_painter->drawGlyphRun(QPointF(x, y), glyphRun); +} + +void PaintCommands::command_drawTextDocument(QRegularExpressionMatch re) +{ + if (!m_shouldDrawText) + return; + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + QString txt = caps.at(3); + + if (m_verboseMode) + printf(" -(lance) drawTextDocument(%d, %d, %s)\n", x, y, qPrintable(txt)); + + QTextDocument doc; + doc.setBaseUrl(QUrl::fromLocalFile(QDir::currentPath() + QLatin1String("/"))); + doc.setHtml(txt); + + m_painter->save(); + m_painter->translate(x, y); + doc.drawContents(m_painter); + m_painter->restore(); +} + +/***************************************************************************************************/ +void PaintCommands::command_fillRect(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + + if (!caps.at(5).isEmpty()) { + QColor color = convertToColor(caps.at(5)); + if (m_verboseMode) + printf(" -(lance) fillRect(%d, %d, %d, %d, %s)\n", x, y, w, h, qPrintable(color.name())); + m_painter->fillRect(x, y, w, h, color); + } else { + if (m_verboseMode) + printf(" -(lance) fillRect(%d, %d, %d, %d)\n", x, y, w, h); + m_painter->fillRect(x, y, w, h, m_painter->brush()); + } +} + +void PaintCommands::command_fillRectF(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double x = convertToDouble(caps.at(1)); + double y = convertToDouble(caps.at(2)); + double w = convertToDouble(caps.at(3)); + double h = convertToDouble(caps.at(4)); + + if (!caps.at(5).isEmpty()) { + QColor color = convertToColor(caps.at(5)); + if (m_verboseMode) + printf(" -(lance) fillRectF(%.2f, %.2f, %.2f, %.2f, %s)\n", x, y, w, h, qPrintable(color.name())); + m_painter->fillRect(QRectF(x, y, w, h), color); + } else { + if (m_verboseMode) + printf(" -(lance) fillRectF(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h); + m_painter->fillRect(QRectF(x, y, w, h), m_painter->brush()); + } +} + +void PaintCommands::command_drawPixmapFragments(QRegularExpressionMatch re) +{ + QPixmap pm; + pm = m_pixmapMap[re.captured(1)]; // try cache first + if (pm.isNull()) + pm = image_load<QPixmap>(re.captured(1)); + if (pm.isNull()) { + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(1); + pm = QPixmap(fileName); + if (pm.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + pm = QPixmap(fileName); + } + } + if (pm.isNull()) { + fprintf(stderr, "ERROR(drawPixmapFragments): failed to load pixmap: '%s'\n", + qPrintable(re.captured(1))); + return; + } + + int count = convertToInt(re.captured(2)); + + struct Fragment { + double posx; + double posy; + double srcx; + double srcy; + double srcw; + double srch; + double sx; + double sy; + double rotation; + double opacity; + }; + + QList<Fragment> fragments; + for (int i = 0; i < count; ++i) { + int captureIndexStart = 3 + i * 10; + if (re.hasCaptured(captureIndexStart)) { + Fragment f; + f.posx = convertToDouble(re.captured(captureIndexStart)); + f.posy = convertToDouble(re.captured(captureIndexStart + 1)); + f.srcx = convertToDouble(re.captured(captureIndexStart + 2)); + f.srcy = convertToDouble(re.captured(captureIndexStart + 3)); + f.srcw = convertToDouble(re.captured(captureIndexStart + 4)); + f.srch = convertToDouble(re.captured(captureIndexStart + 5)); + f.sx = convertToDouble(re.captured(captureIndexStart + 6)); + f.sy = convertToDouble(re.captured(captureIndexStart + 7)); + f.rotation = convertToDouble(re.captured(captureIndexStart + 8)); + f.opacity = convertToDouble(re.captured(captureIndexStart + 9)); + fragments.append(f); + } else { + break; + } + } + + if (m_verboseMode) { + printf(" -(lance) drawPixmapFragments('%s' count=%d ", + qPrintable(re.captured(1)), int(fragments.count())); + for (int i = 0; i < fragments.count(); ++i) { + printf("pos=(%.2f, %.2f) srcrect=(%.2f %.2f %.2f %.2f) scale=(%.2f %.2f) rotation=%.2f opacity=%.2f ", + fragments[i].posx, fragments[i].posy, + fragments[i].srcx, fragments[i].srcy, fragments[i].srcw, fragments[i].srch, + fragments[i].sx, fragments[i].sy, + fragments[i].rotation, + fragments[i].opacity); + } + printf("\n"); + } + + QList<QPainter::PixmapFragment> pixmapFragments; + for (int i = 0; i < fragments.count(); ++i) { + pixmapFragments.append( + QPainter::PixmapFragment::create(QPointF(fragments[i].posx, fragments[i].posy), + QRectF(fragments[i].srcx, fragments[i].srcy, fragments[i].srcw, fragments[i].srch), + fragments[i].sx, fragments[i].sy, + fragments[i].rotation, + fragments[i].opacity)); + } + + m_painter->drawPixmapFragments(pixmapFragments.constData(), pixmapFragments.count(), pm); +} + +/***************************************************************************************************/ +void PaintCommands::command_noop(QRegularExpressionMatch) +{ + if (m_verboseMode) + printf(" -(lance) noop: %s\n", qPrintable(m_currentCommand)); + + if (!m_currentCommand.trimmed().isEmpty()) { + fprintf(stderr, "unknown command: '%s'\n", qPrintable(m_currentCommand.trimmed())); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_path_addText(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x = convertToDouble(caps.at(2)); + double y = convertToDouble(caps.at(3)); + QString text = caps.at(4); + + if (m_verboseMode) + printf(" -(lance) path_addText(%s, %.2f, %.2f, text=%s\n", qPrintable(name), x, y, qPrintable(text)); + + m_pathMap[name].addText(x, y, m_painter->font(), text); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_addEllipse(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x = convertToDouble(caps.at(2)); + double y = convertToDouble(caps.at(3)); + double w = convertToDouble(caps.at(4)); + double h = convertToDouble(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) path_addEllipse(%s, %.2f, %.2f, %.2f, %.2f)\n", qPrintable(name), x, y, w, h); + + m_pathMap[name].addEllipse(x, y, w, h); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_addRect(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x = convertToDouble(caps.at(2)); + double y = convertToDouble(caps.at(3)); + double w = convertToDouble(caps.at(4)); + double h = convertToDouble(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) path_addRect(%s, %.2f, %.2f, %.2f, %.2f)\n", qPrintable(name), x, y, w, h); + + m_pathMap[name].addRect(x, y, w, h); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_addPolygon(QRegularExpressionMatch re) +{ + static QRegularExpression separators("\\s"); + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + QString cap = caps.at(2); + QStringList numbers = cap.split(separators, Qt::SkipEmptyParts); + + QPolygonF array; + for (int i=0; i + 1<numbers.size(); i+=2) + array.append(QPointF(numbers.at(i).toFloat(),numbers.at(i+1).toFloat())); + + if (m_verboseMode) + printf(" -(lance) path_addPolygon(name=%s, size=%zd)\n", qPrintable(name), size_t(array.size())); + + m_pathMap[name].addPolygon(array); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_arcTo(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x = convertToDouble(caps.at(2)); + double y = convertToDouble(caps.at(3)); + double w = convertToDouble(caps.at(4)); + double h = convertToDouble(caps.at(5)); + double angle = convertToDouble(caps.at(6)); + double length = convertToDouble(caps.at(7)); + + if (m_verboseMode) + printf(" -(lance) path_arcTo(%s, %.2f, %.2f, %.2f, %.2f, angle=%.2f, len=%.2f)\n", qPrintable(name), x, y, w, h, angle, length); + + m_pathMap[name].arcTo(x, y, w, h, angle, length); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_createOutline(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + QString newName = caps.at(2); + QPen pen = m_painter->pen(); + + if (m_verboseMode) + printf(" -(lance) path_createOutline(%s, name=%s, width=%d)\n", + qPrintable(name), qPrintable(newName), pen.width()); + + if (!m_pathMap.contains(name)) { + fprintf(stderr, "createOutline(), unknown path: %s\n", qPrintable(name)); + return; + } + QPainterPathStroker stroker; + stroker.setWidth(pen.widthF()); + stroker.setDashPattern(pen.style()); + stroker.setCapStyle(pen.capStyle()); + stroker.setJoinStyle(pen.joinStyle()); + m_pathMap[newName] = stroker.createStroke(m_pathMap[name]); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_cubicTo(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x1 = convertToDouble(caps.at(2)); + double y1 = convertToDouble(caps.at(3)); + double x2 = convertToDouble(caps.at(4)); + double y2 = convertToDouble(caps.at(5)); + double x3 = convertToDouble(caps.at(6)); + double y3 = convertToDouble(caps.at(7)); + + if (m_verboseMode) + printf(" -(lance) path_cubicTo(%s, (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f))\n", qPrintable(name), x1, y1, x2, y2, x3, y3); + + m_pathMap[name].cubicTo(x1, y1, x2, y2, x3, y3); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_moveTo(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x1 = convertToDouble(caps.at(2)); + double y1 = convertToDouble(caps.at(3)); + + if (m_verboseMode) + printf(" -(lance) path_moveTo(%s, (%.2f, %.2f))\n", qPrintable(name), x1, y1); + + m_pathMap[name].moveTo(x1, y1); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_lineTo(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x1 = convertToDouble(caps.at(2)); + double y1 = convertToDouble(caps.at(3)); + + if (m_verboseMode) + printf(" -(lance) path_lineTo(%s, (%.2f, %.2f))\n", qPrintable(name), x1, y1); + + m_pathMap[name].lineTo(x1, y1); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_setFillRule(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + bool winding = caps.at(2).toLower() == "winding"; + + if (m_verboseMode) + printf(" -(lance) path_setFillRule(name=%s, winding=%d)\n", qPrintable(name), winding); + + m_pathMap[name].setFillRule(winding ? Qt::WindingFill : Qt::OddEvenFill); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_closeSubpath(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + + if (m_verboseMode) + printf(" -(lance) path_closeSubpath(name=%s)\n", qPrintable(name)); + + m_pathMap[name].closeSubpath(); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_getClipPath(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + + if (m_verboseMode) + printf(" -(lance) path_closeSubpath(name=%s)\n", qPrintable(name)); + + m_pathMap[name] = m_painter->clipPath(); +} + +/***************************************************************************************************/ +static void qt_debug_path(const QPainterPath &path, const QString &name) +{ + const char *names[] = { + "MoveTo ", + "LineTo ", + "CurveTo ", + "CurveToData" + }; + + printf("\nQPainterPath (%s): elementCount=%d\n", qPrintable(name), path.elementCount()); + for (int i=0; i<path.elementCount(); ++i) { + const QPainterPath::Element &e = path.elementAt(i); + Q_ASSERT(e.type >= 0 && e.type <= QPainterPath::CurveToDataElement); + printf(" - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_path_debugPrint(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + qt_debug_path(m_pathMap[name], name); +} + +/***************************************************************************************************/ +void PaintCommands::command_region_addRect(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + int x = convertToInt(caps.at(2)); + int y = convertToInt(caps.at(3)); + int w = convertToInt(caps.at(4)); + int h = convertToInt(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) region_addRect(%s, %d, %d, %d, %d)\n", qPrintable(name), x, y, w, h); + + m_regionMap[name] += QRect(x, y, w, h); +} + +/***************************************************************************************************/ +void PaintCommands::command_region_addEllipse(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + int x = convertToInt(caps.at(2)); + int y = convertToInt(caps.at(3)); + int w = convertToInt(caps.at(4)); + int h = convertToInt(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) region_addEllipse(%s, %d, %d, %d, %d)\n", qPrintable(name), x, y, w, h); + + m_regionMap[name] += QRegion(x, y, w, h, QRegion::Ellipse); +} + +/***************************************************************************************************/ +void PaintCommands::command_region_getClipRegion(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + QRegion region = m_painter->clipRegion(); + + if (m_verboseMode) + printf(" -(lance) region_getClipRegion(name=%s), bounds=[%d, %d, %d, %d]\n", qPrintable(name), + region.boundingRect().x(), + region.boundingRect().y(), + region.boundingRect().width(), + region.boundingRect().height()); + + m_regionMap[name] = region; +} + +/***************************************************************************************************/ +void PaintCommands::command_resetMatrix(QRegularExpressionMatch) +{ + if (m_verboseMode) + printf(" -(lance) resetMatrix()\n"); + + m_painter->resetTransform(); +} + +/***************************************************************************************************/ +void PaintCommands::command_restore(QRegularExpressionMatch) +{ + if (m_verboseMode) + printf(" -(lance) restore()\n"); + + m_painter->restore(); +} + +/***************************************************************************************************/ +void PaintCommands::command_rotate(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double angle = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) rotate(%.2f)\n", angle); + + m_painter->rotate(angle); +} + +/***************************************************************************************************/ +void PaintCommands::command_rotate_x(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double angle = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) rotate_x(%.2f)\n", angle); + + QTransform transform; + transform.rotate(angle, Qt::XAxis); + m_painter->setTransform(transform, true); +} + +/***************************************************************************************************/ +void PaintCommands::command_rotate_y(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double angle = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) rotate_y(%.2f)\n", angle); + + QTransform transform; + transform.rotate(angle, Qt::YAxis); + m_painter->setTransform(transform, true); +} + +/***************************************************************************************************/ +void PaintCommands::command_save(QRegularExpressionMatch) +{ + if (m_verboseMode) + printf(" -(lance) save()\n"); + + m_painter->save(); +} + +/***************************************************************************************************/ +void PaintCommands::command_mapQuadToQuad(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double x1 = convertToDouble(caps.at(1)); + double y1 = convertToDouble(caps.at(2)); + double x2 = convertToDouble(caps.at(3)); + double y2 = convertToDouble(caps.at(4)); + double x3 = convertToDouble(caps.at(5)); + double y3 = convertToDouble(caps.at(6)); + double x4 = convertToDouble(caps.at(7)); + double y4 = convertToDouble(caps.at(8)); + QPolygonF poly1(4); + poly1[0] = QPointF(x1, y1); + poly1[1] = QPointF(x2, y2); + poly1[2] = QPointF(x3, y3); + poly1[3] = QPointF(x4, y4); + + double x5 = convertToDouble(caps.at(9)); + double y5 = convertToDouble(caps.at(10)); + double x6 = convertToDouble(caps.at(11)); + double y6 = convertToDouble(caps.at(12)); + double x7 = convertToDouble(caps.at(13)); + double y7 = convertToDouble(caps.at(14)); + double x8 = convertToDouble(caps.at(15)); + double y8 = convertToDouble(caps.at(16)); + QPolygonF poly2(4); + poly2[0] = QPointF(x5, y5); + poly2[1] = QPointF(x6, y6); + poly2[2] = QPointF(x7, y7); + poly2[3] = QPointF(x8, y8); + + if (m_verboseMode) + printf(" -(lance) mapQuadToQuad(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f ->\n\t" + ",%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", + x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6, x7, y7, x8, y8); + + QTransform trans; + + if (!QTransform::quadToQuad(poly1, poly2, trans)) { + qWarning("Couldn't perform quad to quad transformation!"); + } + + m_painter->setTransform(trans, true); +} + +/***************************************************************************************************/ +void PaintCommands::command_setMatrix(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double m11 = convertToDouble(caps.at(1)); + double m12 = convertToDouble(caps.at(2)); + double m13 = convertToDouble(caps.at(3)); + double m21 = convertToDouble(caps.at(4)); + double m22 = convertToDouble(caps.at(5)); + double m23 = convertToDouble(caps.at(6)); + double m31 = convertToDouble(caps.at(7)); + double m32 = convertToDouble(caps.at(8)); + double m33 = convertToDouble(caps.at(9)); + + if (m_verboseMode) + printf(" -(lance) setMatrix(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", + m11, m12, m13, m21, m22, m23, m31, m32, m33); + + QTransform trans; + trans.setMatrix(m11, m12, m13, + m21, m22, m23, + m31, m32, m33); + + m_painter->setTransform(trans, true); +} + +/***************************************************************************************************/ +void PaintCommands::command_scale(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double sx = convertToDouble(caps.at(1)); + double sy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) scale(%.2f, %.2f)\n", sx, sy); + + + m_painter->scale(sx, sy); +} + +/***************************************************************************************************/ +void PaintCommands::command_setBackground(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QColor color = convertToColor(caps.at(1)); + QString pattern = caps.at(2); + + int style = translateEnum(brushStyleTable, pattern, Qt::LinearGradientPattern); + if (style < 0) + style = Qt::SolidPattern; + + if (m_verboseMode) + printf(" -(lance) setBackground(%s, %s)\n", qPrintable(color.name()), qPrintable(pattern)); + + m_painter->setBackground(QBrush(color, Qt::BrushStyle(style))); +} + +/***************************************************************************************************/ +void PaintCommands::command_setOpacity(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double opacity = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) setOpacity(%lf)\n", opacity); + + m_painter->setOpacity(opacity); +} + +/***************************************************************************************************/ +void PaintCommands::command_setBgMode(QRegularExpressionMatch re) +{ + QString cap = re.captured(2); + Qt::BGMode mode = Qt::TransparentMode; + if (cap.toLower() == QLatin1String("opaquemode") || cap.toLower() == QLatin1String("opaque")) + mode = Qt::OpaqueMode; + + if (m_verboseMode) + printf(" -(lance) setBackgroundMode(%s)\n", mode == Qt::OpaqueMode ? "OpaqueMode" : "TransparentMode"); + + m_painter->setBackgroundMode(mode); +} + +/***************************************************************************************************/ +void PaintCommands::command_setBrush(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QImage img = m_imageMap[caps.at(1)]; // try cache first + if (img.isNull()) + img = image_load<QImage>(caps.at(1)); + if (!img.isNull()) { // Assume image brush + if (m_verboseMode) + printf(" -(lance) setBrush(image=%s, width=%d, height=%d)\n", + qPrintable(caps.at(1)), img.width(), img.height()); + + m_painter->setBrush(QBrush(img)); + } else if (caps.at(1).toLower() == "nobrush") { + m_painter->setBrush(Qt::NoBrush); + if (m_verboseMode) + printf(" -(lance) setBrush(Qt::NoBrush)\n"); + } else { + QColor color = convertToColor(caps.at(1)); + QString pattern = caps.at(2); + + int style = translateEnum(brushStyleTable, pattern, Qt::LinearGradientPattern); + if (style < 0) + style = Qt::SolidPattern; + + if (m_verboseMode) + printf(" -(lance) setBrush(%s, %s (%d))\n", qPrintable(color.name()), qPrintable(pattern), style); + + m_painter->setBrush(QBrush(color, Qt::BrushStyle(style))); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_setBrushOrigin(QRegularExpressionMatch re) +{ + int x = convertToInt(re.captured(1)); + int y = convertToInt(re.captured(2)); + + if (m_verboseMode) + printf(" -(lance) setBrushOrigin(%d, %d)\n", x, y); + + m_painter->setBrushOrigin(x, y); +} + +/***************************************************************************************************/ +void PaintCommands::command_brushTranslate(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double dx = convertToDouble(caps.at(1)); + double dy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) brushTranslate(%f, %f)\n", dx, dy); + + QBrush new_brush = m_painter->brush(); + QTransform brush_matrix = new_brush.transform(); + brush_matrix.translate(dx, dy); + new_brush.setTransform(brush_matrix); + m_painter->setBrush(new_brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_brushScale(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double sx = convertToDouble(caps.at(1)); + double sy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) brushScale(%f, %f)\n", sx, sy); + + QBrush new_brush = m_painter->brush(); + QTransform brush_matrix = new_brush.transform(); + brush_matrix.scale(sx, sy); + new_brush.setTransform(brush_matrix); + m_painter->setBrush(new_brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_brushRotate(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double rot = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) brushScale(%f)\n", rot); + + QBrush new_brush = m_painter->brush(); + QTransform brush_matrix = new_brush.transform(); + brush_matrix.rotate(rot); + new_brush.setTransform(brush_matrix); + m_painter->setBrush(new_brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_brushShear(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double sx = convertToDouble(caps.at(1)); + double sy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) brushShear(%f, %f)\n", sx, sy); + + QBrush new_brush = m_painter->brush(); + QTransform brush_matrix = new_brush.transform(); + brush_matrix.shear(sx, sy); + new_brush.setTransform(brush_matrix); + m_painter->setBrush(new_brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipping(QRegularExpressionMatch re) +{ + bool clipping = re.captured(1).toLower() == "true"; + + if (m_verboseMode) + printf(" -(lance) setClipping(%d)\n", clipping); + + m_painter->setClipping(clipping); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipRect(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + + int combine = translateEnum(clipOperationTable, caps.at(5), Qt::IntersectClip + 1); + if (combine == -1) + combine = Qt::ReplaceClip; + + if (m_verboseMode) + printf(" -(lance) setClipRect(%d, %d, %d, %d), %s\n", x, y, w, h, clipOperationTable[combine]); + + m_painter->setClipRect(x, y, w, h, Qt::ClipOperation(combine)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipRectF(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double x = convertToDouble(caps.at(1)); + double y = convertToDouble(caps.at(2)); + double w = convertToDouble(caps.at(3)); + double h = convertToDouble(caps.at(4)); + + int combine = translateEnum(clipOperationTable, caps.at(5), Qt::IntersectClip + 1); + if (combine == -1) + combine = Qt::ReplaceClip; + + if (m_verboseMode) + printf(" -(lance) setClipRectF(%f, %f, %f, %f), %s\n", x, y, w, h, clipOperationTable[combine]); + + m_painter->setClipRect(QRectF(x, y, w, h), Qt::ClipOperation(combine)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipPath(QRegularExpressionMatch re) +{ + int combine = translateEnum(clipOperationTable, re.captured(2), Qt::IntersectClip + 1); + if (combine == -1) + combine = Qt::ReplaceClip; + + if (m_verboseMode) + printf(" -(lance) setClipPath(name=%s), %s\n", qPrintable(re.captured(1)), clipOperationTable[combine]); + + if (!m_pathMap.contains(re.captured(1))) + fprintf(stderr, " - setClipPath, no such path"); + m_painter->setClipPath(m_pathMap[re.captured(1)], Qt::ClipOperation(combine)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipRegion(QRegularExpressionMatch re) +{ + int combine = translateEnum(clipOperationTable, re.captured(2), Qt::IntersectClip + 1); + if (combine == -1) + combine = Qt::ReplaceClip; + QRegion r = m_regionMap[re.captured(1)]; + + if (m_verboseMode) + printf(" -(lance) setClipRegion(name=%s), bounds=[%d, %d, %d, %d], %s\n", + qPrintable(re.captured(1)), + r.boundingRect().x(), + r.boundingRect().y(), + r.boundingRect().width(), + r.boundingRect().height(), + clipOperationTable[combine]); + + m_painter->setClipRegion(m_regionMap[re.captured(1)], Qt::ClipOperation(combine)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setFont(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QString family = caps.at(1); + + int size = -1; // Default + QString sizeArg = caps.at(2); + if (!sizeArg.isEmpty()) + size = convertToInt(caps.at(2)); + + int weight = -1; // Default + QString weightArg = caps.at(3); + if (!weightArg.isEmpty()) { + weight = translateEnum(fontWeightTable, weightArg.toLower(), 5); + if (weight != -1) { + switch (weight) { + case 0: weight = QFont::Light; break; + case 1: weight = QFont::Normal; break; + case 2: weight = QFont::DemiBold; break; + case 3: weight = QFont::Bold; break; + case 4: weight = QFont::Black; break; + } + } else { + weight = convertToInt(weightArg); + } + } + + bool italic = caps.at(4).toLower() == "true" || caps.at(4).toLower() == "italic"; + + QFont font(family, size, weight, italic); + + int hinting = translateEnum(fontHintingTable, caps.at(5), 4); + if (hinting == -1) + hinting = 0; + else + font.setHintingPreference(QFont::HintingPreference(hinting)); + + bool underline = caps.at(6).toLower() == "true" || caps.at(6).toLower() == "underline"; + bool strikeOut = caps.at(7).toLower() == "true" || caps.at(7).toLower() == "strikeout"; + bool overline = caps.at(8).toLower() == "true" || caps.at(8).toLower() == "overline"; + font.setUnderline(underline); + font.setStrikeOut(strikeOut); + font.setOverline(overline); + + int capitalization = translateEnum(fontCapitalizationTable, caps.at(9), 5); + if (capitalization == -1) + capitalization = 0; + else + font.setCapitalization(QFont::Capitalization(capitalization)); + + if (m_verboseMode) + printf(" -(lance) setFont(family=%s, size=%d, weight=%d, italic=%d hinting=%s\n", + qPrintable(family), size, weight, italic, fontHintingTable[hinting]); + + m_painter->setFont(font); +} + +/***************************************************************************************************/ +void PaintCommands::command_setPen(QRegularExpressionMatch re) +{ + QString cap = re.captured(1); + int style = translateEnum(penStyleTable, cap, Qt::DashDotDotLine + 1); + if (style >= 0) { + if (m_verboseMode) + printf(" -(lance) setPen(%s)\n", qPrintable(cap)); + + m_painter->setPen(Qt::PenStyle(style)); + } else if (cap.toLower() == "brush") { + QPen pen(m_painter->brush(), 0); + if (m_verboseMode) { + printf(" -(lance) setPen(brush), style=%d, color=%08x\n", + pen.brush().style(), pen.color().rgba()); + } + m_painter->setPen(pen); + } else { + QColor color = convertToColor(cap); + if (m_verboseMode) + printf(" -(lance) setPen(%s)\n", qPrintable(color.name())); + + m_painter->setPen(color); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_setPen2(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QBrush brush; + + if (caps.at(1).toLower() == "brush") + brush = m_painter->brush(); + else + brush = convertToColor(caps.at(1)); + + double width = convertToDouble(caps.at(2)); + int penStyle = translateEnum(penStyleTable, caps.at(3), Qt::DashDotDotLine + 1); + if (penStyle < 0) + penStyle = Qt::SolidLine; + + Qt::PenCapStyle capStyle = Qt::SquareCap; + if (caps.at(4).toLower() == "flatcap") capStyle = Qt::FlatCap; + else if (caps.at(4).toLower() == "squarecap") capStyle = Qt::SquareCap; + else if (caps.at(4).toLower() == "roundcap") capStyle = Qt::RoundCap; + else if (!caps.at(4).isEmpty()) + fprintf(stderr, "ERROR: setPen, unknown capStyle: %s\n", qPrintable(caps.at(4))); + + Qt::PenJoinStyle joinStyle = Qt::BevelJoin; + if (caps.at(5).toLower() == "miterjoin") joinStyle = Qt::MiterJoin; + else if (caps.at(5).toLower() == "beveljoin") joinStyle = Qt::BevelJoin; + else if (caps.at(5).toLower() == "roundjoin") joinStyle = Qt::RoundJoin; + else if (!caps.at(5).isEmpty()) + fprintf(stderr, "ERROR: setPen, unknown joinStyle: %s\n", qPrintable(caps.at(5))); + + if (m_verboseMode) + printf(" -(lance) setPen(%s, width=%f, style=%d, cap=%d, join=%d)\n", + qPrintable(brush.color().name()), width, penStyle, capStyle, joinStyle); + + m_painter->setPen(QPen(brush, width, Qt::PenStyle(penStyle), capStyle, joinStyle)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setRenderHint(QRegularExpressionMatch re) +{ + QString hintString = re.captured(1).toLower(); + QString setting = re.captured(2).toLower(); + + bool on = setting.isEmpty() || setting == "true" || setting == "on"; + QPainter::RenderHint hint; + int hintIdx = -1; + if (hintString.contains("antialiasing")) { + hintIdx = 0; + hint = QPainter::Antialiasing; + } else if (hintString.contains("smoothpixmaptransform")) { + hintIdx = 1; + hint = QPainter::SmoothPixmapTransform; + } else if (hintString.contains("noncosmeticbrushpatterns")) { + hintIdx = 2; + hint = QPainter::NonCosmeticBrushPatterns; + } + if (hintIdx >= 0) { + if (m_verboseMode) + printf(" -(lance) setRenderHint %s %s\n", renderHintTable[hintIdx], on ? "true" : "false"); + m_painter->setRenderHint(hint, on); + } else { + fprintf(stderr, "ERROR(setRenderHint): unknown hint '%s'\n", qPrintable(re.captured(1))); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_clearRenderHint(QRegularExpressionMatch /*re*/) +{ + m_painter->setRenderHint(QPainter::Antialiasing, false); + m_painter->setRenderHint(QPainter::SmoothPixmapTransform, false); + m_painter->setRenderHint(QPainter::NonCosmeticBrushPatterns, false); + if (m_verboseMode) + printf(" -(lance) clearRenderHint\n"); +} + +/***************************************************************************************************/ +void PaintCommands::command_setCompositionMode(QRegularExpressionMatch re) +{ + QString modeString = re.captured(1).toLower(); + int mode = translateEnum(compositionModeTable, modeString, 33); + + if (mode < 0 || mode > QPainter::RasterOp_SourceAndNotDestination) { + fprintf(stderr, "ERROR: invalid mode: %s\n", qPrintable(modeString)); + return; + } + + if (m_verboseMode) + printf(" -(lance) setCompositionMode: %d: %s\n", mode, qPrintable(modeString)); + + m_painter->setCompositionMode(QPainter::CompositionMode(mode)); +} + +/***************************************************************************************************/ +void PaintCommands::command_translate(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double dx = convertToDouble(caps.at(1)); + double dy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) translate(%f, %f)\n", dx, dy); + + m_painter->translate(dx, dy); +} + +/***************************************************************************************************/ +void PaintCommands::command_pixmap_load(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString fileName = caps.at(1); + QString name = caps.at(2); + + if (name.isEmpty()) + name = fileName; + + QImage im = image_load<QImage>(fileName); + QPixmap px = QPixmap::fromImage(im, Qt::OrderedDither | Qt::OrderedAlphaDither); + + if (m_verboseMode) + printf(" -(lance) pixmap_load(%s as %s), size=[%d, %d], depth=%d\n", + qPrintable(fileName), qPrintable(name), + px.width(), px.height(), px.depth()); + + m_pixmapMap[name] = px; +} + +/***************************************************************************************************/ +void PaintCommands::command_bitmap_load(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString fileName = caps.at(1); + QString name = caps.at(2); + + if (name.isEmpty()) + name = fileName; + + QBitmap bm = image_load<QBitmap>(fileName); + + if (m_verboseMode) + printf(" -(lance) bitmap_load(%s as %s), size=[%d, %d], depth=%d\n", + qPrintable(fileName), qPrintable(name), + bm.width(), bm.height(), bm.depth()); + + m_pixmapMap[name] = bm; +} + +void PaintCommands::command_pixmap_setDevicePixelRatio(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString name = caps.at(1); + double dpr = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) pixmap_setDevicePixelRatio(%s), %.1f -> %.1f\n", + qPrintable(name), m_pixmapMap[name].devicePixelRatio(), dpr); + + m_pixmapMap[name].setDevicePixelRatio(dpr); +} + +/***************************************************************************************************/ +void PaintCommands::command_pixmap_setMask(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + QBitmap mask = image_load<QBitmap>(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) pixmap_setMask(%s, %s)\n", qPrintable(caps.at(1)), qPrintable(caps.at(2))); + + if (!m_pixmapMap[caps.at(1)].isNull()) + m_pixmapMap[caps.at(1)].setMask(mask); +} + +/***************************************************************************************************/ +void PaintCommands::command_image_load(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString fileName = caps.at(1); + QString name = caps.at(2); + + if (name.isEmpty()) + name = fileName; + + QImage image = image_load<QImage>(fileName); + + if (m_verboseMode) + printf(" -(lance) image_load(%s as %s), size=[%d, %d], format=%d\n", + qPrintable(fileName), qPrintable(name), + image.width(), image.height(), image.format()); + + m_imageMap[name] = image; +} + +/***************************************************************************************************/ +void PaintCommands::command_image_setColorCount(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString name = caps.at(1); + int count = convertToInt(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) image_setColorCount(%s), %d -> %d\n", + qPrintable(name), m_imageMap[name].colorCount(), count); + + m_imageMap[name].setColorCount(count); +} + +/***************************************************************************************************/ +void PaintCommands::command_image_setColor(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString name = caps.at(1); + int index = convertToInt(caps.at(2)); + QColor color = convertToColor(caps.at(3)); + + if (m_verboseMode) + printf(" -(lance) image_setColor(%s), %d = %08x\n", qPrintable(name), index, color.rgba()); + + m_imageMap[name].setColor(index, color.rgba()); +} + +/***************************************************************************************************/ +void PaintCommands::command_image_setDevicePixelRatio(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString name = caps.at(1); + double dpr = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) image_setDevicePixelRatio(%s), %.1f -> %.1f\n", + qPrintable(name), m_imageMap[name].devicePixelRatio(), dpr); + + m_imageMap[name].setDevicePixelRatio(dpr); +} + +/***************************************************************************************************/ +void PaintCommands::command_abort(QRegularExpressionMatch) +{ + m_abort = true; +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_clearStops(QRegularExpressionMatch) +{ + if (m_verboseMode) + printf(" -(lance) gradient_clearStops\n"); + m_gradientStops.clear(); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_appendStop(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double pos = convertToDouble(caps.at(1)); + QColor color = convertToColor(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) gradient_appendStop(%.2f, %x)\n", pos, color.rgba()); + + m_gradientStops << QGradientStop(pos, color); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setLinear(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double x1 = convertToDouble(caps.at(1)); + double y1 = convertToDouble(caps.at(2)); + double x2 = convertToDouble(caps.at(3)); + double y2 = convertToDouble(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) gradient_setLinear (%.2f, %.2f), (%.2f, %.2f), spread=%d\n", + x1, y1, x2, y2, m_gradientSpread); + + QLinearGradient lg(QPointF(x1, y1), QPointF(x2, y2)); + lg.setStops(m_gradientStops); + lg.setSpread(m_gradientSpread); + lg.setCoordinateMode(m_gradientCoordinate); + QBrush brush(lg); + QTransform brush_matrix = m_painter->brush().transform(); + brush.setTransform(brush_matrix); + m_painter->setBrush(brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setLinearPen(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double x1 = convertToDouble(caps.at(1)); + double y1 = convertToDouble(caps.at(2)); + double x2 = convertToDouble(caps.at(3)); + double y2 = convertToDouble(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) gradient_setLinear (%.2f, %.2f), (%.2f, %.2f), spread=%d\n", + x1, y1, x2, y2, m_gradientSpread); + + QLinearGradient lg(QPointF(x1, y1), QPointF(x2, y2)); + lg.setStops(m_gradientStops); + lg.setSpread(m_gradientSpread); + lg.setCoordinateMode(m_gradientCoordinate); + QPen pen = m_painter->pen(); + pen.setBrush(lg); + m_painter->setPen(pen); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setRadial(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double cx = convertToDouble(caps.at(1)); + double cy = convertToDouble(caps.at(2)); + double rad = convertToDouble(caps.at(3)); + double fx = convertToDouble(caps.at(4)); + double fy = convertToDouble(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) gradient_setRadial center=(%.2f, %.2f), radius=%.2f, focal=(%.2f, %.2f), " + "spread=%d\n", + cx, cy, rad, fx, fy, m_gradientSpread); + + QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy)); + rg.setStops(m_gradientStops); + rg.setSpread(m_gradientSpread); + rg.setCoordinateMode(m_gradientCoordinate); + QBrush brush(rg); + QTransform brush_matrix = m_painter->brush().transform(); + brush.setTransform(brush_matrix); + m_painter->setBrush(brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setRadialExtended(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double cx = convertToDouble(caps.at(1)); + double cy = convertToDouble(caps.at(2)); + double rad = convertToDouble(caps.at(3)); + double fx = convertToDouble(caps.at(4)); + double fy = convertToDouble(caps.at(5)); + double frad = convertToDouble(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) gradient_setRadialExtended center=(%.2f, %.2f), radius=%.2f, focal=(%.2f, %.2f), " + "focal radius=%.2f, spread=%d\n", + cx, cy, rad, fx, fy, frad, m_gradientSpread); + + QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy), frad); + rg.setStops(m_gradientStops); + rg.setSpread(m_gradientSpread); + rg.setCoordinateMode(m_gradientCoordinate); + QBrush brush(rg); + QTransform brush_matrix = m_painter->brush().transform(); + brush.setTransform(brush_matrix); + m_painter->setBrush(brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setConical(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double cx = convertToDouble(caps.at(1)); + double cy = convertToDouble(caps.at(2)); + double angle = convertToDouble(caps.at(3)); + + if (m_verboseMode) { + printf(" -(lance) gradient_setConical center=(%.2f, %.2f), angle=%.2f\n, spread=%d", + cx, cy, angle, m_gradientSpread); + } + + QConicalGradient cg(QPointF(cx, cy), angle); + cg.setStops(m_gradientStops); + cg.setSpread(m_gradientSpread); + cg.setCoordinateMode(m_gradientCoordinate); + QBrush brush(cg); + QTransform brush_matrix = m_painter->brush().transform(); + brush.setTransform(brush_matrix); + m_painter->setBrush(brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setSpread(QRegularExpressionMatch re) +{ + int spreadMethod = translateEnum(spreadMethodTable, re.captured(1), 3); + + if (m_verboseMode) + printf(" -(lance) gradient_setSpread %d=[%s]\n", spreadMethod, spreadMethodTable[spreadMethod]); + + m_gradientSpread = QGradient::Spread(spreadMethod); +} + +void PaintCommands::command_gradient_setCoordinateMode(QRegularExpressionMatch re) +{ + int coord = translateEnum(coordinateMethodTable, re.captured(1), 4); + + if (m_verboseMode) + printf(" -(lance) gradient_setCoordinateMode %d=[%s]\n", coord, + coordinateMethodTable[coord]); + + m_gradientCoordinate = QGradient::CoordinateMode(coord); +} + +/***************************************************************************************************/ +void PaintCommands::command_surface_begin(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double x = convertToDouble(caps.at(1)); + double y = convertToDouble(caps.at(2)); + double w = convertToDouble(caps.at(3)); + double h = convertToDouble(caps.at(4)); + + if (m_surface_painter) { + fprintf(stderr, "ERROR: surface already active"); + return; + } + + if (m_verboseMode) + printf(" -(lance) surface_begin, pos=[%.2f, %.2f], size=[%.2f, %.2f]\n", x, y, w, h); + + m_surface_painter = m_painter; + + if (m_type == OpenGLType || m_type == OpenGLBufferType) { +#ifndef QT_NO_OPENGL + m_default_glcontext = QOpenGLContext::currentContext(); + m_surface_glcontext = new QOpenGLContext(); + // Pick up the format from the current context; this is especially + // important in order to pick the right version/profile to test. + m_surface_glcontext->setFormat(m_default_glcontext->format()); + m_surface_glcontext->create(); + m_surface_glcontext->makeCurrent(m_default_glcontext->surface()); + QOpenGLFramebufferObjectFormat fmt; // ###TBD: get format from caller + fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + fmt.setSamples(4); + m_surface_glbuffer = new QOpenGLFramebufferObject(qRound(w), qRound(h), fmt); + m_surface_glbuffer->bind(); + m_surface_glpaintdevice = new QOpenGLPaintDevice(qRound(w), qRound(h)); + m_painter = new QPainter(m_surface_glpaintdevice); + m_painter->save(); + m_painter->setCompositionMode(QPainter::CompositionMode_Clear); + m_painter->fillRect(QRect(0, 0, qRound(w), qRound(h)), Qt::transparent); + m_painter->restore(); +#endif + } else { + QImage::Format surface_format; + if (QImage::toPixelFormat(m_format).alphaUsage() != QPixelFormat::UsesAlpha) + surface_format = qt_alphaVersion(m_format); + else + surface_format = m_format; + + m_surface_image = QImage(qRound(w), qRound(h), surface_format); + m_surface_image.fill(0); + m_painter = new QPainter(&m_surface_image); + } + m_surface_rect = QRectF(x, y, w, h); +} + +/***************************************************************************************************/ +void PaintCommands::command_surface_end(QRegularExpressionMatch) +{ + if (!m_surface_painter) { + fprintf(stderr, "ERROR: surface not active"); + return; + } + + if (m_verboseMode) + printf(" -(lance) surface_end, pos=[%.2f, %.2f], size=[%.2f, %.2f]\n", + m_surface_rect.x(), + m_surface_rect.y(), + m_surface_rect.width(), + m_surface_rect.height()); + m_painter->end(); + + delete m_painter; + m_painter = m_surface_painter; + m_surface_painter = 0; + + if (m_type == OpenGLType || m_type == OpenGLBufferType) { +#ifndef QT_NO_OPENGL + QImage new_image = m_surface_glbuffer->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + + delete m_surface_glpaintdevice; + m_surface_glpaintdevice = 0; + delete m_surface_glbuffer; + m_surface_glbuffer = 0; + delete m_surface_glcontext; + m_surface_glcontext = 0; + + m_default_glcontext->makeCurrent(m_default_glcontext->surface()); + m_painter->drawImage(m_surface_rect, new_image); + // Flush the pipeline: + m_painter->beginNativePainting(); + m_painter->endNativePainting(); +#endif + } else { + m_painter->drawImage(m_surface_rect, m_surface_image); + m_surface_image = QImage(); + } + m_surface_rect = QRectF(); +} + +/***************************************************************************************************/ +void PaintCommands::command_image_convertToFormat(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString srcName = caps.at(1); + QString destName = caps.at(2); + + if (!m_imageMap.contains(srcName)) { + fprintf(stderr, "ERROR(convertToFormat): no such image '%s'\n", qPrintable(srcName)); + return; + } + + int format = translateEnum(imageFormatTable, caps.at(3), QImage::NImageFormats); + if (format < 0 || format >= QImage::NImageFormats) { + fprintf(stderr, "ERROR(convertToFormat): invalid format %d = '%s'\n", + format, qPrintable(caps.at(3))); + return; + } + + QImage src = m_imageMap[srcName]; + QImage dest = src.convertToFormat(QImage::Format(format), + Qt::OrderedAlphaDither | Qt::OrderedDither); + + if (m_verboseMode) { + printf(" -(lance) convertToFormat %s:%d -> %s:%d\n", + qPrintable(srcName), src.format(), + qPrintable(destName), dest.format()); + } + + m_imageMap[destName] = dest; +} + +/***************************************************************************************************/ +void PaintCommands::command_textlayout_draw(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + + QString text = caps.at(1); + double width = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) textlayout_draw text='%s', width=%f\n", + qPrintable(text), width); + + QFont copy = m_painter->font(); + copy.setPointSize(10); + + QTextLayout layout(text, copy, m_painter->device()); + layout.beginLayout(); + + double y_offset = 0; + + while (true) { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(width); + line.setPosition(QPointF(0, y_offset)); + + y_offset += line.height(); + } + + layout.draw(m_painter, QPointF(0, 0)); +} + +/***************************************************************************************************/ +void PaintCommands::command_pen_setDashOffset(QRegularExpressionMatch re) +{ + QStringList caps = re.capturedTexts(); + double offset = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) setDashOffset(%lf)\n", offset); + + QPen p = m_painter->pen(); + p.setDashOffset(offset); + m_painter->setPen(p); +} + +/***************************************************************************************************/ +void PaintCommands::command_pen_setDashPattern(QRegularExpressionMatch re) +{ + static QRegularExpression separators("\\s"); + QStringList caps = re.capturedTexts(); + QString cap = caps.at(1); + QStringList numbers = cap.split(separators, Qt::SkipEmptyParts); + + QList<qreal> pattern; + for (int i=0; i<numbers.size(); ++i) + pattern.append(convertToDouble(numbers.at(i))); + + if (m_verboseMode) + printf(" -(lance) pen_setDashPattern(size=%zd)\n", size_t(pattern.size())); + + QPen p = m_painter->pen(); + p.setDashPattern(pattern); + m_painter->setPen(p); +} + +/***************************************************************************************************/ +void PaintCommands::command_pen_setCosmetic(QRegularExpressionMatch re) +{ + QString hm = re.capturedTexts().at(1); + bool on = hm == "true" || hm == "yes" || hm == "on"; + + if (m_verboseMode) { + printf(" -(lance) pen_setCosmetic(%s)\n", on ? "true" : "false"); + } + + QPen p = m_painter->pen(); + p.setCosmetic(on); + + m_painter->setPen(p); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawConvexPolygon(QRegularExpressionMatch re) +{ + static QRegularExpression separators("\\s"); + QStringList caps = re.capturedTexts(); + QString cap = caps.at(1); + QStringList numbers = cap.split(separators, Qt::SkipEmptyParts); + + QPolygonF array; + for (int i=0; i + 1<numbers.size(); i+=2) + array.append(QPointF(convertToDouble(numbers.at(i)), convertToDouble(numbers.at(i+1)))); + + if (m_verboseMode) + printf(" -(lance) drawConvexPolygon(size=%zd)\n", size_t(array.size())); + + + m_painter->drawConvexPolygon(array); +} diff --git a/tests/baseline/shared/paintcommands.h b/tests/baseline/shared/paintcommands.h new file mode 100644 index 0000000000..45f78f9af6 --- /dev/null +++ b/tests/baseline/shared/paintcommands.h @@ -0,0 +1,323 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#ifndef PAINTCOMMANDS_H +#define PAINTCOMMANDS_H + +#include <qcolor.h> +#include <qmap.h> +#include <qpainterpath.h> +#include <qregion.h> +#include <qregularexpression.h> +#include <qstringlist.h> +#include <qpixmap.h> +#include <qbrush.h> +#include <qhash.h> + +QT_FORWARD_DECLARE_CLASS(QPainter) +#ifndef QT_NO_OPENGL +QT_FORWARD_DECLARE_CLASS(QOpenGLFramebufferObject) +QT_FORWARD_DECLARE_CLASS(QOpenGLPaintDevice) +QT_FORWARD_DECLARE_CLASS(QOpenGLContext) +#endif + +enum DeviceType { + WidgetType, + BitmapType, + PixmapType, + ImageType, + ImageMonoType, + OpenGLType, + OpenGLBufferType, + PictureType, + PrinterType, + PdfType, + PsType, + GrabType, + CustomDeviceType, + CustomWidgetType, + ImageWidgetType +}; + +/************************************************************************/ +class PaintCommands +{ +public: + // construction / initialization + PaintCommands(const QStringList &cmds, int /*w*/, int /*h*/, QImage::Format format) + : m_painter(0) + , m_surface_painter(0) + , m_format(format) + , m_commands(cmds) + , m_gradientSpread(QGradient::PadSpread) + , m_gradientCoordinate(QGradient::LogicalMode) + , m_verboseMode(false) + , m_type(WidgetType) + , m_checkers_background(true) + , m_shouldDrawText(true) +#ifndef QT_NO_OPENGL + , m_default_glcontext(0) + , m_surface_glcontext(0) + , m_surface_glbuffer(0) + , m_surface_glpaintdevice(0) +#endif + { + staticInit(); + } + +public: + void setCheckersBackground(bool b) { staticInit(); m_checkers_background = b; } + void setContents(const QStringList &cmds) { + staticInit(); + m_blockMap.clear(); + m_pathMap.clear(); + m_pixmapMap.clear(); + m_imageMap.clear(); + m_regionMap.clear(); + m_gradientStops.clear(); + m_controlPoints.clear(); + m_gradientSpread = QGradient::PadSpread; + m_gradientCoordinate = QGradient::LogicalMode; + m_commands = cmds; + + + } + void setPainter(QPainter *pt) { staticInit(); m_painter = pt; } + void setType(DeviceType t) { staticInit(); m_type = t; } + void setFilePath(const QString &path) { staticInit(); m_filepath = path; } + void setControlPoints(const QList<QPointF> &points) + { + staticInit(); + m_controlPoints = points; + } + void setVerboseMode(bool v) { staticInit(); m_verboseMode = v; } + void insertAt(int commandIndex, const QStringList &newCommands); + void setShouldDrawText(bool drawText) { m_shouldDrawText = drawText; } + + // run + void runCommands(); + +private: + // run + void runCommand(const QString &scriptLine); + + // conversion methods + int convertToInt(const QString &str); + double convertToDouble(const QString &str); + float convertToFloat(const QString &str); + QColor convertToColor(const QString &str); + + // commands: comments + void command_comment(QRegularExpressionMatch re); + + // commands: importer + void command_import(QRegularExpressionMatch re); + + // commands: blocks + void command_begin_block(QRegularExpressionMatch re); + void command_end_block(QRegularExpressionMatch re); + void command_repeat_block(QRegularExpressionMatch re); + + // commands: misc + void command_textlayout_draw(QRegularExpressionMatch re); + void command_abort(QRegularExpressionMatch re); + + // commands: noops + void command_noop(QRegularExpressionMatch re); + + // commands: setters + void command_setBgMode(QRegularExpressionMatch re); + void command_setBackground(QRegularExpressionMatch re); + void command_setOpacity(QRegularExpressionMatch re); + void command_path_setFillRule(QRegularExpressionMatch re); + void command_setBrush(QRegularExpressionMatch re); + void command_setBrushOrigin(QRegularExpressionMatch re); + void command_brushTranslate(QRegularExpressionMatch re); + void command_brushRotate(QRegularExpressionMatch re); + void command_brushScale(QRegularExpressionMatch re); + void command_brushShear(QRegularExpressionMatch re); + void command_setClipPath(QRegularExpressionMatch re); + void command_setClipRect(QRegularExpressionMatch re); + void command_setClipRectF(QRegularExpressionMatch re); + void command_setClipRegion(QRegularExpressionMatch re); + void command_setClipping(QRegularExpressionMatch re); + void command_setCompositionMode(QRegularExpressionMatch re); + void command_setFont(QRegularExpressionMatch re); + void command_setPen(QRegularExpressionMatch re); + void command_setPen2(QRegularExpressionMatch re); + void command_pen_setDashOffset(QRegularExpressionMatch re); + void command_pen_setDashPattern(QRegularExpressionMatch re); + void command_pen_setCosmetic(QRegularExpressionMatch re); + void command_setRenderHint(QRegularExpressionMatch re); + void command_clearRenderHint(QRegularExpressionMatch re); + void command_gradient_appendStop(QRegularExpressionMatch re); + void command_gradient_clearStops(QRegularExpressionMatch re); + void command_gradient_setConical(QRegularExpressionMatch re); + void command_gradient_setLinear(QRegularExpressionMatch re); + void command_gradient_setRadial(QRegularExpressionMatch re); + void command_gradient_setRadialExtended(QRegularExpressionMatch re); + void command_gradient_setLinearPen(QRegularExpressionMatch re); + void command_gradient_setSpread(QRegularExpressionMatch re); + void command_gradient_setCoordinateMode(QRegularExpressionMatch re); + + // commands: drawing ops + void command_drawArc(QRegularExpressionMatch re); + void command_drawChord(QRegularExpressionMatch re); + void command_drawConvexPolygon(QRegularExpressionMatch re); + void command_drawEllipse(QRegularExpressionMatch re); + void command_drawImage(QRegularExpressionMatch re); + void command_drawLine(QRegularExpressionMatch re); + void command_drawLines(QRegularExpressionMatch re); + void command_drawPath(QRegularExpressionMatch re); + void command_drawPie(QRegularExpressionMatch re); + void command_drawPixmap(QRegularExpressionMatch re); + void command_drawPoint(QRegularExpressionMatch re); + void command_drawPolygon(QRegularExpressionMatch re); + void command_drawPolyline(QRegularExpressionMatch re); + void command_drawRect(QRegularExpressionMatch re); + void command_drawRoundedRect(QRegularExpressionMatch re); + void command_drawRoundRect(QRegularExpressionMatch re); + void command_drawText(QRegularExpressionMatch re); + void command_drawStaticText(QRegularExpressionMatch re); + void command_drawGlyphRun(QRegularExpressionMatch re); + void command_drawTextDocument(QRegularExpressionMatch re); + void command_drawTiledPixmap(QRegularExpressionMatch re); + void command_fillRect(QRegularExpressionMatch re); + void command_fillRectF(QRegularExpressionMatch re); + void command_drawPixmapFragments(QRegularExpressionMatch re); + + // paths + void command_path_addEllipse(QRegularExpressionMatch re); + void command_path_addPolygon(QRegularExpressionMatch re); + void command_path_addRect(QRegularExpressionMatch re); + void command_path_addText(QRegularExpressionMatch re); + void command_path_arcTo(QRegularExpressionMatch re); + void command_path_closeSubpath(QRegularExpressionMatch re); + void command_path_createOutline(QRegularExpressionMatch re); + void command_path_cubicTo(QRegularExpressionMatch re); + void command_path_debugPrint(QRegularExpressionMatch re); + void command_path_lineTo(QRegularExpressionMatch re); + void command_path_moveTo(QRegularExpressionMatch re); + void command_region_addEllipse(QRegularExpressionMatch re); + void command_region_addRect(QRegularExpressionMatch re); + + // getters + void command_region_getClipRegion(QRegularExpressionMatch re); + void command_path_getClipPath(QRegularExpressionMatch re); + + // commands: surface begin/end + void command_surface_begin(QRegularExpressionMatch re); + void command_surface_end(QRegularExpressionMatch re); + + // commands: save/restore painter state + void command_restore(QRegularExpressionMatch re); + void command_save(QRegularExpressionMatch re); + + // commands: pixmap/image + void command_pixmap_load(QRegularExpressionMatch re); + void command_pixmap_setMask(QRegularExpressionMatch re); + void command_bitmap_load(QRegularExpressionMatch re); + void command_pixmap_setDevicePixelRatio(QRegularExpressionMatch re); + void command_image_convertToFormat(QRegularExpressionMatch re); + void command_image_load(QRegularExpressionMatch re); + void command_image_setColor(QRegularExpressionMatch re); + void command_image_setColorCount(QRegularExpressionMatch re); + void command_image_setDevicePixelRatio(QRegularExpressionMatch re); + + // commands: transformation + void command_resetMatrix(QRegularExpressionMatch re); + void command_translate(QRegularExpressionMatch re); + void command_rotate(QRegularExpressionMatch re); + void command_rotate_x(QRegularExpressionMatch re); + void command_rotate_y(QRegularExpressionMatch re); + void command_scale(QRegularExpressionMatch re); + void command_mapQuadToQuad(QRegularExpressionMatch re); + void command_setMatrix(QRegularExpressionMatch re); + + // attributes + QPainter *m_painter; + QPainter *m_surface_painter; + QImage::Format m_format; + QImage m_surface_image; + QRectF m_surface_rect; + QStringList m_commands; + QString m_currentCommand; + int m_currentCommandIndex; + QString m_filepath; + QMap<QString, QStringList> m_blockMap; + QMap<QString, QPainterPath> m_pathMap; + QMap<QString, QPixmap> m_pixmapMap; + QMap<QString, QImage> m_imageMap; + QMap<QString, QRegion> m_regionMap; + QGradientStops m_gradientStops; + QGradient::Spread m_gradientSpread; + QGradient::CoordinateMode m_gradientCoordinate; + bool m_abort; + + bool m_verboseMode; + DeviceType m_type; + bool m_checkers_background; + bool m_shouldDrawText; + + QList<QPointF> m_controlPoints; + +#ifndef QT_NO_OPENGL + QOpenGLContext *m_default_glcontext; + QOpenGLContext *m_surface_glcontext; + QOpenGLFramebufferObject *m_surface_glbuffer; + QOpenGLPaintDevice *m_surface_glpaintdevice; +#endif + + // painter functionalities string tables + static const char *brushStyleTable[]; + static const char *penStyleTable[]; + static const char *fontWeightTable[]; + static const char *fontHintingTable[]; + static const char *fontCapitalizationTable[]; + static const char *clipOperationTable[]; + static const char *spreadMethodTable[]; + static const char *coordinateMethodTable[]; + static const char *compositionModeTable[]; + static const char *imageFormatTable[]; + static const char *sizeModeTable[]; + static const char *renderHintTable[]; + static int translateEnum(const char *table[], const QString &pattern, int limit); + + // utility + template <typename T> T image_load(const QString &filepath); + + // commands dictionary management + static void staticInit(); + +public: + struct PaintCommandInfos + { + PaintCommandInfos(QString id, void (PaintCommands::*p)(QRegularExpressionMatch), QRegularExpression r, QString sy, QString sa) + : identifier(id) + , regExp(r) + , syntax(sy) + , sample(sa) + , paintMethod(p) + {} + PaintCommandInfos(QString title) + : identifier(title), paintMethod(0) {} + bool isSectionHeader() const { return paintMethod == 0; } + QString identifier; + QRegularExpression regExp; + QString syntax; + QString sample; + void (PaintCommands::*paintMethod)(QRegularExpressionMatch); + }; + + static PaintCommandInfos *findCommandById(const QString &identifier) { + for (int i=0; i<s_commandInfoTable.size(); i++) + if (s_commandInfoTable[i].identifier == identifier) + return &s_commandInfoTable[i]; + return 0; + } + + static QList<PaintCommandInfos> s_commandInfoTable; + static QList<QPair<QString,QStringList> > s_enumsTable; + static QMultiHash<QString, int> s_commandHash; +}; + +#endif // PAINTCOMMANDS_H diff --git a/tests/baseline/shared/qbaselinetest.cpp b/tests/baseline/shared/qbaselinetest.cpp new file mode 100644 index 0000000000..e41b8d5321 --- /dev/null +++ b/tests/baseline/shared/qbaselinetest.cpp @@ -0,0 +1,426 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qbaselinetest.h" +#include "baselineprotocol.h" +#include <QtCore/QDir> +#include <QFile> + +#define MAXCMDLINEARGS 128 + +namespace QBaselineTest { + +static char *fargv[MAXCMDLINEARGS]; +static bool simfail = false; +static PlatformInfo customInfo; +static bool customAutoModeSet = false; + +static BaselineProtocol proto; +static bool connected = false; +static bool triedConnecting = false; +static bool dryRunMode = false; +static enum { UploadMissing, UploadAll, UploadNone } baselinePolicy = UploadMissing; +static bool abortIfUnstable = true; + +static QByteArray curFunction; +static ImageItemList itemList; +static bool gotBaselines; + + +void handleCmdLineArgs(int *argcp, char ***argvp) +{ + if (!argcp || !argvp) + return; + + bool showHelp = false; + + int fargc = 0; + int numArgs = *argcp; + + for (int i = 0; i < numArgs; i++) { + QByteArray arg = (*argvp)[i]; + QByteArray nextArg = (i+1 < numArgs) ? (*argvp)[i+1] : nullptr; + + if (arg == "-simfail") { + simfail = true; + } else if (arg == "-fuzzlevel") { + i++; + bool ok = false; + (void)nextArg.toInt(&ok); + if (!ok) { + qWarning() << "-fuzzlevel requires integer parameter"; + showHelp = true; + break; + } + customInfo.insert("FuzzLevel", QString::fromLatin1(nextArg)); + } else if (arg == "-auto") { + customAutoModeSet = true; + customInfo.setAdHocRun(false); + } else if (arg == "-adhoc") { + customAutoModeSet = true; + customInfo.setAdHocRun(true); + } else if (arg == "-setbaselines") { + baselinePolicy = UploadAll; + } else if (arg == "-keeprunning") { + abortIfUnstable = false; + } else if (arg == "-nosetbaselines") { + baselinePolicy = UploadNone; + } else if (arg == "-compareto") { + i++; + int split = qMax(0, nextArg.indexOf('=')); + QByteArray key = nextArg.left(split).trimmed(); + QByteArray value = nextArg.mid(split+1).trimmed(); + if (key.isEmpty() || value.isEmpty()) { + qWarning() << "-compareto requires parameter of the form <key>=<value>"; + showHelp = true; + break; + } + customInfo.addOverride(key, value); + } else { + if ( (arg == "-help") || (arg == "--help") ) + showHelp = true; + if (fargc >= MAXCMDLINEARGS) { + qWarning() << "Too many command line arguments!"; + break; + } + fargv[fargc++] = (*argvp)[i]; + } + } + *argcp = fargc; + *argvp = fargv; + + if (showHelp) { + // TBD: arrange for this to be printed *after* QTest's help + QTextStream out(stdout); + out << "\n Baseline testing (lancelot) options:\n"; + out << " -simfail : Force an image comparison mismatch. For testing purposes.\n"; + out << " -fuzzlevel <int> : Specify the percentage of fuzziness in comparison. Overrides server default. 0 means exact match.\n"; + out << " -auto : Inform server that this run is done by a daemon, CI system or similar.\n"; + out << " -adhoc (default) : The inverse of -auto; this run is done by human, e.g. for testing.\n"; + out << " -keeprunning : Run all tests even if the system is unstable \n"; + out << " -setbaselines : Store ALL rendered images as new baselines. Forces replacement of previous baselines.\n"; + out << " -nosetbaselines : Do not store rendered images as new baselines when previous baselines are missing.\n"; + out << " -compareto KEY=VAL : Force comparison to baselines from a different client,\n"; + out << " for example: -compareto QtVersion=4.8.0\n"; + out << " Multiple -compareto client specifications may be given.\n"; + out << "\n"; + } +} + +bool shouldAbortIfUnstable() +{ + return abortIfUnstable; +} + +void addClientProperty(const QString& key, const QString& value) +{ + customInfo.insert(key, value); +} + + +/* + If a client property script is present, run it and accept its output + in the form of one 'key: value' property per line +*/ +void fetchCustomClientProperties() +{ + QFile file("hostinfo.txt"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + return; + QTextStream in(&file); + + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); // ###local8bit? utf8? + if (line.startsWith(QLatin1Char('#'))) // Ignore comments in file + continue; + QString key, val; + int colonPos = line.indexOf(':'); + if (colonPos > 0) { + key = line.left(colonPos).simplified().replace(' ', '_'); + val = line.mid(colonPos+1).trimmed(); + } + if (!key.isEmpty() && key.size() < 64 && val.size() < 256) // ###TBD: maximum 256 chars in value? + addClientProperty(key, val); + else + qDebug() << "Unparseable script output ignored:" << line; + } +} + + +bool connect(QByteArray *msg, bool *error) +{ + if (connected) { + return true; + } + else if (triedConnecting) { + // Avoid repeated connection attempts, to avoid the program using Timeout * #testItems seconds before giving up + *msg = "Not connected to baseline server."; + *error = true; + return false; + } + + triedConnecting = true; + fetchCustomClientProperties(); + // Merge the platform info set by the program with the protocols default info + PlatformInfo clientInfo = customInfo; + PlatformInfo defaultInfo = PlatformInfo::localHostInfo(); + const auto &defaultInfoKeys = defaultInfo.keys(); + for (const QString &key : defaultInfoKeys) { + if (!clientInfo.contains(key)) + clientInfo.insert(key, defaultInfo.value(key)); + } + if (!customAutoModeSet) + clientInfo.setAdHocRun(defaultInfo.isAdHocRun()); + + QString testCase = clientInfo.value(PI_TestCase); + if (testCase.isEmpty() && QTest::testObject() && QTest::testObject()->metaObject()) { + //qDebug() << "Trying to Read TestCaseName from Testlib!"; + testCase = QTest::testObject()->metaObject()->className(); + } + if (testCase.isEmpty()) { + qWarning("QBaselineTest::connect: No test case name specified, cannot connect."); + return false; + } + + if (!proto.connect(testCase, &dryRunMode, clientInfo)) { + *msg += "Failed to connect to baseline server: " + proto.errorMessage().toLatin1(); + *error = true; + return false; + } + connected = true; + return true; +} + +bool disconnectFromBaselineServer() +{ + if (proto.disconnect()) { + connected = false; + triedConnecting = false; + return true; + } + + return false; +} + +bool connectToBaselineServer(QByteArray *msg) +{ + bool dummy; + QByteArray dummyMsg; + return connect(msg ? msg : &dummyMsg, &dummy); +} + +void setAutoMode(bool mode) +{ + customInfo.setAdHocRun(!mode); + customAutoModeSet = true; +} + +void setSimFail(bool fail) +{ + simfail = fail; +} + +void setProject(const QString &projectName) +{ + addClientProperty(PI_Project, projectName); +} + +void setProjectImageKeys(const QStringList &keys) +{ + QString keyList = keys.join(QLC(',')); + addClientProperty(PI_ProjectImageKeys, keyList); +} + +void modifyImage(QImage *img) +{ + uint c0 = 0x0000ff00; + uint c1 = 0x0080ff00; + img->setPixel(1,1,c0); + img->setPixel(2,1,c1); + img->setPixel(3,1,c0); + img->setPixel(1,2,c1); + img->setPixel(1,3,c0); + img->setPixel(2,3,c1); + img->setPixel(3,3,c0); + img->setPixel(1,4,c1); + img->setPixel(1,5,c0); +} + + +bool compareItem(const ImageItem &baseline, const QImage &img, QByteArray *msg, bool *error) +{ + *error = false; + ImageItem item = baseline; + if (simfail) { + // Simulate test failure by forcing image mismatch; for testing purposes + QImage misImg = img; + modifyImage(&misImg); + item.image = misImg; + simfail = false; // One failure is typically enough + } else { + item.image = img; + } + bool isNewItem = false; + item.imageChecksums.clear(); + item.imageChecksums.prepend(ImageItem::computeChecksum(item.image)); + QByteArray srvMsg; + switch (baseline.status) { + case ImageItem::Ok: + break; + case ImageItem::IgnoreItem : + qDebug() << msg->constData() << "Ignored, blacklisted on server."; + return true; + break; + case ImageItem::BaselineNotFound: + if (!customInfo.overrides().isEmpty()) + return true; + if (baselinePolicy == UploadNone) { + isNewItem = true; + break; + } + if (proto.submitNewBaseline(item, &srvMsg)) + qDebug() << msg->constData() << "Baseline not found on server. New baseline uploaded."; + else + qDebug() << msg->constData() << "Baseline not found on server. Uploading of new baseline failed:" << srvMsg; + return true; + break; + default: + qWarning() << "Unexpected reply from baseline server."; + return true; + break; + } + // The actual comparison of the given image with the baseline: + if (baseline.imageChecksums.contains(item.imageChecksums.at(0))) { + if (!proto.submitMatch(item, &srvMsg)) + qWarning() << "Failed to report image match to server:" << srvMsg; + return true; + } + // At this point, we have established a legitimate mismatch + if (baselinePolicy == UploadAll) { + if (proto.submitNewBaseline(item, &srvMsg)) + qDebug() << msg->constData() << "Forcing new baseline; uploaded ok."; + else + qDebug() << msg->constData() << "Forcing new baseline; uploading failed:" << srvMsg; + return true; + } + bool fuzzyMatch = false; + bool res = proto.submitMismatch(item, &srvMsg, &fuzzyMatch); + if (res && fuzzyMatch) { + qInfo() << "Baseline server reports:" << srvMsg; + return true; // The server decides: a fuzzy match means no mismatch + } + if (isNewItem) + *msg += "No baseline on server, so cannot compare."; + else + *msg += "Mismatch."; + *msg += " See report:\n " + srvMsg; + if (dryRunMode) { + qDebug() << "Dryrun, so ignoring" << *msg; + return true; + } + return false; +} + +bool checkImage(const QImage &img, const char *name, quint16 checksum, QByteArray *msg, bool *error, int manualdatatag) +{ + if (!connected && !connect(msg, error)) + return true; + + QByteArray itemName; + bool hasName = qstrlen(name); + + const char *tag = QTest::currentDataTag(); + if (qstrlen(tag)) { + itemName = tag; + if (hasName) + itemName.append('_').append(name); + } else { + itemName = hasName ? name : "default_name"; + } + + if (manualdatatag > 0) + { + itemName.prepend("_"); + itemName.prepend(QByteArray::number(manualdatatag)); + } + + *msg = "Baseline check of image '" + itemName + "': "; + + + ImageItem item; + item.itemName = QString::fromLatin1(itemName); + item.itemChecksum = checksum; + item.testFunction = QString::fromLatin1(QTest::currentTestFunction()); + ImageItemList list; + list.append(item); + if (!proto.requestBaselineChecksums(QLatin1String(QTest::currentTestFunction()), &list) || list.isEmpty()) { + *msg = "Communication with baseline server failed: " + proto.errorMessage().toLatin1(); + *error = true; + return true; + } + + return compareItem(list.at(0), img, msg, error); +} + + +QTestData &newRow(const char *dataTag, quint16 checksum) +{ + if (QTest::currentTestFunction() != curFunction) { + curFunction = QTest::currentTestFunction(); + itemList.clear(); + gotBaselines = false; + } + ImageItem item; + item.itemName = QString::fromLatin1(dataTag); + item.itemChecksum = checksum; + item.testFunction = QString::fromLatin1(QTest::currentTestFunction()); + itemList.append(item); + + return QTest::newRow(dataTag); +} + +const ImageItem *findCurrentItem(QByteArray *msg, bool *error) +{ + if (!connected && !connect(msg, error)) + return nullptr; + + if (QTest::currentTestFunction() != curFunction || itemList.isEmpty()) { + qWarning() << "Usage error: QBASELINE_ macro used without corresponding QBaselineTest::newRow()"; + return nullptr; + } + + if (!gotBaselines) { + if (!proto.requestBaselineChecksums(QString::fromLatin1(QTest::currentTestFunction()), &itemList) || itemList.isEmpty()) { + *msg = "Communication with baseline server failed: " + proto.errorMessage().toLatin1(); + *error = true; + return nullptr; + } + gotBaselines = true; + } + + QString curTag = QString::fromLatin1(QTest::currentDataTag()); + ImageItemList::const_iterator it = itemList.constBegin(); + while (it != itemList.constEnd() && it->itemName != curTag) + ++it; + if (it == itemList.constEnd()) { + qWarning() << "Usage error: QBASELINE_ macro used without corresponding QBaselineTest::newRow() for row" << curTag; + return nullptr; + } + return &(*it); +} + +bool testImage(const QImage &img, QByteArray *msg, bool *error) +{ + const ImageItem *item = findCurrentItem(msg, error); + return item ? compareItem(*item, img, msg, error) : true; +} + +bool isCurrentItemBlacklisted() +{ + QByteArray msg; + bool error = false; + const ImageItem *item = findCurrentItem(&msg, &error); + return item ? (item->status == ImageItem::IgnoreItem) : false; +} + +} diff --git a/tests/baseline/shared/qbaselinetest.h b/tests/baseline/shared/qbaselinetest.h new file mode 100644 index 0000000000..f120e2bcd8 --- /dev/null +++ b/tests/baseline/shared/qbaselinetest.h @@ -0,0 +1,69 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef BASELINETEST_H +#define BASELINETEST_H + +#include <QTest> +#include <QString> + +namespace QBaselineTest { +void setAutoMode(bool mode); +void setSimFail(bool fail); +void handleCmdLineArgs(int *argcp, char ***argvp); +void setProject(const QString &projectName); // Selects server config settings and top level dir +void setProjectImageKeys(const QStringList &keys); // Overrides the ItemPathKeys config setting +void addClientProperty(const QString& key, const QString& value); +bool connectToBaselineServer(QByteArray *msg = nullptr); +bool checkImage(const QImage& img, const char *name, quint16 checksum, QByteArray *msg, bool *error, int manualdatatag = 0); +bool testImage(const QImage& img, QByteArray *msg, bool *error); +QTestData &newRow(const char *dataTag, quint16 checksum = 0); +bool isCurrentItemBlacklisted(); +bool disconnectFromBaselineServer(); +bool shouldAbortIfUnstable(); +} + +#define QBASELINE_CHECK_SUM(image, name, checksum)\ +do {\ + QByteArray _msg;\ + bool _err = false;\ + if (!QBaselineTest::checkImage((image), (name), (checksum), &_msg, &_err)) {\ + QFAIL(_msg.constData());\ + } else if (_err) {\ + QSKIP(_msg.constData());\ + }\ +} while (0) + +#define QBASELINE_CHECK_SUM_DEFERRED(image, name, checksum)\ +do {\ + QByteArray _msg;\ + bool _err = false;\ + if (!QBaselineTest::checkImage((image), (name), (checksum), &_msg, &_err)) {\ + QTest::qFail(_msg.constData(), __FILE__, __LINE__);\ + } else if (_err) {\ + QSKIP(_msg.constData());\ + }\ +} while (0) + +#define QBASELINE_CHECK(image, name) QBASELINE_CHECK_SUM(image, name, 0) + +#define QBASELINE_CHECK_DEFERRED(image, name) QBASELINE_CHECK_SUM_DEFERRED(image, name, 0) + +#define QBASELINE_TEST(image)\ +do {\ + QByteArray _msg;\ + bool _err = false;\ + if (!QBaselineTest::testImage((image), &_msg, &_err)) {\ + QFAIL(_msg.constData());\ + } else if (_err) {\ + QSKIP(_msg.constData());\ + }\ +} while (0) + +#define QBASELINE_SKIP_IF_BLACKLISTED \ +do {\ + if (QBaselineTest::isCurrentItemBlacklisted())\ + QSKIP("Blacklisted on baseline server.");\ +} while (0) + +#endif // BASELINETEST_H diff --git a/tests/baseline/shared/qbaselinetest.pri b/tests/baseline/shared/qbaselinetest.pri new file mode 100644 index 0000000000..453bc341f1 --- /dev/null +++ b/tests/baseline/shared/qbaselinetest.pri @@ -0,0 +1,14 @@ +QT *= testlib + +SOURCES += \ + $$PWD/qbaselinetest.cpp + +HEADERS += \ + $$PWD/qbaselinetest.h + +qtHaveModule(widgets) { + SOURCES += $$PWD/qwidgetbaselinetest.cpp + HEADERS += $$PWD/qwidgetbaselinetest.h +} + +include($$PWD/baselineprotocol.pri) diff --git a/tests/baseline/shared/qwidgetbaselinetest.cpp b/tests/baseline/shared/qwidgetbaselinetest.cpp new file mode 100644 index 0000000000..72a074e268 --- /dev/null +++ b/tests/baseline/shared/qwidgetbaselinetest.cpp @@ -0,0 +1,192 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qwidgetbaselinetest.h" + +#include <qbaselinetest.h> +#include <QApplication> +#include <QStyle> +#include <QStyleHints> +#include <QScreen> + +#include <QtWidgets/private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +QWidgetBaselineTest::QWidgetBaselineTest() +{ + QBaselineTest::setProject("Widgets"); + + // Set key platform properties that are relevant for the appearance of widgets + const QString platformName = QGuiApplication::platformName() + "-" + QSysInfo::productType(); + QBaselineTest::addClientProperty("PlatformName", platformName); + QBaselineTest::addClientProperty("OSVersion", QSysInfo::productVersion()); + + // Encode a number of parameters that impact the UI + QPalette palette; + QFont font; + const QString styleName = +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QApplication::style()->metaObject()->className(); +#else + QApplication::style()->name(); +#endif + // turn off animations and make the cursor flash time really long to avoid blinking + QApplication::style()->setProperty("_qt_animation_time", QTime()); + QGuiApplication::styleHints()->setCursorFlashTime(50000); + + QByteArray appearanceBytes; + { + QDataStream appearanceStream(&appearanceBytes, QIODevice::WriteOnly); + appearanceStream << palette << font; + const qreal screenDpr = QApplication::primaryScreen()->devicePixelRatio(); + if (screenDpr != 1.0) { + qWarning() << "DPR is" << screenDpr << "- images will not be compared to 1.0 baseline!"; + appearanceStream << screenDpr; + } + } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + const quint16 appearanceId = qChecksum(appearanceBytes, appearanceBytes.size()); +#else + const quint16 appearanceId = qChecksum(appearanceBytes); +#endif + + // Assume that text that's darker than the background means we run in light mode + // This results in a more meaningful appearance ID between different runs than + // just the checksum of the various attributes. + const QColor windowColor = palette.window().color(); + const QColor textColor = palette.text().color(); + const QString appearanceIdString = (windowColor.value() > textColor.value() + ? QString("light-%1-%2") : QString("dark-%1-%2")) + .arg(styleName).arg(appearanceId, 0, 16); + QBaselineTest::addClientProperty("AppearanceID", appearanceIdString); + + // let users know where they can find the results + qDebug() << "PlatformName computed to be:" << platformName; + qDebug() << "Appearance ID computed as:" << appearanceIdString; +} + +void QWidgetBaselineTest::initTestCase() + { + // Check and setup the environment. Failure to do so skips the test. + QByteArray msg; + if (!QBaselineTest::connectToBaselineServer(&msg)) + QSKIP(msg); +} + +void QWidgetBaselineTest::init() +{ + QVERIFY(!window); + background = new QWidget(nullptr, Qt::FramelessWindowHint); + window = new QWidget(background, Qt::Window); + window->setWindowTitle(QTest::currentDataTag()); + window->setFocusPolicy(Qt::StrongFocus); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + background->setScreen(QGuiApplication::primaryScreen()); + window->setScreen(QGuiApplication::primaryScreen()); +#endif + background->move(QGuiApplication::primaryScreen()->availableGeometry().topLeft()); + window->move(QGuiApplication::primaryScreen()->availableGeometry().topLeft()); + + doInit(); +} + +void QWidgetBaselineTest::cleanup() +{ + doCleanup(); + + delete background; + background = nullptr; + window = nullptr; +} + +void QWidgetBaselineTest::makeVisible() +{ + Q_ASSERT(window); + background->showMaximized(); + window->show(); + QApplicationPrivate::setActiveWindow(window); + QVERIFY(QTest::qWaitForWindowActive(window)); + // explicitly set focus on the window so that the test widget doesn't have it + window->setFocus(Qt::OtherFocusReason); + QTRY_COMPARE(window->focusWidget(), window); +} + +/* + Grabs the test window and returns the resulting QImage, without + compensating for DPR differences. +*/ +QImage QWidgetBaselineTest::takeSnapshot() +{ + // make sure all effects are done + QTest::qWait(250); + return window->grab().toImage(); +} + +/* + Grabs the test window screen and returns the resulting QImage, without + compensating for DPR differences. + This can be used for popup windows. +*/ +QImage QWidgetBaselineTest::takeScreenSnapshot(const QRect& windowRect) +{ + // make sure all effects are done - wait longer here because entire + // windows might be fading in and out. + QTest::qWait(750); + return window->screen()->grabWindow(0, windowRect.x(), windowRect.y(), + windowRect.width(), windowRect.height()).toImage(); +} + +/*! + Sets standard widget properties on the test window and its children, + and uploads snapshots. The widgets are returned in the same state + that they had before. + + Call this helper after setting up the test window. +*/ +void QWidgetBaselineTest::takeStandardSnapshots() +{ + makeVisible(); + + QWidget *oldFocusWidget = testWindow()->focusWidget(); + QCOMPARE(oldFocusWidget, testWindow()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "default"); + + // try hard to set focus + QWidget *testWidget = window->nextInFocusChain(); + if (!testWidget) + testWidget = window->findChild<QWidget*>(); + QVERIFY(testWidget); + // use TabFocusReason, some widgets handle that specifically to e.g. select + testWidget->setFocus(Qt::TabFocusReason); + + if (testWindow()->focusWidget() != oldFocusWidget) { + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "focused"); + // set focus back + oldFocusWidget->setFocus(Qt::OtherFocusReason); + } else { + qWarning() << "Couldn't set focus on tested widget" << testWidget; + } + + // this disables all children + window->setEnabled(false); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "disabled"); + window->setEnabled(true); + + // show and activate another window so that our test window becomes inactive + QWidget otherWindow; + otherWindow.move(window->geometry().bottomRight() + QPoint(10, 10)); + otherWindow.resize(50, 50); + otherWindow.setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint); + otherWindow.show(); + otherWindow.windowHandle()->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&otherWindow)); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "inactive"); + + window->windowHandle()->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + if (window->focusWidget()) + window->focusWidget()->clearFocus(); +} + +QT_END_NAMESPACE diff --git a/tests/baseline/shared/qwidgetbaselinetest.h b/tests/baseline/shared/qwidgetbaselinetest.h new file mode 100644 index 0000000000..2142217c09 --- /dev/null +++ b/tests/baseline/shared/qwidgetbaselinetest.h @@ -0,0 +1,42 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#pragma once + +#include <QObject> +#include <QImage> + +QT_BEGIN_NAMESPACE + +class QWidget; + +class QWidgetBaselineTest : public QObject +{ + Q_OBJECT + +public: + QWidgetBaselineTest(); + + void takeStandardSnapshots(); + QWidget *testWindow() const { return window; } + +protected: + virtual void doInit() {} + virtual void doCleanup() {} + +private slots: + void initTestCase(); + void init(); + void cleanup(); + +protected: + void makeVisible(); + QImage takeSnapshot(); + QImage takeScreenSnapshot(const QRect& rect = QRect()); + +private: + QWidget *background = nullptr; + QWidget *window = nullptr; +}; + +QT_END_NAMESPACE diff --git a/tests/baseline/stylesheet/CMakeLists.txt b/tests/baseline/stylesheet/CMakeLists.txt new file mode 100644 index 0000000000..3fdaa739fe --- /dev/null +++ b/tests/baseline/stylesheet/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +file(GLOB_RECURSE test_data_glob + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + qss/*) +list(APPEND test_data ${test_data_glob}) + +qt_internal_add_test(tst_baseline_stylesheet + SOURCES + ../shared/baselineprotocol.cpp ../shared/baselineprotocol.h ../shared/lookup3.cpp + ../shared/qbaselinetest.cpp ../shared/qbaselinetest.h + ../shared/qwidgetbaselinetest.cpp ../shared/qwidgetbaselinetest.h + tst_baseline_stylesheet.cpp + INCLUDE_DIRECTORIES + ../shared + LIBRARIES + Qt::Gui + Qt::Widgets + Qt::WidgetsPrivate + Qt::Network + TESTDATA ${test_data} +) + +qt6_add_resources(tst_baseline_stylesheet "tst_baseline_stylesheet" + PREFIX + "/" + FILES + "icons/align-center.png" + "icons/align-left.png" + "icons/align-right.png" + "icons/arrow-up.png" +) diff --git a/tests/baseline/stylesheet/icons.qrc b/tests/baseline/stylesheet/icons.qrc new file mode 100644 index 0000000000..8b3e7ca6cc --- /dev/null +++ b/tests/baseline/stylesheet/icons.qrc @@ -0,0 +1,9 @@ +<!DOCTYPE RCC> +<RCC version="1.0"> +<qresource> + <file>icons/align-center.png</file> + <file>icons/align-left.png</file> + <file>icons/align-right.png</file> + <file>icons/arrow-up.png</file> +</qresource> +</RCC> diff --git a/tests/baseline/stylesheet/icons/align-center.png b/tests/baseline/stylesheet/icons/align-center.png Binary files differnew file mode 100644 index 0000000000..a7ce2fad52 --- /dev/null +++ b/tests/baseline/stylesheet/icons/align-center.png diff --git a/tests/baseline/stylesheet/icons/align-left.png b/tests/baseline/stylesheet/icons/align-left.png Binary files differnew file mode 100644 index 0000000000..ad5b975480 --- /dev/null +++ b/tests/baseline/stylesheet/icons/align-left.png diff --git a/tests/baseline/stylesheet/icons/align-right.png b/tests/baseline/stylesheet/icons/align-right.png Binary files differnew file mode 100644 index 0000000000..7ebfd6dd35 --- /dev/null +++ b/tests/baseline/stylesheet/icons/align-right.png diff --git a/tests/baseline/stylesheet/icons/arrow-up.png b/tests/baseline/stylesheet/icons/arrow-up.png Binary files differnew file mode 100644 index 0000000000..70c43a7c62 --- /dev/null +++ b/tests/baseline/stylesheet/icons/arrow-up.png diff --git a/tests/baseline/stylesheet/qss/default.qss b/tests/baseline/stylesheet/qss/default.qss new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/baseline/stylesheet/qss/default.qss diff --git a/tests/baseline/stylesheet/qss/dummy.qss b/tests/baseline/stylesheet/qss/dummy.qss new file mode 100644 index 0000000000..7f09309153 --- /dev/null +++ b/tests/baseline/stylesheet/qss/dummy.qss @@ -0,0 +1,31 @@ +/* dummy stylesheet to reproduce QTBUG-100433 for QToolButton +QDummyView { + alternate-background-color: yellow; +} + +QDummyView { + show-decoration-selected: 1; +} + +QDummyView::item { + border: 1px solid #d9d9d9; + border-top-color: transparent; + border-bottom-color: transparent; +} + +QDummyView::item:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); + border: 1px solid #bfcde4; +} + +QDummyView::item:selected { + border: 1px solid #567dbc; +} + +QDummyView::item:selected:active{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc); +} + +QDummyView::item:selected:!active { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf); +} diff --git a/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss b/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss new file mode 100644 index 0000000000..1c45a99767 --- /dev/null +++ b/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss @@ -0,0 +1,16 @@ +QHeaderView::section { + background-color: red; + font-size: 10px; +} + +QHeaderView::section:checked { + background-color: green; + font-size: 20px; + font-weight: bold; +} + +QHeaderView::section:first { + background-color: yellow; + font-size: 20px; + font-weight: normal; +} diff --git a/tests/baseline/stylesheet/qss/qscrollarea/no_border.qss b/tests/baseline/stylesheet/qss/qscrollarea/no_border.qss new file mode 100644 index 0000000000..0c9744de7c --- /dev/null +++ b/tests/baseline/stylesheet/qss/qscrollarea/no_border.qss @@ -0,0 +1 @@ +border: none diff --git a/tests/baseline/stylesheet/qss/qscrollarea/styled_scrollbars.qss b/tests/baseline/stylesheet/qss/qscrollarea/styled_scrollbars.qss new file mode 100644 index 0000000000..94fa3db183 --- /dev/null +++ b/tests/baseline/stylesheet/qss/qscrollarea/styled_scrollbars.qss @@ -0,0 +1,72 @@ +QScrollBar:horizontal { + border: 2px solid grey; + background: #32CC99; + height: 15px; + margin: 0px 20px 0 20px; +} +QScrollBar::handle:horizontal { + background: white; + min-width: 20px; +} +QScrollBar::add-line:horizontal { + border: 2px solid grey; + background: #32CC99; + width: 20px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal { + border: 2px solid grey; + background: #32CC99; + width: 20px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal { + border: 2px solid grey; + width: 3px; + height: 3px; + background: white; +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; +} + +QScrollBar:vertical { + border: 2px solid grey; + background: #32CC99; + width: 15px; + margin: 22px 0 22px 0; +} +QScrollBar::handle:vertical { + background: white; + min-height: 20px; +} +QScrollBar::add-line:vertical { + border: 2px solid grey; + background: #32CC99; + height: 20px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical { + border: 2px solid grey; + background: #32CC99; + height: 20px; + subcontrol-position: top; + subcontrol-origin: margin; +} +QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + border: 2px solid grey; + width: 3px; + height: 3px; + background: white; +} + +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; +} diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_no_border.qss b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_no_border.qss new file mode 100644 index 0000000000..e9e098eb5c --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_no_border.qss @@ -0,0 +1 @@ +QToolButton::menu-button { border: none } diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_padding.qss b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_padding.qss new file mode 100644 index 0000000000..44e67671f0 --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_padding.qss @@ -0,0 +1,12 @@ +QToolButton { + border: 5px solid #9e9e9e; + background: #ffffff; + padding-top: 8px; + padding-bottom: 8px; +} +QToolButton[popupMode=InstantPopup] { + padding-right: 75px; +} +QToolButton::menu-indicator { + subcontrol-position: right; +}; diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_position.qss b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_position.qss new file mode 100644 index 0000000000..4a1a5f0c23 --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_position.qss @@ -0,0 +1,4 @@ +QToolButton::menu-indicator { + subcontrol-position: right center; + subcontrol-origin: padding; +} diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/no_border.qss b/tests/baseline/stylesheet/qss/qtoolbutton/no_border.qss new file mode 100644 index 0000000000..0c9744de7c --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtoolbutton/no_border.qss @@ -0,0 +1 @@ +border: none diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/styled.qss b/tests/baseline/stylesheet/qss/qtoolbutton/styled.qss new file mode 100644 index 0000000000..799be9bf31 --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtoolbutton/styled.qss @@ -0,0 +1,38 @@ +QToolButton::menu-button { + border: 2px solid gray; + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; + /* 16px width + 4px for border = 20px allocated above */ + width: 16px; +} + +QToolButton::menu-indicator { + image: url(:/icons/arrow-up.png); + width: 16px; + height: 16px; + subcontrol-position: right bottom; +} + +QToolButton::menu-arrow { + subcontrol-position: bottom right; + image: url(:/icons/arrow-up.png); +} +QToolButton::down-arrow { + image: url(:/icons/arrow-up.png); + background-color: blue +} +QToolButton::up-arrow { + image: url(:/icons/arrow-up.png); + background-color: green +} +QToolButton::left-arrow { + image: url(:/icons/arrow-up.png); + background-color: red +} +QToolButton::right-arrow { + image: url(:/icons/arrow-up.png); + background-color: cyan; + width: 15px; + height: 15px; + subcontrol-position: right bottom; +} diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/styled_no_border.qss b/tests/baseline/stylesheet/qss/qtoolbutton/styled_no_border.qss new file mode 100644 index 0000000000..7cb753120f --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtoolbutton/styled_no_border.qss @@ -0,0 +1,42 @@ +QToolButton { + border: none +} + +QToolButton::menu-button { + border: 2px solid gray; + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; + /* 16px width + 4px for border = 20px allocated above */ + width: 16px; +} + +QToolButton::menu-indicator { + image: url(:/icons/arrow-up.png); + width: 16px; + height: 16px; + subcontrol-position: right bottom; +} + +QToolButton::menu-arrow { + subcontrol-position: bottom right; + image: url(:/icons/arrow-up.png); +} +QToolButton::down-arrow { + image: url(:/icons/arrow-up.png); + background-color: blue +} +QToolButton::up-arrow { + image: url(:/icons/arrow-up.png); + background-color: green +} +QToolButton::left-arrow { + image: url(:/icons/arrow-up.png); + background-color: red +} +QToolButton::right-arrow { + image: url(:/icons/arrow-up.png); + background-color: cyan; + width: 15px; + height: 15px; + subcontrol-position: right bottom; +} diff --git a/tests/baseline/stylesheet/qss/qtreeview/showDecorationSelected.qss b/tests/baseline/stylesheet/qss/qtreeview/showDecorationSelected.qss new file mode 100644 index 0000000000..b279b587bd --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtreeview/showDecorationSelected.qss @@ -0,0 +1,3 @@ +QTreeView { + show-decoration-selected: 1 +} diff --git a/tests/baseline/stylesheet/qss/qtreeview/styledIndicators.qss b/tests/baseline/stylesheet/qss/qtreeview/styledIndicators.qss new file mode 100644 index 0000000000..02263ad644 --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtreeview/styledIndicators.qss @@ -0,0 +1,18 @@ +QTreeWidget::indicator:indeterminate { + background: red +} +QTreeWidget::indicator:indeterminate:disabled { + background: pink +} +QTreeWidget::indicator:checked { + background: green +} +QTreeWidget::indicator:checked:disabled { + background: lightgreen +} +QTreeWidget::indicator:unchecked { + background: blue +} +QTreeWidget::indicator:unchecked:disabled { + background: lightblue +}; diff --git a/tests/baseline/stylesheet/qss/qtreeview/styledItem.qss b/tests/baseline/stylesheet/qss/qtreeview/styledItem.qss new file mode 100644 index 0000000000..1da627881c --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtreeview/styledItem.qss @@ -0,0 +1,7 @@ +QAbstractItemView::item +{ + background: grey; +} +QTreeWidget::indicator:checked { + background: green +} diff --git a/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss b/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss new file mode 100644 index 0000000000..7d54a74fe5 --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss @@ -0,0 +1,10 @@ +QTreeView { + alternate-background-color: yellow; + show-decoration-selected: 1; +} +QTreeView::item:selected:active { + background: qlineargradient(x1:0, y1:0 x2: 0, y2: 1, stop: 0 #fea1f1 stop: 1 #567dbc) +} +QTreeView::branch { + border: 2px +} diff --git a/tests/baseline/stylesheet/stylesheet.pro b/tests/baseline/stylesheet/stylesheet.pro new file mode 100644 index 0000000000..8c6d79124c --- /dev/null +++ b/tests/baseline/stylesheet/stylesheet.pro @@ -0,0 +1,10 @@ +CONFIG += testcase +TARGET = tst_baseline_stylesheet +QT += widgets testlib gui-private + +SOURCES += tst_baseline_stylesheet.cpp +RESOURCES += icons.qrc + +include($$PWD/../shared/qbaselinetest.pri) + +TESTDATA += qss/* diff --git a/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp b/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp new file mode 100644 index 0000000000..67a618988b --- /dev/null +++ b/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp @@ -0,0 +1,240 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <qbaselinetest.h> +#include <qwidgetbaselinetest.h> +#include <QtWidgets> +#include <QByteArray> + +class tst_Stylesheet : public QWidgetBaselineTest +{ + Q_OBJECT + +public: + tst_Stylesheet(); + + void loadTestFiles(); + + void doInit() override; + +private slots: + void tst_QToolButton_data(); + void tst_QToolButton(); + + void tst_QScrollArea_data(); + void tst_QScrollArea(); + + void tst_QTreeView_data(); + void tst_QTreeView(); + + void tst_QHeaderView_data(); + void tst_QHeaderView(); + +private: + QDir styleSheetDir; +}; + +tst_Stylesheet::tst_Stylesheet() +{ + QString baseDir = QFINDTESTDATA("qss/default.qss"); + styleSheetDir = QDir(QFileInfo(baseDir).path()); +} + +void tst_Stylesheet::doInit() +{ + QFETCH(QString, styleSheet); + testWindow()->setStyleSheet(styleSheet); +} + +void tst_Stylesheet::loadTestFiles() +{ + QTest::addColumn<QString>("styleSheet"); + + QStringList qssFiles; + // first add generic test files + for (const auto &qssFile : styleSheetDir.entryList({QStringLiteral("*.qss")}, QDir::Files | QDir::Readable)) + qssFiles << styleSheetDir.absoluteFilePath(qssFile); + + // then test-function specific files + const QString testFunction = QString(QTest::currentTestFunction()).remove("tst_").toLower(); + if (styleSheetDir.cd(testFunction)) { + for (const auto &qssFile : styleSheetDir.entryList({QStringLiteral("*.qss")}, QDir::Files | QDir::Readable)) + qssFiles << styleSheetDir.absoluteFilePath(qssFile); + styleSheetDir.cdUp(); + } + + for (const auto &qssFile : qssFiles) { + QFileInfo fileInfo(qssFile); + QFile file(qssFile); + QVERIFY(file.open(QFile::ReadOnly)); + QString styleSheet = QString::fromUtf8(file.readAll()); + QBaselineTest::newRow(fileInfo.baseName().toUtf8()) << styleSheet; + } +} + +void tst_Stylesheet::tst_QToolButton_data() +{ + loadTestFiles(); +} + +void tst_Stylesheet::tst_QToolButton() +{ + const QIcon trashIcon = QApplication::style()->standardIcon(QStyle::SP_TrashIcon); + + QVBoxLayout *vbox = new QVBoxLayout; + + QHBoxLayout *normalButtons = new QHBoxLayout; + for (const auto &buttonStyle : {Qt::ToolButtonIconOnly, Qt::ToolButtonTextOnly, + Qt::ToolButtonTextUnderIcon, Qt::ToolButtonTextBesideIcon}) { + QToolButton *normal = new QToolButton; + normal->setToolButtonStyle(buttonStyle); + normal->setText("Norm"); + normal->setIcon(trashIcon); + normalButtons->addWidget(normal); + } + vbox->addLayout(normalButtons); + + QHBoxLayout *arrowButtons = new QHBoxLayout; + for (const auto &arrowType : {Qt::LeftArrow, Qt::RightArrow, Qt::UpArrow, Qt::DownArrow}) { + QToolButton *arrow = new QToolButton; + arrow->setText("Arrs"); + arrow->setArrowType(arrowType); + arrowButtons->addWidget(arrow); + } + vbox->addLayout(arrowButtons); + + QHBoxLayout *arrowWithTextButtons = new QHBoxLayout; + for (const auto &buttonStyle : {Qt::ToolButtonTextOnly, + Qt::ToolButtonTextUnderIcon, Qt::ToolButtonTextBesideIcon}) { + QToolButton *arrow = new QToolButton; + arrow->setText("ArrTxt"); + arrow->setArrowType(Qt::UpArrow); + arrow->setToolButtonStyle(buttonStyle); + arrowWithTextButtons->addWidget(arrow); + } + vbox->addLayout(arrowWithTextButtons); + + QHBoxLayout *menuButtons = new QHBoxLayout; + for (const auto &popupMode : {QToolButton::InstantPopup, QToolButton::MenuButtonPopup, + QToolButton::DelayedPopup}) { + QToolButton *menuButton = new QToolButton; + menuButton->setText("PppMd"); + menuButton->setIcon(trashIcon); + QMenu *menuButtonMenu = new QMenu; + menuButtonMenu->addAction(QIcon(":/icons/align-left.png"), "Left"); + menuButtonMenu->addAction(QIcon(":/icons/align-right.png"), "Right"); + menuButtonMenu->addAction(QIcon(":/icons/align-center.png"), "Center"); + menuButton->setMenu(menuButtonMenu); + menuButton->setPopupMode(popupMode); + menuButtons->addWidget(menuButton); + } + vbox->addLayout(menuButtons); + testWindow()->setLayout(vbox); + + makeVisible(); + QBASELINE_TEST(takeSnapshot()); +} + +void tst_Stylesheet::tst_QScrollArea_data() +{ + loadTestFiles(); +} + +void tst_Stylesheet::tst_QScrollArea() +{ + QHBoxLayout *layout = new QHBoxLayout; + QTableWidget *table = new QTableWidget(20, 20); + layout->addWidget(table); + testWindow()->setLayout(layout); + + makeVisible(); + QBASELINE_TEST(takeSnapshot()); +} + +void tst_Stylesheet::tst_QTreeView_data() +{ + loadTestFiles(); +} + +void tst_Stylesheet::tst_QTreeView() +{ + QHBoxLayout *layout = new QHBoxLayout; + QTreeWidget *tw = new QTreeWidget(); + tw->header()->hide(); + layout->addWidget(tw); + + enum { + Unchecked = 0, + Checked = 1, + Children = 2, + Disabled = 3, + CheckedDisabled = 4, + ChildrenDisabled = 5, + NConfigs + }; + + for (int i = 0; i < NConfigs; ++i) { + QTreeWidgetItem *topLevelItem = new QTreeWidgetItem(tw, QStringList{QString("top %1").arg(i)}); + switch (i) { + case Unchecked: + case Disabled: + topLevelItem->setCheckState(0, Qt::Unchecked); + break; + case Checked: + case CheckedDisabled: + topLevelItem->setCheckState(0, Qt::Checked); + break; + case Children: + case ChildrenDisabled: + topLevelItem->setCheckState(0, Qt::PartiallyChecked); + topLevelItem->setExpanded(true); + for (int j = 0; j < 2; ++j) { + QTreeWidgetItem *childItem = new QTreeWidgetItem(topLevelItem, QStringList{QString("child %1").arg(j)}); + childItem->setCheckState(0, j % 2 ? Qt::Unchecked : Qt::Checked); + } + break; + } + topLevelItem->setDisabled(i >= Disabled); + } + testWindow()->setLayout(layout); + tw->setRootIsDecorated(true); + makeVisible(); + + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "rootDecorated"); + tw->setRootIsDecorated(false); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "rootNotDecorated"); + + tw->topLevelItem(Children)->child(0)->setSelected(true); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "itemSelected"); +} + +void tst_Stylesheet::tst_QHeaderView_data() +{ + loadTestFiles(); +} + +void tst_Stylesheet::tst_QHeaderView() +{ + QHBoxLayout *layout = new QHBoxLayout; + QTableWidget *tw = new QTableWidget(10, 10); + tw->setCurrentCell(1, 1); + layout->addWidget(tw); + testWindow()->setLayout(layout); + makeVisible(); + QBASELINE_TEST(takeSnapshot()); +} + +#define main _realmain +QTEST_MAIN(tst_Stylesheet) +#undef main + +int main(int argc, char *argv[]) +{ + // Avoid rendering variations caused by QHash randomization + QHashSeed::setDeterministicGlobalSeed(); + + QBaselineTest::handleCmdLineArgs(&argc, &argv); + return _realmain(argc, argv); +} + +#include "tst_baseline_stylesheet.moc" diff --git a/tests/baseline/text/CMakeLists.txt b/tests/baseline/text/CMakeLists.txt new file mode 100644 index 0000000000..74d01337cb --- /dev/null +++ b/tests/baseline/text/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +list(APPEND test_data "./data") + +qt_internal_add_test(tst_baseline_text + SOURCES + ../shared/baselineprotocol.cpp ../shared/baselineprotocol.h ../shared/lookup3.cpp + ../shared/qbaselinetest.cpp ../shared/qbaselinetest.h + ../shared/qwidgetbaselinetest.cpp ../shared/qwidgetbaselinetest.h + tst_baseline_text.cpp + INCLUDE_DIRECTORIES + ../shared + LIBRARIES + Qt::Gui + Qt::Widgets + Qt::WidgetsPrivate + Qt::Network + TESTDATA ${test_data} +) diff --git a/tests/baseline/text/data/colored_list.html b/tests/baseline/text/data/colored_list.html new file mode 100644 index 0000000000..d1cca94460 --- /dev/null +++ b/tests/baseline/text/data/colored_list.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html> +<head> +<style type="text/css"> +p, li { white-space: pre-wrap; } +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +body { background-color: #111155; color: #ffffff; } +</style> +</head> +<body> + +<ul> +<li>disc</li> +<li style=" color:#a58d47;">bronze</li> +<li style=" color:red;"><span style=" color:#ffcdb9;">red bullet, pink text</span></li> +<li style=" color:#dddddd;" class="checked">checked</li> +<li style=" color:#dddddd;" class="unchecked">unchecked</li> +</ul> + +<ul type="circle"> +<li>circle</li> +<li style=" color:#dddddd;">silver</li> +<li style=" color:lightgrey;"><span style=" color:#ffcdb9;">grey bullet, pink text</span></li> +<li style=" color:#dddddd;" class="checked">checked</li> +<li style=" color:#dddddd;" class="unchecked">unchecked</li> +</ul> + +<ul type="square"> +<li style=" color:#ffffff;">square</li> +<li style=" color:#fceebb;">gold</li> +<li style=" color:yellow;"><span style=" color:#ffcdb9;">yellow bullet, pink text</span></li> +<li style=" color:#dddddd;" class="checked">checked</li> +<li style=" color:#dddddd;" class="unchecked">unchecked</li> +</ul> + +<ol> +<li>decimal</li> +<li style=" color:#a58d47;">bronze decimal</li> +<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li> +</ol> + +<ol type="A"> +<li>uppercase</li> +<li style=" color:#a58d47;">bronze uppercase</li> +<li style=" color:red;"><span style=" color:#ffcdb9;">red letter, pink text</span></li> +</ol> + +<ol type="a"> +<li>lowercase</li> +<li style=" color:#a58d47;">bronze lowercase</li> +<li style=" color:red;"><span style=" color:#ffcdb9;">red letter, pink text</span></li> +</ol> + +<ol type="i"> +<li>lower roman</li> +<li style=" color:#a58d47;">bronze roman</li> +<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li> +</ol> + +<ol type="I"> +<li>upper roman</li> +<li style=" color:#a58d47;">bronze roman</li> +<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li> +</ol> +</body> +</html> diff --git a/tests/baseline/text/data/empty.html b/tests/baseline/text/data/empty.html new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/baseline/text/data/empty.html diff --git a/tests/baseline/text/data/list_items_with_code.html b/tests/baseline/text/data/list_items_with_code.html new file mode 100644 index 0000000000..f2823c8065 --- /dev/null +++ b/tests/baseline/text/data/list_items_with_code.html @@ -0,0 +1,8 @@ +<!-- QTBUG-99148 --> +<h1>Header</h1> +<ol> + <li><p>Something (<code>this is code</code> something else)</p></li> + <li><p>Maybe <code>this is code</code> or not?</p></li> + <li><p><code>this is code</code> and it seems to break</p></li> + <li><p>This has no code</p></li> +</ol> diff --git a/tests/baseline/text/tst_baseline_text.cpp b/tests/baseline/text/tst_baseline_text.cpp new file mode 100644 index 0000000000..59a5f478a5 --- /dev/null +++ b/tests/baseline/text/tst_baseline_text.cpp @@ -0,0 +1,119 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <qbaselinetest.h> +#include <qwidgetbaselinetest.h> +#include <QtWidgets> + +class tst_Text : public QWidgetBaselineTest +{ + Q_OBJECT + +public: + tst_Text(); + + void loadTestFiles(); + +private slots: + void tst_render_data(); + void tst_render(); + void tst_differentScriptsBackgrounds(); + +private: + QDir htmlDir; +}; + +tst_Text::tst_Text() +{ + QString baseDir = QFINDTESTDATA("data/empty.html"); + htmlDir = QDir(QFileInfo(baseDir).path()); +} + +void tst_Text::loadTestFiles() +{ + QTest::addColumn<QString>("html"); + + QStringList htmlFiles; + // first add generic test files + for (const auto &qssFile : htmlDir.entryList({QStringLiteral("*.html")}, QDir::Files | QDir::Readable)) + htmlFiles << htmlDir.absoluteFilePath(qssFile); + + // then test-function specific files + const QString testFunction = QString(QTest::currentTestFunction()).remove("tst_").toLower(); + if (htmlDir.cd(testFunction)) { + for (const auto &htmlFile : htmlDir.entryList({QStringLiteral("*.html")}, QDir::Files | QDir::Readable)) + htmlFiles << htmlDir.absoluteFilePath(htmlFile); + htmlDir.cdUp(); + } + + for (const auto &htmlFile : htmlFiles) { + QFileInfo fileInfo(htmlFile); + QFile file(htmlFile); + QVERIFY(file.open(QFile::ReadOnly)); + QString html = QString::fromUtf8(file.readAll()); + QBaselineTest::newRow(fileInfo.baseName().toUtf8()) << html; + } +} + +void tst_Text::tst_render_data() +{ + loadTestFiles(); +} + +void tst_Text::tst_render() +{ + QFETCH(QString, html); + + QTextDocument textDocument; + textDocument.setPageSize(QSizeF(800, 600)); + textDocument.setHtml(html); + + QImage image(800, 600, QImage::Format_ARGB32); + image.fill(Qt::white); + + { + QPainter painter(&image); + + QAbstractTextDocumentLayout::PaintContext context; + context.palette.setColor(QPalette::Text, Qt::black); + textDocument.documentLayout()->draw(&painter, context); + } + + QBASELINE_TEST(image); +} + +void tst_Text::tst_differentScriptsBackgrounds() +{ + QTextDocument textDocument; + textDocument.setPageSize(QSizeF(800, 600)); + textDocument.setHtml(QString::fromUtf8("<i><font style=\"font-size:72px\"><font style=\"background:#FFFF00\">イ雨エ</font></font></i>")); + + QImage image(800, 600, QImage::Format_ARGB32); + image.fill(Qt::white); + + { + QPainter painter(&image); + + QAbstractTextDocumentLayout::PaintContext context; + context.palette.setColor(QPalette::Text, Qt::black); + textDocument.documentLayout()->draw(&painter, context); + } + + QBASELINE_CHECK(image, "tst_differentScriptsBackgrounds"); +} + + +#define main _realmain +QTEST_MAIN(tst_Text) +#undef main + +int main(int argc, char *argv[]) +{ + // Avoid rendering variations caused by QHash randomization + QHashSeed::setDeterministicGlobalSeed(); + + QBaselineTest::handleCmdLineArgs(&argc, &argv); + return _realmain(argc, argv); +} + +#include "tst_baseline_text.moc" diff --git a/tests/baseline/widgets/CMakeLists.txt b/tests/baseline/widgets/CMakeLists.txt new file mode 100644 index 0000000000..07938f69b4 --- /dev/null +++ b/tests/baseline/widgets/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_test(tst_baseline_widgets + SOURCES + ../shared/baselineprotocol.cpp ../shared/baselineprotocol.h ../shared/lookup3.cpp + ../shared/qbaselinetest.cpp ../shared/qbaselinetest.h + ../shared/qwidgetbaselinetest.cpp ../shared/qwidgetbaselinetest.h + tst_baseline_widgets.cpp + INCLUDE_DIRECTORIES + ../shared + LIBRARIES + Qt::Gui + Qt::Widgets + Qt::WidgetsPrivate + Qt::Network +) diff --git a/tests/baseline/widgets/tst_baseline_widgets.cpp b/tests/baseline/widgets/tst_baseline_widgets.cpp new file mode 100644 index 0000000000..8a763eb8fa --- /dev/null +++ b/tests/baseline/widgets/tst_baseline_widgets.cpp @@ -0,0 +1,1291 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <qbaselinetest.h> +#include <qwidgetbaselinetest.h> +#include <QtWidgets> +#include <QStyleOptionSlider> + +class tst_Widgets : public QWidgetBaselineTest +{ + Q_OBJECT + +public: + tst_Widgets() = default; + +private slots: + void tst_QSlider_data(); + void tst_QSlider(); + + void tst_QPushButton_data(); + void tst_QPushButton(); + + void tst_QPushButtonSquare(); + + void tst_QProgressBar_data(); + void tst_QProgressBar(); + + void tst_QSpinBox_data(); + void tst_QSpinBox(); + + void tst_QDoubleSpinBox_data(); + void tst_QDoubleSpinBox(); + + void tst_QDateTimeEdit_data(); + void tst_QDateTimeEdit(); + + void tst_QTimeEdit_data(); + void tst_QTimeEdit(); + + void tst_QDateEdit_data(); + void tst_QDateEdit(); + + void tst_QDial_data(); + void tst_QDial(); + + void tst_QCheckbox_data(); + void tst_QCheckbox(); + + void tst_QRadioButton_data(); + void tst_QRadioButton(); + + void tst_QScrollBar_data(); + void tst_QScrollBar(); + + void tst_QTabBar_data(); + void tst_QTabBar(); + + void tst_QTabWidget_data(); + void tst_QTabWidget(); + + void tst_QListView_data(); + void tst_QListView(); + + void tst_QTableView_data(); + void tst_QTableView(); + + void tst_QTreeView_data(); + void tst_QTreeView(); + + void tst_QLineEdit_data(); + void tst_QLineEdit(); + + void tst_QMenu_data(); + void tst_QMenu(); + + void tst_QCombobox_data(); + void tst_QCombobox(); + + void tst_QCommandLinkButton_data(); + void tst_QCommandLinkButton(); + + void tst_QLCDNumber_data(); + void tst_QLCDNumber(); + +private: + + // Abstract SpinBox test for QSpinBox, QDoubleSpinBox, QDateTimeEdit, QDateEdit, QTimeEdit + void tst_SpinBox_data(); + void tst_SpinBox(QAbstractSpinBox* spinBox); + + // 78 standard icons from 6.3 + const int numberStandardIcons = 78; + + // recursive methods for QTreeView population + void tst_QTreeView_populateTree(QStandardItem* node, int height, int itemsPerNode, bool hasIcon); + QStandardItem* tst_QTreeView_populateItem(int height, int number, bool hasIcon); +}; + +void tst_Widgets::tst_QSlider_data() +{ + QTest::addColumn<Qt::Orientation>("orientation"); + QTest::addColumn<QSlider::TickPosition>("tickPosition"); + + QBaselineTest::newRow("horizontal") << Qt::Horizontal << QSlider::NoTicks; + QBaselineTest::newRow("horizontal ticks above") << Qt::Horizontal << QSlider::TicksAbove; + QBaselineTest::newRow("horizontal ticks below") << Qt::Horizontal << QSlider::TicksBelow; + QBaselineTest::newRow("horizontal ticks both") << Qt::Horizontal << QSlider::TicksBothSides; + QBaselineTest::newRow("vertical") << Qt::Vertical << QSlider::NoTicks; + QBaselineTest::newRow("vertical ticks left") << Qt::Vertical << QSlider::TicksLeft; + QBaselineTest::newRow("vertical ticks right") << Qt::Vertical << QSlider::TicksRight; + QBaselineTest::newRow("vertical ticks both") << Qt::Vertical << QSlider::TicksBothSides; +} + +void tst_Widgets::tst_QSlider() +{ + struct PublicSlider : QSlider { friend tst_Widgets; }; + QFETCH(Qt::Orientation, orientation); + QFETCH(QSlider::TickPosition, tickPosition); + + QBoxLayout *box = new QBoxLayout(orientation == Qt::Horizontal ? QBoxLayout::TopToBottom + : QBoxLayout::LeftToRight); + QList<QSlider*> _sliders; + for (int i = 0; i < 3; ++i) { + QSlider *slider = new QSlider; + slider->setOrientation(orientation); + slider->setTickPosition(tickPosition); + _sliders << slider; + box->addWidget(slider); + } + const auto sliders = _sliders; + + testWindow()->setLayout(box); + + // we want to see sliders with different values + int value = 0; + for (const auto &slider : sliders) + slider->setValue(value += 33); + + takeStandardSnapshots(); + + PublicSlider *slider = static_cast<PublicSlider*>(sliders.first()); + QStyleOptionSlider sliderOptions; + slider->initStyleOption(&sliderOptions); + const QRect handleRect = slider->style()->subControlRect(QStyle::CC_Slider, &sliderOptions, + QStyle::SubControl::SC_SliderHandle, slider); + QTest::mousePress(slider, Qt::LeftButton, {}, handleRect.center()); + QBASELINE_CHECK(takeSnapshot(), "pressed"); + QTest::mouseRelease(slider, Qt::LeftButton, {}, handleRect.center()); + QBASELINE_CHECK(takeSnapshot(), "released"); + + slider->setSliderDown(true); + QBASELINE_CHECK(takeSnapshot(), "down"); + + sliders.first()->setSliderDown(false); + QBASELINE_CHECK(takeSnapshot(), "notdown"); +} + +void tst_Widgets::tst_QPushButton_data() +{ + QTest::addColumn<bool>("isFlat"); + + QBaselineTest::newRow("normal") << false; + QBaselineTest::newRow("flat") << true; +} + +void tst_Widgets::tst_QPushButton() +{ + QFETCH(bool, isFlat); + + QVBoxLayout *vbox = new QVBoxLayout; + QPushButton *testButton = new QPushButton("Ok"); + testButton->setFlat(isFlat); + vbox->addWidget(testButton); + + testWindow()->setLayout(vbox); + takeStandardSnapshots(); + + testButton->setDown(true); + QBASELINE_CHECK(takeSnapshot(), "down"); + testButton->setDown(false); + QBASELINE_CHECK(takeSnapshot(), "up"); + + testButton->setDefault(true); + QBASELINE_CHECK(takeSnapshot(), "default_up"); + testButton->setDown(true); + QBASELINE_CHECK(takeSnapshot(), "default_down"); + testButton->setDown(false); +} + +void tst_Widgets::tst_QPushButtonSquare() +{ + QVBoxLayout layout; + + QPushButton button(testWindow()); + button.setText(QLatin1String("Square")); + const auto sizeHint = button.sizeHint().width(); + // Depending on the current QStyle, this may result in + // a different button look - on macOS it will look as + // a toolbutton: + button.setFixedSize(sizeHint, sizeHint); + + layout.addWidget(&button); + testWindow()->setLayout(&layout); + + takeStandardSnapshots(); + + button.setCheckable(true); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "square_unchecked"); + button.setChecked(true); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "square_checked"); +} + +void tst_Widgets::tst_QProgressBar_data() +{ + QTest::addColumn<Qt::Orientation>("orientation"); + QTest::addColumn<bool>("invertedAppearance"); + QTest::addColumn<bool>("textVisible"); + + QTest::newRow("vertical_normalAppearance_textVisible") << Qt::Vertical << false << true; + QTest::newRow("vertical_invertedAppearance_textVisible") << Qt::Vertical << true << true; + QTest::newRow("horizontal_normalAppearance_textVisible") << Qt::Horizontal << false << true; + QTest::newRow("horizontal_invertedAppearance_textVisible") << Qt::Horizontal << true << true; + QTest::newRow("vertical_normalAppearance_textNotVisible") << Qt::Vertical << false << false; + QTest::newRow("vertical_invertedAppearance_textNotVisible") << Qt::Vertical << true << false; + QTest::newRow("horizontal_normalAppearance_textNotVisible") << Qt::Horizontal << false << false; + QTest::newRow("horizontal_invertedAppearance_textNotVisible") << Qt::Horizontal << true << false; +} + +void tst_Widgets::tst_QProgressBar() +{ + QFETCH(Qt::Orientation, orientation); + QFETCH(bool, invertedAppearance); + QFETCH(bool, textVisible); + + QBoxLayout box((orientation == Qt::Vertical) ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom); + + for (int i = 0; i < 4; ++i) { + QProgressBar *bar = new QProgressBar(testWindow()); + bar->setOrientation(orientation); + bar->setInvertedAppearance(invertedAppearance); + bar->setTextVisible(textVisible); + bar->setValue(i * 33); + box.addWidget(bar); + } + + testWindow()->setLayout(&box); + takeStandardSnapshots(); +} + +void tst_Widgets::tst_SpinBox_data() +{ + QTest::addColumn<QAbstractSpinBox::ButtonSymbols>("buttons"); + + QTest::addRow("NoButtons") << QAbstractSpinBox::NoButtons; + QTest::addRow("UpDownArrows") << QAbstractSpinBox::UpDownArrows; + QTest::addRow("PlusMinus") << QAbstractSpinBox::PlusMinus; +} + +void tst_Widgets::tst_SpinBox(QAbstractSpinBox *spinBox) +{ + QFETCH(const QAbstractSpinBox::ButtonSymbols, buttons); + + spinBox->setButtonSymbols(buttons); + spinBox->setMinimumWidth(200); + + QVBoxLayout layout; + layout.addWidget(spinBox); + testWindow()->setLayout(&layout); + + takeStandardSnapshots(); + + spinBox->setAlignment(Qt::AlignHCenter); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignCenter"); + + spinBox->setAlignment(Qt::AlignRight); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignRight"); + + // Press / release up button + QStyleOptionSpinBox styleOption; + styleOption.initFrom(spinBox); + QPoint clickTarget = spinBox->style()->subControlRect(QStyle::CC_SpinBox,&styleOption, + QStyle::SC_SpinBoxUp,spinBox).center(); + + QTest::mousePress(spinBox, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "upPressed"); + QTest::mouseRelease(spinBox, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "upReleased"); + + // Press / release down button + clickTarget = spinBox->style()->subControlRect(QStyle::CC_SpinBox,&styleOption, + QStyle::SC_SpinBoxDown,spinBox).center(); + + QTest::mousePress(spinBox, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "downPressed"); + QTest::mouseRelease(spinBox, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "downReleased"); +} + +void tst_Widgets::tst_QSpinBox_data() +{ + tst_SpinBox_data(); +} + +void tst_Widgets::tst_QSpinBox() +{ + QSpinBox spinBox; + tst_SpinBox(&spinBox); +} + +void tst_Widgets::tst_QDoubleSpinBox_data() +{ + tst_SpinBox_data(); +} + +void tst_Widgets::tst_QDoubleSpinBox() +{ + QDoubleSpinBox spinBox; + tst_SpinBox(&spinBox); +} + +void tst_Widgets::tst_QDateTimeEdit_data() +{ + tst_SpinBox_data(); +} + +void tst_Widgets::tst_QDateTimeEdit() +{ + QDateTimeEdit edit; + tst_SpinBox(&edit); + + // show calendar popup + QStyleOptionSpinBox styleOption; + styleOption.initFrom(&edit); + const QRect buttonUp = edit.style()->subControlRect(QStyle::CC_SpinBox,&styleOption, + QStyle::SC_SpinBoxUp,&edit); + + // no rect for popup button => use bottom center of up-button + QPoint clickTarget = buttonUp.center(); + clickTarget.setY(buttonUp.bottomLeft().y()); + edit.setCalendarPopup(true); + QTest::mouseClick(&edit, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget); + QCalendarWidget* calendar = edit.calendarWidget(); + QVERIFY(calendar); + QVBoxLayout layout; + layout.addWidget(calendar); + testWindow()->setLayout(&layout); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "showCalendar"); +} + +void tst_Widgets::tst_QTimeEdit_data() +{ + tst_SpinBox_data(); +} + +void tst_Widgets::tst_QTimeEdit() +{ + QTimeEdit edit; + tst_SpinBox(&edit); +} + +void tst_Widgets::tst_QDateEdit_data() +{ + tst_SpinBox_data(); +} + +void tst_Widgets::tst_QDateEdit() +{ + QDateEdit edit; + tst_SpinBox(&edit); +} + +void tst_Widgets::tst_QDial_data() +{ + QTest::addColumn<int>("minimum"); + QTest::addColumn<int>("maximum"); + QTest::addColumn<bool>("notchesVisible"); + QTest::addColumn<qreal>("notchTarget"); + + QTest::newRow("0..99_notches") << 0 << 99 << true << 3.7; + QTest::newRow("0..99_noNotches") << 0 << 99 << false << 3.7; + QTest::newRow("1..100_notches") << 1 << 100 << true << 5.7; + QTest::newRow("1..100_noNotches") << 1 << 100 << false << 3.7; + QTest::newRow("1..5_notches") << 1 << 5 << true << 8.7; + QTest::newRow("1..5_noNotches") << 1 << 5 << false << 3.7; +} + +void tst_Widgets::tst_QDial() +{ + QFETCH(int, minimum); + QFETCH(int, maximum); + QFETCH(bool, notchesVisible); + QFETCH(qreal, notchTarget); + + QVERIFY(maximum > minimum); + const int steps = maximum - minimum; + + QDial dial(testWindow()); + dial.setMinimum(minimum); + dial.setMaximum(maximum); + dial.setNotchTarget(notchTarget); + dial.setSliderPosition(minimum + (steps / 2)); + dial.setNotchesVisible(notchesVisible); + + QBoxLayout box(QBoxLayout::LeftToRight); + box.addWidget(&dial); + testWindow()->setLayout(&box); + takeStandardSnapshots(); +} + +void tst_Widgets::tst_QCheckbox_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<bool>("hasIcon"); + QTest::addColumn<bool>("isTriState"); + + QTest::newRow("SimpleCheckbox") << "" << false << false; + QTest::newRow("SimpleCheckboxWithIcon") << "" << true << false; + QTest::newRow("SimpleCheckboxWithText") << "checkBox" << false << false; + QTest::newRow("SimpleCheckboxWithTextAndIcon") << "checkBox with icon" << true << false; + QTest::newRow("SimpleTristate") << "" << false << true; + QTest::newRow("SimpleTristateWithText") << "tristateBox" << false << true; +} + +void tst_Widgets::tst_QCheckbox() +{ + QFETCH(QString, text); + QFETCH(bool, hasIcon); + QFETCH(bool, isTriState); + + class CheckBox : public QCheckBox + { + public: + using QCheckBox::initStyleOption; + }; + + QBoxLayout layout(QBoxLayout::TopToBottom); + CheckBox box; + box.setTristate(isTriState); + + if (!text.isEmpty()) + box.setText(text); + + if (hasIcon) + box.setIcon(QApplication::style()->standardIcon(QStyle::SP_ComputerIcon)); + + layout.addWidget(&box); + testWindow()->setLayout(&layout); + takeStandardSnapshots(); + + do { + const Qt::CheckState checkState = box.checkState(); + QStyleOptionButton styleOption; + box.initStyleOption(&styleOption); + const QPoint clickTarget = box.style()->subElementRect(QStyle::SE_CheckBoxClickRect, &styleOption, &box).center(); + + const std::array titles = {"unChecked", "partiallyChecked", "checked"}; + const QString snapShotTitle = titles[checkState]; + + QTest::mousePress(&box,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(box.isDown()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), (snapShotTitle + "_pressed").toLocal8Bit().constData()); + + QTest::mouseRelease(&box,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(!box.isDown()); + QVERIFY(checkState != box.checkState()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), (snapShotTitle + "_released").toLocal8Bit().constData()); + + } while (box.checkState() != Qt::Unchecked); +} + +void tst_Widgets::tst_QRadioButton_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<bool>("hasIcon"); + + QTest::newRow("SimpleRadioButton") << "" << false; + QTest::newRow("RadioButtonWithText") << "RadioButton" << false; + QTest::newRow("SimpleRadioButtonWithIcon") << "" << true; + QTest::newRow("RadioButtonWithTextAndIcon") << "RadioButton" << true; +} + +void tst_Widgets::tst_QRadioButton() +{ + QFETCH(QString,text); + QFETCH(bool,hasIcon); + + class RadioButton : public QRadioButton + { + public: + using QRadioButton::QRadioButton; + using QRadioButton::initStyleOption; + }; + + RadioButton button1(testWindow()); + + if (!text.isEmpty()) + button1.setText(text); + + if (hasIcon) + button1.setIcon(QApplication::style()->standardIcon(QStyle::SP_ComputerIcon)); + + button1.setChecked(false); + + RadioButton button2(testWindow()); + + if (!text.isEmpty()) + button2.setText(text); + + if (hasIcon) + button2.setIcon(QApplication::style()->standardIcon(QStyle::SP_ComputerIcon)); + + // button2 has to start checked for the following tests to work + button2.setChecked(true); + + QBoxLayout box(QBoxLayout::TopToBottom); + box.addWidget(&button1); + box.addWidget(&button2); + testWindow()->setLayout(&box); + takeStandardSnapshots(); + + QStyleOptionButton styleOption; + button1.initStyleOption(&styleOption); + const QPoint clickTarget = button1.style()->subElementRect(QStyle::SE_RadioButtonClickRect, &styleOption, &button1).center(); + + QTest::mousePress(&button1,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(button1.isDown()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressUnchecked"); + QTest::mouseRelease(&button1,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(!button1.isDown()); + + // button1 has grabbed the check from button2 + QVERIFY(button1.isChecked()); + QVERIFY(!button2.isChecked()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "releaseUnchecked"); + + // press and release checked button1 again + QTest::mousePress(&button1,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(button1.isDown()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressChecked"); + QTest::mouseRelease(&button1,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(!button1.isDown()); + + // checkstate not supposed to change + QVERIFY(button1.isChecked()); + QVERIFY(!button2.isChecked()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "releaseChecked"); +} + +void tst_Widgets::tst_QScrollBar_data() +{ + QTest::addColumn<Qt::Orientation>("orientation"); + + QTest::newRow("Horizontal") << Qt::Horizontal; + QTest::newRow("Vertical") << Qt::Vertical; +} + +void tst_Widgets::tst_QScrollBar() +{ + QFETCH(Qt::Orientation, orientation); + + QBoxLayout box((orientation == Qt::Vertical) ? QBoxLayout::LeftToRight + : QBoxLayout::TopToBottom); + QList<QScrollBar*> bars; + for (int i = 0; i < 4; ++i) { + + QScrollBar *bar = new QScrollBar(testWindow()); + (orientation == Qt::Vertical) ? bar->setFixedHeight(100) + : bar->setFixedWidth(100); + + bar->setOrientation(orientation); + bar->setValue(i * 33); + box.addWidget(bar); + bars.append(bar); + } + + testWindow()->setLayout(&box); + takeStandardSnapshots(); + + // press left/up of first bar + QScrollBar *bar = bars.at(0); + QStyleOptionSlider styleOption = qt_qscrollbarStyleOption(bar); + QPoint clickTarget = bar->style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, + QStyle::SC_ScrollBarSubLine, bar).center(); + QTest::mousePress(bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressLeftUp"); + QTest::mouseRelease(bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + + // press slider of first bar + styleOption = qt_qscrollbarStyleOption(bar); + clickTarget = bar->style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, + QStyle::SC_ScrollBarSlider, bar).center(); + QTest::mousePress(bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(bar->isSliderDown()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressSlider"); + QTest::mouseRelease(bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + + // Press AddPage up on first bar + clickTarget = bar->style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, + QStyle::SC_ScrollBarAddPage, bar).center(); + QTest::mousePress(bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressAddPage"); + QTest::mouseRelease(bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + + // press SubPage of last bar + bar = bars.at(3); + styleOption = qt_qscrollbarStyleOption(bar); + clickTarget = bar->style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, + QStyle::SC_ScrollBarAddLine, bar).center(); + QTest::mousePress(bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressRightDown"); + QTest::mouseRelease(bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); +} + +void tst_Widgets::tst_QTabBar_data() +{ + QTest::addColumn<QTabBar::Shape>("shape"); + QTest::addColumn<int>("numberTabs"); + QTest::addColumn<int>("fixedWidth"); + QTest::addColumn<bool>("isClosable"); + + // fixedWidth <0 will be interpreted as variable width + QTest::newRow("RoundedNorth_3_variableWidth") << QTabBar::RoundedNorth << 3 << -1 << false; + QTest::newRow("RoundedEast_3_variableWidth") << QTabBar::RoundedEast << 3 << -1 << false; + QTest::newRow("RoundedWest_3_variableWidth") << QTabBar::RoundedWest << 3 << -1 << false; + QTest::newRow("RoundedSouth_3_variableWidth") << QTabBar::RoundedSouth << 3 << -1 << false; + QTest::newRow("RoundedNorth_20_fixedWidth") << QTabBar::RoundedNorth << 20 << 250 << true; +} + +void tst_Widgets::tst_QTabBar() +{ + QFETCH(QTabBar::Shape, shape); + QFETCH(int, numberTabs); + QFETCH(int, fixedWidth); + QFETCH(bool, isClosable); + + QTabBar bar (testWindow()); + bar.setShape(shape); + bar.setTabsClosable(isClosable); + if (fixedWidth > 0) + bar.setFixedWidth(fixedWidth); + + for (int i = 0; i < numberTabs; ++i) { + bar.insertTab(i,"Tab_" + QString::number(i)); + } + + QBoxLayout box(QBoxLayout::LeftToRight, testWindow()); + box.addWidget(&bar); + testWindow()->setLayout(&box); + + takeStandardSnapshots(); + + // press/release first tab + bar.setCurrentIndex(0); + QPoint clickTarget = bar.tabRect(0).center(); + QTest::mousePress(&bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressFirstTab"); + QTest::mouseRelease(&bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(bar.currentIndex() == 0); + + // press/release second tab if it exists + if (bar.count() > 1) { + clickTarget = bar.tabRect(1).center(); + QTest::mousePress(&bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressSecondTab"); + QTest::mouseRelease(&bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(bar.currentIndex() == 1); + } + + // test press/release on close button + if (isClosable) { + + // CloseButton is either left or right + QWidget *leftButton = bar.tabButton(bar.currentIndex(),QTabBar::ButtonPosition::LeftSide); + QWidget *rightButton = bar.tabButton(bar.currentIndex(),QTabBar::ButtonPosition::RightSide); + QAbstractButton *button = qobject_cast<QAbstractButton*>(leftButton); + if (button == nullptr) + button = qobject_cast<QAbstractButton*>(rightButton); + + if (button != nullptr) { + clickTarget = button->rect().center(); + QTest::mousePress(button,Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressCloseFirstTab"); + QTest::mouseRelease(button,Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "releaseCloseFirstTab"); + } + } +} + +void tst_Widgets::tst_QTabWidget_data() +{ + QTest::addColumn<QTabWidget::TabPosition>("tabPosition"); + QTest::addColumn<int>("numberTabs"); + QTest::addColumn<QString>("tabText"); + QTest::addColumn<int>("fixedWidth"); + QTest::addColumn<bool>("isClosable"); + QTest::addColumn<bool>("isDocumentMode"); + + // fixedWidth <0 will be interpreted as variable width + QTest::newRow("North_3_variableWidthDocMode") << QTabWidget::North << 3 << "This is a tab text" << -1 << false << true; + QTest::newRow("East_3_variableWidth") << QTabWidget::East << 3 << "This is a tab text" << -1 << false << false; + QTest::newRow("West_3_variableWidthDocMode") << QTabWidget::West << 3 << "This is a tab text" << -1 << false << true; + QTest::newRow("South_3_variableWidth") << QTabWidget::South << 3 << "This is a tab text" << -1 << true << false; + QTest::newRow("North_20_fixedWidthDocMode") << QTabWidget::North << 20 + << "This is a very long text to actually force wrapping!" << 100 << true << true; + QTest::newRow("South_20_variableWidth") << QTabWidget::South << 20 + << "This is a very long text to actually force wrapping!" << -1 << false << false; +} + +void tst_Widgets::tst_QTabWidget() +{ + QFETCH(QTabWidget::TabPosition, tabPosition); + QFETCH(int, numberTabs); + QFETCH(QString, tabText); + QFETCH(int, fixedWidth); + QFETCH(bool, isClosable); + QFETCH(bool, isDocumentMode); + + QTabWidget tabWidget (testWindow()); + if (fixedWidth > 0) + tabWidget.setFixedWidth(fixedWidth); + tabWidget.setTabPosition(tabPosition); + tabWidget.setTabsClosable(isClosable); + tabWidget.setDocumentMode(isDocumentMode); + + for (int i = 0; i < numberTabs; ++i) { + QLabel *tabLabel = new QLabel("Tab number " + QString::number(i) + "\n" + tabText, &tabWidget); + QBoxLayout *tabBox = new QBoxLayout(QBoxLayout::TopToBottom,&tabWidget); + tabBox->addWidget(tabLabel); + tabWidget.insertTab(i,tabLabel,"Tab_" + QString::number(i)); + tabWidget.setCurrentIndex(i); + tabWidget.currentWidget()->setLayout(tabBox); + } + + tabWidget.setCurrentIndex(0); + QBoxLayout box(QBoxLayout::LeftToRight, testWindow()); + box.addWidget(&tabWidget); + testWindow()->setLayout(&box); + takeStandardSnapshots(); + + // press/release on second tab if it exists + if (numberTabs > 1) { + const QPoint clickTarget = tabWidget.tabBar()->tabRect(1).center(); + QTest::mousePress(tabWidget.tabBar(),Qt::MouseButton::LeftButton,Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressSecondTab"); + QTest::mouseRelease(tabWidget.tabBar(),Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0); + QVERIFY(tabWidget.currentIndex() == 1); + } + + // test press/release on close button + if (isClosable) { + + // CloseButton is either left or right + QWidget *leftButton = tabWidget.tabBar()->tabButton(tabWidget.currentIndex(),QTabBar::ButtonPosition::LeftSide); + QWidget *rightButton = tabWidget.tabBar()->tabButton(tabWidget.currentIndex(),QTabBar::ButtonPosition::RightSide); + QAbstractButton *button = qobject_cast<QAbstractButton*>(leftButton); + if (button == nullptr) + button = qobject_cast<QAbstractButton*>(rightButton); + + if (button != nullptr) { + const QPoint clickTarget = button->rect().center(); + QTest::mousePress(button,Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressCloseTab"); + QTest::mouseRelease(button,Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "releaseCloseTab"); + } + } +} + +void tst_Widgets::tst_QListView_data() +{ + QTest::addColumn<QListView::ViewMode>("viewMode"); + QTest::addColumn<bool>("isWrapping"); + QTest::addColumn<bool>("hasWordWrap"); + QTest::addColumn<int>("numberItems"); + QTest::addColumn<QSize>("fixedSize"); + + + // QSize() will be interpreted as variable size + QTest::newRow("ListModeWrappingNoWordWrapFixed_10") << + QListView::ListMode << true << false << 10 << QSize(100, 500); + QTest::newRow("ListModeNoWrappingNoWordWrapVariable_20") << + QListView::ListMode << false << true << 20 << QSize(); + QTest::newRow("ListModeNoWrappingWordWrapVariable_30") << + QListView::ListMode << false << true << 30 << QSize(); + QTest::newRow("IconModeNoWrappingNoWordWrapFixed_10") << + QListView::IconMode << false << false << 10 << QSize(100, 500); + QTest::newRow("IconModeWrappingNoWordWrapVariable_20") << + QListView::IconMode << true << false << 20 << QSize(); + QTest::newRow("IconModeWrappingWordWrapVariable_30") << + QListView::IconMode << true << true << 30 << QSize(100, 500); +} +void tst_Widgets::tst_QListView() +{ + QFETCH(QListView::ViewMode,viewMode); + QFETCH(bool,isWrapping); + QFETCH(bool,hasWordWrap); + QFETCH(int,numberItems); + QFETCH(QSize,fixedSize); + + QListView listView; + listView.setViewMode(viewMode); + listView.setWrapping(isWrapping); + listView.setWordWrap(hasWordWrap); + if (fixedSize.isValid()) + listView.setFixedSize(fixedSize); + + QStandardItemModel model(0,1,testWindow()); + + // Populate model, add standard icons if required + const QString itemText = hasWordWrap ? "This is a long text for word wrapping Item_" + : "ListItem_"; + int icon = 0; + for (int i = 0; i < numberItems; ++i) { + QStandardItem *item; + if (viewMode == QListView::IconMode) { + item = new QStandardItem(QApplication::style()->standardIcon + (static_cast<QStyle::StandardPixmap>(icon)), itemText + QString::number(i)); + icon = (icon + 1) % numberStandardIcons; + } else { + item = new QStandardItem(itemText + QString::number(i)); + } + model.appendRow(item); + } + + listView.setModel(&model); + QBoxLayout layout(QBoxLayout::LeftToRight, testWindow()); + layout.addWidget(&listView); + testWindow()->setLayout(&layout); + takeStandardSnapshots(); + + // click on first item + QPoint clickTarget = listView.visualRect(model.index(0,0)).center(); + QTest::mouseClick(listView.viewport(),Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickFirstItem"); + + // click on scond item + if (numberItems > 1) { + clickTarget = listView.visualRect(model.index(1,0)).center(); + QTest::mouseClick(listView.viewport(),Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickSecondItem"); + } + + // Hide first row + listView.setRowHidden(0,true); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "hideFirstItem"); +} + +void tst_Widgets::tst_QTableView_data() +{ + QTest::addColumn<bool>("hasHeader"); + QTest::addColumn<bool>("hasRowNumbers"); + QTest::addColumn<bool>("hasWordWrap"); + QTest::addColumn<int>("numberRows"); + QTest::addColumn<int>("numberColumns"); + QTest::addColumn<int>("iconColumn"); + QTest::addColumn<QSize>("fixedSize"); + + // QSize() => variable size; iconColumn -1 => no icon + QTest::newRow("HeaderRowNumWordWrapFixed_10") << true << true << true << 10 << 3 << -1 << QSize(500, 100); + QTest::newRow("HeaderVariable_20") << true << false << false << 20 << 4 << 1 << QSize(); + QTest::newRow("HeaderFixed_20") << true << false << false << 20 << 4 << 1 << QSize(500, 700); +} + +void tst_Widgets::tst_QTableView() +{ + QFETCH(bool, hasHeader); + QFETCH(bool, hasRowNumbers); + QFETCH(bool, hasWordWrap); + QFETCH(int, numberRows); + QFETCH(int, numberColumns); + QFETCH(int, iconColumn); + QFETCH(QSize, fixedSize); + + // Populate model + int icon = 0; + QStandardItemModel model(numberRows, numberColumns, testWindow()); + + if (hasHeader) { + for (int i = 0; i < numberColumns; ++i) + model.setHorizontalHeaderItem(i, new QStandardItem("Header_" + QString::number(i))); + } + + const QString wrap = hasWordWrap ? "\n long text to wrap words" : "" ; + for (int row = 0; row < numberRows; ++row) { + for (int column = 0; column < numberColumns; ++column) { + QStandardItem *item; + const QString itemText = QString::number(row) + "/" + QString::number(column) + wrap; + if (iconColumn == column) { + item = new QStandardItem(QApplication::style()->standardIcon + (static_cast<QStyle::StandardPixmap>(icon)),itemText); + + icon = (icon + 1) % numberStandardIcons; + } else { + item = new QStandardItem(itemText); + } + model.setItem(row,column,item); + } + if (hasRowNumbers) + model.setVerticalHeaderItem(row, new QStandardItem(QString::number(row))); + } + + QTableView tableView(testWindow()); + tableView.setWordWrap(hasWordWrap); + if (fixedSize.isValid()) + tableView.setFixedSize(fixedSize); + + QBoxLayout layout(QBoxLayout::LeftToRight, testWindow()); + tableView.setModel(&model); + layout.addWidget(&tableView); + + takeStandardSnapshots(); + + // Hide grid + tableView.setShowGrid(false); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "hideGrid"); + tableView.setShowGrid(true); + + // click item 0,0 + QPoint clickTarget = tableView.visualRect(model.index(0,0)).center(); + QTest::mouseClick(tableView.viewport(),Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickFirstItem"); + + // click item 0,1 if it exists + if (numberColumns > 1) { + clickTarget = tableView.visualRect(model.index(0,1)).center(); + QTest::mouseClick(tableView.viewport(),Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget,0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickSecondItem"); + } + + tableView.clearSelection(); + + // Hide first row and column + tableView.setRowHidden(0, true); + tableView.setColumnHidden(0, true); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "hideFirstRowColumn"); + tableView.setRowHidden(0, false); + tableView.setColumnHidden(0, false); + + // Select first row + tableView.selectRow(0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "selectFirstRow"); + + // Select first column + tableView.selectColumn(0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "selectFirstColumn"); +} + +void tst_Widgets::tst_QTreeView_data() +{ + QTest::addColumn<bool>("showHeader"); + QTest::addColumn<bool>("hasIcons"); + QTest::addColumn<bool>("alternatingRowColors"); + QTest::addColumn<QSize>("fixedSize"); + QTest::addColumn<int>("treeHeight"); + QTest::addColumn<int>("itemsPerNode"); + + // QSize() => variable size + QTest::newRow("HeaderIcons_4_3") << true << true << false << QSize() << 3 << 2; + QTest::newRow("NoHeaderNoIcons_4_4") << false << false << false << QSize(100, 350) << 3 << 2; + QTest::newRow("AlternatingRows") << true << true << true << QSize() << 3 << 2; +} + +void tst_Widgets::tst_QTreeView() +{ + QFETCH(bool, showHeader); + QFETCH(bool, hasIcons); + QFETCH(bool, alternatingRowColors); + QFETCH(QSize, fixedSize); + QFETCH(int, treeHeight); + QFETCH(int, itemsPerNode); + QVERIFY(treeHeight > 0 && itemsPerNode > 0); + + QTreeView treeView(testWindow()); + fixedSize.isValid() ? treeView.setFixedSize(fixedSize) + : treeView.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + + QStandardItemModel model(&treeView); + showHeader ? model.setHorizontalHeaderItem(0, new QStandardItem("TreeHeader")) + : treeView.setHeaderHidden(true); + + treeView.setAlternatingRowColors(alternatingRowColors); + + // Populate tree model + for (int i = 0; i < itemsPerNode; ++i) { + QStandardItem* root = tst_QTreeView_populateItem(treeHeight, i, hasIcons); + tst_QTreeView_populateTree(root,treeHeight - 1,itemsPerNode, hasIcons); + model.appendRow(root); + } + + treeView.setModel(&model); + QBoxLayout layout(QBoxLayout::LeftToRight, testWindow()); + layout.addWidget(&treeView); + testWindow()->setLayout(&layout); + + treeView.expandAll(); + treeView.resizeColumnToContents(0); + takeStandardSnapshots(); + + // Partly expand if possible + if (treeHeight > 1) { + treeView.expandToDepth(1); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "partlyExpanded"); + } + + // Click on first node + QPoint clickTarget = treeView.visualRect(model.index(0, 0)).center(); + QTest::mouseClick(treeView.viewport(),Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget, 0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickFirstNode"); + + // Hide first row + treeView.setRowHidden(0, model.index(0, 0), true); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "hideFirstRow"); + treeView.setRowHidden(0, model.index(0, 0), false); + + // Click on second row if it exists + if (itemsPerNode > 1) { + clickTarget = treeView.visualRect(model.index(1, 0)).center(); + QTest::mouseClick(treeView.viewport(), Qt::MouseButton::LeftButton, + Qt::KeyboardModifiers(), clickTarget, 0); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickSecondNode"); + } +} + +void tst_Widgets::tst_QTreeView_populateTree(QStandardItem* node, int height, int itemsPerNode, bool hasIcon) +{ + QList<QStandardItem*> items; + for (int i = 0; i < itemsPerNode; ++i) { + if (height == 0) { + items.append(tst_QTreeView_populateItem(height, i, hasIcon)); + } else { + QStandardItem* item = tst_QTreeView_populateItem(height, i, hasIcon); + tst_QTreeView_populateTree(item, height - 1, itemsPerNode, hasIcon); + items.append(item); + } + } + return node->appendColumn(items); +} + +QStandardItem* tst_Widgets::tst_QTreeView_populateItem(int height, int number, bool hasIcon) +{ + static int icon = 0; + static int itemCount = 0; + + QStandardItem* item; + const QString itemText = QString("%1/%2/%3").arg(height).arg(number).arg(itemCount); + ++itemCount; + + if (hasIcon) { + item = new QStandardItem(QApplication::style()->standardIcon + (static_cast<QStyle::StandardPixmap>(icon)), itemText); + + icon = (icon + 1) % numberStandardIcons; + } else { + item = new QStandardItem(itemText); + } + return item; +} + +void tst_Widgets::tst_QLineEdit_data() +{ + QTest::addColumn<bool>("hasFrame"); + QTest::addColumn<QLineEdit::EchoMode>("echoMode"); + QTest::addColumn<QString>("placeHolderText"); + QTest::addColumn<QString>("text"); + + QTest::newRow("framePassword") << true << QLineEdit::Password << "password" << "secret"; + QTest::newRow("noFrameCleartext") << false << QLineEdit::Normal << "text" << "this is a text"; +} + +void tst_Widgets::tst_QLineEdit() +{ + QFETCH(const bool, hasFrame); + QFETCH(const QLineEdit::EchoMode, echoMode); + QFETCH(const QString, placeHolderText); + QFETCH(const QString, text); + + QLineEdit lineEdit(testWindow()); + lineEdit.setFrame(hasFrame); + lineEdit.setEchoMode(echoMode); + lineEdit.setPlaceholderText(placeHolderText); + + QHBoxLayout layout; + layout.addWidget(&lineEdit); + testWindow()->setLayout(&layout); + takeStandardSnapshots(); + + lineEdit.setText(text); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "setText"); + + lineEdit.setAlignment(Qt::AlignRight); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignedRight"); + + lineEdit.setAlignment(Qt::AlignCenter); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignedCenter"); + + lineEdit.setSelection(0,text.size()); + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "textSelected"); +} + +void tst_Widgets::tst_QMenu_data() +{ + QTest::addColumn<QStringList>("actions"); + + const QStringList menu1 = {"Text", "", "TextAndIcon", "", "SubMenu", "", "Checked"}; + QTest::newRow("showMenuPopup") << menu1; +} + +void tst_Widgets::tst_QMenu() +{ + QFETCH(const QStringList, actions); + + testWindow()->resize(300, 200); + + QBoxLayout layout(QBoxLayout::TopToBottom); + QMenu menu1; + + for (const auto& menuItem : actions) { + if (!menuItem.isEmpty()) { + if (menuItem == "Text") { + menu1.addAction(QString("MenuItem")); + menu1.addAction(QString("")); + } else if (menuItem == "TextAndIcon") { + // Using pixmap icon + QPixmap pix(10, 10); + pix.fill(Qt::green); + menu1.addAction(QIcon(pix), QString("MenuWithIcon")); + menu1.addAction(QIcon(), QString("MenuNoIcon")); + } else if (menuItem == "SubMenu") { + QMenu* submenu = menu1.addMenu(QString("&Submenu1")); + submenu->addAction("SubMenuA"); + submenu->addAction("SubMenuB"); + } else if (menuItem == "Checked") { + auto checked = menu1.addAction(QString("MenuChecked")); + checked->setCheckable(true); + checked->setChecked(true); + auto notChecked = menu1.addAction(QString("MenuNotChecked")); + notChecked->setCheckable(true); + notChecked->setChecked(false); + } + } else { + menu1.addSeparator(); + } + } + + layout.addWidget(&menu1); + testWindow()->setLayout(&layout); + + testWindow()->show(); + QVERIFY(QTest::qWaitForWindowExposed(testWindow())); + QRect testWindowRect(testWindow()->geometry()); + // There can be rounded corners in the window and this leads to test + // case to be fuzzy. Adjust window rectangle that need to be captured + int adjustPixel = menu1.geometry().left(); + testWindowRect.adjust(adjustPixel, adjustPixel, -adjustPixel, -adjustPixel); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "showitems"); + + // Normal menu item with text + QTest::keyClick(&menu1, Qt::Key_Down); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenutext"); + QTest::keyClick(&menu1, Qt::Key_Down); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenunotext"); + + // Menu with icon and text + QTest::keyClick(&menu1, Qt::Key_Down); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenuwithicon"); + QTest::keyClick(&menu1, Qt::Key_Down); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenuwithnullicon"); + + // Sub-menu items + QTest::keyClick(&menu1, Qt::Key_Down); + QTest::keyClick(&menu1, Qt::Key_Right); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectsubmenu"); + QTest::keyClick(&menu1, Qt::Key_Left); + + // Checked menu + QTest::keyClick(&menu1, Qt::Key_Down); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenuchecked"); + QTest::keyClick(&menu1, Qt::Key_Down); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenunotchecked"); +} + +void tst_Widgets::tst_QCombobox_data() +{ + QTest::addColumn<bool>("hasFrame"); + QTest::addColumn<bool>("isEditable"); + + QTest::addRow("frameNonEditable") << true << false; + QTest::addRow("frameEditable") << true << true; + QTest::addRow("noFrameNonEditable") << false << false; + QTest::addRow("noFrameEditable") << false << true; +} + +void tst_Widgets::tst_QCombobox() +{ + QFETCH(const bool, hasFrame); + QFETCH(const bool, isEditable); + + testWindow()->resize(300, 300); + + QScopedPointer<QComboBox> combobox(new QComboBox(testWindow())); + QStringList items; + items << tr("Item1") << tr("Item2") << tr("Item3"); + QStringListModel* itemModel = new QStringListModel(items, this); + combobox->setModel(itemModel); + combobox->setFrame(hasFrame); + combobox->setEditable(isEditable); + + QHBoxLayout layout; + layout.addWidget(combobox.get()); + testWindow()->setLayout(&layout); + takeStandardSnapshots(); + + QTest::keyClick(combobox.get(), Qt::Key_Down, Qt::AltModifier); + QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindow()->geometry()), "combobox"); +} + +void tst_Widgets::tst_QCommandLinkButton_data() +{ + QTest::addColumn<bool>("flat"); + QTest::addColumn<QString>("description"); + + QTest::addRow("flatDescription") << true << QString("Command button very specific to windows vista"); + QTest::addRow("flatNoDescription") << true << QString(""); + QTest::addRow("noFlatNoDescription") << false << QString(""); +} + +void tst_Widgets::tst_QCommandLinkButton() +{ + QFETCH(const bool, flat); + QFETCH(const QString, description); + + QScopedPointer<QCommandLinkButton> commandLink(new QCommandLinkButton(QString("CommandLink"), description, testWindow())); + commandLink->setFlat(flat); + commandLink->setDescription(description); + + QHBoxLayout layout; + layout.addWidget(commandLink.get()); + testWindow()->setLayout(&layout); + takeStandardSnapshots(); +} + +void tst_Widgets::tst_QLCDNumber_data() +{ + QTest::addColumn<int>("segmentstyle"); + + QTest::addRow("outline") << 0; + QTest::addRow("filled") << 1; + QTest::addRow("flat") << 2; +} + +void tst_Widgets::tst_QLCDNumber() +{ + QFETCH(const int, segmentstyle); + + testWindow()->resize(100, 100); + + QScopedPointer<QLCDNumber> lcdNumber(new QLCDNumber(99, testWindow())); + lcdNumber->setHexMode(); + lcdNumber->setSegmentStyle(static_cast<QLCDNumber::SegmentStyle>(segmentstyle)); + + + QHBoxLayout layout; + layout.addWidget(lcdNumber.get()); + testWindow()->setLayout(&layout); + + QBASELINE_CHECK_DEFERRED(takeSnapshot(), "lcdnumber"); +} + +#define main _realmain +QTEST_MAIN(tst_Widgets) +#undef main + +int main(int argc, char *argv[]) +{ + // Avoid rendering variations caused by QHash randomization + QHashSeed::setDeterministicGlobalSeed(); + + QBaselineTest::handleCmdLineArgs(&argc, &argv); + return _realmain(argc, argv); +} + +#include "tst_baseline_widgets.moc" |