summaryrefslogtreecommitdiffstats
path: root/vcl/qa/cppunit
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /vcl/qa/cppunit
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/qa/cppunit')
-rw-r--r--vcl/qa/cppunit/BackendTest.cxx1640
-rw-r--r--vcl/qa/cppunit/BinaryDataContainerTest.cxx78
-rw-r--r--vcl/qa/cppunit/BitmapExTest.cxx114
-rw-r--r--vcl/qa/cppunit/BitmapFilterTest.cxx283
-rw-r--r--vcl/qa/cppunit/BitmapProcessorTest.cxx88
-rw-r--r--vcl/qa/cppunit/BitmapScaleTest.cxx312
-rw-r--r--vcl/qa/cppunit/BitmapTest.cxx739
-rw-r--r--vcl/qa/cppunit/BmpFilterTest.cxx220
-rw-r--r--vcl/qa/cppunit/FontFeatureTest.cxx336
-rw-r--r--vcl/qa/cppunit/GraphicDescriptorTest.cxx176
-rw-r--r--vcl/qa/cppunit/GraphicFormatDetectorTest.cxx489
-rw-r--r--vcl/qa/cppunit/GraphicNativeMetadataTest.cxx105
-rw-r--r--vcl/qa/cppunit/GraphicTest.cxx1385
-rw-r--r--vcl/qa/cppunit/PDFDocumentTest.cxx600
-rw-r--r--vcl/qa/cppunit/PDFiumLibraryTest.cxx454
-rw-r--r--vcl/qa/cppunit/ScanlineToolsTest.cxx227
-rw-r--r--vcl/qa/cppunit/TypeSerializerTest.cxx393
-rw-r--r--vcl/qa/cppunit/VectorGraphicSearchTest.cxx288
-rw-r--r--vcl/qa/cppunit/XpmFilterTest.cxx76
-rw-r--r--vcl/qa/cppunit/animation.cxx69
-rw-r--r--vcl/qa/cppunit/app/test_IconThemeInfo.cxx111
-rw-r--r--vcl/qa/cppunit/app/test_IconThemeScanner.cxx82
-rw-r--r--vcl/qa/cppunit/app/test_IconThemeSelector.cxx183
-rw-r--r--vcl/qa/cppunit/bitmapcolor.cxx263
-rw-r--r--vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx286
-rw-r--r--vcl/qa/cppunit/bitmaprender/data/ImageRGBA.pngbin0 -> 106 bytes
-rw-r--r--vcl/qa/cppunit/bitmaprender/data/tdf104141.gifbin0 -> 12205 bytes
-rw-r--r--vcl/qa/cppunit/bitmaprender/data/tdf113918.pngbin0 -> 20043 bytes
-rw-r--r--vcl/qa/cppunit/bitmaprender/data/tdf116888.gifbin0 -> 1875 bytes
-rw-r--r--vcl/qa/cppunit/blocklistparsertest.cxx174
-rw-r--r--vcl/qa/cppunit/builder/demo.ui1883
-rw-r--r--vcl/qa/cppunit/canvasbitmaptest.cxx791
-rw-r--r--vcl/qa/cppunit/complextext.cxx274
-rw-r--r--vcl/qa/cppunit/data/123_Numbers.gifbin0 -> 1515 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_8bit_RLE.bmpbin0 -> 1194 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_A8R8G8B8.bmpbin0 -> 202 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_Paint_1bit.bmpbin0 -> 78 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_Paint_24bit.bmpbin0 -> 102 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_Paint_4bit.bmpbin0 -> 134 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_Paint_8bit.bmpbin0 -> 1094 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_R5G6B5.bmpbin0 -> 338 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_R8G8B8.bmpbin0 -> 442 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_RLE.bmpbin0 -> 1188 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_RLE_V2.bmpbin0 -> 810 bytes
-rw-r--r--vcl/qa/cppunit/data/BMP_RLE_V3.bmpbin0 -> 1104 bytes
-rw-r--r--vcl/qa/cppunit/data/DocumentWithNull.pdfbin0 -> 1080 bytes
-rw-r--r--vcl/qa/cppunit/data/Exif1.jpgbin0 -> 759 bytes
-rw-r--r--vcl/qa/cppunit/data/Exif1_090CW.jpgbin0 -> 771 bytes
-rw-r--r--vcl/qa/cppunit/data/Exif1_180.jpgbin0 -> 771 bytes
-rw-r--r--vcl/qa/cppunit/data/Exif1_270CW.jpgbin0 -> 771 bytes
-rw-r--r--vcl/qa/cppunit/data/Pangram.pdfbin0 -> 16880 bytes
-rw-r--r--vcl/qa/cppunit/data/PangramAcrobatAnnotations.pdfbin0 -> 21709 bytes
-rw-r--r--vcl/qa/cppunit/data/PangramWithAnnotations.pdfbin0 -> 17785 bytes
-rw-r--r--vcl/qa/cppunit/data/PangramWithMultipleTypeOfAnnotations.pdfbin0 -> 23143 bytes
-rw-r--r--vcl/qa/cppunit/data/SimpleExample.svg4
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.bmpbin0 -> 442 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.emfbin0 -> 696 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.emzbin0 -> 397 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.eps82
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.gifbin0 -> 50 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.jpgbin0 -> 992 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.metbin0 -> 629 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.pcxbin0 -> 284 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.pdfbin0 -> 962 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.pngbin0 -> 94 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.psdbin0 -> 1338 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.svg4
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.svgzbin0 -> 166 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.tgabin0 -> 148 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.tifbin0 -> 603 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.webpbin0 -> 52 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.wmfbin0 -> 290 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.wmzbin0 -> 196 bytes
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.xbm5
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.xpm15
-rw-r--r--vcl/qa/cppunit/data/XPM_1.xpm15
-rw-r--r--vcl/qa/cppunit/data/XPM_4.xpm23
-rw-r--r--vcl/qa/cppunit/data/XPM_8.xpm263
-rw-r--r--vcl/qa/cppunit/data/basic.pdf71
-rw-r--r--vcl/qa/cppunit/data/basicSource.pdf60
-rw-r--r--vcl/qa/cppunit/data/form-fields.pdf95
-rw-r--r--vcl/qa/cppunit/data/graphic-descriptor-mapmode.bmpbin0 -> 4922 bytes
-rw-r--r--vcl/qa/cppunit/data/inch-size.emfbin0 -> 28322 bytes
-rw-r--r--vcl/qa/cppunit/data/roundtrip.wmfbin0 -> 6475 bytes
-rw-r--r--vcl/qa/cppunit/data/tdf73523.bmpbin0 -> 70 bytes
-rw-r--r--vcl/qa/cppunit/data/testBasicMorphology.pngbin0 -> 226 bytes
-rw-r--r--vcl/qa/cppunit/data/testBasicMorphologyDilated1.pngbin0 -> 219 bytes
-rw-r--r--vcl/qa/cppunit/data/testBasicMorphologyDilated1Eroded1.pngbin0 -> 224 bytes
-rw-r--r--vcl/qa/cppunit/data/testBasicMorphologyDilated2.pngbin0 -> 174 bytes
-rw-r--r--vcl/qa/cppunit/data/testBasicMorphologyDilated2Eroded1.pngbin0 -> 178 bytes
-rw-r--r--vcl/qa/cppunit/data/testColorChange-red-linear-gradient.pngbin0 -> 9341 bytes
-rw-r--r--vcl/qa/cppunit/data/to-wmf.emfbin0 -> 1057 bytes
-rw-r--r--vcl/qa/cppunit/data/wmf-embedded-emfplus.wmfbin0 -> 10610 bytes
-rw-r--r--vcl/qa/cppunit/dndtest.cxx311
-rw-r--r--vcl/qa/cppunit/drawmode.cxx368
-rw-r--r--vcl/qa/cppunit/errorhandler.cxx73
-rw-r--r--vcl/qa/cppunit/filter/igif/data/logic-lazy-read.gifbin0 -> 1258 bytes
-rw-r--r--vcl/qa/cppunit/filter/igif/igif.cxx47
-rw-r--r--vcl/qa/cppunit/filter/ipdf/data/add-visible-signature-last-page.pdf111
-rw-r--r--vcl/qa/cppunit/filter/ipdf/data/comment-end.pdf69
-rw-r--r--vcl/qa/cppunit/filter/ipdf/data/dict-array-dict.pdf55
-rw-r--r--vcl/qa/cppunit/filter/ipdf/data/real-numbers.pdf55
-rw-r--r--vcl/qa/cppunit/filter/ipdf/ipdf.cxx208
-rw-r--r--vcl/qa/cppunit/font.cxx161
-rw-r--r--vcl/qa/cppunit/fontcharmap.cxx48
-rw-r--r--vcl/qa/cppunit/fontmetric.cxx138
-rw-r--r--vcl/qa/cppunit/fontmocks.hxx67
-rw-r--r--vcl/qa/cppunit/gen/data/tdf121120.pngbin0 -> 3196 bytes
-rw-r--r--vcl/qa/cppunit/gen/gen.cxx116
-rw-r--r--vcl/qa/cppunit/gradient.cxx256
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/README7
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2004-0691-1.bmpbin0 -> 313 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2006-0006-1.bmpbin0 -> 43218 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-2244-1.bmpbin0 -> 21424 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-3741-1.bmpbin0 -> 8585 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-3741-2.bmpbin0 -> 8620 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2008-1097-1.bmpbin0 -> 93078 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2008-5870-1.bmp1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2016-10504-1.bmpbin0 -> 2616 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/EDB-24743-1.bmpbin0 -> 2222 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/EDB-24743-4.bmpbin0 -> 73470 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/afl-sample-bad-rle-1.bmpbin0 -> 1038 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/nodict-compress.bmpbin0 -> 110 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2014-1947-1.bmpbin0 -> 5000 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/EDB-22680-1.bmpbin0 -> 18862 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/crash-1.bmpbin0 -> 632 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/fail/CVE-2010-1681-1.dxfbin0 -> 4063 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/fail/hang-1.dxf1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/pass/bigangle-1.dxf143
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/pass/loop-1.dxf17320
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/pass/loop-2.dxf13974
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/dxf/pass/pyramid.dxf25008
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2004-0209-1.emfbin0 -> 576 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2008-1083-1.emfbin0 -> 3524 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2009-1217-1.emfbin0 -> 1075 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/crash-2.emfbin0 -> 3848 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/crash-3.emfbin0 -> 456 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/fdo71307-2.emfbin0 -> 24229 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/hang-1.emfbin0 -> 2225 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/hang-2.emfbin0 -> 7057 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/slow-moveclip-1.emfbin0 -> 8700 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-1087-1.emfbin0 -> 3380 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-2245-1.emfbin0 -> 3524 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0168-1.emfbin0 -> 1040240 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0168-2.emfbin0 -> 3872 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-1.emfbin0 -> 3792 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-2.emfbin0 -> 3792 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-3.emfbin0 -> 3792 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0170-1.emfbin0 -> 3792 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3301-1.emfbin0 -> 42756 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3303-1.emfbin0 -> 42756 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3304-1.emfbin0 -> 25160 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/crash-1.emfbin0 -> 7068 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/crash-2.emfbin0 -> 133136 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/fdo38580-3.emfbin0 -> 7068 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/eps/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/eps/fail/CVE-2009-4195-1.epsbin0 -> 45336 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/eps/fail/short-1.epsbin0 -> 29 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/eps/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/eps/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/eps/pass/CVE-2013-4979-1.epsbin0 -> 5708521 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/eps/pass/fdo13433-4.eps667
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2007-3958-1.gifbin0 -> 328 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2008-5937-1.gif1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/EBD-36334-1.gif2
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/EBD-36335-1.gifbin0 -> 1190 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/EDB-23279-1.gif1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/too-small-1.gifbin0 -> 3080 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2007-6715-1.gifbin0 -> 47778 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2008-3013-1.gifbin0 -> 2382 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2011-2131-1.gifbin0 -> 10998 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2012-0282-1.gifbin0 -> 2876 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/EDB-19333-1.gif1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/afl-sample-short-read-1.gifbin0 -> 275 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/afl-sample-short-read-2.gifbin0 -> 35 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/crash-1.gifbin0 -> 111 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/crash-2.gifbin0 -> 257 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/sf_3e0068c9b19bb548826bed0599f65745-15940-minimized.gifbin0 -> 47778 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-1.jpgbin0 -> 31214 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-2.jpgbin0 -> 31129 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-3.jpgbin0 -> 31214 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-4.jpgbin0 -> 31214 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-5.jpgbin0 -> 31214 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-5314-1.jpgbin0 -> 12000000 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/crash-1.jpgbin0 -> 443 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-1.jpgbin0 -> 4098 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-2.jpgbin0 -> 1674 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-3.jpgbin0 -> 2634 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-4.jpgbin0 -> 4098 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-5.jpgbin0 -> 8903 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2017-9614-1.jpgbin0 -> 504 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/EDB-24743-2.jpgbin0 -> 8559 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/EDB-24743-3.jpgbin0 -> 24253 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/fatalerror-1.jpgbin0 -> 276 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/fail/afl-divide-zero-1.metbin0 -> 629 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/fail/afl-msan-1.metbin0 -> 27 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/fail/crash-1.metbin0 -> 681 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/fail/hang-1.metbin0 -> 600 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/fail/hang-2.metbin0 -> 289 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/fail/hang-3.metbin0 -> 608 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/met/pass/sample.metbin0 -> 629 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pbm/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pbm/fail/crash-1.pbm6
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pbm/fail/hang-1.pbmbin0 -> 266 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pbm/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pbm/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pbm/pass/rhbz160429-1.pbmbin0 -> 456 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcd/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcd/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcd/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcd/pass/blank-square.pcdbin0 -> 788480 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-1.pcxbin0 -> 41066 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-2.pcxbin0 -> 41136 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-3.pcxbin0 -> 41107 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2008-1097-1.pcxbin0 -> 91531 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/fail/hang-1.pcxbin0 -> 897 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pcx/pass/rhbz469075-1.pcxbin0 -> 58596 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/clipping-problem.pctbin0 -> 32768 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2008-1097-1.pctbin0 -> 22898 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2012-0277-1.pctbin0 -> 30649 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2013-2577-1.pctbin0 -> 3725256 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/fail/EDB-19332-1.pctbin0 -> 95604 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/fail/exception-1.pctbin0 -> 11086 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/fail/hang-1.pctbin0 -> 97206 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/indeterminate/.gitignore2
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/pass/ooo25876-2.pctbin0 -> 11168 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/pict/pass/tdf92789.pctbin0 -> 62988 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2004-0597-1.png3
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2005-0633-1.pngbin0 -> 346 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2006-7210-1.pngbin0 -> 2495 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2007-2365-1.pngbin0 -> 18470 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2009-1511-1.png1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0951-2.png1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-1.png1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-2.pngbin0 -> 383 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/EDB-34720-1.pngbin0 -> 5000 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/ofz32026.pngbin0 -> 41 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/pass/CVE-2016-0951-1.png1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-IDAT.pngbin0 -> 260 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-Z_NEED_DICT.pngbin0 -> 260 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/pass/black.pngbin0 -> 175 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/pass/invalid-chunk.pngbin0 -> 5312 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ppm/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ppm/fail/CVE-2008-1097-1.ppmbin0 -> 92583 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ppm/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ppm/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ppm/pass/fdo19811-2.ppmbin0 -> 90735 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/psd/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/psd/fail/CVE-2007-3741-1.psdbin0 -> 896870 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/psd/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/psd/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/psd/pass/blank-square.psdbin0 -> 23846 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/psd/pass/hang-1.psdbin0 -> 67086 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/psd/pass/rhbz899670-1.psdbin0 -> 2147990 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/psd/tdf142629.psdbin0 -> 53812 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ras/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ras/fail/CVE-2007-2356-1.rasbin0 -> 4000 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ras/fail/CVE-2008-1097-1.rasbin0 -> 92752 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ras/fail/crash-1.rasbin0 -> 913 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ras/fail/hang-1.rasbin0 -> 40 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ras/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ras/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/ras/pass/marbles.rasbin0 -> 4262290 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-1.svmbin0 -> 152 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-2.svmbin0 -> 110 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-3.svmbin0 -> 142 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-4.svmbin0 -> 532 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-5.svmbin0 -> 162 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-6.svmbin0 -> 79 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/fail/ofz7165-1.svmbin0 -> 816777 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/pass/leak-1.svmbin0 -> 856 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz-timeout-1.svmbin0 -> 3027 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz32885-1.svmbin0 -> 49 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz45269-1.svmbin0 -> 198 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz45583-1.svmbin0 -> 2238 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tga/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tga/fail/CVE-2012-3755-1.tgabin0 -> 1440044 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tga/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tga/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tga/pass/fdo14924-5.tgabin0 -> 2005 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tga/pass/fdo14924-6.tgabin0 -> 3171 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/blue16.tifbin0 -> 873 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/blue8.tifbin0 -> 576 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/BID-51132-1.tiffbin0 -> 115150 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2006-3459-1.tiffbin0 -> 2180 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2007-2217-1.tiffbin0 -> 16202 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2009-2285-1.tiffbin0 -> 214342 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2010-2482-1.tiffbin0 -> 5052 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2013-3906-1.tiffbin0 -> 19098 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2013-5575-1.tiffbin0 -> 125824 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-10688-1.tiffbin0 -> 5356 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-9147-1.tiffbin0 -> 226 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-9936-1.tiffbin0 -> 2492 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/EBD-22681-1.tiffbin0 -> 5052 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/EDB-24743-5.tiffbin0 -> 67100 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-1.tiffbin0 -> 257 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-2.tiffbin0 -> 260 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-3.tiffbin0 -> 260 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-4.tiffbin0 -> 260 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-5.tiffbin0 -> 252 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-6.tiffbin0 -> 260 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-7.tiffbin0 -> 179 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-1.tiffbin0 -> 205 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-10.tiffbin0 -> 5254 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-2.tiffbin0 -> 111 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-3.tiffbin0 -> 17 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-4.tiffbin0 -> 43 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-5.tiffbin0 -> 281 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-6.tiffbin0 -> 259 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-7.tiffbin0 -> 504 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-8.tiffbin0 -> 272 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-9.tiffbin0 -> 188 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/fail/ofz47589.tiffbin0 -> 82 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/green16.tifbin0 -> 875 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/green8.tifbin0 -> 577 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/indeterminate/.gitignore2
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2005-1544-1.tiffbin0 -> 1340 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2006-2656-1.tiffbin0 -> 563386 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-0276-1.tiffbin0 -> 115150 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-0276-2.tiffbin0 -> 72236 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-2027-1.tiffbin0 -> 115150 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/pass/multi-page-1.tiffbin0 -> 1202 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/pass/tdf149417.tiffbin0 -> 74205 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/red16.tifbin0 -> 842 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/red8.tifbin0 -> 542 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/tdf115863.tifbin0 -> 40962 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/tdf126460.tifbin0 -> 9054 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/tdf138818.tifbin0 -> 46428 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/tdf149418.tifbin0 -> 50938 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/tiff/tdf74331.tifbin0 -> 80146 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossless.webpbin0 -> 744 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossy.webpbin0 -> 826 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossless.webpbin0 -> 762 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossy.webpbin0 -> 782 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2123-1.wmf-0.009-676bin0 -> 684 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2124-1.wmfbin0 -> 218 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-4560-1.wmfbin0 -> 12178 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-1.wmf1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-2.wmfbin0 -> 68 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2007-1238-1.wmfbin0 -> 382 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2007-1245-1.wmfbin0 -> 382 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-1.wmfbin0 -> 675 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-2.wmfbin0 -> 375 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-3.wmf5
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-4.wmf3
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/bitcount-1.wmfbin0 -> 1916 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/exttextout-2.wmfbin0 -> 54196 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/facename-1.wmfbin0 -> 4197 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz35149-1.wmfbin0 -> 75 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz35150-1.wmfbin0 -> 74 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz5942-1.wmfbin0 -> 16064 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/seek-1.wmfbin0 -> 5082 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2005-2123-1.wmfbin0 -> 684 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2006-4071-1.wmf1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1090-1.wmfbin0 -> 238 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2015-0848-1.wmfbin0 -> 4192 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/exttextout-1.wmfbin0 -> 2142 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/noheader.wmfbin0 -> 13801 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xbm/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xbm/fail/crash-1.xbm12
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xbm/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xbm/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xbm/pass/grafix4.xbm2011
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xpm/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xpm/fail/gentoo22729-1.xpmbin0 -> 645514 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xpm/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xpm/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/xpm/pass/tdf111925-1.xpm306
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-dxf-test.cxx61
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-eps-test.cxx61
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-met-test.cxx59
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-pcd-test.cxx61
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-pcx-test.cxx61
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-pict-test.cxx92
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-ppm-test.cxx64
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-psd-test.cxx84
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-ras-test.cxx61
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-test.cxx188
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-tga-test.cxx60
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx316
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx203
-rw-r--r--vcl/qa/cppunit/implanimview.cxx121
-rw-r--r--vcl/qa/cppunit/jpeg/JpegReaderTest.cxx202
-rw-r--r--vcl/qa/cppunit/jpeg/JpegWriterTest.cxx117
-rw-r--r--vcl/qa/cppunit/jpeg/data/8BitGrayscale.jpgbin0 -> 1384 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/8BitNonGrayscale.gifbin0 -> 1875 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/JPEGTestCMYK.jpegbin0 -> 405 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/JPEGTestGray.jpegbin0 -> 196 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/JPEGTestRGB.jpegbin0 -> 619 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/tdf138950.jpegbin0 -> 60662 bytes
-rw-r--r--vcl/qa/cppunit/lifecycle.cxx314
-rw-r--r--vcl/qa/cppunit/mnemonic.cxx61
-rw-r--r--vcl/qa/cppunit/outdev.cxx2237
-rw-r--r--vcl/qa/cppunit/pdfexport/data/6m-wide.odgbin0 -> 9146 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odtbin0 -> 12595 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/ComplexContentDictionary.pdfbin0 -> 29050 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odtbin0 -> 22599 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdfbin0 -> 4836 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdfbin0 -> 17693 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt560
-rw-r--r--vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odtbin0 -> 25317 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/alternativeText.fodp489
-rw-r--r--vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odtbin0 -> 13423 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/flowframe_null_ptr_deref.sample654
-rw-r--r--vcl/qa/cppunit/pdfexport/data/forcepoint71.keybin0 -> 114022 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf1
-rw-r--r--vcl/qa/cppunit/pdfexport/data/form-font-name.odtbin0 -> 8548 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/image-shape.fodt141
-rw-r--r--vcl/qa/cppunit/pdfexport/data/link-wrong-page-partial.odgbin0 -> 11175 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/link-wrong-page.odpbin0 -> 12293 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/master.odmbin0 -> 22304 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odgbin0 -> 29714 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odgbin0 -> 28633 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdfbin0 -> 1372 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/pdf-image-rotate-180.pdfbin0 -> 1319 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/rectangles.pdf54
-rw-r--r--vcl/qa/cppunit/pdfexport/data/reduce-image.fodt29
-rw-r--r--vcl/qa/cppunit/pdfexport/data/reduce-small-image.fodt21
-rw-r--r--vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odtbin0 -> 9071 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf105093.odpbin0 -> 211126 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf105461.odpbin0 -> 10320 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf105954.odtbin0 -> 74147 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf105972.fodt175
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf106059.odtbin0 -> 13585 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf106206.odtbin0 -> 74641 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf106693.odtbin0 -> 13585 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf106702.odtbin0 -> 42158 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odtbin0 -> 21561 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf106972.odtbin0 -> 21376 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf107013.odtbin0 -> 19823 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf107018.odtbin0 -> 15787 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf107089.odtbin0 -> 20171 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf107868.odtbin0 -> 10567 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf108963.odpbin0 -> 10369 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf109143.odtbin0 -> 68155 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf113143.odpbin0 -> 100637 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf114256.odsbin0 -> 7716 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf115117-1.odtbin0 -> 8566 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf115117-2.odtbin0 -> 8629 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf115262.odsbin0 -> 27638 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf115967.odtbin0 -> 12091 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf118244_radioButtonGroup.odtbin0 -> 12847 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf121615.odtbin0 -> 10188 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf121962.odtbin0 -> 14974 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf124272.odtbin0 -> 10292 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf127217.odtbin0 -> 9243 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf128445.odpbin0 -> 41261 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf128630.odpbin0 -> 17558 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf129085.docxbin0 -> 44600 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp239
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf135346.odsbin0 -> 10422 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf139736-1.odtbin0 -> 33041 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf141171.odtbin0 -> 9512 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf144222.odsbin0 -> 9410 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf145274.docxbin0 -> 3788 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf145873.pptxbin0 -> 52342 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf147027.odsbin0 -> 16310 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf147164.odpbin0 -> 17732 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf148442.odtbin0 -> 10558 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf148706.odtbin0 -> 9969 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf66597-1.odtbin0 -> 9286 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf66597-2.odtbin0 -> 8265 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf66597-3.odtbin0 -> 8251 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf84283.docbin0 -> 36352 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf99680-2.odtbin0 -> 215797 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf99680.odtbin0 -> 30257 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/toc-link.fodt45
-rw-r--r--vcl/qa/cppunit/pdfexport/pdfexport.cxx3990
-rw-r--r--vcl/qa/cppunit/physicalfontcollection.cxx551
-rw-r--r--vcl/qa/cppunit/physicalfontface.cxx301
-rw-r--r--vcl/qa/cppunit/physicalfontfacecollection.cxx53
-rw-r--r--vcl/qa/cppunit/physicalfontfamily.cxx149
-rw-r--r--vcl/qa/cppunit/png/PngFilterTest.cxx252
-rw-r--r--vcl/qa/cppunit/png/data/alpha-rect-8bit-RGBA.pngbin0 -> 158 bytes
-rw-r--r--vcl/qa/cppunit/png/data/color-rect-4bit-pal.pngbin0 -> 104 bytes
-rw-r--r--vcl/qa/cppunit/png/data/color-rect-8bit-RGB-interlaced.pngbin0 -> 92 bytes
-rw-r--r--vcl/qa/cppunit/png/data/color-rect-8bit-RGB.pngbin0 -> 90 bytes
-rw-r--r--vcl/qa/cppunit/png/data/ms-gif.pngbin0 -> 15901 bytes
-rw-r--r--vcl/qa/cppunit/png/data/rect-1bit-pal.pngbin0 -> 89 bytes
-rw-r--r--vcl/qa/cppunit/skia/skia.cxx588
-rw-r--r--vcl/qa/cppunit/svm/data/arc.svmbin0 -> 279 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/bitmapexs.svmbin0 -> 3773 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/bitmaps.svmbin0 -> 599 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/chord.svmbin0 -> 279 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/clipregion.svmbin0 -> 431 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/comment.svmbin0 -> 357 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/ellipse.svmbin0 -> 263 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/eps.svmbin0 -> 542 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/fillcolor.svmbin0 -> 244 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/floattransparent.svmbin0 -> 520 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/font.svmbin0 -> 320 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/gradient.svmbin0 -> 15497 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/gradientex.svmbin0 -> 2946 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/hatch.svmbin0 -> 271 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/intersectrectclipregion.svmbin0 -> 254 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/intersectregionclipregion.svmbin0 -> 378 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/layoutmode.svmbin0 -> 237 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/line.svmbin0 -> 325 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/linecolor.svmbin0 -> 244 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/mapmode.svmbin0 -> 336 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/masks.svmbin0 -> 603 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/moveclipregion.svmbin0 -> 287 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/overlinecolor.svmbin0 -> 244 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/pie.svmbin0 -> 279 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/pixel.svmbin0 -> 253 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/point.svmbin0 -> 229 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/polygon.svmbin0 -> 336 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/polyline.svmbin0 -> 400 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/polypolygon.svmbin0 -> 332 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/pushpop.svmbin0 -> 456 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/rasterop.svmbin0 -> 223 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/rect.svmbin0 -> 263 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/refpoint.svmbin0 -> 247 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/roundrect.svmbin0 -> 271 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/strecthtext.svmbin0 -> 259 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/text.svmbin0 -> 249 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/textalign.svmbin0 -> 223 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/textarray.svmbin0 -> 275 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/textcolor.svmbin0 -> 225 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/textfillecolor.svmbin0 -> 226 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/textlanguage.svmbin0 -> 233 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/textline.svmbin0 -> 245 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/textlinecolor.svmbin0 -> 226 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/textrectangle.svmbin0 -> 261 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/transparent.svmbin0 -> 251 bytes
-rw-r--r--vcl/qa/cppunit/svm/data/wallpaper.svmbin0 -> 323 bytes
-rw-r--r--vcl/qa/cppunit/svm/svmtest.cxx2334
-rw-r--r--vcl/qa/cppunit/test_blocklist_evaluate.xml46
-rw-r--r--vcl/qa/cppunit/test_blocklist_parse.xml63
-rw-r--r--vcl/qa/cppunit/test_blocklist_vulkan.xml30
-rw-r--r--vcl/qa/cppunit/text.cxx752
-rw-r--r--vcl/qa/cppunit/timer.cxx567
-rw-r--r--vcl/qa/cppunit/widgetdraw/WidgetDefinitionReaderTest.cxx139
-rw-r--r--vcl/qa/cppunit/widgetdraw/data/definition1.xml82
-rw-r--r--vcl/qa/cppunit/widgetdraw/data/definitionSettings1.xml5
-rw-r--r--vcl/qa/cppunit/widgetdraw/data/definitionSettings2.xml6
-rw-r--r--vcl/qa/cppunit/widgetdraw/data/definitionSettings3.xml13
574 files changed, 91085 insertions, 0 deletions
diff --git a/vcl/qa/cppunit/BackendTest.cxx b/vcl/qa/cppunit/BackendTest.cxx
new file mode 100644
index 000000000..4aeec2914
--- /dev/null
+++ b/vcl/qa/cppunit/BackendTest.cxx
@@ -0,0 +1,1640 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/bitmap.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+
+#include <svdata.hxx>
+#include <salinst.hxx>
+#include <salgdi.hxx>
+
+#include <test/outputdevice.hxx>
+
+// Run tests from visualbackendtest ('bin/run visualbackendtest').
+class BackendTest : public test::BootstrapFixture
+{
+ // if enabled - check the result images with:
+ // "xdg-open ./workdir/CppunitTest/vcl_backend_test.test.core/"
+ static constexpr const bool mbExportBitmap = false;
+
+ void exportImage(OUString const& rsFilename, BitmapEx const& rBitmapEx)
+ {
+ if (mbExportBitmap)
+ {
+ BitmapEx aBitmapEx(rBitmapEx);
+ aBitmapEx.Scale(Size(128, 128), BmpScaleFlag::Fast);
+ SvFileStream aStream(rsFilename, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter::GetGraphicFilter().compressAsPNG(aBitmapEx, aStream);
+ }
+ }
+
+ void exportImage(OUString const& rsFilename, Bitmap const& rBitmap)
+ {
+ if (mbExportBitmap)
+ {
+ Bitmap aBitmap(rBitmap);
+ aBitmap.Scale(Size(128, 128), BmpScaleFlag::Fast);
+ SvFileStream aStream(rsFilename, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter::GetGraphicFilter().compressAsPNG(BitmapEx(aBitmap), aStream);
+ }
+ }
+
+ void exportDevice(const OUString& filename, const VclPtr<VirtualDevice>& device)
+ {
+ if (mbExportBitmap)
+ {
+ BitmapEx aBitmapEx(device->GetBitmapEx(Point(0, 0), device->GetOutputSizePixel()));
+ SvFileStream aStream(filename, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter::GetGraphicFilter().compressAsPNG(aBitmapEx, aStream);
+ }
+ }
+
+ bool is32bppSupported() { return ImplGetSVData()->mpDefInst->supportsBitmap32(); }
+
+public:
+ BackendTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ // We need to enable tests ONE BY ONE as they fail because of backend bugs
+ // it is still important to have the test defined so we know the issues
+ // exist and we need to fix them. Consistent behaviour of our backends
+ // is of highest priority.
+
+ static bool assertBackendNameNotEmpty(const OUString& name)
+ {
+ // This ensures that all backends return a valid name.
+ assert(!name.isEmpty());
+ (void)name;
+ return true;
+ }
+
+// Check whether tests should fail depending on which backend is used
+// (not all work). If you want to disable just a specific test
+// for a specific backend, use something like
+// 'if(SHOULD_ASSERT && aOutDevTest.getRenderBackendName() != "skia")'.
+// The macro uses opt-out rather than opt-in so that this doesn't "pass"
+// silently in case a new backend is added.
+#define SHOULD_ASSERT \
+ (assertBackendNameNotEmpty(aOutDevTest.getRenderBackendName()) \
+ && aOutDevTest.getRenderBackendName() != "qt5" \
+ && aOutDevTest.getRenderBackendName() != "qt5svp" \
+ && aOutDevTest.getRenderBackendName() != "gtk3svp" \
+ && aOutDevTest.getRenderBackendName() != "aqua" \
+ && aOutDevTest.getRenderBackendName() != "gen" \
+ && aOutDevTest.getRenderBackendName() != "genpsp" \
+ && aOutDevTest.getRenderBackendName() != "win")
+
+#ifdef MACOSX
+ static OUString getRenderBackendName(OutputDevice* device)
+ {
+ assert(device);
+ return device->GetGraphics()->getRenderBackendName();
+ }
+#endif
+
+ void testDrawRectWithRectangle()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ exportImage("01-01_rectangle_test-rectangle.png", aBitmap);
+
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectWithPixel()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPixel aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ exportImage("01-02_rectangle_test-pixel.png", aBitmap);
+
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectWithLine()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ exportImage("01-03_rectangle_test-line.png", aBitmap);
+
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectWithPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ exportImage("01-04_rectangle_test-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectWithPolyLine()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ exportImage("01-05_rectangle_test-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectWithPolyLineB2D()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ exportImage("01-06_rectangle_test-polyline_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectWithPolyPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ exportImage("01-07_rectangle_test-polypolygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectWithPolyPolygonB2D()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ exportImage("01-08_rectangle_test-polypolygon_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectAAWithRectangle()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ exportImage("02-01_rectangle_AA_test-rectangle.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectAAWithPixel()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPixel aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ exportImage("02-02_rectangle_AA_test-pixel.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectAAWithLine()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ exportImage("02-03_rectangle_AA_test-line.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectAAWithPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ exportImage("02-04_rectangle_AA_test-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectAAWithPolyLine()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ exportImage("02-05_rectangle_AA_test-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectAAWithPolyLineB2D()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ exportImage("02-06_rectangle_AA_test-polyline_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectAAWithPolyPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ exportImage("02-07_rectangle_AA_test-polypolygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawRectAAWithPolyPolygonB2D()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ exportImage("02-08_rectangle_AA_test-polypolygon_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawFilledRectWithRectangle()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false);
+ exportImage("03-01_filled_rectangle_test-rectangle_noline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ aBitmap = aOutDevTest.setupFilledRectangle(true);
+ eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true);
+ exportImage("03-01_filled_rectangle_test-rectangle_line.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawFilledRectWithPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false);
+ exportImage("03-02_filled_rectangle_test-polygon_noline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ aBitmap = aOutDevTest.setupFilledRectangle(true);
+ eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true);
+ exportImage("03-02_filled_rectangle_test-polygon_line.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawFilledRectWithPolyPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false);
+ exportImage("03-03_filled_rectangle_test-polypolygon_noline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ aBitmap = aOutDevTest.setupFilledRectangle(true);
+ eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true);
+ exportImage("03-03_filled_rectangle_test-polypolygon_line.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawFilledRectWithPolyPolygon2D()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false);
+ exportImage("03-04_filled_rectangle_test-polypolygon_b2d_noline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ aBitmap = aOutDevTest.setupFilledRectangle(true);
+ eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true);
+ exportImage("03-04_filled_rectangle_test-polypolygon_b2d_line.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawDiamondWithPolygon()
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap);
+ exportImage("04-01_diamond_test-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawDiamondWithLine()
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap);
+ exportImage("04-02_diamond_test-line.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawDiamondWithPolyline()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap);
+ exportImage("04-03_diamond_test-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawDiamondWithPolylineB2D()
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap);
+ exportImage("04-04_diamond_test-polyline_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawInvertWithRectangle()
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_NONE();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkInvertRectangle(aBitmap);
+ exportImage("05-01_invert_test-rectangle.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawInvertN50WithRectangle()
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_N50();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkInvertN50Rectangle(aBitmap);
+ exportImage("05-02_invert_N50_test-rectangle.png", aBitmap);
+ if (SHOULD_ASSERT && aOutDevTest.getRenderBackendName() != "svp")
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawInvertTrackFrameWithRectangle()
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_TrackFrame();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkInvertTrackFrameRectangle(aBitmap);
+ exportImage("05-03_invert_TrackFrame_test-rectangle.png", aBitmap);
+ if (SHOULD_ASSERT && aOutDevTest.getRenderBackendName() != "svp")
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBezierWithPolylineB2D()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupBezier();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkBezier(aBitmap);
+ exportImage("06-01_bezier_test-polyline_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBezierAAWithPolylineB2D()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAABezier();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkBezier(aBitmap);
+ exportImage("07-01_bezier_AA_test-polyline_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBitmap24bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmap(vcl::PixelFormat::N24_BPP);
+ exportImage("08-01_bitmap_test_24bpp.png", aBitmap);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawTransformedBitmap24bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap(vcl::PixelFormat::N24_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap);
+ exportImage("08-02_transformed_bitmap_test_24bpp.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testComplexDrawTransformedBitmap24bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupComplexDrawTransformedBitmap(vcl::PixelFormat::N24_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkComplexTransformedBitmap(aBitmap);
+ exportImage("08-03_transformed_bitmap_test_24bpp.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBitmapExWithAlpha24bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmapExWithAlpha(vcl::PixelFormat::N24_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkBitmapExWithAlpha(aBitmap);
+ exportImage("08-04_bitmapex_with_alpha_test_24bpp.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawMask24bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawMask(vcl::PixelFormat::N24_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkMask(aBitmap);
+ exportImage("08-05_mask_test_24bpp.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBlend24bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ BitmapEx aBitmapEx = aOutDevTest.setupDrawBlend(vcl::PixelFormat::N24_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkBlend(aBitmapEx);
+ exportImage("08-06_blend_test_24bpp.png", aBitmapEx);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBitmap32bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmap(vcl::PixelFormat::N32_BPP);
+ exportImage("09-01_bitmap_test_32bpp.png", aBitmap);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap);
+ if (SHOULD_ASSERT && is32bppSupported())
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawTransformedBitmap32bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap(vcl::PixelFormat::N32_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap);
+ exportImage("09-02_transformed_bitmap_test_32bpp.png", aBitmap);
+ if (SHOULD_ASSERT && is32bppSupported())
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBitmapExWithAlpha32bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmapExWithAlpha(vcl::PixelFormat::N32_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkBitmapExWithAlpha(aBitmap);
+ exportImage("09-03_bitmapex_with_alpha_test_32bpp.png", aBitmap);
+ if (SHOULD_ASSERT && is32bppSupported())
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawMask32bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawMask(vcl::PixelFormat::N32_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkMask(aBitmap);
+ exportImage("09-04_mask_test_32bpp.png", aBitmap);
+ if (SHOULD_ASSERT && is32bppSupported())
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBlend32bpp()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ BitmapEx aBitmapEx = aOutDevTest.setupDrawBlend(vcl::PixelFormat::N32_BPP);
+ auto eResult = vcl::test::OutputDeviceTestBitmap::checkBlend(aBitmapEx);
+ exportImage("09-05_blend_test_32bpp.png", aBitmapEx);
+ if (SHOULD_ASSERT && is32bppSupported())
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawBitmap8bppGreyScale()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmap(vcl::PixelFormat::N8_BPP, true);
+ exportImage("010-01_bitmap_test_8bpp_greyscale.png", aBitmap);
+ auto eResult
+ = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap8bppGreyScale(aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawTransformedBitmap8bppGreyScale()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap(vcl::PixelFormat::N8_BPP, true);
+ auto eResult
+ = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap8bppGreyScale(aBitmap);
+ exportImage("010-02_transformed_bitmap_test_8bpp_greyscale.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawXor()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupXOR();
+ auto eResult = vcl::test::OutputDeviceTestAnotherOutDev::checkXOR(aBitmap);
+ exportImage("08-06_xor_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawTransformedBitmapExAlpha()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ ScopedVclPtrInstance<VirtualDevice> device;
+#ifdef MACOSX
+ // TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
+ if (getRenderBackendName(device) == "aqua")
+ return;
+#endif
+ device->SetOutputSizePixel(Size(16, 16));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+ {
+ // Fill the top left quarter with black.
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(COL_WHITE);
+ for (int i = 0; i < 8; ++i)
+ for (int j = 0; j < 8; ++j)
+ pWriteAccess->SetPixel(j, i, COL_BLACK);
+ }
+ BitmapEx aBitmapEx(aBitmap);
+ basegfx::B2DHomMatrix aMatrix;
+ // Draw with no transformation, only alpha change.
+ aMatrix.scale(16, 16);
+ device->DrawTransformedBitmapEx(aMatrix, aBitmapEx, 0.5);
+ BitmapEx result = device->GetBitmapEx(Point(0, 0), Size(16, 16));
+ CPPUNIT_ASSERT_EQUAL(Color(0x80, 0x80, 0x80), result.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, result.GetPixelColor(15, 15));
+ // Draw rotated and move to the bottom-left corner.
+ device->Erase();
+ aMatrix.identity();
+ aMatrix.scale(16, 16);
+ aMatrix.rotate(M_PI / 2);
+ aMatrix.translate(8, 8);
+ device->DrawTransformedBitmapEx(aMatrix, aBitmapEx, 0.5);
+ result = device->GetBitmap(Point(0, 0), Size(16, 16));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, result.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x80, 0x80, 0x80), result.GetPixelColor(0, 15));
+ }
+
+ void testClipRectangle()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipRectangle();
+ auto eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+ exportImage("09-01_clip_rectangle_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testClipPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipPolygon();
+ auto eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+ exportImage("09-02_clip_polygon_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testClipPolyPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipPolyPolygon();
+ auto eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+ exportImage("09-03_clip_polypolygon_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testClipB2DPolyPolygon()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipB2DPolyPolygon();
+ auto eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+ exportImage("09-04_clip_b2dpolypolygon_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOutDev()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDev();
+ auto eResult = vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDev(aBitmap);
+ exportImage("10-01_draw_out_dev_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOutDevScaledClipped()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDevScaledClipped();
+ auto eResult
+ = vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDevScaledClipped(aBitmap);
+ exportImage("10-02_draw_out_dev_scaled_clipped_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOutDevSelf()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDevSelf();
+ auto eResult = vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDevSelf(aBitmap);
+ exportImage("10-03_draw_out_dev_self_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDashedLine()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDashedLine();
+ auto eResult = vcl::test::OutputDeviceTestLine::checkDashedLine(aBitmap);
+ exportImage("11-01_dashed_line_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testErase()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ {
+ // Create normal virtual device (no alpha).
+ ScopedVclPtr<VirtualDevice> device
+ = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(10, 10));
+ // Erase with white, check it's white.
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ exportDevice("12-01_erase.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(5, 5)));
+ // Erase with black, check it's black.
+ device->SetBackground(Wallpaper(COL_BLACK));
+ device->Erase();
+ exportDevice("12-02_erase.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(5, 5)));
+ // Erase with cyan, check it's cyan.
+ device->SetBackground(Wallpaper(COL_CYAN));
+ device->Erase();
+ exportDevice("12-03_erase.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(5, 5)));
+ }
+ {
+ // Create virtual device with alpha.
+ ScopedVclPtr<VirtualDevice> device
+ = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(10, 10));
+ // Erase with white, check it's white.
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ exportDevice("12-04_erase.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(5, 5)));
+ // Erase with black, check it's black.
+ device->SetBackground(Wallpaper(COL_BLACK));
+ device->Erase();
+ exportDevice("12-05_erase.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(5, 5)));
+ // Erase with cyan, check it's cyan.
+ device->SetBackground(Wallpaper(COL_CYAN));
+ device->Erase();
+ exportDevice("12-06_erase.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(5, 5)));
+ // Erase with transparent, check it's transparent.
+ device->SetBackground(Wallpaper(COL_TRANSPARENT));
+ device->Erase();
+ exportDevice("12-07_erase.png", device);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), device->GetPixel(Point(0, 0)).GetAlpha());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), device->GetPixel(Point(9, 9)).GetAlpha());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), device->GetPixel(Point(5, 5)).GetAlpha());
+ }
+ }
+
+ void testLinearGradient()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradient();
+ auto eResult = vcl::test::OutputDeviceTestGradient::checkLinearGradient(aBitmap);
+ exportImage("13-01_linear_gradient_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLinearGradientAngled()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientAngled();
+ auto eResult = vcl::test::OutputDeviceTestGradient::checkLinearGradientAngled(aBitmap);
+ exportImage("13-02_linear_gradient_angled_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLinearGradientBorder()
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientBorder();
+ auto eResult = vcl::test::OutputDeviceTestGradient::checkLinearGradientBorder(aBitmap);
+ exportImage("13-03_linear_gradient_border_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLinearGradientIntensity()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientIntensity();
+ auto eResult = vcl::test::OutputDeviceTestGradient::checkLinearGradientIntensity(aBitmap);
+ exportImage("13-04_linear_gradient_intensity_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLinearGradientSteps()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientSteps();
+ auto eResult = vcl::test::OutputDeviceTestGradient::checkLinearGradientSteps(aBitmap);
+ exportImage("13-05_linear_gradient_steps_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testAxialGradient()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAxialGradient();
+ auto eResult = vcl::test::OutputDeviceTestGradient::checkAxialGradient(aBitmap);
+ exportImage("13-06_axial_gradient_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testRadialGradient()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRadialGradient();
+ auto eResult = vcl::test::OutputDeviceTestGradient::checkRadialGradient(aBitmap);
+ exportImage("13-07_radial_gradient_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testRadialGradientOfs()
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRadialGradientOfs();
+ auto eResult = vcl::test::OutputDeviceTestGradient::checkRadialGradientOfs(aBitmap);
+ exportImage("13-08_radial_gradient_ofs_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLineJoinBevel()
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinBevel();
+ auto eResult = vcl::test::OutputDeviceTestLine::checkLineJoinBevel(aBitmap);
+ exportImage("14-01_line_join_bevel_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLineJoinRound()
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinRound();
+ auto eResult = vcl::test::OutputDeviceTestLine::checkLineJoinRound(aBitmap);
+ exportImage("14-02_line_join_round_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLineJoinMiter()
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinMiter();
+ auto eResult = vcl::test::OutputDeviceTestLine::checkLineJoinMiter(aBitmap);
+ exportImage("14-03_line_join_miter_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLineJoinNone()
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinNone();
+ auto eResult = vcl::test::OutputDeviceTestLine::checkLineJoinNone(aBitmap);
+ exportImage("14-04_line_join_none_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLineCapRound()
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapRound();
+ auto eResult = vcl::test::OutputDeviceTestLine::checkLineCapRound(aBitmap);
+ exportImage("14-05_line_cap_round_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLineCapSquare()
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapSquare();
+ auto eResult = vcl::test::OutputDeviceTestLine::checkLineCapSquare(aBitmap);
+ exportImage("14-06_line_cap_square_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testLineCapButt()
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapButt();
+ auto eResult = vcl::test::OutputDeviceTestLine::checkLineCapButt(aBitmap);
+ exportImage("14-07_line_cap_butt_test.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawDropShapeWithPolyline()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDropShape();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkDropShape(aBitmap);
+ exportImage("15-01_drop_shape_test-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawDropShapeAAWithPolyline()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAADropShape();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkDropShape(aBitmap, true);
+ exportImage("15-02_drop_shape_AA_test-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawDropShapeWithPolygon()
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDropShape();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkDropShape(aBitmap);
+ exportImage("16-01_drop_shape_test-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawDropShapeAAWithPolygon()
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAADropShape();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkDropShape(aBitmap, true);
+ exportImage("16-02_drop_shape_AA_test-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawHaflEllipseWithPolyLine()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkHalfEllipse(aBitmap);
+ exportImage("17-01_half_ellipse_test-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawHaflEllipseAAWithPolyLine()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkHalfEllipse(aBitmap, true);
+ exportImage("17-02_half_ellipse_AA_test-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawHaflEllipseWithPolyLineB2D()
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkHalfEllipse(aBitmap);
+ exportImage("17-03_half_ellipse_test-polylineb2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawHaflEllipseAAWithPolyLineB2D()
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkHalfEllipse(aBitmap, true);
+ exportImage("17-03_half_ellipse_AA_test-polylineb2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawHaflEllipseWithPolygon()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkHalfEllipse(aBitmap);
+ exportImage("17-04_half_ellipse_test-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawHaflEllipseAAWithPolygon()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse(true);
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkHalfEllipse(aBitmap, true);
+ exportImage("17-05_half_ellipse_AA_test-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testClosedBezierWithPolyline()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClosedBezier();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkClosedBezier(aBitmap);
+ exportImage("18-01_closed_bezier-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testClosedBezierWithPolygon()
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClosedBezier();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkClosedBezier(aBitmap);
+ exportImage("18-02_closed_bezier-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testFilledAsymmetricalDropShape()
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledAsymmetricalDropShape();
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestLine::checkFilledAsymmetricalDropShape(aBitmap);
+ exportImage("19-01_filled_drop_shape-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ // Test SalGraphics::blendBitmap() and blendAlphaBitmap() calls.
+ void testDrawBlendExtended()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ // Create virtual device with alpha.
+ ScopedVclPtr<VirtualDevice> device
+ = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
+#ifdef MACOSX
+ // TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
+ if (getRenderBackendName(device) == "aqua")
+ return;
+#endif
+ device->SetOutputSizePixel(Size(10, 10));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ Bitmap bitmap(Size(5, 5), vcl::PixelFormat::N24_BPP);
+ bitmap.Erase(COL_BLUE);
+ // No alpha, this will actually call SalGraphics::DrawBitmap(), but still check
+ // the alpha of the device is handled correctly.
+ device->DrawBitmapEx(Point(2, 2), BitmapEx(bitmap));
+ exportDevice("blend_extended_01.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(2, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(6, 6)));
+ // Check pixels outside of the bitmap aren't affected.
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(1, 1)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(7, 7)));
+
+ device->Erase();
+ AlphaMask alpha(Size(5, 5));
+ alpha.Erase(0); // opaque
+ device->DrawBitmapEx(Point(2, 2), BitmapEx(bitmap, alpha));
+ exportDevice("blend_extended_02.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(2, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(6, 6)));
+
+ device->Erase();
+ alpha.Erase(255); // transparent
+ device->DrawBitmapEx(Point(2, 2), BitmapEx(bitmap, alpha));
+ exportDevice("blend_extended_03.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(2, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(6, 6)));
+
+ // Skia optimizes bitmaps that have just been Erase()-ed, so explicitly
+ // set some pixels in the alpha to avoid this and have an actual bitmap
+ // as the alpha mask.
+ device->Erase();
+ alpha.Erase(255); // transparent
+ BitmapWriteAccess* alphaWrite = alpha.AcquireAlphaWriteAccess();
+ alphaWrite->SetPixelIndex(0, 0, 0); // opaque
+ alpha.ReleaseAccess(alphaWrite);
+ device->DrawBitmapEx(Point(2, 2), BitmapEx(bitmap, alpha));
+ exportDevice("blend_extended_04.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(2, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(6, 6)));
+ }
+
+ void testDrawAlphaBitmapMirrored()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ // Normal virtual device.
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+#ifdef MACOSX
+ // TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
+ if (getRenderBackendName(device) == "aqua")
+ return;
+#endif
+ // Virtual device with alpha.
+ ScopedVclPtr<VirtualDevice> alphaDevice
+ = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(20, 20));
+ device->SetBackground(Wallpaper(COL_BLACK));
+ device->Erase();
+ alphaDevice->SetOutputSizePixel(Size(20, 20));
+ alphaDevice->SetBackground(Wallpaper(COL_BLACK));
+ alphaDevice->Erase();
+ Bitmap bitmap(Size(4, 4), vcl::PixelFormat::N24_BPP);
+ AlphaMask alpha(Size(4, 4));
+ bitmap.Erase(COL_LIGHTBLUE);
+ {
+ BitmapScopedWriteAccess writeAccess(bitmap);
+ writeAccess->SetPixel(3, 3, COL_LIGHTRED);
+ }
+ // alpha 127 will make COL_LIGHTRED -> COL_RED and the same for blue
+ alpha.Erase(127);
+ // Normal device.
+ device->DrawBitmapEx(Point(5, 5), Size(-4, -4), BitmapEx(bitmap));
+ device->DrawBitmapEx(Point(15, 15), Size(4, 4), BitmapEx(bitmap));
+ exportDevice("draw_alpha_bitmap_mirrored_01.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, device->GetPixel(Point(18, 18)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, device->GetPixel(Point(17, 18)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, device->GetPixel(Point(2, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, device->GetPixel(Point(3, 2)));
+ device->Erase();
+ device->DrawBitmapEx(Point(5, 5), Size(-4, -4), BitmapEx(bitmap, alpha));
+ device->DrawBitmapEx(Point(15, 15), Size(4, 4), BitmapEx(bitmap, alpha));
+ exportDevice("draw_alpha_bitmap_mirrored_02.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_RED, device->GetPixel(Point(18, 18)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(17, 18)));
+ CPPUNIT_ASSERT_EQUAL(COL_RED, device->GetPixel(Point(2, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(3, 2)));
+ device->Erase();
+ // Now with alpha device.
+ alphaDevice->DrawBitmapEx(Point(5, 5), Size(-4, -4), BitmapEx(bitmap));
+ alphaDevice->DrawBitmapEx(Point(15, 15), Size(4, 4), BitmapEx(bitmap));
+ exportDevice("draw_alpha_bitmap_mirrored_03.png", alphaDevice);
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, alphaDevice->GetPixel(Point(18, 18)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, alphaDevice->GetPixel(Point(17, 18)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, alphaDevice->GetPixel(Point(2, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, alphaDevice->GetPixel(Point(3, 2)));
+ alphaDevice->Erase();
+ alphaDevice->DrawBitmapEx(Point(5, 5), Size(-4, -4), BitmapEx(bitmap, alpha));
+ alphaDevice->DrawBitmapEx(Point(15, 15), Size(4, 4), BitmapEx(bitmap, alpha));
+ exportDevice("draw_alpha_bitmap_mirrored_04.png", alphaDevice);
+ CPPUNIT_ASSERT_EQUAL(COL_RED, alphaDevice->GetPixel(Point(18, 18)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, alphaDevice->GetPixel(Point(17, 18)));
+ CPPUNIT_ASSERT_EQUAL(COL_RED, alphaDevice->GetPixel(Point(2, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, alphaDevice->GetPixel(Point(3, 2)));
+ alphaDevice->Erase();
+ }
+
+ void testDrawingText()
+ {
+#ifndef _WIN32
+ vcl::test::OutputDeviceTestText aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupTextBitmap();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkTextLocation(aBitmap);
+ exportImage("17-01_test_text_Drawing.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+#endif
+ }
+
+ void testEvenOddRuleInIntersectionRectangles()
+ {
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupIntersectingRectangles();
+ auto eResult
+ = vcl::test::OutputDeviceTestCommon::checkEvenOddRuleInIntersectingRecs(aBitmap);
+ exportImage("18-01_test_Even-Odd-rule_intersecting_Recs.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOpenPolygonWithPolyLine()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ exportImage("19-01_open_polygon-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOpenPolygonWithPolyLineB2D()
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ exportImage("19-02_open_polygon-polyline_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOpenPolygonWithPolygon()
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ exportImage("19-03_open_polygon-polygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOpenPolygonWithPolyPolygon()
+ {
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ exportImage("19-04_open_polygon-polypolygon.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOpenPolygonWithPolyPolygonB2D()
+ {
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ exportImage("19-04_open_polygon-polypolygon_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOpenBezierWithPolyLine()
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenBezier();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkOpenBezier(aBitmap);
+ exportImage("19-01_open_bezier-polyline.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testDrawOpenBezierWithPolyLineB2D()
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenBezier();
+ auto eResult = vcl::test::OutputDeviceTestCommon::checkOpenBezier(aBitmap);
+ exportImage("19-01_open_bezier-polyline_b2d.png", aBitmap);
+ if (SHOULD_ASSERT)
+ CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+ }
+
+ void testTdf124848()
+ {
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+#ifdef MACOSX
+ // TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
+ if (getRenderBackendName(device) == "aqua")
+ return;
+#endif
+ device->SetOutputSizePixel(Size(100, 100));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ device->SetAntialiasing(AntialiasingFlags::Enable);
+ device->SetLineColor(COL_BLACK);
+ basegfx::B2DHomMatrix matrix;
+ // DrawPolyLine() would apply the whole matrix to the line width, making it negative
+ // in case of a larger rotation.
+ matrix.rotate(M_PI); //180 degrees
+ matrix.translate(100, 100);
+ CPPUNIT_ASSERT(device->DrawPolyLineDirect(matrix,
+ basegfx::B2DPolygon{ { 50, 50 }, { 50, 100 } },
+ 100, 0, nullptr, basegfx::B2DLineJoin::Miter));
+ exportDevice("tdf124848-1.png", device);
+ // 100px wide line should fill the entire width of the upper half
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(2, 2)));
+
+ // Also check hairline.
+ device->Erase();
+ CPPUNIT_ASSERT(device->DrawPolyLineDirect(matrix,
+ basegfx::B2DPolygon{ { 50, 50 }, { 50, 100 } }, 0,
+ 0, nullptr, basegfx::B2DLineJoin::Miter));
+ exportDevice("tdf124848-2.png", device);
+ // 1px wide
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(50, 20)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(49, 20)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(51, 20)));
+ }
+
+ void testTdf136171()
+ {
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ // Create virtual device with alpha.
+ ScopedVclPtr<VirtualDevice> device
+ = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(10, 10));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ bitmap.Erase(COL_BLUE);
+ basegfx::B2DHomMatrix matrix;
+ matrix.scale(bitmap.GetSizePixel().Width(),
+ bitmap.GetSizePixel().Height()); // draw as 10x10
+ // Draw a blue bitmap to the device. The bug was that there was no alpha, but OutputDevice::DrawTransformBitmapExDirect()
+ // supplied a fully opaque alpha done with Erase() on the alpha bitmap, and Skia backend didn't handle such alpha correctly.
+ device->DrawTransformedBitmapEx(matrix, BitmapEx(bitmap));
+ exportDevice("tdf136171.png", device);
+ // The whole virtual device content now should be blue.
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(9, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(0, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(4, 4)));
+ }
+
+ void testTdf145811()
+ {
+ // VCL may call copyArea()/copyBits() of backends even with coordinates partially
+ // outside of the device, so try various copying like that.
+ ScopedVclPtr<VirtualDevice> device1 = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device1->SetOutputSizePixel(Size(100, 100));
+ device1->SetBackground(Wallpaper(COL_YELLOW));
+ device1->Erase();
+ device1->SetLineColor(COL_BLUE);
+ device1->DrawPixel(Point(0, 0), COL_BLUE);
+ device1->DrawPixel(Point(99, 99), COL_BLUE);
+#ifdef MACOSX
+ // TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
+ if (getRenderBackendName(device1) == "aqua")
+ return;
+#endif
+
+ // Plain 1:1 copy device1->device2.
+ ScopedVclPtr<VirtualDevice> device2 = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device2->SetOutputSizePixel(Size(100, 100));
+ device2->DrawOutDev(Point(0, 0), Size(100, 100), Point(0, 0), Size(100, 100), *device1);
+ exportDevice("tdf145811-1.png", device2);
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(1, 1)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(98, 98)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(99, 99)));
+
+ // For the rest call directly SalGraphics, because OutputDevice does range checking,
+ // but other code may call copyArea()/copyBits() of SalGraphics directly without range checking.
+ SalGraphics* graphics1 = device1->GetGraphics();
+ SalGraphics* graphics2 = device2->GetGraphics();
+
+ device2->DrawOutDev(Point(0, 0), Size(100, 100), Point(0, 0), Size(100, 100), *device1);
+ // Copy device1->device2 offset by 10,10.
+ graphics2->CopyBits(SalTwoRect(0, 0, 100, 100, 10, 10, 100, 100), *graphics1, *device2,
+ *device1);
+ exportDevice("tdf145811-2.png", device2);
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(0, 0))); // unmodified
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(10, 10)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(11, 11)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(99, 99)));
+
+ device2->DrawOutDev(Point(0, 0), Size(100, 100), Point(0, 0), Size(100, 100), *device1);
+ // Copy area of device2 offset by 10,10.
+ graphics2->CopyArea(10, 10, 0, 0, 100, 100, *device1);
+ exportDevice("tdf145811-3.png", device2);
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(0, 0))); // unmodified
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(10, 10)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(11, 11)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(99, 99)));
+
+ device2->DrawOutDev(Point(0, 0), Size(100, 100), Point(0, 0), Size(100, 100), *device1);
+ // Copy device1->device2 offset by -20,-20.
+ graphics2->CopyBits(SalTwoRect(0, 0, 100, 100, -20, -20, 100, 100), *graphics1, *device2,
+ *device1);
+ exportDevice("tdf145811-4.png", device2);
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(78, 78)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(79, 79)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(80, 80)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(99, 99))); // unmodified
+
+ device2->DrawOutDev(Point(0, 0), Size(100, 100), Point(0, 0), Size(100, 100), *device1);
+ // Copy area of device2 offset by -20,-20.
+ graphics2->CopyArea(-20, -20, 0, 0, 100, 100, *device1);
+ exportDevice("tdf145811-5.png", device2);
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(78, 78)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(79, 79)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(80, 80)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(99, 99))); // unmodified
+
+ device2->DrawOutDev(Point(0, 0), Size(100, 100), Point(0, 0), Size(100, 100), *device1);
+ // Copy device1->device2 offset by -10,-10 starting from -20,-20 at 150x150 size
+ // (i.e. outside in all directions).
+ graphics2->CopyBits(SalTwoRect(-20, -20, 150, 150, -30, -30, 150, 150), *graphics1,
+ *device2, *device1);
+ exportDevice("tdf145811-6.png", device2);
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(88, 88)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(89, 89)));
+ // (90,90) and further originate from outside and may be garbage.
+
+ device2->DrawOutDev(Point(0, 0), Size(100, 100), Point(0, 0), Size(100, 100), *device1);
+ // Copy area of device2 offset by -10,-10 starting from -20,-20 at 150x150 size
+ // (i.e. outside in all directions).
+ graphics2->CopyArea(-30, -30, -20, -20, 150, 150, *device1);
+ exportDevice("tdf145811-7.png", device2);
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, device2->GetPixel(Point(88, 88)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, device2->GetPixel(Point(89, 89)));
+ // (90,90) and further originate from outside and may be garbage.
+ }
+
+ CPPUNIT_TEST_SUITE(BackendTest);
+ CPPUNIT_TEST(testDrawRectWithRectangle);
+ CPPUNIT_TEST(testDrawRectWithPixel);
+ CPPUNIT_TEST(testDrawRectWithLine);
+ CPPUNIT_TEST(testDrawRectWithPolygon);
+ CPPUNIT_TEST(testDrawRectWithPolyLine);
+ CPPUNIT_TEST(testDrawRectWithPolyLineB2D);
+ CPPUNIT_TEST(testDrawRectWithPolyPolygon);
+ CPPUNIT_TEST(testDrawRectWithPolyPolygonB2D);
+
+ CPPUNIT_TEST(testDrawRectAAWithRectangle);
+ CPPUNIT_TEST(testDrawRectAAWithPixel);
+ CPPUNIT_TEST(testDrawRectAAWithLine);
+ CPPUNIT_TEST(testDrawRectAAWithPolygon);
+ CPPUNIT_TEST(testDrawRectAAWithPolyLine);
+ CPPUNIT_TEST(testDrawRectAAWithPolyLineB2D);
+ CPPUNIT_TEST(testDrawRectAAWithPolyPolygon);
+ CPPUNIT_TEST(testDrawRectAAWithPolyPolygonB2D);
+
+ CPPUNIT_TEST(testDrawFilledRectWithRectangle);
+ CPPUNIT_TEST(testDrawFilledRectWithPolygon);
+ CPPUNIT_TEST(testDrawFilledRectWithPolyPolygon);
+ CPPUNIT_TEST(testDrawFilledRectWithPolyPolygon2D);
+
+ CPPUNIT_TEST(testDrawDiamondWithPolygon);
+ CPPUNIT_TEST(testDrawDiamondWithLine);
+ CPPUNIT_TEST(testDrawDiamondWithPolyline);
+ CPPUNIT_TEST(testDrawDiamondWithPolylineB2D);
+
+ CPPUNIT_TEST(testDrawInvertWithRectangle);
+ CPPUNIT_TEST(testDrawInvertN50WithRectangle);
+ CPPUNIT_TEST(testDrawInvertTrackFrameWithRectangle);
+
+ CPPUNIT_TEST(testDrawBezierWithPolylineB2D);
+ CPPUNIT_TEST(testDrawBezierAAWithPolylineB2D);
+
+ CPPUNIT_TEST(testDrawDropShapeWithPolyline);
+ CPPUNIT_TEST(testDrawDropShapeAAWithPolyline);
+
+ CPPUNIT_TEST(testDrawDropShapeWithPolygon);
+ CPPUNIT_TEST(testDrawDropShapeAAWithPolygon);
+
+ CPPUNIT_TEST(testDrawHaflEllipseWithPolyLine);
+ CPPUNIT_TEST(testDrawHaflEllipseAAWithPolyLine);
+ CPPUNIT_TEST(testDrawHaflEllipseWithPolyLineB2D);
+ CPPUNIT_TEST(testDrawHaflEllipseAAWithPolyLineB2D);
+ CPPUNIT_TEST(testDrawHaflEllipseWithPolygon);
+ CPPUNIT_TEST(testDrawHaflEllipseAAWithPolygon);
+
+ CPPUNIT_TEST(testClosedBezierWithPolyline);
+ CPPUNIT_TEST(testClosedBezierWithPolygon);
+
+ CPPUNIT_TEST(testFilledAsymmetricalDropShape);
+
+ CPPUNIT_TEST(testDrawBitmap24bpp);
+ CPPUNIT_TEST(testDrawTransformedBitmap24bpp);
+ CPPUNIT_TEST(testComplexDrawTransformedBitmap24bpp);
+ CPPUNIT_TEST(testDrawBitmapExWithAlpha24bpp);
+ CPPUNIT_TEST(testDrawMask24bpp);
+ CPPUNIT_TEST(testDrawBlend24bpp);
+
+ CPPUNIT_TEST(testDrawXor);
+
+ CPPUNIT_TEST(testDrawBitmap32bpp);
+ CPPUNIT_TEST(testDrawTransformedBitmap32bpp);
+ CPPUNIT_TEST(testDrawBitmapExWithAlpha32bpp);
+ CPPUNIT_TEST(testDrawMask32bpp);
+ CPPUNIT_TEST(testDrawBlend32bpp);
+
+ CPPUNIT_TEST(testDrawTransformedBitmap8bppGreyScale);
+ CPPUNIT_TEST(testDrawBitmap8bppGreyScale);
+
+ CPPUNIT_TEST(testDrawTransformedBitmapExAlpha);
+
+ CPPUNIT_TEST(testClipRectangle);
+ CPPUNIT_TEST(testClipPolygon);
+ CPPUNIT_TEST(testClipPolyPolygon);
+ CPPUNIT_TEST(testClipB2DPolyPolygon);
+
+ CPPUNIT_TEST(testDrawOutDev);
+ CPPUNIT_TEST(testDrawOutDevScaledClipped);
+ CPPUNIT_TEST(testDrawOutDevSelf);
+
+ CPPUNIT_TEST(testDashedLine);
+
+ CPPUNIT_TEST(testErase);
+
+ CPPUNIT_TEST(testLinearGradient);
+ CPPUNIT_TEST(testLinearGradientAngled);
+ CPPUNIT_TEST(testLinearGradientBorder);
+ CPPUNIT_TEST(testLinearGradientIntensity);
+ CPPUNIT_TEST(testLinearGradientSteps);
+ CPPUNIT_TEST(testAxialGradient);
+ CPPUNIT_TEST(testRadialGradient);
+ CPPUNIT_TEST(testRadialGradientOfs);
+
+ CPPUNIT_TEST(testLineCapRound);
+ CPPUNIT_TEST(testLineCapSquare);
+ CPPUNIT_TEST(testLineCapButt);
+ CPPUNIT_TEST(testLineJoinBevel);
+ CPPUNIT_TEST(testLineJoinRound);
+ CPPUNIT_TEST(testLineJoinMiter);
+ CPPUNIT_TEST(testLineJoinNone);
+
+ CPPUNIT_TEST(testDrawBlendExtended);
+ CPPUNIT_TEST(testDrawAlphaBitmapMirrored);
+
+ CPPUNIT_TEST(testDrawingText);
+ CPPUNIT_TEST(testEvenOddRuleInIntersectionRectangles);
+
+ CPPUNIT_TEST(testDrawOpenPolygonWithPolyLine);
+ CPPUNIT_TEST(testDrawOpenPolygonWithPolyLineB2D);
+ CPPUNIT_TEST(testDrawOpenPolygonWithPolygon);
+ CPPUNIT_TEST(testDrawOpenPolygonWithPolyPolygon);
+ CPPUNIT_TEST(testDrawOpenPolygonWithPolyPolygonB2D);
+
+ CPPUNIT_TEST(testDrawOpenBezierWithPolyLine);
+ CPPUNIT_TEST(testDrawOpenBezierWithPolyLineB2D);
+
+ CPPUNIT_TEST(testTdf124848);
+ CPPUNIT_TEST(testTdf136171);
+ CPPUNIT_TEST(testTdf145811);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BackendTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/BinaryDataContainerTest.cxx b/vcl/qa/cppunit/BinaryDataContainerTest.cxx
new file mode 100644
index 000000000..09bb036d8
--- /dev/null
+++ b/vcl/qa/cppunit/BinaryDataContainerTest.cxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <vcl/BinaryDataContainer.hxx>
+
+using namespace css;
+
+namespace
+{
+class BinaryDataContainerTest : public CppUnit::TestFixture
+{
+ void testConstruct();
+
+ CPPUNIT_TEST_SUITE(BinaryDataContainerTest);
+ CPPUNIT_TEST(testConstruct);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void BinaryDataContainerTest::testConstruct()
+{
+ {
+ BinaryDataContainer aContainer;
+ CPPUNIT_ASSERT_EQUAL(true, aContainer.isEmpty());
+ CPPUNIT_ASSERT_EQUAL(size_t(0), aContainer.getSize());
+ }
+ {
+ std::vector<sal_uInt8> aTestByteArray = { 1, 2, 3, 4 };
+ BinaryDataContainer aContainer(aTestByteArray.data(), aTestByteArray.size());
+ CPPUNIT_ASSERT_EQUAL(false, aContainer.isEmpty());
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aContainer.getSize());
+
+ // Test Copy
+ BinaryDataContainer aCopyOfContainer = aContainer;
+ CPPUNIT_ASSERT_EQUAL(false, aCopyOfContainer.isEmpty());
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aCopyOfContainer.getSize());
+ CPPUNIT_ASSERT_EQUAL(aCopyOfContainer.getData(), aContainer.getData());
+
+ // Test Move
+ BinaryDataContainer aMovedInContainer = std::move(aCopyOfContainer);
+ CPPUNIT_ASSERT_EQUAL(false, aMovedInContainer.isEmpty());
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aMovedInContainer.getSize());
+ CPPUNIT_ASSERT_EQUAL(aMovedInContainer.getData(), aContainer.getData());
+
+ CPPUNIT_ASSERT_EQUAL(true, aCopyOfContainer.isEmpty());
+ CPPUNIT_ASSERT_EQUAL(size_t(0), aCopyOfContainer.getSize());
+ }
+ {
+ // construct a unique_ptr data array
+ std::vector<sal_uInt8> aTestByteArray = { 1, 2, 3, 4 };
+ auto aConstructionByteArray = std::make_unique<std::vector<sal_uInt8>>(aTestByteArray);
+
+ // remember for later to compare
+ const sal_uInt8* pInternal = aConstructionByteArray->data();
+
+ BinaryDataContainer aContainer(std::move(aConstructionByteArray));
+
+ // make sure the unique_ptr was moved into BinaryDataContainer
+ CPPUNIT_ASSERT_EQUAL(false, bool(aConstructionByteArray));
+ // make sure we didn't copy data into BinaryDataContainer (pointers match)
+ CPPUNIT_ASSERT_EQUAL(pInternal, aContainer.getData());
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BinaryDataContainerTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/BitmapExTest.cxx b/vcl/qa/cppunit/BitmapExTest.cxx
new file mode 100644
index 000000000..a0a6b3096
--- /dev/null
+++ b/vcl/qa/cppunit/BitmapExTest.cxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <vcl/bitmapex.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <svdata.hxx>
+#include <salinst.hxx>
+
+namespace
+{
+class BitmapExTest : public CppUnit::TestFixture
+{
+ void testGetPixelColor24_8();
+ void testGetPixelColor32();
+ void testTransformBitmapEx();
+
+ CPPUNIT_TEST_SUITE(BitmapExTest);
+ CPPUNIT_TEST(testGetPixelColor24_8);
+ CPPUNIT_TEST(testGetPixelColor32);
+ CPPUNIT_TEST(testTransformBitmapEx);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void BitmapExTest::testGetPixelColor24_8()
+{
+ Bitmap aBitmap(Size(3, 3), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(Color(ColorTransparency, 0x00, 0x00, 0xFF, 0x00));
+ }
+ AlphaMask aMask(Size(3, 3));
+ {
+ AlphaScopedWriteAccess pWriteAccess(aMask);
+ pWriteAccess->Erase(Color(ColorTransparency, 0x00, 0xAA, 0xAA, 0xAA));
+ }
+
+ BitmapEx aBitmapEx(aBitmap, aMask);
+
+ CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xAA, 0x00, 0xFF, 0x00),
+ aBitmapEx.GetPixelColor(0, 0));
+}
+
+void BitmapExTest::testGetPixelColor32()
+{
+ // Check backend capabilities and return from the test successfully
+ // if the backend doesn't support 32-bit bitmap
+ if (!ImplGetSVData()->mpDefInst->supportsBitmap32())
+ return;
+
+ Bitmap aBitmap(Size(3, 3), vcl::PixelFormat::N32_BPP);
+ {
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(Color(ColorTransparency, 0xAA, 0x00, 0xFF, 0x00));
+ }
+
+ BitmapEx aBitmapEx(aBitmap);
+
+ CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xAA, 0x00, 0xFF, 0x00),
+ aBitmapEx.GetPixelColor(0, 0));
+}
+
+void BitmapExTest::testTransformBitmapEx()
+{
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(COL_WHITE);
+ for (int i = 0; i < 8; ++i)
+ {
+ for (int j = 0; j < 8; ++j)
+ {
+ pWriteAccess->SetPixel(i, j, COL_BLACK);
+ }
+ }
+ }
+ BitmapEx aBitmapEx(aBitmap);
+
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.rotate(M_PI / 2);
+ BitmapEx aTransformed = aBitmapEx.TransformBitmapEx(16, 16, aMatrix);
+ aBitmap = aTransformed.GetBitmap();
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ for (int i = 0; i < 16; ++i)
+ {
+ for (int j = 0; j < 16; ++j)
+ {
+ BitmapColor aColor = pAccess->GetPixel(i, j);
+ std::stringstream ss;
+ ss << "Color is expected to be white or black, is '" << aColor.AsRGBHexString() << "'";
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expression: aColor == COL_WHITE || aColor == COL_BLACK
+ // - Color is expected to be white or black, is 'bfbfbf'
+ // i.e. smoothing introduced noise for a simple 90 deg rotation.
+ CPPUNIT_ASSERT_MESSAGE(ss.str(), aColor == COL_WHITE || aColor == COL_BLACK);
+ }
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BitmapExTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/BitmapFilterTest.cxx b/vcl/qa/cppunit/BitmapFilterTest.cxx
new file mode 100644
index 000000000..a2aa37ceb
--- /dev/null
+++ b/vcl/qa/cppunit/BitmapFilterTest.cxx
@@ -0,0 +1,283 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/bitmap.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+
+#include <tools/stream.hxx>
+#include <vcl/graphicfilter.hxx>
+
+#include <vcl/BitmapBasicMorphologyFilter.hxx>
+#include <vcl/BitmapFilterStackBlur.hxx>
+#include <BitmapSymmetryCheck.hxx>
+
+#include <chrono>
+#include <string_view>
+
+namespace
+{
+constexpr bool constWriteResultBitmap(false);
+constexpr bool constEnablePerformanceTest(false);
+
+class BitmapFilterTest : public test::BootstrapFixture
+{
+public:
+ BitmapFilterTest()
+ : test::BootstrapFixture(true, false)
+ {
+ }
+
+ void testBlurCorrectness();
+ void testBasicMorphology();
+ void testPerformance();
+ void testGenerateStripRanges();
+
+ CPPUNIT_TEST_SUITE(BitmapFilterTest);
+ CPPUNIT_TEST(testBlurCorrectness);
+ CPPUNIT_TEST(testBasicMorphology);
+ CPPUNIT_TEST(testPerformance);
+ CPPUNIT_TEST(testGenerateStripRanges);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(u"vcl/qa/cppunit/data/") + sFileName;
+ }
+
+ BitmapEx loadBitmap(std::u16string_view sFileName)
+ {
+ Graphic aGraphic;
+ const OUString aURL(getFullUrl(sFileName));
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ ErrCode aResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, aResult);
+ return aGraphic.GetBitmapEx();
+ }
+
+ template <class BitmapT> // handle both Bitmap and BitmapEx
+ void savePNG(const OUString& sWhere, const BitmapT& rBmp)
+ {
+ SvFileStream aStream(sWhere, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(rBmp), aStream);
+ }
+};
+
+void BitmapFilterTest::testBlurCorrectness()
+{
+ // Setup test bitmap
+ Size aSize(41, 31);
+ Bitmap aBitmap24Bit(aSize, vcl::PixelFormat::N24_BPP);
+
+ ScanlineFormat scanlineFormat = ScanlineFormat::NONE;
+ auto ePixelFormat = aBitmap24Bit.getPixelFormat();
+
+ {
+ tools::Long aMargin1 = 1;
+ tools::Long aMargin2 = 3;
+ BitmapScopedWriteAccess aWriteAccess(aBitmap24Bit);
+ scanlineFormat = aWriteAccess->GetScanlineFormat();
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(COL_BLACK);
+
+ tools::Rectangle aRectangle1(aMargin1, aMargin1, aSize.Width() - 1 - aMargin1,
+ aSize.Height() - 1 - aMargin1);
+
+ tools::Rectangle aRectangle2(aMargin2, aMargin2, aSize.Width() - 1 - aMargin2,
+ aSize.Height() - 1 - aMargin2);
+
+ tools::Rectangle aRectangle3(aSize.Width() / 2, aSize.Height() / 2, aSize.Width() / 2,
+ aSize.Height() / 2);
+
+ aWriteAccess->DrawRect(aRectangle1);
+ aWriteAccess->DrawRect(aRectangle2);
+ aWriteAccess->DrawRect(aRectangle3);
+ }
+
+ if (constWriteResultBitmap)
+ {
+ savePNG("~/blurBefore.png", aBitmap24Bit);
+ }
+
+ // Perform blur
+ BitmapFilterStackBlur aBlurFilter(2);
+ aBitmap24Bit = aBlurFilter.filter(aBitmap24Bit);
+
+ // Check the result
+
+ if (constWriteResultBitmap)
+ {
+ savePNG("~/blurAfter.png", aBitmap24Bit);
+ }
+
+ // Check blurred bitmap parameters
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(41), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(31), aBitmap24Bit.GetSizePixel().Height());
+
+ CPPUNIT_ASSERT_EQUAL(ePixelFormat, aBitmap24Bit.getPixelFormat());
+
+ // Check that the bitmap is horizontally and vertically symmetrical
+ CPPUNIT_ASSERT(BitmapSymmetryCheck::check(aBitmap24Bit));
+
+ {
+ Bitmap::ScopedReadAccess aReadAccess(aBitmap24Bit);
+ CPPUNIT_ASSERT_EQUAL(scanlineFormat, aReadAccess->GetScanlineFormat());
+ }
+}
+
+void BitmapFilterTest::testBasicMorphology()
+{
+ const BitmapEx aOrigBitmap = loadBitmap(u"testBasicMorphology.png");
+ const BitmapEx aRefBitmapDilated1 = loadBitmap(u"testBasicMorphologyDilated1.png");
+ const BitmapEx aRefBitmapDilated1Eroded1
+ = loadBitmap(u"testBasicMorphologyDilated1Eroded1.png");
+ const BitmapEx aRefBitmapDilated2 = loadBitmap(u"testBasicMorphologyDilated2.png");
+ const BitmapEx aRefBitmapDilated2Eroded1
+ = loadBitmap(u"testBasicMorphologyDilated2Eroded1.png");
+
+ BitmapEx aTransformBitmap = aOrigBitmap;
+ BitmapFilter::Filter(aTransformBitmap, BitmapDilateFilter(1));
+ if (constWriteResultBitmap)
+ savePNG("~/Dilated1.png", aTransformBitmap);
+ CPPUNIT_ASSERT_EQUAL(aRefBitmapDilated1.GetChecksum(), aTransformBitmap.GetChecksum());
+ BitmapFilter::Filter(aTransformBitmap, BitmapErodeFilter(1));
+ if (constWriteResultBitmap)
+ savePNG("~/Dilated1Eroded1.png", aTransformBitmap);
+ CPPUNIT_ASSERT_EQUAL(aRefBitmapDilated1Eroded1.GetChecksum(), aTransformBitmap.GetChecksum());
+
+ aTransformBitmap = aOrigBitmap;
+ BitmapFilter::Filter(aTransformBitmap, BitmapDilateFilter(2));
+ if (constWriteResultBitmap)
+ savePNG("~/Dilated2.png", aTransformBitmap);
+ CPPUNIT_ASSERT_EQUAL(aRefBitmapDilated2.GetChecksum(), aTransformBitmap.GetChecksum());
+ BitmapFilter::Filter(aTransformBitmap, BitmapErodeFilter(1));
+ if (constWriteResultBitmap)
+ savePNG("~/Dilated2Eroded1.png", aTransformBitmap);
+ CPPUNIT_ASSERT_EQUAL(aRefBitmapDilated2Eroded1.GetChecksum(), aTransformBitmap.GetChecksum());
+}
+
+void BitmapFilterTest::testPerformance()
+{
+ if (!constEnablePerformanceTest)
+ return;
+
+ Size aSize(4000, 3000); // A rather common picture size
+
+ // Prepare bitmap
+ Bitmap aBigBitmap(aSize, vcl::PixelFormat::N24_BPP);
+ {
+ tools::Long aMargin = 500;
+ BitmapScopedWriteAccess aWriteAccess(aBigBitmap);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(COL_BLACK);
+ aWriteAccess->SetFillColor(COL_BLACK);
+ tools::Rectangle aRectangle(aMargin, aMargin, aSize.Width() - 1 - aMargin,
+ aSize.Height() - 1 - aMargin);
+
+ aWriteAccess->DrawRect(aRectangle);
+ }
+
+ int nIterations = 10;
+ auto start = std::chrono::high_resolution_clock::now();
+ Bitmap aResult;
+ for (int i = 0; i < nIterations; i++)
+ {
+ BitmapFilterStackBlur aBlurFilter(250);
+ aResult = aBlurFilter.filter(aBigBitmap);
+ }
+ auto end = std::chrono::high_resolution_clock::now();
+ auto elapsed = (end - start) / nIterations;
+
+ if (constWriteResultBitmap)
+ {
+ std::unique_ptr<SvFileStream> pStream(
+ new SvFileStream("~/BlurBigPerformance.png", StreamMode::WRITE | StreamMode::TRUNC));
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(aResult), *pStream);
+
+ pStream.reset(new SvFileStream("~/BlurBigPerformance.txt", StreamMode::WRITE));
+ pStream->WriteOString("Blur average time: ");
+ pStream->WriteOString(OString::number(
+ std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count()));
+ pStream->WriteOString("\n");
+ }
+}
+
+void BitmapFilterTest::testGenerateStripRanges()
+{
+ {
+ constexpr tools::Long nFirstIndex = 0;
+ constexpr tools::Long nLastIndex = 100;
+ constexpr tools::Long nStripSize = 32;
+
+ std::vector<std::tuple<tools::Long, tools::Long, bool>> aRanges;
+
+ vcl::bitmap::generateStripRanges<nStripSize>(
+ nFirstIndex, nLastIndex,
+ [&](tools::Long const nStart, tools::Long const nEnd, bool const bLast) {
+ aRanges.emplace_back(nStart, nEnd, bLast);
+ });
+
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aRanges.size());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), std::get<0>(aRanges[0]));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(31), std::get<1>(aRanges[0]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[0]));
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(32), std::get<0>(aRanges[1]));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(63), std::get<1>(aRanges[1]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[1]));
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(64), std::get<0>(aRanges[2]));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(95), std::get<1>(aRanges[2]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[2]));
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(96), std::get<0>(aRanges[3]));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), std::get<1>(aRanges[3]));
+ CPPUNIT_ASSERT_EQUAL(true, std::get<2>(aRanges[3]));
+ }
+
+ {
+ constexpr tools::Long nFirstIndex = 0;
+ constexpr tools::Long nLastIndex = 95;
+ constexpr tools::Long nStripSize = 32;
+
+ std::vector<std::tuple<tools::Long, tools::Long, bool>> aRanges;
+
+ vcl::bitmap::generateStripRanges<nStripSize>(
+ nFirstIndex, nLastIndex,
+ [&](tools::Long const nStart, tools::Long const nEnd, bool const bLast) {
+ aRanges.emplace_back(nStart, nEnd, bLast);
+ });
+
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aRanges.size());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), std::get<0>(aRanges[0]));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(31), std::get<1>(aRanges[0]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[0]));
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(32), std::get<0>(aRanges[1]));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(63), std::get<1>(aRanges[1]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[1]));
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(64), std::get<0>(aRanges[2]));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(95), std::get<1>(aRanges[2]));
+ CPPUNIT_ASSERT_EQUAL(true, std::get<2>(aRanges[2]));
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BitmapFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/BitmapProcessorTest.cxx b/vcl/qa/cppunit/BitmapProcessorTest.cxx
new file mode 100644
index 000000000..b855aa146
--- /dev/null
+++ b/vcl/qa/cppunit/BitmapProcessorTest.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <vcl/bitmap.hxx>
+#include <vcl/alpha.hxx>
+
+#include <bitmap/BitmapDisabledImageFilter.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+
+namespace
+{
+class BitmapProcessorTest : public CppUnit::TestFixture
+{
+ void testDisabledImage();
+
+ CPPUNIT_TEST_SUITE(BitmapProcessorTest);
+ CPPUNIT_TEST(testDisabledImage);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void BitmapProcessorTest::testDisabledImage()
+{
+ {
+ Bitmap aBitmap(Size(3, 3), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(Color(ColorTransparency, 0x00, 0x00, 0xFF, 0x00));
+ }
+ BitmapEx aBitmapEx(aBitmap);
+ BitmapDisabledImageFilter aDisabledImageFilter;
+ BitmapEx aDisabledBitmapEx(aDisabledImageFilter.execute(aBitmapEx));
+ Bitmap aDisabledBitmap(aDisabledBitmapEx.GetBitmap());
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aDisabledBitmap);
+ Color aColor(pReadAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x00C5C5C5), aColor);
+ }
+ }
+
+ {
+ Bitmap aBitmap(Size(3, 3), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(Color(ColorTransparency, 0x00, 0x00, 0xFF, 0x00));
+ }
+ AlphaMask aMask(Size(3, 3));
+ {
+ AlphaScopedWriteAccess pWriteAccess(aMask);
+ pWriteAccess->Erase(Color(ColorTransparency, 0x00, 0xAA, 0xAA, 0xAA));
+ }
+
+ BitmapEx aBitmapEx(aBitmap, aMask);
+ BitmapDisabledImageFilter aDisabledImageFilter;
+ BitmapEx aDisabledBitmapEx(aDisabledImageFilter.execute(aBitmapEx));
+
+ Bitmap aDisabledBitmap(aDisabledBitmapEx.GetBitmap());
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aDisabledBitmap);
+ Color aColor(pReadAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x00C5C5C5), aColor);
+ }
+ AlphaMask aDisabledAlphaMask(aDisabledBitmapEx.GetAlpha());
+ {
+ AlphaMask::ScopedReadAccess pReadAccess(aDisabledAlphaMask);
+ Color aColor(pReadAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x0000AA), aColor);
+ }
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BitmapProcessorTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/BitmapScaleTest.cxx b/vcl/qa/cppunit/BitmapScaleTest.cxx
new file mode 100644
index 000000000..ce8f67437
--- /dev/null
+++ b/vcl/qa/cppunit/BitmapScaleTest.cxx
@@ -0,0 +1,312 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <vcl/bitmap.hxx>
+
+#include <tools/stream.hxx>
+#include <vcl/graphicfilter.hxx>
+
+#include <BitmapSymmetryCheck.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+
+namespace
+{
+class BitmapScaleTest : public CppUnit::TestFixture
+{
+ void testScale();
+ void testScale2();
+ void testScaleSymmetry();
+
+ CPPUNIT_TEST_SUITE(BitmapScaleTest);
+ CPPUNIT_TEST(testScale);
+ CPPUNIT_TEST(testScale2);
+ CPPUNIT_TEST(testScaleSymmetry);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool checkBitmapColor(Bitmap const& rBitmap, Color const& rExpectedColor)
+{
+ bool bResult = true;
+ Bitmap aBitmap(rBitmap);
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ tools::Long nHeight = pReadAccess->Height();
+ tools::Long nWidth = pReadAccess->Width();
+ for (tools::Long y = 0; y < nHeight; ++y)
+ {
+ Scanline pScanlineRead = pReadAccess->GetScanline(y);
+ for (tools::Long x = 0; x < nWidth; ++x)
+ {
+ Color aColor = pReadAccess->GetPixelFromData(pScanlineRead, x);
+ if (aColor != rExpectedColor)
+ bResult = false;
+ }
+ }
+
+ return bResult;
+}
+
+void assertColorsAreSimilar(int maxDifference, int line, const BitmapColor& expected,
+ const BitmapColor& actual)
+{
+ // Check that the two colors match or are reasonably similar.
+ if (expected.GetColorError(actual) <= maxDifference)
+ return;
+
+ std::stringstream stream;
+ stream << "Line: " << line;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(stream.str(), expected, actual);
+}
+
+void BitmapScaleTest::testScale()
+{
+ const bool bExportBitmap(false);
+ using tools::Rectangle;
+
+ static const BmpScaleFlag scaleMethods[]
+ = { BmpScaleFlag::Default, BmpScaleFlag::Fast, BmpScaleFlag::BestQuality,
+ BmpScaleFlag::Interpolate, BmpScaleFlag::Lanczos, BmpScaleFlag::BiCubic,
+ BmpScaleFlag::BiLinear };
+ for (BmpScaleFlag scaleMethod : scaleMethods)
+ {
+ struct ScaleSize
+ {
+ Size srcSize;
+ Size destSize;
+ };
+ static const ScaleSize scaleSizes[]
+ = { // test no-op
+ { Size(16, 16), Size(16, 16) },
+ // powers of 2 (OpenGL may use texture atlas)
+ { Size(16, 16), Size(14, 14) },
+ { Size(14, 14), Size(16, 16) }, // both upscaling and downscaling
+ // "random" sizes
+ { Size(18, 18), Size(14, 14) },
+ { Size(14, 14), Size(18, 18) },
+ // different x/y ratios
+ { Size(16, 30), Size(14, 18) },
+ { Size(14, 18), Size(16, 30) },
+ // ratio larger than 16 (triggers different paths in some OpenGL algorithms)
+ { Size(18 * 20, 18 * 20), Size(14, 14) },
+ { Size(14, 14), Size(18 * 20, 18 * 20) },
+ // Boundary cases.
+ { Size(1, 1), Size(1, 1) },
+ { Size(16, 1), Size(12, 1) },
+ { Size(1, 16), Size(1, 12) }
+ };
+ for (const ScaleSize& scaleSize : scaleSizes)
+ {
+ OString testStr = "Testing scale (" + scaleSize.srcSize.toString() + ")->("
+ + scaleSize.destSize.toString() + "), method "
+ + OString::number(static_cast<int>(scaleMethod));
+ fprintf(stderr, "%s\n", testStr.getStr());
+ Bitmap bitmap(scaleSize.srcSize, vcl::PixelFormat::N24_BPP);
+ {
+ // Fill each quarter of the source bitmap with a different color,
+ // and center with yet another color.
+ BitmapScopedWriteAccess writeAccess(bitmap);
+ const int halfW = scaleSize.srcSize.getWidth() / 2;
+ const int halfH = scaleSize.srcSize.getHeight() / 2;
+ const Size aSize(std::max(halfW, 1), std::max(halfH, 1));
+
+ writeAccess->SetFillColor(COL_GREEN);
+ writeAccess->FillRect(Rectangle(Point(0, 0), aSize));
+ writeAccess->SetFillColor(COL_RED);
+ writeAccess->FillRect(Rectangle(Point(0, halfH), aSize));
+ writeAccess->SetFillColor(COL_YELLOW);
+ writeAccess->FillRect(Rectangle(Point(halfW, 0), aSize));
+ writeAccess->SetFillColor(COL_BLACK);
+ writeAccess->FillRect(Rectangle(Point(halfW, halfH), aSize));
+ writeAccess->SetFillColor(COL_BLUE);
+ writeAccess->FillRect(Rectangle(Point(halfW / 2, halfH / 2), aSize));
+ }
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("~/scale_before.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(bitmap), aStream);
+ }
+ CPPUNIT_ASSERT(bitmap.Scale(scaleSize.destSize, scaleMethod));
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("~/scale_after.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(bitmap), aStream);
+ }
+ CPPUNIT_ASSERT_EQUAL(scaleSize.destSize, bitmap.GetSizePixel());
+ const int lastW = scaleSize.destSize.getWidth() - 1;
+ const int lastH = scaleSize.destSize.getHeight() - 1;
+ if (scaleSize.srcSize.getWidth() == 1 && scaleSize.srcSize.getHeight() == 1)
+ {
+ BitmapReadAccess readAccess(bitmap);
+ assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(0, 0));
+ assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(lastH, 0));
+ assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(0, lastW));
+ assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(lastH, lastW));
+ assertColorsAreSimilar(2, __LINE__, COL_BLUE,
+ readAccess.GetColor(lastH / 2, lastW / 2));
+ }
+ else if (lastW && lastH)
+ {
+ // Scaling should keep each quarter of the resulting bitmap have the same color,
+ // so check that color in each corner of the result bitmap is the same color,
+ // or reasonably close (some algorithms may alter the color very slightly).
+ BitmapReadAccess readAccess(bitmap);
+ assertColorsAreSimilar(2, __LINE__, COL_GREEN, readAccess.GetColor(0, 0));
+ assertColorsAreSimilar(2, __LINE__, COL_RED, readAccess.GetColor(lastH, 0));
+ assertColorsAreSimilar(2, __LINE__, COL_YELLOW, readAccess.GetColor(0, lastW));
+ assertColorsAreSimilar(2, __LINE__, COL_BLACK, readAccess.GetColor(lastH, lastW));
+ assertColorsAreSimilar(2, __LINE__, COL_BLUE,
+ readAccess.GetColor(lastH / 2, lastW / 2));
+ }
+ else if (lastW)
+ {
+ BitmapReadAccess readAccess(bitmap);
+ assertColorsAreSimilar(2, __LINE__, COL_RED, readAccess.GetColor(0, 0));
+ assertColorsAreSimilar(2, __LINE__, COL_BLACK, readAccess.GetColor(0, lastW));
+ assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(0, lastW / 2));
+ }
+ else if (lastH)
+ {
+ BitmapReadAccess readAccess(bitmap);
+ assertColorsAreSimilar(2, __LINE__, COL_YELLOW, readAccess.GetColor(0, 0));
+ assertColorsAreSimilar(2, __LINE__, COL_BLACK, readAccess.GetColor(lastH, 0));
+ assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(lastH / 2, 0));
+ }
+ }
+ }
+}
+
+void BitmapScaleTest::testScale2()
+{
+ const bool bExportBitmap(false);
+
+ Bitmap aBitmap24Bit(Size(4096, 4096), vcl::PixelFormat::N24_BPP);
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap24Bit.getPixelFormat());
+ Color aBitmapColor = COL_YELLOW;
+ {
+ BitmapScopedWriteAccess aWriteAccess(aBitmap24Bit);
+ aWriteAccess->Erase(aBitmapColor);
+ }
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("scale_before.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(aBitmap24Bit), aStream);
+ }
+
+ // Scale - 65x65
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Height());
+ Bitmap aScaledBitmap = aBitmap24Bit;
+ aScaledBitmap.Scale(Size(65, 65));
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("scale_after_65x65.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(aScaledBitmap), aStream);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(65), aScaledBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(65), aScaledBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
+
+ // Scale - 64x64
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Height());
+ aScaledBitmap = aBitmap24Bit;
+ aScaledBitmap.Scale(Size(64, 64));
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("scale_after_64x64.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(aScaledBitmap), aStream);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(64), aScaledBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(64), aScaledBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
+
+ // Scale - 63x63
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Height());
+ aScaledBitmap = aBitmap24Bit;
+ aScaledBitmap.Scale(Size(63, 63));
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("scale_after_63x63.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(aScaledBitmap), aStream);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(63), aScaledBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(63), aScaledBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
+}
+
+void BitmapScaleTest::testScaleSymmetry()
+{
+ const bool bExportBitmap(false);
+
+ Bitmap aBitmap24Bit(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap24Bit.getPixelFormat());
+
+ {
+ BitmapScopedWriteAccess aWriteAccess(aBitmap24Bit);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(COL_BLACK);
+ aWriteAccess->DrawRect(tools::Rectangle(1, 1, 8, 8));
+ aWriteAccess->DrawRect(tools::Rectangle(3, 3, 6, 6));
+ }
+
+ BitmapSymmetryCheck aBitmapSymmetryCheck;
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(10), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(10), aBitmap24Bit.GetSizePixel().Height());
+
+ // Check symmetry of the bitmap
+ CPPUNIT_ASSERT(BitmapSymmetryCheck::check(aBitmap24Bit));
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("~/scale_before.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(aBitmap24Bit), aStream);
+ }
+
+ aBitmap24Bit.Scale(2, 2, BmpScaleFlag::Fast);
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(20), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(20), aBitmap24Bit.GetSizePixel().Height());
+
+ // After scaling the bitmap should still be symmetrical. This check guarantees that
+ // scaling doesn't misalign the bitmap.
+ CPPUNIT_ASSERT(BitmapSymmetryCheck::check(aBitmap24Bit));
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("~/scale_after.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(aBitmap24Bit), aStream);
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BitmapScaleTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/BitmapTest.cxx b/vcl/qa/cppunit/BitmapTest.cxx
new file mode 100644
index 000000000..79f779f2a
--- /dev/null
+++ b/vcl/qa/cppunit/BitmapTest.cxx
@@ -0,0 +1,739 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <config_features.h>
+
+#include <rtl/strbuf.hxx>
+
+#include <vcl/BitmapTools.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/skia/SkiaHelper.hxx>
+#include <vcl/BitmapMonochromeFilter.hxx>
+
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <bitmap/Octree.hxx>
+#include <salinst.hxx>
+#include <svdata.hxx>
+
+#include <unordered_map>
+
+namespace
+{
+class BitmapTest : public CppUnit::TestFixture
+{
+ void testCreation();
+ void testEmpty();
+ void testMonochrome();
+ void testN8Greyscale();
+ void testConvert();
+ void testCRC();
+ void testGreyPalette();
+ void testCustom8BitPalette();
+ void testErase();
+ void testBitmap32();
+ void testOctree();
+ void testEmptyAccess();
+ void testDitherSize();
+ void testMirror();
+ void testCrop();
+ void testCroppedDownsampledBitmap();
+
+ CPPUNIT_TEST_SUITE(BitmapTest);
+ CPPUNIT_TEST(testCreation);
+ CPPUNIT_TEST(testEmpty);
+ CPPUNIT_TEST(testMonochrome);
+ CPPUNIT_TEST(testConvert);
+ CPPUNIT_TEST(testN8Greyscale);
+ CPPUNIT_TEST(testCRC);
+ CPPUNIT_TEST(testGreyPalette);
+ CPPUNIT_TEST(testCustom8BitPalette);
+ CPPUNIT_TEST(testErase);
+ CPPUNIT_TEST(testBitmap32);
+ CPPUNIT_TEST(testOctree);
+ CPPUNIT_TEST(testEmptyAccess);
+ CPPUNIT_TEST(testDitherSize);
+ CPPUNIT_TEST(testMirror);
+ CPPUNIT_TEST(testCrop);
+ CPPUNIT_TEST(testCroppedDownsampledBitmap);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void assertColorsAreSimilar(int maxDifference, const std::string& message,
+ const BitmapColor& expected, const BitmapColor& actual)
+{
+ // Check that the two colors match or are reasonably similar.
+ if (expected.GetColorError(actual) <= maxDifference)
+ return;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual);
+}
+
+void BitmapTest::testCreation()
+{
+ {
+ Bitmap aBmp;
+ Size aSize = aBmp.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(0), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(0), aSize.Height());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
+ CPPUNIT_ASSERT_MESSAGE("Not empty", aBmp.IsEmpty());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::INVALID,
+ aBmp.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_Int64>(0),
+ aBmp.GetSizeBytes());
+ }
+
+ {
+ Bitmap aBmp(Size(10, 10), vcl::PixelFormat::N1_BPP);
+ Size aSize = aBmp.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
+ CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::N1_BPP,
+ aBmp.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_Int64>(12),
+ aBmp.GetSizeBytes());
+ }
+
+ {
+ Bitmap aBmp(Size(10, 10), vcl::PixelFormat::N8_BPP);
+ Size aSize = aBmp.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
+ CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::N8_BPP,
+ aBmp.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_Int64>(100),
+ aBmp.GetSizeBytes());
+ }
+
+ {
+ Bitmap aBmp(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ Size aSize = aBmp.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
+ CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::N24_BPP,
+ aBmp.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_Int64>(300),
+ aBmp.GetSizeBytes());
+ }
+
+ // Check backend capabilities and return from the test successfully
+ // if the backend doesn't support 32-bit bitmap
+ if (ImplGetSVData()->mpDefInst->supportsBitmap32())
+ {
+ Bitmap aBmp(Size(10, 10), vcl::PixelFormat::N32_BPP);
+ Size aSize = aBmp.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
+ CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::N32_BPP,
+ aBmp.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", sal_Int64(400), aBmp.GetSizeBytes());
+ }
+}
+
+void BitmapTest::testEmpty()
+{
+ Bitmap aBitmap(Size(10, 10), vcl::PixelFormat::N8_BPP);
+ aBitmap.Erase(COL_LIGHTGRAYBLUE);
+
+ CPPUNIT_ASSERT(!aBitmap.IsEmpty());
+
+ aBitmap.SetEmpty();
+ CPPUNIT_ASSERT(aBitmap.IsEmpty());
+}
+
+Bitmap createTestBitmap()
+{
+ Bitmap aBmp(Size(4, 4), vcl::PixelFormat::N24_BPP);
+ BitmapWriteAccess aBmpAccess(aBmp);
+
+ // row 1
+ aBmpAccess.SetPixel(0, 0, BitmapColor(COL_BLACK));
+ aBmpAccess.SetPixel(0, 1, BitmapColor(COL_BLUE));
+ aBmpAccess.SetPixel(0, 2, BitmapColor(COL_GREEN));
+ aBmpAccess.SetPixel(0, 3, BitmapColor(COL_CYAN));
+
+ // row 2
+ aBmpAccess.SetPixel(1, 0, BitmapColor(COL_RED));
+ aBmpAccess.SetPixel(1, 1, BitmapColor(COL_MAGENTA));
+ aBmpAccess.SetPixel(1, 2, BitmapColor(COL_BROWN));
+ aBmpAccess.SetPixel(1, 3, BitmapColor(COL_GRAY));
+
+ // row 3
+ aBmpAccess.SetPixel(2, 0, BitmapColor(COL_LIGHTGRAY));
+ aBmpAccess.SetPixel(2, 1, BitmapColor(COL_LIGHTBLUE));
+ aBmpAccess.SetPixel(2, 2, BitmapColor(COL_LIGHTGREEN));
+ aBmpAccess.SetPixel(2, 3, BitmapColor(COL_LIGHTCYAN));
+
+ // row 4
+ aBmpAccess.SetPixel(3, 0, BitmapColor(COL_LIGHTRED));
+ aBmpAccess.SetPixel(3, 1, BitmapColor(COL_LIGHTMAGENTA));
+ aBmpAccess.SetPixel(3, 2, BitmapColor(COL_YELLOW));
+ aBmpAccess.SetPixel(3, 3, BitmapColor(COL_WHITE));
+
+ return aBmp;
+}
+
+void BitmapTest::testMonochrome()
+{
+ Bitmap aBmp = createTestBitmap();
+
+ BitmapEx aBmpEx(aBmp);
+ BitmapFilter::Filter(aBmpEx, BitmapMonochromeFilter(63));
+ aBmp = aBmpEx.GetBitmap();
+ BitmapReadAccess aBmpReadAccess(aBmp);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Black pixel wrong monochrome value", BitmapColor(COL_BLACK),
+ aBmpReadAccess.GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue pixel wrong monochrome value", BitmapColor(COL_BLACK),
+ aBmpReadAccess.GetColor(0, 1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Cyan pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(0, 3));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red pixel wrong monochrome value", BitmapColor(COL_BLACK),
+ aBmpReadAccess.GetColor(1, 0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Magenta pixel wrong monochrome value", BitmapColor(COL_BLACK),
+ aBmpReadAccess.GetColor(1, 1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Brown pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(1, 2));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Gray pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(1, 3));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Light gray pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Light blue pixel wrong monochrome value", BitmapColor(COL_BLACK),
+ aBmpReadAccess.GetColor(2, 1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Light green pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(2, 2));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Light cyan pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(2, 3));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Light red pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(3, 0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Light magenta pixel wrong monochrome value",
+ BitmapColor(COL_WHITE), aBmpReadAccess.GetColor(3, 1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Yellow pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(3, 2));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("White pixel wrong monochrome value", BitmapColor(COL_WHITE),
+ aBmpReadAccess.GetColor(3, 3));
+}
+
+void BitmapTest::testN8Greyscale()
+{
+ Bitmap aBmp = createTestBitmap();
+ BitmapPalette aGreyscalePalette = Bitmap::GetGreyPalette(256);
+
+ aBmp.Convert(BmpConversion::N8BitGreys);
+ BitmapReadAccess aBmpReadAccess(aBmp);
+
+ assertColorsAreSimilar(1, "Black pixel wrong 8-bit greyscale value", aGreyscalePalette[0],
+ aBmpReadAccess.GetColor(0, 0));
+ assertColorsAreSimilar(1, "Blue pixel wrong 8-bit greyscale value", aGreyscalePalette[14],
+ aBmpReadAccess.GetColor(0, 1));
+ assertColorsAreSimilar(1, "Green pixel wrong 8-bit greyscale value", aGreyscalePalette[75],
+ aBmpReadAccess.GetColor(0, 2));
+ assertColorsAreSimilar(1, "Cyan pixel wrong 8-bit greyscale value", aGreyscalePalette[89],
+ aBmpReadAccess.GetColor(0, 3));
+ assertColorsAreSimilar(1, "Red pixel wrong 8-bit greyscale value", aGreyscalePalette[38],
+ aBmpReadAccess.GetColor(1, 0));
+ assertColorsAreSimilar(1, "Magenta pixel wrong 8-bit greyscale value", aGreyscalePalette[52],
+ aBmpReadAccess.GetColor(1, 1));
+ assertColorsAreSimilar(1, "Brown pixel wrong 8-bit greyscale value", aGreyscalePalette[114],
+ aBmpReadAccess.GetColor(1, 2));
+ assertColorsAreSimilar(1, "Gray pixel wrong 8-bit greyscale value", aGreyscalePalette[128],
+ aBmpReadAccess.GetColor(1, 3));
+ assertColorsAreSimilar(1, "Light gray pixel wrong 8-bit greyscale value",
+ aGreyscalePalette[192], aBmpReadAccess.GetColor(2, 0));
+ assertColorsAreSimilar(1, "Light blue pixel wrong 8-bit greyscale value", aGreyscalePalette[27],
+ aBmpReadAccess.GetColor(2, 1));
+ assertColorsAreSimilar(1, "Light green pixel wrong 8-bit greyscale value",
+ aGreyscalePalette[150], aBmpReadAccess.GetColor(2, 2));
+ assertColorsAreSimilar(1, "Light cyan pixel wrong 8-bit greyscale value",
+ aGreyscalePalette[178], aBmpReadAccess.GetColor(2, 3));
+ assertColorsAreSimilar(1, "Light red pixel wrong 8-bit greyscale value", aGreyscalePalette[76],
+ aBmpReadAccess.GetColor(3, 0));
+ assertColorsAreSimilar(1, "Light magenta pixel wrong 8-bit greyscale value",
+ aGreyscalePalette[104], aBmpReadAccess.GetColor(3, 1));
+ assertColorsAreSimilar(1, "Yellow pixel wrong 8-bit greyscale value", aGreyscalePalette[227],
+ aBmpReadAccess.GetColor(3, 2));
+ assertColorsAreSimilar(1, "White pixel wrong 8-bit greyscale value", aGreyscalePalette[255],
+ aBmpReadAccess.GetColor(3, 3));
+}
+
+void BitmapTest::testConvert()
+{
+ Bitmap aBitmap(Size(10, 10), vcl::PixelFormat::N8_BPP);
+
+ aBitmap.Erase(COL_LIGHTGRAYBLUE);
+
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(8), pReadAccess->GetBitCount());
+#if defined MACOSX || defined IOS
+ if (SkiaHelper::isVCLSkiaEnabled())
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(12), pReadAccess->GetScanlineSize());
+ else
+ //it would be nice to find and change the stride for quartz to be the same as everyone else
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(10), pReadAccess->GetScanlineSize());
+#else
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(12), pReadAccess->GetScanlineSize());
+#endif
+ CPPUNIT_ASSERT(pReadAccess->HasPalette());
+ const BitmapColor& rColor = pReadAccess->GetPaletteColor(pReadAccess->GetPixelIndex(1, 1));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor.GetRed()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor.GetGreen()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(rColor.GetBlue()));
+ }
+
+ aBitmap.Convert(BmpConversion::N24Bit);
+
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap.getPixelFormat());
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ // 24 bit Bitmap on SVP backend can now use 24bit RGB everywhere.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(24), pReadAccess->GetBitCount());
+
+ if (SkiaHelper::isVCLSkiaEnabled()) // aligned to 4 bytes
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
+ else
+#if defined LINUX || defined FREEBSD
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
+ }
+#elif defined(_WIN32)
+ {
+ // GDI Scanlines padded to DWORD multiples, it seems
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
+ }
+#else
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(30), pReadAccess->GetScanlineSize());
+ }
+#endif
+
+ CPPUNIT_ASSERT(!pReadAccess->HasPalette());
+ Color aColor = pReadAccess->GetPixel(0, 0);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor.GetRed()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor.GetGreen()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(aColor.GetBlue()));
+ }
+}
+
+typedef std::unordered_map<sal_uInt64, const char*> CRCHash;
+
+void checkAndInsert(CRCHash& rHash, sal_uInt64 nCRC, const char* pLocation)
+{
+ auto it = rHash.find(nCRC);
+ if (it != rHash.end())
+ {
+ OStringBuffer aBuf("CRC collision between ");
+ aBuf.append(pLocation);
+ aBuf.append(" and ");
+ aBuf.append(it->second);
+ aBuf.append(" hash is 0x");
+ aBuf.append(static_cast<sal_Int64>(nCRC), 16);
+ CPPUNIT_FAIL(aBuf.toString().getStr());
+ }
+ rHash[nCRC] = pLocation;
+}
+
+void checkAndInsert(CRCHash& rHash, Bitmap const& rBmp, const char* pLocation)
+{
+ checkAndInsert(rHash, rBmp.GetChecksum(), pLocation);
+}
+
+Bitmap getAsBitmap(VclPtr<OutputDevice> const& pOut)
+{
+ return pOut->GetBitmap(Point(), pOut->GetOutputSizePixel());
+}
+
+void BitmapTest::testCRC()
+{
+ CRCHash aCRCs;
+
+ Bitmap aBitmap(Size(1023, 759), vcl::PixelFormat::N24_BPP);
+ aBitmap.Erase(COL_BLACK);
+ checkAndInsert(aCRCs, aBitmap, "black bitmap");
+ aBitmap.Invert();
+ checkAndInsert(aCRCs, aBitmap, "white bitmap");
+
+ ScopedVclPtrInstance<VirtualDevice> aVDev;
+ aVDev->SetBackground(Wallpaper(COL_WHITE));
+ aVDev->SetOutputSizePixel(Size(1023, 759));
+
+#if 0 // disabled for now - oddly breaks on OS/X - but why ?
+ Bitmap aWhiteCheck = getAsBitmap(aVDev);
+ CPPUNIT_ASSERT(aCRCs.find(aWhiteCheck.GetChecksum()) != aCRCs.end());
+#endif
+
+ // a 1x1 black & white checkerboard
+ aVDev->DrawCheckered(Point(), aVDev->GetOutputSizePixel(), 1, Color(0, 0, 1));
+ Bitmap aChecker = getAsBitmap(aVDev);
+ checkAndInsert(aCRCs, aChecker, "checkerboard");
+ aChecker.Invert();
+ checkAndInsert(aCRCs, aChecker, "inverted checkerboard");
+}
+
+void BitmapTest::testGreyPalette()
+{
+ {
+ BitmapPalette aPalette = Bitmap::GetGreyPalette(2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(2),
+ aPalette.GetEntryCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(255, 255, 255), aPalette[1]);
+ }
+
+ {
+ BitmapPalette aPalette = Bitmap::GetGreyPalette(4);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(4),
+ aPalette.GetEntryCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(85, 85, 85), aPalette[1]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 3 wrong", BitmapColor(170, 170, 170), aPalette[2]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 4 wrong", BitmapColor(255, 255, 255), aPalette[3]);
+ }
+
+ {
+ BitmapPalette aPalette = Bitmap::GetGreyPalette(16);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(16),
+ aPalette.GetEntryCount());
+ // this is a *real* specific number of greys, incremented in units of 17 so may
+ // as well test them all...
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(17, 17, 17), aPalette[1]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 3 wrong", BitmapColor(34, 34, 34), aPalette[2]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 4 wrong", BitmapColor(51, 51, 51), aPalette[3]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 5 wrong", BitmapColor(68, 68, 68), aPalette[4]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 6 wrong", BitmapColor(85, 85, 85), aPalette[5]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 7 wrong", BitmapColor(102, 102, 102), aPalette[6]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 8 wrong", BitmapColor(119, 119, 119), aPalette[7]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 9 wrong", BitmapColor(136, 136, 136), aPalette[8]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 10 wrong", BitmapColor(153, 153, 153), aPalette[9]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 11 wrong", BitmapColor(170, 170, 170), aPalette[10]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 12 wrong", BitmapColor(187, 187, 187), aPalette[11]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 13 wrong", BitmapColor(204, 204, 204), aPalette[12]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 14 wrong", BitmapColor(221, 221, 221), aPalette[13]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 15 wrong", BitmapColor(238, 238, 238), aPalette[14]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 16 wrong", BitmapColor(255, 255, 255), aPalette[15]);
+ }
+
+ {
+ BitmapPalette aPalette = Bitmap::GetGreyPalette(256);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries",
+ static_cast<sal_uInt16>(256), aPalette.GetEntryCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 127 wrong", BitmapColor(127, 127, 127), aPalette[127]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 255 wrong", BitmapColor(255, 255, 255), aPalette[255]);
+ }
+}
+
+void BitmapTest::testCustom8BitPalette()
+{
+ BitmapPalette aCustomPalette;
+ aCustomPalette.SetEntryCount(256);
+ for (sal_uInt16 i = 0; i < 256; i++)
+ {
+ aCustomPalette[i] = BitmapColor(sal_uInt8(i), sal_uInt8(0xCC), sal_uInt8(0x22));
+ }
+ Bitmap aBitmap(Size(3, 2), vcl::PixelFormat::N8_BPP, &aCustomPalette);
+
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->SetPixelIndex(0, 0, 0);
+ pAccess->SetPixelIndex(0, 1, 1);
+ pAccess->SetPixelIndex(0, 2, 2);
+
+ pAccess->SetPixelIndex(1, 0, 253);
+ pAccess->SetPixelIndex(1, 1, 254);
+ pAccess->SetPixelIndex(1, 2, 255);
+ }
+
+ {
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ CPPUNIT_ASSERT_EQUAL(0, int(pAccess->GetPixelIndex(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xCC, 0x22), pAccess->GetColor(0, 0));
+
+ CPPUNIT_ASSERT_EQUAL(1, int(pAccess->GetPixelIndex(0, 1)));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0x01, 0xCC, 0x22), pAccess->GetColor(0, 1));
+
+ CPPUNIT_ASSERT_EQUAL(2, int(pAccess->GetPixelIndex(0, 2)));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0x02, 0xCC, 0x22), pAccess->GetColor(0, 2));
+
+ CPPUNIT_ASSERT_EQUAL(253, int(pAccess->GetPixelIndex(1, 0)));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFD, 0xCC, 0x22), pAccess->GetColor(1, 0));
+
+ CPPUNIT_ASSERT_EQUAL(254, int(pAccess->GetPixelIndex(1, 1)));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFE, 0xCC, 0x22), pAccess->GetColor(1, 1));
+
+ CPPUNIT_ASSERT_EQUAL(255, int(pAccess->GetPixelIndex(1, 2)));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xCC, 0x22), pAccess->GetColor(1, 2));
+ }
+}
+
+void BitmapTest::testErase()
+{
+ Bitmap aBitmap(Size(3, 3), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(Color(0x11, 0x22, 0x33));
+ }
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ BitmapColor aColor(pReadAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x11, 0x22, 0x33, 0x00), aColor);
+ }
+}
+
+void BitmapTest::testBitmap32()
+{
+ // Check backend capabilities and return from the test successfully
+ // if the backend doesn't support 32-bit bitmap
+ if (!ImplGetSVData()->mpDefInst->supportsBitmap32())
+ return;
+
+ Bitmap aBitmap(Size(3, 3), vcl::PixelFormat::N32_BPP);
+ {
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(Color(ColorTransparency, 0xFF, 0x11, 0x22, 0x33));
+ pWriteAccess->SetPixel(1, 1, BitmapColor(ColorTransparency, 0x44, 0xFF, 0xBB, 0x00));
+ pWriteAccess->SetPixel(2, 2, BitmapColor(ColorTransparency, 0x99, 0x77, 0x66, 0x55));
+ }
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ BitmapColor aColor = pReadAccess->GetPixel(0, 0);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x00, 0xFF), aColor);
+
+ aColor = pReadAccess->GetPixel(1, 1);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x44, 0xFF, 0xBB, 0x00), aColor);
+
+ aColor = pReadAccess->GetPixel(2, 2);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x99, 0x77, 0x66, 0x55), aColor);
+ }
+}
+
+void BitmapTest::testOctree()
+{
+ Size aSize(1000, 100);
+ Bitmap aBitmap(aSize, vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ for (tools::Long y = 0; y < aSize.Height(); ++y)
+ {
+ for (tools::Long x = 0; x < aSize.Width(); ++x)
+ {
+ double fPercent = double(x) / double(aSize.Width());
+ pWriteAccess->SetPixel(y, x,
+ BitmapColor(255.0 * fPercent, 64.0 + (128.0 * fPercent),
+ 255.0 - 255.0 * fPercent));
+ }
+ }
+ }
+
+ {
+ // Reduce to 1 color
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ Octree aOctree(*pAccess, 1);
+ auto aBitmapPalette = aOctree.GetPalette();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), aBitmapPalette.GetEntryCount());
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7e, 0x7f, 0x7f), aBitmapPalette[0]);
+ }
+
+ {
+ // Reduce to 4 color
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ Octree aOctree(*pAccess, 4);
+ auto aBitmapPalette = aOctree.GetPalette();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), aBitmapPalette.GetEntryCount());
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x7f, 0x7f), aBitmapPalette[0]);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0x3e, 0x5f, 0xbf), aBitmapPalette[1]);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x80, 0x7f), aBitmapPalette[2]);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(0xbe, 0x9f, 0x3f), aBitmapPalette[3]);
+ }
+
+ {
+ // Reduce to 256 color
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ Octree aOctree(*pAccess, 256);
+ auto aBitmapPalette = aOctree.GetPalette();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(74), aBitmapPalette.GetEntryCount());
+ }
+}
+
+void BitmapTest::testEmptyAccess()
+{
+ Bitmap empty;
+ BitmapInfoAccess access(empty);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), access.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), access.Height());
+}
+
+void BitmapTest::testDitherSize()
+{
+ // no need to do anything for a 1x1 pixel bitmap
+ {
+ Bitmap aBitmap(Size(1, 1), vcl::PixelFormat::N24_BPP);
+ CPPUNIT_ASSERT(aBitmap.Dither());
+ }
+
+ // cannot dither a bitmap with a width of 2 or 3 pixels
+ {
+ Bitmap aBitmap(Size(2, 4), vcl::PixelFormat::N24_BPP);
+ CPPUNIT_ASSERT(!aBitmap.Dither());
+ }
+
+ {
+ Bitmap aBitmap(Size(3, 4), vcl::PixelFormat::N24_BPP);
+ CPPUNIT_ASSERT(!aBitmap.Dither());
+ }
+
+ // cannot dither a bitmap with a height of 2 pixels
+ {
+ Bitmap aBitmap(Size(4, 2), vcl::PixelFormat::N24_BPP);
+ CPPUNIT_ASSERT(!aBitmap.Dither());
+ }
+
+ // only dither bitmaps with a width > 3 pixels and height > 2 pixels
+ {
+ Bitmap aBitmap(Size(4, 3), vcl::PixelFormat::N24_BPP);
+ CPPUNIT_ASSERT(aBitmap.Dither());
+ }
+}
+
+void BitmapTest::testMirror()
+{
+ vcl::PixelFormat bppArray[]
+ = { vcl::PixelFormat::N8_BPP, vcl::PixelFormat::N24_BPP, vcl::PixelFormat::N32_BPP };
+
+ for (vcl::PixelFormat bpp : bppArray)
+ {
+ Bitmap bitmap(Size(11, 11), bpp);
+ {
+ bitmap.Erase(COL_MAGENTA);
+ BitmapWriteAccess write(bitmap);
+ if (write.HasPalette())
+ {
+ // Note that SetPixel() and GetColor() take arguments as Y,X.
+ write.SetPixel(0, 0, BitmapColor(write.GetBestPaletteIndex(COL_BLACK)));
+ write.SetPixel(10, 0, BitmapColor(write.GetBestPaletteIndex(COL_WHITE)));
+ write.SetPixel(0, 10, BitmapColor(write.GetBestPaletteIndex(COL_RED)));
+ write.SetPixel(10, 10, BitmapColor(write.GetBestPaletteIndex(COL_BLUE)));
+ write.SetPixel(5, 0, BitmapColor(write.GetBestPaletteIndex(COL_GREEN)));
+ write.SetPixel(0, 5, BitmapColor(write.GetBestPaletteIndex(COL_YELLOW)));
+ }
+ else
+ {
+ write.SetPixel(0, 0, COL_BLACK);
+ write.SetPixel(10, 0, COL_WHITE);
+ write.SetPixel(0, 10, COL_RED);
+ write.SetPixel(10, 10, COL_BLUE);
+ write.SetPixel(5, 0, COL_GREEN);
+ write.SetPixel(0, 5, COL_YELLOW);
+ }
+ }
+ bitmap.Mirror(BmpMirrorFlags::Horizontal);
+ {
+ BitmapReadAccess read(bitmap);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK), read.GetColor(0, 10));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), read.GetColor(10, 10));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), read.GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLUE), read.GetColor(10, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_GREEN), read.GetColor(5, 10));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_YELLOW), read.GetColor(0, 5));
+ }
+ bitmap.Mirror(BmpMirrorFlags::Vertical);
+ {
+ BitmapReadAccess read(bitmap);
+ // Now is effectively mirrored in both directions.
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK), read.GetColor(10, 10));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), read.GetColor(0, 10));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), read.GetColor(10, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLUE), read.GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_GREEN), read.GetColor(5, 10));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_YELLOW), read.GetColor(10, 5));
+ }
+ bitmap.Mirror(BmpMirrorFlags::Vertical | BmpMirrorFlags::Horizontal);
+ {
+ BitmapReadAccess read(bitmap);
+ // Now is back the original.
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK), read.GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), read.GetColor(10, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), read.GetColor(0, 10));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLUE), read.GetColor(10, 10));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_GREEN), read.GetColor(5, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_YELLOW), read.GetColor(0, 5));
+ }
+ }
+}
+
+void BitmapTest::testCroppedDownsampledBitmap()
+{
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+ Bitmap aDownsampledBmp(vcl::bitmap::GetDownsampledBitmap(Size(10, 10), Point(20, 20),
+ Size(5, 5), aBitmap, 72, 72));
+ CPPUNIT_ASSERT(aDownsampledBmp.IsEmpty());
+}
+
+void BitmapTest::testCrop()
+{
+ Bitmap aBitmap(Bitmap(Size(16, 16), vcl::PixelFormat::N24_BPP));
+
+ {
+ Bitmap aCroppedBmp(aBitmap);
+ CPPUNIT_ASSERT_MESSAGE("Crop was fully outside of bitmap bounds",
+ !aCroppedBmp.Crop(tools::Rectangle(Point(20, 20), Size(5, 5))));
+ CPPUNIT_ASSERT_EQUAL(Size(16, 16), aCroppedBmp.GetSizePixel());
+ }
+
+ {
+ Bitmap aCroppedBmp(aBitmap);
+ CPPUNIT_ASSERT_MESSAGE("Crop same size as bitmap",
+ !aCroppedBmp.Crop(tools::Rectangle(Point(0, 0), Size(16, 16))));
+ CPPUNIT_ASSERT_EQUAL(Size(16, 16), aCroppedBmp.GetSizePixel());
+ }
+
+ {
+ Bitmap aCroppedBmp(aBitmap);
+ CPPUNIT_ASSERT_MESSAGE("Crop larger than bitmap",
+ !aCroppedBmp.Crop(tools::Rectangle(Point(0, 0), Size(100, 100))));
+ CPPUNIT_ASSERT_EQUAL(Size(16, 16), aCroppedBmp.GetSizePixel());
+ }
+
+ {
+ Bitmap aCroppedBmp(aBitmap);
+ CPPUNIT_ASSERT_MESSAGE("Crop partially overcrops bitmap",
+ aCroppedBmp.Crop(tools::Rectangle(Point(10, 10), Size(100, 100))));
+ CPPUNIT_ASSERT_EQUAL(Size(6, 6), aCroppedBmp.GetSizePixel());
+ }
+
+ {
+ Bitmap aCroppedBmp(aBitmap);
+ CPPUNIT_ASSERT_MESSAGE("Crop inside bitmap",
+ aCroppedBmp.Crop(tools::Rectangle(Point(5, 5), Size(10, 10))));
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), aCroppedBmp.GetSizePixel());
+ }
+}
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BitmapTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/BmpFilterTest.cxx b/vcl/qa/cppunit/BmpFilterTest.cxx
new file mode 100644
index 000000000..1ab7bc2a0
--- /dev/null
+++ b/vcl/qa/cppunit/BmpFilterTest.cxx
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/bitmapex.hxx>
+#include <tools/stream.hxx>
+#include <filter/BmpReader.hxx>
+#include <unotools/tempfile.hxx>
+
+class BmpFilterTest : public test::BootstrapFixture
+{
+public:
+ OUString maDataUrl;
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(maDataUrl) + sFileName;
+ }
+ BmpFilterTest()
+ : maDataUrl(u"/vcl/qa/cppunit/data/")
+ {
+ }
+};
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_RGB_888)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_R8G8B8.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(9, 9));
+ CPPUNIT_ASSERT_EQUAL(Color(0x72, 0xd1, 0xc8), aBitmap.GetPixelColor(1, 1));
+ CPPUNIT_ASSERT_EQUAL(Color(0x72, 0xd1, 0xc8), aBitmap.GetPixelColor(8, 8));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_RGB_565)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_R5G6B5.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap.getPixelFormat());
+
+ // White is not completely white
+ //CPPUNIT_ASSERT_EQUAL(Color(0xf8, 0xfc, 0xf8), aBitmap.GetPixelColor(0, 0));
+ //CPPUNIT_ASSERT_EQUAL(Color(0xf8, 0xfc, 0xf8), aBitmap.GetPixelColor(9, 9));
+
+ //CPPUNIT_ASSERT_EQUAL(Color(0x70, 0xd0, 0xc0), aBitmap.GetPixelColor(1, 1));
+ //CPPUNIT_ASSERT_EQUAL(Color(0x70, 0xd0, 0xc0), aBitmap.GetPixelColor(8, 8));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_32_ARGB_8888)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_A8R8G8B8.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+
+ //CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ //CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ //CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ //CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_Paint_24_RGB_888)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_Paint_24bit.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap.getPixelFormat());
+
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_Index_1BPP)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_Paint_1bit.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N1_BPP, aBitmap.getPixelFormat());
+
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_Index_4BPP)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_Paint_4bit.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_Index_8BPP)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_Paint_8bit.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_Index_8BPP_RLE)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_8bit_RLE.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_V4)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_RLE.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_V3)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_RLE_V3.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_V2)
+{
+ SvFileStream aFileStream(getFullUrl(u"BMP_RLE_V2.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testTdf73523)
+{
+ SvFileStream aFileStream(getFullUrl(u"tdf73523.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: c[80000000]
+ // - Actual : c[00000000]
+ // i.e. the pixel is red not black
+ CPPUNIT_ASSERT_EQUAL(COL_RED, aBitmap.GetPixelColor(0, 0));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/FontFeatureTest.cxx b/vcl/qa/cppunit/FontFeatureTest.cxx
new file mode 100644
index 000000000..0e9ada19c
--- /dev/null
+++ b/vcl/qa/cppunit/FontFeatureTest.cxx
@@ -0,0 +1,336 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <config_features.h>
+#include <config_fonts.h>
+#include <cppunit/TestAssert.h>
+
+#include <vcl/font/Feature.hxx>
+#include <vcl/font/FeatureParser.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+
+class FontFeatureTest : public test::BootstrapFixture
+{
+public:
+ FontFeatureTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testGetFontFeatures();
+ void testParseFeature();
+
+ CPPUNIT_TEST_SUITE(FontFeatureTest);
+ CPPUNIT_TEST(testGetFontFeatures);
+ CPPUNIT_TEST(testParseFeature);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void FontFeatureTest::testGetFontFeatures()
+{
+#if HAVE_MORE_FONTS
+ ScopedVclPtrInstance<VirtualDevice> aVDev(*Application::GetDefaultDevice(),
+ DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
+ aVDev->SetOutputSizePixel(Size(10, 10));
+
+ OUString aFontName("Linux Libertine G");
+ CPPUNIT_ASSERT(aVDev->IsFontAvailable(aFontName));
+
+ vcl::Font aFont = aVDev->GetFont();
+ aFont.SetFamilyName(aFontName);
+ aFont.SetWeight(FontWeight::WEIGHT_NORMAL);
+ aFont.SetItalic(FontItalic::ITALIC_NORMAL);
+ aFont.SetWidthType(FontWidth::WIDTH_NORMAL);
+ aVDev->SetFont(aFont);
+
+ std::vector<vcl::font::Feature> rFontFeatures;
+ CPPUNIT_ASSERT(aVDev->GetFontFeatures(rFontFeatures));
+
+ // We're interested only in defaults here
+ std::vector<vcl::font::Feature> rDefaultFontFeatures;
+ OUString aFeaturesString;
+ for (vcl::font::Feature const& rFeature : rFontFeatures)
+ {
+ if (rFeature.m_aID.m_aScriptCode == vcl::font::featureCode("DFLT")
+ && rFeature.m_aID.m_aLanguageCode == vcl::font::featureCode("dflt"))
+ {
+ rDefaultFontFeatures.push_back(rFeature);
+ aFeaturesString += vcl::font::featureCodeAsString(rFeature.m_aID.m_aFeatureCode) + " ";
+ }
+ }
+
+ CPPUNIT_ASSERT_EQUAL(size_t(53), rDefaultFontFeatures.size());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("c2sc case dlig fina frac hlig liga lnum "
+ "locl onum pnum sa01 sa02 sa03 sa04 sa05 "
+ "sa06 sa07 sa08 salt sinf smcp ss01 ss02 "
+ "ss03 sups tnum zero ingl cpsp lith litt "
+ "itlc para algn arti circ dash dbls foot "
+ "frsp grkn hang lng minu nfsp name quot "
+ "texm thou vari caps ligc "),
+ aFeaturesString);
+
+ // Check C2SC feature
+ {
+ vcl::font::Feature& rFeature = rDefaultFontFeatures[0];
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("c2sc"), rFeature.m_aID.m_aFeatureCode);
+
+ vcl::font::FeatureDefinition& rFracFeatureDefinition = rFeature.m_aDefinition;
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("c2sc"), rFracFeatureDefinition.getCode());
+ CPPUNIT_ASSERT(!rFracFeatureDefinition.getDescription().isEmpty());
+ CPPUNIT_ASSERT_EQUAL(vcl::font::FeatureParameterType::BOOL,
+ rFracFeatureDefinition.getType());
+
+ CPPUNIT_ASSERT_EQUAL(size_t(0), rFracFeatureDefinition.getEnumParameters().size());
+ }
+
+ // Check FRAC feature
+ {
+ vcl::font::Feature& rFeature = rDefaultFontFeatures[4];
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("frac"), rFeature.m_aID.m_aFeatureCode);
+
+ vcl::font::FeatureDefinition& rFracFeatureDefinition = rFeature.m_aDefinition;
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("frac"), rFracFeatureDefinition.getCode());
+ CPPUNIT_ASSERT(!rFracFeatureDefinition.getDescription().isEmpty());
+ CPPUNIT_ASSERT_EQUAL(vcl::font::FeatureParameterType::ENUM,
+ rFracFeatureDefinition.getType());
+
+ CPPUNIT_ASSERT_EQUAL(size_t(3), rFracFeatureDefinition.getEnumParameters().size());
+
+ vcl::font::FeatureParameter const& rParameter1
+ = rFracFeatureDefinition.getEnumParameters()[0];
+ CPPUNIT_ASSERT_EQUAL(uint32_t(0), rParameter1.getCode());
+ CPPUNIT_ASSERT(!rParameter1.getDescription().isEmpty());
+
+ vcl::font::FeatureParameter const& rParameter2
+ = rFracFeatureDefinition.getEnumParameters()[1];
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), rParameter2.getCode());
+ CPPUNIT_ASSERT(!rParameter2.getDescription().isEmpty());
+
+ vcl::font::FeatureParameter const& rParameter3
+ = rFracFeatureDefinition.getEnumParameters()[2];
+ CPPUNIT_ASSERT_EQUAL(uint32_t(2), rParameter3.getCode());
+ CPPUNIT_ASSERT(!rParameter2.getDescription().isEmpty());
+ }
+
+ aVDev.disposeAndClear();
+#endif // HAVE_MORE_FONTS
+}
+
+void FontFeatureTest::testParseFeature()
+{
+ { // No font features specified
+ vcl::font::FeatureParser aParser(u"Font name with no features");
+ CPPUNIT_ASSERT_EQUAL(size_t(0), aParser.getFeatures().size());
+ }
+ { // One feature specified, no value
+ vcl::font::FeatureParser aParser(u"Font name:abcd");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ }
+ { // One feature specified, explicit value
+ vcl::font::FeatureParser aParser(u"Font name:abcd=5");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(5), aFeatures[0].m_nValue);
+ }
+ { // One feature specified, explicit zero value
+ vcl::font::FeatureParser aParser(u"Font name:abcd=0");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+ }
+ { // One feature specified, using plus prefix
+ vcl::font::FeatureParser aParser(u"Font name:+abcd");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ }
+ { // One feature specified, using minus prefix
+ vcl::font::FeatureParser aParser(u"Font name:-abcd");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+ }
+ { // One feature specified, with empty character range
+ vcl::font::FeatureParser aParser(u"Font name:abcd[]");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with empty character range
+ vcl::font::FeatureParser aParser(u"Font name:abcd[:]");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with start character range
+ vcl::font::FeatureParser aParser(u"Font name:abcd[3:]");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with end character range
+ vcl::font::FeatureParser aParser(u"Font name:abcd[:3]");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with character range
+ vcl::font::FeatureParser aParser(u"Font name:abcd[3:6]");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with character range
+ vcl::font::FeatureParser aParser(u"Font name:abcd[3]");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(4), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with character range and value
+ vcl::font::FeatureParser aParser(u"Font name:abcd[3:6]=2");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(2), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with character range and 0 value
+ vcl::font::FeatureParser aParser(u"Font name:abcd[3:6]=0");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with character range and minus prefix
+ vcl::font::FeatureParser aParser(u"Font name:-abcd[3:6]");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures[0].m_nEnd);
+ }
+ { // One feature specified, with CSS on
+ vcl::font::FeatureParser aParser(u"Font name:\"abcd\" on");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+ }
+ { // One feature specified, with CSS off
+ vcl::font::FeatureParser aParser(u"Font name:'abcd' off");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+ }
+ { // One feature specified, with CSS value
+ vcl::font::FeatureParser aParser(u"Font name:\"abcd\" 2");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(2), aFeatures[0].m_nValue);
+ }
+ { // Multiple features specified, no values
+ vcl::font::FeatureParser aParser(u"Font name:abcd&bcde&efgh");
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("bcde"), aFeatures[1].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[1].m_nValue);
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("efgh"), aFeatures[2].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[2].m_nValue);
+ }
+ {
+ // Multiple features specified, explicit values
+ // Only 4 char parameter names supported - "toolong" is too long and ignored
+ vcl::font::FeatureParser aParser(u"Font name:abcd=1&bcde=0&toolong=1&cdef=3");
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("bcde"), aFeatures[1].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[1].m_nValue);
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("cdef"), aFeatures[2].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(3), aFeatures[2].m_nValue);
+ }
+ {
+ // Special case - "lang" is parsed specially and access separately not as a feature.
+
+ vcl::font::FeatureParser aParser(u"Font name:abcd=1&lang=slo");
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+ auto aFeatures = aParser.getFeatures();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+ CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("slo"), aParser.getLanguage());
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FontFeatureTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/GraphicDescriptorTest.cxx b/vcl/qa/cppunit/GraphicDescriptorTest.cxx
new file mode 100644
index 000000000..c86d95ede
--- /dev/null
+++ b/vcl/qa/cppunit/GraphicDescriptorTest.cxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/bootstrapfixturebase.hxx>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+
+using namespace css;
+
+namespace
+{
+class GraphicDescriptorTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/data/") + sFileName;
+ }
+ void testDetectPNG();
+ void testDetectJPG();
+ void testDetectGIF();
+ void testDetectTIF();
+ void testDetectBMP();
+ void testDetectWEBP();
+ void testDetectEMF();
+
+ CPPUNIT_TEST_SUITE(GraphicDescriptorTest);
+ CPPUNIT_TEST(testDetectPNG);
+ CPPUNIT_TEST(testDetectJPG);
+ CPPUNIT_TEST(testDetectGIF);
+ CPPUNIT_TEST(testDetectTIF);
+ CPPUNIT_TEST(testDetectBMP);
+ CPPUNIT_TEST(testDetectWEBP);
+ CPPUNIT_TEST(testDetectEMF);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+BitmapEx createBitmap()
+{
+ Bitmap aBitmap(Size(100, 100), vcl::PixelFormat::N24_BPP);
+ aBitmap.Erase(COL_LIGHTRED);
+
+ return BitmapEx(aBitmap);
+}
+
+void createBitmapAndExportForType(SvStream& rStream, std::u16string_view sType)
+{
+ BitmapEx aBitmapEx = createBitmap();
+
+ uno::Sequence<beans::PropertyValue> aFilterData;
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName(sType);
+ rGraphicFilter.ExportGraphic(aBitmapEx, u"none", rStream, nFilterFormat, &aFilterData);
+
+ rStream.Seek(STREAM_SEEK_TO_BEGIN);
+}
+
+void GraphicDescriptorTest::testDetectPNG()
+{
+ SvMemoryStream aStream;
+ createBitmapAndExportForType(aStream, u"png");
+
+ GraphicDescriptor aDescriptor(aStream, nullptr);
+ aDescriptor.Detect(true);
+
+ CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::PNG, aDescriptor.GetFileFormat());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Height());
+}
+
+void GraphicDescriptorTest::testDetectJPG()
+{
+ SvMemoryStream aStream;
+ createBitmapAndExportForType(aStream, u"jpg");
+
+ GraphicDescriptor aDescriptor(aStream, nullptr);
+ aDescriptor.Detect(true);
+
+ CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::JPG, aDescriptor.GetFileFormat());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Height());
+}
+
+void GraphicDescriptorTest::testDetectGIF()
+{
+ SvMemoryStream aStream;
+ createBitmapAndExportForType(aStream, u"gif");
+
+ GraphicDescriptor aDescriptor(aStream, nullptr);
+ aDescriptor.Detect(true);
+
+ CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::GIF, aDescriptor.GetFileFormat());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Height());
+}
+
+void GraphicDescriptorTest::testDetectTIF()
+{
+ SvMemoryStream aStream;
+ createBitmapAndExportForType(aStream, u"tif");
+
+ GraphicDescriptor aDescriptor(aStream, nullptr);
+ aDescriptor.Detect(true);
+
+ CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::TIF, aDescriptor.GetFileFormat());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Height());
+}
+
+void GraphicDescriptorTest::testDetectBMP()
+{
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ SvFileStream aFileStream(getFullUrl(u"graphic-descriptor-mapmode.bmp"), StreamMode::READ);
+
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aFileStream);
+
+ CPPUNIT_ASSERT(!aGraphic.isAvailable());
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 2 (MapUnit::MapMM)
+ // - Actual : 0 (MapUnit::Map100thMM)
+ // i.e. lazy load and load created different map modes, breaking the contour polygon code in
+ // Writer.
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapMM, aGraphic.GetPrefMapMode().GetMapUnit());
+ aGraphic.makeAvailable();
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapMM, aGraphic.GetPrefMapMode().GetMapUnit());
+}
+
+void GraphicDescriptorTest::testDetectWEBP()
+{
+ SvMemoryStream aStream;
+ createBitmapAndExportForType(aStream, u"webp");
+
+ GraphicDescriptor aDescriptor(aStream, nullptr);
+ aDescriptor.Detect(true);
+
+ CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::WEBP, aDescriptor.GetFileFormat());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Height());
+}
+
+void GraphicDescriptorTest::testDetectEMF()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.emf"), StreamMode::READ);
+ GraphicDescriptor aDescriptor(aFileStream, nullptr);
+ aDescriptor.Detect(true);
+ CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::EMF, aDescriptor.GetFileFormat());
+ // Test that Bounds/Frame values are fetched from header
+ CPPUNIT_ASSERT_EQUAL(tools::Long(142), aDescriptor.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(142), aDescriptor.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(300), aDescriptor.GetSize_100TH_MM().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(300), aDescriptor.GetSize_100TH_MM().Height());
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(GraphicDescriptorTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx b/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
new file mode 100644
index 000000000..e142c94ab
--- /dev/null
+++ b/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
@@ -0,0 +1,489 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <unotest/bootstrapfixturebase.hxx>
+
+#include <graphic/GraphicFormatDetector.hxx>
+#include <graphic/DetectorTools.hxx>
+
+#include <tools/stream.hxx>
+#include <o3tl/string_view.hxx>
+
+using namespace css;
+
+namespace
+{
+class GraphicFormatDetectorTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/data/") + sFileName;
+ }
+
+ void testDetectMET();
+ void testDetectBMP();
+ void testDetectWMF();
+ void testDetectWMZ();
+ void testDetectPCX();
+ void testDetectJPG();
+ void testDetectPNG();
+ void testDetectGIF();
+ void testDetectPSD();
+ void testDetectTGA();
+ void testDetectTIF();
+ void testDetectXBM();
+ void testDetectXPM();
+ void testDetectSVG();
+ void testDetectSVGZ();
+ void testDetectPDF();
+ void testDetectEPS();
+ void testDetectWEBP();
+ void testDetectEMF();
+ void testDetectEMZ();
+ void testMatchArray();
+ void testCheckArrayForMatchingStrings();
+
+ CPPUNIT_TEST_SUITE(GraphicFormatDetectorTest);
+ CPPUNIT_TEST(testDetectMET);
+ CPPUNIT_TEST(testDetectBMP);
+ CPPUNIT_TEST(testDetectWMF);
+ CPPUNIT_TEST(testDetectWMZ);
+ CPPUNIT_TEST(testDetectPCX);
+ CPPUNIT_TEST(testDetectJPG);
+ CPPUNIT_TEST(testDetectPNG);
+ CPPUNIT_TEST(testDetectGIF);
+ CPPUNIT_TEST(testDetectPSD);
+ CPPUNIT_TEST(testDetectTGA);
+ CPPUNIT_TEST(testDetectTIF);
+ CPPUNIT_TEST(testDetectXBM);
+ CPPUNIT_TEST(testDetectXPM);
+ CPPUNIT_TEST(testDetectSVG);
+ CPPUNIT_TEST(testDetectSVGZ);
+ CPPUNIT_TEST(testDetectPDF);
+ CPPUNIT_TEST(testDetectEPS);
+ CPPUNIT_TEST(testDetectWEBP);
+ CPPUNIT_TEST(testDetectEMF);
+ CPPUNIT_TEST(testDetectEMZ);
+ CPPUNIT_TEST(testMatchArray);
+ CPPUNIT_TEST(testCheckArrayForMatchingStrings);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void GraphicFormatDetectorTest::testDetectMET()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.met"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "MET");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkMET());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("MET"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectBMP()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.bmp"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "BMP");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkBMP());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("BMP"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectWMF()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.wmf"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "WMF");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkWMForEMF());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("WMF"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectWMZ()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.wmz"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "WMF");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkWMForEMF());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("WMF"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectPCX()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.pcx"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "PCX");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkPCX());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("PCX"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectJPG()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.jpg"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "JPG");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkJPG());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("JPG"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectPNG()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.png"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "PNG");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkPNG());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("PNG"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectGIF()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.gif"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "GIF");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkGIF());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("GIF"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectPSD()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.psd"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "PSD");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkPSD());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("PSD"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectTGA()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.tga"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "TGA");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkTGA());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension("TGA"); // detection is based on extension only
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("TGA"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectTIF()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.tif"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "TIF");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkTIF());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("TIF"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectXBM()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.xbm"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "XBM");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkXBM());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("XBM"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectXPM()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.xpm"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "XPM");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkXPM());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("XPM"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectSVG()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.svg"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "SVG");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkSVG());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("SVG"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectSVGZ()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.svgz"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "SVG");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkSVG());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("SVG"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectPDF()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.pdf"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "PDF");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkPDF());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("PDF"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectEPS()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.eps"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "EPS");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkEPS());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("EPS"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectWEBP()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.webp"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "WEBP");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkWEBP());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("WEBP"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectEMF()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.emf"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "EMF");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkWMForEMF());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("EMF"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testDetectEMZ()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.emz"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "EMF");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkWMForEMF());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("EMF"), rFormatExtension);
+}
+
+void GraphicFormatDetectorTest::testMatchArray()
+{
+ std::string aString("<?xml version=\"1.0\" standalone=\"no\"?>\n"
+ "<svg width=\"5cm\" height=\"4cm\" version=\"1.1\"\n"
+ "xmlns=\"http://www.w3.org/2000/svg\">\n"
+ "</svg>");
+
+ const char* pCompleteStringPointer = aString.c_str();
+ const char* pMatchPointer;
+ int nCheckSize = aString.size();
+
+ // Check beginning of the input string
+ pMatchPointer = vcl::matchArrayWithString(pCompleteStringPointer, nCheckSize, "<?xml");
+ CPPUNIT_ASSERT(pMatchPointer != nullptr);
+ CPPUNIT_ASSERT_EQUAL(0, int(pMatchPointer - pCompleteStringPointer));
+ CPPUNIT_ASSERT_EQUAL(true, o3tl::starts_with(pMatchPointer, "<?xml"));
+
+ // Check middle of the input string
+ pMatchPointer = vcl::matchArrayWithString(aString.c_str(), nCheckSize, "version");
+ CPPUNIT_ASSERT(pMatchPointer != nullptr);
+ CPPUNIT_ASSERT_EQUAL(6, int(pMatchPointer - pCompleteStringPointer));
+ CPPUNIT_ASSERT_EQUAL(true, o3tl::starts_with(pMatchPointer, "version"));
+
+ pMatchPointer = vcl::matchArrayWithString(aString.c_str(), nCheckSize, "<svg");
+ CPPUNIT_ASSERT(pMatchPointer != nullptr);
+ CPPUNIT_ASSERT_EQUAL(38, int(pMatchPointer - pCompleteStringPointer));
+ CPPUNIT_ASSERT_EQUAL(true, o3tl::starts_with(pMatchPointer, "<svg"));
+
+ // Check end of the input string
+ pMatchPointer = vcl::matchArrayWithString(aString.c_str(), nCheckSize, "/svg>");
+ CPPUNIT_ASSERT(pMatchPointer != nullptr);
+ CPPUNIT_ASSERT_EQUAL(119, int(pMatchPointer - pCompleteStringPointer));
+ CPPUNIT_ASSERT_EQUAL(true, o3tl::starts_with(pMatchPointer, "/svg>"));
+
+ // Check that non-existing search string
+ pMatchPointer = vcl::matchArrayWithString(aString.c_str(), nCheckSize, "none");
+ CPPUNIT_ASSERT(pMatchPointer == nullptr);
+}
+
+void GraphicFormatDetectorTest::testCheckArrayForMatchingStrings()
+{
+ std::string aString("<?xml version=\"1.0\" standalone=\"no\"?>\n"
+ "<svg width=\"5cm\" height=\"4cm\" version=\"1.1\"\n"
+ "xmlns=\"http://www.w3.org/2000/svg\">\n"
+ "</svg>");
+ const char* pCompleteStringPointer = aString.c_str();
+ int nCheckSize = aString.size();
+ bool bResult;
+
+ // check beginning string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize, { "<?xml" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check ending string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize, { "/svg>" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check middle string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize, { "version" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check beginning and then ending string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "<?xml", "/svg>" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check ending and then beginning string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "/svg>", "<?xml" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+
+ // check middle strings
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "version", "<svg" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check beginning, middle and ending strings
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "<?xml", "version", "<svg", "/svg>" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check non-existing
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize, { "none" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+
+ // check non-existing on the beginning
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "none", "version", "<svg", "/svg>" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+
+ // check non-existing on the end
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "<?xml", "version", "<svg", "none" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+
+ // check non-existing after the end
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "<?xml", "/svg>", "none" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(GraphicFormatDetectorTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/GraphicNativeMetadataTest.cxx b/vcl/qa/cppunit/GraphicNativeMetadataTest.cxx
new file mode 100644
index 000000000..49bf55fa9
--- /dev/null
+++ b/vcl/qa/cppunit/GraphicNativeMetadataTest.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <unotest/bootstrapfixturebase.hxx>
+
+#include <vcl/GraphicNativeMetadata.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+
+using namespace css;
+
+namespace
+{
+class GraphicNativeMetadataTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/data/") + sFileName;
+ }
+
+ void testReadFromGraphic();
+ void testExifRotationJpeg();
+
+ CPPUNIT_TEST_SUITE(GraphicNativeMetadataTest);
+ CPPUNIT_TEST(testReadFromGraphic);
+ CPPUNIT_TEST(testExifRotationJpeg);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void GraphicNativeMetadataTest::testReadFromGraphic()
+{
+ SvFileStream aFileStream(getFullUrl(u"Exif1_180.jpg"), StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+
+ // don't load the graphic, but try to get the metadata
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aFileStream);
+
+ {
+ GraphicNativeMetadata aMetadata;
+ aMetadata.read(aFileStream);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(1800), aMetadata.getRotation().get());
+ // just the metadata shouldn't make the graphic available
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ }
+
+ // now load, and it should still work the same
+ {
+ aGraphic.makeAvailable();
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ GraphicNativeMetadata aMetadata;
+ aMetadata.read(aFileStream);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(1800), aMetadata.getRotation().get());
+ }
+}
+
+void GraphicNativeMetadataTest::testExifRotationJpeg()
+{
+ {
+ // No rotation in metadata
+ SvFileStream aFileStream(getFullUrl(u"Exif1.jpg"), StreamMode::READ);
+ GraphicNativeMetadata aMetadata;
+ aMetadata.read(aFileStream);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aMetadata.getRotation().get());
+ }
+ {
+ // Rotation 90 degree clock-wise = 270 degree counter-clock-wise
+ SvFileStream aFileStream(getFullUrl(u"Exif1_090CW.jpg"), StreamMode::READ);
+ GraphicNativeMetadata aMetadata;
+ aMetadata.read(aFileStream);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(2700), aMetadata.getRotation().get());
+ }
+ {
+ // Rotation 180 degree
+ SvFileStream aFileStream(getFullUrl(u"Exif1_180.jpg"), StreamMode::READ);
+ GraphicNativeMetadata aMetadata;
+ aMetadata.read(aFileStream);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(1800), aMetadata.getRotation().get());
+ }
+ {
+ // Rotation 270 degree clock-wise = 90 degree counter-clock-wise
+ SvFileStream aFileStream(getFullUrl(u"Exif1_270CW.jpg"), StreamMode::READ);
+ GraphicNativeMetadata aMetadata;
+ aMetadata.read(aFileStream);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(900), aMetadata.getRotation().get());
+ }
+}
+
+} // anonymous namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(GraphicNativeMetadataTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/GraphicTest.cxx b/vcl/qa/cppunit/GraphicTest.cxx
new file mode 100644
index 000000000..1d6d49891
--- /dev/null
+++ b/vcl/qa/cppunit/GraphicTest.cxx
@@ -0,0 +1,1385 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <config_oox.h>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/graphic/XGraphicTransformer.hpp>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <test/bootstrapfixture.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+#include <unotest/directories.hxx>
+#include <comphelper/DirectoryHelper.hxx>
+#include <comphelper/hash.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/tempfile.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/wmf.hxx>
+
+#include <impgraph.hxx>
+#include <graphic/GraphicFormatDetector.hxx>
+
+#if USE_TLS_NSS
+#include <nss.h>
+#endif
+
+using namespace css;
+
+namespace
+{
+class GraphicTest : public test::BootstrapFixture
+{
+public:
+ ~GraphicTest();
+
+private:
+ void testUnloadedGraphic();
+ void testUnloadedGraphicLoading();
+ void testUnloadedGraphicWmf();
+ void testUnloadedGraphicAlpha();
+ void testUnloadedGraphicSizeUnit();
+
+ void testWMFRoundtrip();
+ void testWMFWithEmfPlusRoundtrip();
+ void testEmfToWmfConversion();
+
+ void testSwappingGraphic_PNG_WithGfxLink();
+ void testSwappingGraphic_PNG_WithoutGfxLink();
+ void testSwappingGraphicProperties_PNG_WithGfxLink();
+ void testSwappingGraphicProperties_PNG_WithoutGfxLink();
+
+ void testSwappingVectorGraphic_SVG_WithGfxLink();
+ void testSwappingVectorGraphic_SVG_WithoutGfxLink();
+ void testSwappingGraphicProperties_SVG_WithGfxLink();
+ void testSwappingGraphicProperties_SVG_WithoutGfxLink();
+
+ void testSwappingVectorGraphic_PDF_WithGfxLink();
+ void testSwappingVectorGraphic_PDF_WithoutGfxLink();
+
+ void testSwappingAnimationGraphic_GIF_WithGfxLink();
+ void testSwappingAnimationGraphic_GIF_WithoutGfxLink();
+
+ void testLoadMET();
+ void testLoadBMP();
+ void testLoadPSD();
+ void testLoadTGA();
+ void testLoadXBM();
+ void testLoadXPM();
+ void testLoadPCX();
+ void testLoadEPS();
+ void testLoadWEBP();
+
+ void testAvailableThreaded();
+ void testColorChangeToTransparent();
+
+ CPPUNIT_TEST_SUITE(GraphicTest);
+ CPPUNIT_TEST(testUnloadedGraphic);
+ CPPUNIT_TEST(testUnloadedGraphicLoading);
+ CPPUNIT_TEST(testUnloadedGraphicWmf);
+ CPPUNIT_TEST(testUnloadedGraphicAlpha);
+ CPPUNIT_TEST(testUnloadedGraphicSizeUnit);
+ CPPUNIT_TEST(testWMFRoundtrip);
+ CPPUNIT_TEST(testWMFWithEmfPlusRoundtrip);
+ CPPUNIT_TEST(testEmfToWmfConversion);
+
+ CPPUNIT_TEST(testSwappingGraphic_PNG_WithGfxLink);
+ CPPUNIT_TEST(testSwappingGraphic_PNG_WithoutGfxLink);
+ CPPUNIT_TEST(testSwappingGraphicProperties_PNG_WithGfxLink);
+ CPPUNIT_TEST(testSwappingGraphicProperties_PNG_WithoutGfxLink);
+
+ CPPUNIT_TEST(testSwappingVectorGraphic_SVG_WithGfxLink);
+ CPPUNIT_TEST(testSwappingVectorGraphic_SVG_WithoutGfxLink);
+ CPPUNIT_TEST(testSwappingGraphicProperties_SVG_WithGfxLink);
+ CPPUNIT_TEST(testSwappingGraphicProperties_SVG_WithoutGfxLink);
+
+ CPPUNIT_TEST(testSwappingVectorGraphic_PDF_WithGfxLink);
+ CPPUNIT_TEST(testSwappingVectorGraphic_PDF_WithoutGfxLink);
+
+ CPPUNIT_TEST(testSwappingAnimationGraphic_GIF_WithGfxLink);
+ CPPUNIT_TEST(testSwappingAnimationGraphic_GIF_WithoutGfxLink);
+
+ CPPUNIT_TEST(testLoadMET);
+ CPPUNIT_TEST(testLoadBMP);
+ CPPUNIT_TEST(testLoadPSD);
+ CPPUNIT_TEST(testLoadTGA);
+ CPPUNIT_TEST(testLoadXBM);
+ CPPUNIT_TEST(testLoadXPM);
+ CPPUNIT_TEST(testLoadPCX);
+ CPPUNIT_TEST(testLoadEPS);
+ CPPUNIT_TEST(testLoadWEBP);
+
+ CPPUNIT_TEST(testAvailableThreaded);
+ CPPUNIT_TEST(testColorChangeToTransparent);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+GraphicTest::~GraphicTest()
+{
+#if USE_TLS_NSS
+ NSS_Shutdown();
+#endif
+}
+
+BitmapEx createBitmap(bool alpha = false)
+{
+ Bitmap aBitmap(Size(120, 100), vcl::PixelFormat::N24_BPP);
+ aBitmap.Erase(COL_LIGHTRED);
+
+ aBitmap.SetPrefSize(Size(6000, 5000));
+ aBitmap.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+
+ if (alpha)
+ {
+ sal_uInt8 uAlphaValue = 0x80;
+ AlphaMask aAlphaMask(Size(120, 100), &uAlphaValue);
+
+ return BitmapEx(aBitmap, aAlphaMask);
+ }
+ else
+ {
+ return BitmapEx(aBitmap);
+ }
+}
+
+void createBitmapAndExportForType(SvStream& rStream, std::u16string_view sType, bool alpha)
+{
+ BitmapEx aBitmapEx = createBitmap(alpha);
+
+ uno::Sequence<beans::PropertyValue> aFilterData;
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName(sType);
+ rGraphicFilter.ExportGraphic(aBitmapEx, u"none", rStream, nFilterFormat, &aFilterData);
+
+ rStream.Seek(STREAM_SEEK_TO_BEGIN);
+}
+
+Graphic makeUnloadedGraphic(std::u16string_view sType, bool alpha = false)
+{
+ SvMemoryStream aStream;
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ createBitmapAndExportForType(aStream, sType, alpha);
+ return rGraphicFilter.ImportUnloadedGraphic(aStream);
+}
+
+std::string toHexString(const std::vector<unsigned char>& a)
+{
+ std::stringstream aStrm;
+ for (auto& i : a)
+ {
+ aStrm << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(i);
+ }
+
+ return aStrm.str();
+}
+
+std::unique_ptr<SvStream> createStream(OUString const& rSwapFileURL)
+{
+ std::unique_ptr<SvStream> xStream;
+
+ try
+ {
+ xStream = ::utl::UcbStreamHelper::CreateStream(
+ rSwapFileURL, StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE);
+ }
+ catch (const css::uno::Exception&)
+ {
+ }
+
+ return xStream;
+}
+
+std::vector<unsigned char> calculateHash(std::unique_ptr<SvStream>& rStream)
+{
+ comphelper::Hash aHashEngine(comphelper::HashType::SHA1);
+ const sal_uInt32 nSize(rStream->remainingSize());
+ std::vector<sal_uInt8> aData(nSize);
+ aHashEngine.update(aData.data(), nSize);
+ return aHashEngine.finalize();
+}
+
+bool checkBitmap(Graphic& rGraphic)
+{
+ bool bResult = true;
+
+ Bitmap aBitmap(rGraphic.GetBitmapEx().GetBitmap());
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ for (tools::Long y = 0; y < rGraphic.GetSizePixel().Height(); y++)
+ {
+ for (tools::Long x = 0; x < rGraphic.GetSizePixel().Width(); x++)
+ {
+ if (pReadAccess->HasPalette())
+ {
+ sal_uInt32 nIndex = pReadAccess->GetPixelIndex(y, x);
+ Color aColor = pReadAccess->GetPaletteColor(nIndex);
+ bResult &= (aColor == Color(0xff, 0x00, 0x00));
+ }
+ else
+ {
+ Color aColor = pReadAccess->GetPixel(y, x);
+ bResult &= (aColor == Color(0xff, 0x00, 0x00));
+ }
+ }
+ }
+ }
+
+ return bResult;
+}
+
+constexpr OUStringLiteral DATA_DIRECTORY = u"/vcl/qa/cppunit/data/";
+constexpr OUStringLiteral PDFEXPORT_DATA_DIRECTORY = u"/vcl/qa/cppunit/pdfexport/data/";
+
+Graphic loadGraphic(std::u16string_view const& rFilename)
+{
+ test::Directories aDirectories;
+ OUString aFilename = aDirectories.getURLFromSrc(DATA_DIRECTORY) + rFilename;
+ SvFileStream aFileStream(aFilename, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+
+ Graphic aGraphic;
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, rGraphicFilter.ImportGraphic(aGraphic, u"", aFileStream,
+ GRFILTER_FORMAT_DONTKNOW));
+ return aGraphic;
+}
+
+Graphic importUnloadedGraphic(std::u16string_view const& rFilename)
+{
+ test::Directories aDirectories;
+ OUString aFilename = aDirectories.getURLFromSrc(DATA_DIRECTORY) + rFilename;
+ SvFileStream aFileStream(aFilename, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ return rGraphicFilter.ImportUnloadedGraphic(aFileStream);
+}
+
+void GraphicTest::testUnloadedGraphic()
+{
+ // make unloaded test graphic
+ Graphic aGraphic = makeUnloadedGraphic(u"png");
+ Graphic aGraphic2 = aGraphic;
+
+ // check available
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic2.isAvailable());
+
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic2.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic2.isAvailable());
+
+ // check GetSizePixel doesn't load graphic
+ aGraphic = makeUnloadedGraphic(u"png");
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // check GetPrefSize doesn't load graphic
+ CPPUNIT_ASSERT_EQUAL(tools::Long(6000), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(5000), aGraphic.GetPrefSize().Height());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // check GetSizeBytes loads graphic
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ //check Type
+ aGraphic = makeUnloadedGraphic(u"png");
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+}
+
+void GraphicTest::testUnloadedGraphicLoading()
+{
+ const OUString aFormats[] = { "png", "gif", "jpg", "tif", "webp" };
+
+ for (OUString const& sFormat : aFormats)
+ {
+ Graphic aGraphic = makeUnloadedGraphic(sFormat);
+
+ // check available
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ if (sFormat != "jpg")
+ CPPUNIT_ASSERT_EQUAL(true, checkBitmap(aGraphic));
+ }
+}
+
+void GraphicTest::testUnloadedGraphicWmf()
+{
+ // Create some in-memory WMF data, set its own preferred size to 99x99.
+ BitmapEx aBitmapEx = createBitmap();
+ SvMemoryStream aStream;
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName(u"wmf");
+ Graphic aGraphic(aBitmapEx);
+ aGraphic.SetPrefSize(Size(99, 99));
+ aGraphic.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ rGraphicFilter.ExportGraphic(aGraphic, u"none", aStream, nFilterFormat);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Now lazy-load this WMF data, with a custom preferred size of 42x42.
+ Size aMtfSize100(42, 42);
+ aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream, 0, &aMtfSize100);
+ aGraphic.makeAvailable();
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 42x42
+ // - Actual : 99x99
+ // i.e. the custom preferred size was lost after lazy-load.
+ CPPUNIT_ASSERT_EQUAL(Size(42, 42), aGraphic.GetPrefSize());
+}
+
+void GraphicTest::testUnloadedGraphicAlpha()
+{
+ // make unloaded test graphic with alpha
+ Graphic aGraphic = makeUnloadedGraphic(u"png", true);
+
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsAlpha());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsTransparent());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // make unloaded test graphic without alpha
+ aGraphic = makeUnloadedGraphic(u"png", false);
+
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsAlpha());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsTransparent());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+}
+
+void GraphicTest::testUnloadedGraphicSizeUnit()
+{
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "inch-size.emf";
+ Size aMtfSize100(42, 42);
+ SvFileStream aStream(aURL, StreamMode::READ);
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream, 0, &aMtfSize100);
+
+ CPPUNIT_ASSERT_EQUAL(Size(42, 42), aGraphic.GetPrefSize());
+
+ // Force it to swap in
+ aGraphic.makeAvailable();
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 400x363
+ // - Actual : 42x42
+ // i.e. a mm100 size was used as a hint and the inch size was set for a non-matching unit.
+ CPPUNIT_ASSERT_EQUAL(Size(400, 363), aGraphic.GetPrefSize());
+}
+
+void GraphicTest::testWMFRoundtrip()
+{
+ // Load a WMF file.
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(u"vcl/qa/cppunit/data/roundtrip.wmf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ sal_uInt64 nExpectedSize = aStream.TellEnd();
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+
+ // Save as WMF.
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ sal_uInt16 nFormat = rGraphicFilter.GetExportFormatNumberForShortName(u"WMF");
+ SvStream& rOutStream = *aTempFile.GetStream(StreamMode::READWRITE);
+ rGraphicFilter.ExportGraphic(aGraphic, u"", rOutStream, nFormat);
+
+ // Check if we preserved the WMF data perfectly.
+ sal_uInt64 nActualSize = rOutStream.TellEnd();
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 6475
+ // - Actual : 2826
+ // i.e. we lost some of the WMF data on roundtrip.
+ CPPUNIT_ASSERT_EQUAL(nExpectedSize, nActualSize);
+}
+
+int getEmfPlusActionsCount(const Graphic& graphic)
+{
+ const GDIMetaFile& metafile = graphic.GetGDIMetaFile();
+ int emfPlusCount = 0;
+ for (size_t i = 0; i < metafile.GetActionSize(); ++i)
+ {
+ MetaAction* action = metafile.GetAction(i);
+ if (action->GetType() == MetaActionType::COMMENT)
+ {
+ const MetaCommentAction* commentAction = static_cast<const MetaCommentAction*>(action);
+ if (commentAction->GetComment() == "EMF_PLUS")
+ ++emfPlusCount;
+ }
+ }
+ return emfPlusCount;
+}
+
+int getPolygonActionsCount(const Graphic& graphic)
+{
+ const GDIMetaFile& metafile = graphic.GetGDIMetaFile();
+ int polygonCount = 0;
+ for (size_t i = 0; i < metafile.GetActionSize(); ++i)
+ {
+ MetaAction* action = metafile.GetAction(i);
+ if (action->GetType() == MetaActionType::POLYGON)
+ ++polygonCount;
+ }
+ return polygonCount;
+}
+
+void GraphicTest::testWMFWithEmfPlusRoundtrip()
+{
+ // Load a WMF file.
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(u"vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ sal_uInt64 nExpectedSize = aStream.TellEnd();
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+
+ CPPUNIT_ASSERT_GREATER(0, getEmfPlusActionsCount(aGraphic));
+ CPPUNIT_ASSERT_EQUAL(0, getPolygonActionsCount(aGraphic));
+
+ for (bool useConvertMetafile : { false, true })
+ {
+ // Save as WMF.
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ SvStream& rOutStream = *aTempFile.GetStream(StreamMode::READWRITE);
+ if (useConvertMetafile)
+ ConvertGraphicToWMF(aGraphic, rOutStream, nullptr);
+ else
+ {
+ sal_uInt16 nFormat = rGraphicFilter.GetExportFormatNumberForShortName(u"WMF");
+ rGraphicFilter.ExportGraphic(aGraphic, u"", rOutStream, nFormat);
+ }
+ CPPUNIT_ASSERT_EQUAL(nExpectedSize, rOutStream.TellEnd());
+
+ rOutStream.Seek(0);
+ Graphic aNewGraphic = rGraphicFilter.ImportUnloadedGraphic(rOutStream);
+ // Check that reading the WMF back preserves the EMF+ actions in it.
+ CPPUNIT_ASSERT_GREATER(0, getEmfPlusActionsCount(aNewGraphic));
+ // EmfReader::ReadEnhWMF() drops non-EMF+ drawing actions if EMF+ is found.
+ CPPUNIT_ASSERT_EQUAL(0, getPolygonActionsCount(aNewGraphic));
+
+ // With EMF+ disabled there should be no EMF+ actions.
+ auto aVectorGraphicData = std::make_shared<VectorGraphicData>(
+ aNewGraphic.GetGfxLink().getDataContainer(), VectorGraphicDataType::Wmf);
+ aVectorGraphicData->setEnableEMFPlus(false);
+ Graphic aNoEmfPlusGraphic(aVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(0, getEmfPlusActionsCount(aNoEmfPlusGraphic));
+ CPPUNIT_ASSERT_GREATER(0, getPolygonActionsCount(aNoEmfPlusGraphic));
+ }
+}
+
+void GraphicTest::testEmfToWmfConversion()
+{
+ // Load EMF data.
+ GraphicFilter aGraphicFilter;
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "to-wmf.emf";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ // This similar to an application/x-openoffice-wmf mime type in manifest.xml in the ODF case.
+ sal_uInt16 nFormat = aGraphicFilter.GetImportFormatNumberForShortName(u"WMF");
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE,
+ aGraphicFilter.ImportGraphic(aGraphic, u"", aStream, nFormat));
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Wmf, aGraphic.getVectorGraphicData()->getType());
+
+ // Save as WMF.
+ sal_uInt16 nFilterType = aGraphicFilter.GetExportFormatNumberForShortName(u"WMF");
+ SvMemoryStream aGraphicStream;
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE,
+ aGraphicFilter.ExportGraphic(aGraphic, u"", aGraphicStream, nFilterType));
+ aGraphicStream.Seek(0);
+ vcl::GraphicFormatDetector aDetector(aGraphicStream, OUString());
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkWMForEMF());
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: WMF
+ // - Actual : EMF
+ // i.e. EMF data was requested to be converted to WMF, but the output was still EMF.
+ CPPUNIT_ASSERT_EQUAL(OUString("WMF"), aDetector.msDetectedFormat);
+
+ // Import the WMF result and check for traces of EMF+ in it.
+ Graphic aWmfGraphic;
+ aGraphicStream.Seek(0);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE,
+ aGraphicFilter.ImportGraphic(aWmfGraphic, u"", aGraphicStream, nFormat));
+ int nCommentCount = 0;
+ for (size_t i = 0; i < aWmfGraphic.GetGDIMetaFile().GetActionSize(); ++i)
+ {
+ MetaAction* pAction = aWmfGraphic.GetGDIMetaFile().GetAction(i);
+ if (pAction->GetType() == MetaActionType::COMMENT)
+ {
+ auto pComment = static_cast<MetaCommentAction*>(pAction);
+ if (pComment->GetComment().startsWith("EMF_PLUS"))
+ {
+ ++nCommentCount;
+ }
+ }
+ }
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected less or equal than: 4
+ // - Actual : 8
+ // i.e. even more EMF+ comments were left in the WMF output. The ideal would be to get this down
+ // to 0, though.
+ CPPUNIT_ASSERT_LESSEQUAL(4, nCommentCount);
+}
+
+void GraphicTest::testSwappingGraphic_PNG_WithGfxLink()
+{
+ // Prepare Graphic from a PNG image first
+ Graphic aGraphic = makeUnloadedGraphic(u"png");
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
+
+ BitmapChecksum aChecksumBeforeSwapping = aGraphic.GetChecksum();
+
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsGfxLink());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(319), aGraphic.GetGfxLink().GetDataSize());
+
+ // We loaded the Graphic and made it available
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ // Get the declared byte size of the graphic
+ sal_uLong rByteSize = aGraphic.GetSizeBytes();
+
+ // Check the swap file (shouldn't exist)
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->getSwapFileURL().isEmpty());
+
+ // Swapping out
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Byte size doesn't change when we swapped out
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+
+ // Check the swap file (still shouldn't exist)
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->getSwapFileURL().isEmpty());
+
+ // Let's swap in
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ CPPUNIT_ASSERT_EQUAL(aChecksumBeforeSwapping, aGraphic.GetChecksum());
+
+ // Check the bitmap
+ CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(true, checkBitmap(aGraphic));
+}
+
+void GraphicTest::testSwappingGraphic_PNG_WithoutGfxLink()
+{
+ // Prepare Graphic from a PNG image first
+
+ // Make sure to construct the Graphic from BitmapEx, so that we
+ // don't have the GfxLink present.
+ Graphic aGraphic(makeUnloadedGraphic(u"png").GetBitmapEx());
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
+
+ BitmapChecksum aChecksumBeforeSwapping = aGraphic.GetChecksum();
+
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsGfxLink());
+
+ // We loaded the Graphic and made it available
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Get the declared byte size of the graphic
+ sal_uLong rByteSize = aGraphic.GetSizeBytes();
+ OUString rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
+ CPPUNIT_ASSERT_EQUAL(true, rSwapFileURL.isEmpty());
+
+ // Swapping out
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Byte size doesn't change when we swapped out
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+
+ // Let's check the swap file
+ rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
+ CPPUNIT_ASSERT_EQUAL(true, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
+
+ { // Check the swap file content
+ std::unique_ptr<SvStream> xStream = createStream(rSwapFileURL);
+ CPPUNIT_ASSERT_EQUAL(true, bool(xStream));
+
+ // Check size of the stream
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(36079), xStream->remainingSize());
+
+ std::vector<unsigned char> aHash = calculateHash(xStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("9347511e3b80dfdfaadf91a3bdef55a8ae85552b"),
+ toHexString(aHash));
+ }
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // reset the checksum to make sure we don't get the cached value
+ aGraphic.ImplGetImpGraphic()->resetChecksum();
+ CPPUNIT_ASSERT_EQUAL(aChecksumBeforeSwapping, aGraphic.GetChecksum());
+
+ // File shouldn't be available anymore
+ CPPUNIT_ASSERT_EQUAL(false, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
+
+ // Check the bitmap
+ CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
+
+ CPPUNIT_ASSERT_EQUAL(true, checkBitmap(aGraphic));
+}
+
+void GraphicTest::testSwappingGraphicProperties_PNG_WithGfxLink()
+{
+ // Prepare Graphic from a PNG image
+ Graphic aGraphic = makeUnloadedGraphic(u"png");
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ // Origin URL
+ aGraphic.setOriginURL("Origin URL");
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+
+ //Set PrefMapMode
+ CPPUNIT_ASSERT_EQUAL(MapUnit::Map100thMM, aGraphic.GetPrefMapMode().GetMapUnit());
+ aGraphic.SetPrefMapMode(MapMode(MapUnit::MapTwip));
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapTwip, aGraphic.GetPrefMapMode().GetMapUnit());
+
+ // Set the PrefSize
+ CPPUNIT_ASSERT_EQUAL(tools::Long(6000), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(5000), aGraphic.GetPrefSize().Height());
+ aGraphic.SetPrefSize(Size(200, 100));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+
+ // SWAP OUT
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Check properties
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapTwip, aGraphic.GetPrefMapMode().GetMapUnit());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Check properties
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapTwip, aGraphic.GetPrefMapMode().GetMapUnit());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+}
+
+void GraphicTest::testSwappingGraphicProperties_PNG_WithoutGfxLink()
+{
+ // Prepare Graphic from a PNG image
+ Graphic aGraphic(makeUnloadedGraphic(u"png").GetBitmapEx());
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ // Origin URL
+ aGraphic.setOriginURL("Origin URL");
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+
+ //Set PrefMapMode
+ CPPUNIT_ASSERT_EQUAL(MapUnit::Map100thMM, aGraphic.GetPrefMapMode().GetMapUnit());
+ aGraphic.SetPrefMapMode(MapMode(MapUnit::MapTwip));
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapTwip, aGraphic.GetPrefMapMode().GetMapUnit());
+
+ // Set the PrefSize
+ CPPUNIT_ASSERT_EQUAL(tools::Long(6000), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(5000), aGraphic.GetPrefSize().Height());
+ aGraphic.SetPrefSize(Size(200, 100));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+
+ // SWAP OUT
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Check properties
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapTwip, aGraphic.GetPrefMapMode().GetMapUnit());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Check properties
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapTwip, aGraphic.GetPrefMapMode().GetMapUnit());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+}
+
+void GraphicTest::testSwappingVectorGraphic_SVG_WithGfxLink()
+{
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "SimpleExample.svg";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ // Loaded into "prepared" state
+
+ // Check that the state is as expected
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Load the vector graphic
+ auto pVectorData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT_EQUAL(true, bool(pVectorData));
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ CPPUNIT_ASSERT_EQUAL(size_t(223), pVectorData->getBinaryDataContainer().getSize());
+
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsGfxLink());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(223), aGraphic.GetGfxLink().GetDataSize());
+
+ // Remember checksum so we can compare after swapping back in again
+ BitmapChecksum aBitmapChecksumBeforeSwapping = aGraphic.GetBitmapEx().GetChecksum();
+
+ // Check we are not swapped out yet
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Get the declared byte size of the graphic
+ sal_uLong rByteSize = aGraphic.GetSizeBytes();
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(223), rByteSize);
+
+ // Make sure we don't have a file
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->getSwapFileURL().isEmpty());
+
+ // SWAP OUT the Graphic and make sure it's not available currently
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // We use GfxLink so no swap file in this case
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->getSwapFileURL().isEmpty());
+
+ // Byte size doesn't change when we swapped out
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Compare that the checksum of the bitmap is still the same
+ CPPUNIT_ASSERT_EQUAL(aBitmapChecksumBeforeSwapping, aGraphic.GetBitmapEx().GetChecksum());
+
+ // Byte size shouldn't change
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+}
+
+void GraphicTest::testSwappingVectorGraphic_SVG_WithoutGfxLink()
+{
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "SimpleExample.svg";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+
+ Graphic aInputGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ CPPUNIT_ASSERT_EQUAL(size_t(223),
+ aInputGraphic.getVectorGraphicData()->getBinaryDataContainer().getSize());
+
+ // Create graphic
+ Graphic aGraphic(aInputGraphic.getVectorGraphicData());
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, bool(aGraphic.getVectorGraphicData()));
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ CPPUNIT_ASSERT_EQUAL(size_t(223),
+ aGraphic.getVectorGraphicData()->getBinaryDataContainer().getSize());
+
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsGfxLink());
+
+ BitmapChecksum aBitmapChecksumBeforeSwapping = aGraphic.GetBitmapEx().GetChecksum();
+
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Get the declared byte size of the graphic
+ sal_uLong rByteSize = aGraphic.GetSizeBytes();
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(223), rByteSize);
+
+ OUString rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
+ CPPUNIT_ASSERT_EQUAL(true, rSwapFileURL.isEmpty());
+
+ // Swapping out
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Byte size doesn't change when we swapped out
+ // TODO: In case we don't trigger GetBitmapEx (above) the size is 0
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+
+ // Let's check the swap file
+ rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
+ CPPUNIT_ASSERT_EQUAL(false, rSwapFileURL.isEmpty());
+ CPPUNIT_ASSERT_EQUAL(true, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
+
+ {
+ // Check the swap file content
+ std::unique_ptr<SvStream> xStream = createStream(rSwapFileURL);
+ CPPUNIT_ASSERT_EQUAL(true, bool(xStream));
+
+ // Check size of the stream
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(247), xStream->remainingSize());
+
+ std::vector<unsigned char> aHash = calculateHash(xStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("666820973fd95e6cd9e7bc5f1c53732acbc99326"),
+ toHexString(aHash));
+ }
+
+ // Let's swap in
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ // Check the Graphic
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, bool(aGraphic.getVectorGraphicData()));
+
+ size_t nVectorByteSize = aGraphic.getVectorGraphicData()->getBinaryDataContainer().getSize();
+ CPPUNIT_ASSERT_EQUAL(size_t(223), nVectorByteSize);
+
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsGfxLink());
+
+ CPPUNIT_ASSERT_EQUAL(aBitmapChecksumBeforeSwapping, aGraphic.GetBitmapEx().GetChecksum());
+
+ // File shouldn't be available anymore
+ CPPUNIT_ASSERT_EQUAL(false, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
+}
+
+void GraphicTest::testSwappingGraphicProperties_SVG_WithGfxLink()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ // We check that Graphic properties like MapMode, PrefSize are properly
+ // restored through a swap cycle
+
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "SimpleExample.svg";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ // Loaded into "prepared" state
+
+ // Load the vector graphic
+ auto pVectorData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT_EQUAL(true, bool(pVectorData));
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ // Origin URL
+ aGraphic.setOriginURL("Origin URL");
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+
+ // Check size in pixels
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Height());
+
+ // Set and check the PrefSize
+ CPPUNIT_ASSERT_EQUAL(tools::Long(1349), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(1349), aGraphic.GetPrefSize().Height());
+ aGraphic.SetPrefSize(Size(200, 100));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+
+ // SWAP OUT the Graphic and make sure it's not available currently
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Check properties
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Height());
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Check properties
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testSwappingGraphicProperties_SVG_WithoutGfxLink()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "SimpleExample.svg";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+
+ Graphic aInputGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ CPPUNIT_ASSERT_EQUAL(size_t(223),
+ aInputGraphic.getVectorGraphicData()->getBinaryDataContainer().getSize());
+
+ // Create graphic
+ Graphic aGraphic(aInputGraphic.getVectorGraphicData());
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, bool(aGraphic.getVectorGraphicData()));
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsGfxLink());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Origin URL
+ aGraphic.setOriginURL("Origin URL");
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+
+ // Check size in pixels
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Height());
+
+ // Set and check the PrefSize
+ CPPUNIT_ASSERT_EQUAL(tools::Long(1349), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(1349), aGraphic.GetPrefSize().Height());
+ aGraphic.SetPrefSize(Size(200, 100));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+
+ // SWAP OUT the Graphic and make sure it's not available currently
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Height());
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Origin URL"), aGraphic.getOriginURL());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aGraphic.GetPrefSize().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetPrefSize().Height());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(51), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testSwappingVectorGraphic_PDF_WithGfxLink()
+{
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(PDFEXPORT_DATA_DIRECTORY) + "SimpleMultiPagePDF.pdf";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Load the vector graphic
+ CPPUNIT_ASSERT_EQUAL(true, bool(aGraphic.getVectorGraphicData()));
+
+ // Set the page index
+ aGraphic.getVectorGraphicData()->setPageIndex(1);
+
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, aGraphic.getVectorGraphicData()->getType());
+ CPPUNIT_ASSERT_EQUAL(size_t(17693),
+ aGraphic.getVectorGraphicData()->getBinaryDataContainer().getSize());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aGraphic.getVectorGraphicData()->getPageIndex());
+
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // SWAP OUT
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aGraphic.getVectorGraphicData()->getPageIndex());
+}
+
+void GraphicTest::testSwappingVectorGraphic_PDF_WithoutGfxLink()
+{
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(PDFEXPORT_DATA_DIRECTORY) + "SimpleMultiPagePDF.pdf";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aInputGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+
+ // Create graphic
+ Graphic aGraphic(aInputGraphic.getVectorGraphicData());
+
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, bool(aGraphic.getVectorGraphicData()));
+
+ // Set the page index
+ aGraphic.getVectorGraphicData()->setPageIndex(1);
+
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, aGraphic.getVectorGraphicData()->getType());
+ CPPUNIT_ASSERT_EQUAL(size_t(17693),
+ aGraphic.getVectorGraphicData()->getBinaryDataContainer().getSize());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aGraphic.getVectorGraphicData()->getPageIndex());
+
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // SWAP OUT
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aGraphic.getVectorGraphicData()->getPageIndex());
+}
+
+void GraphicTest::testSwappingAnimationGraphic_GIF_WithGfxLink()
+{
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "123_Numbers.gif";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ // Loaded into "prepared" state
+
+ // Check that the state is as expected
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsGfxLink());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(124), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(146), aGraphic.GetSizePixel().Height());
+
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(1515), aGraphic.GetGfxLink().GetDataSize());
+
+ // Remember checksum so we can compare after swapping back in again
+ BitmapChecksum aBitmapChecksumBeforeSwapping = aGraphic.GetBitmapEx().GetChecksum();
+
+ // Check we are not swapped out yet
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Get the declared byte size of the graphic
+ sal_uLong rByteSize = aGraphic.GetSizeBytes();
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(89552), rByteSize);
+
+ // Make sure we don't have a file
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->getSwapFileURL().isEmpty());
+
+ // SWAP OUT the Graphic and make sure it's not available currently
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // We use GfxLink so no swap file in this case
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->getSwapFileURL().isEmpty());
+
+ // Byte size doesn't change when we swapped out
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Compare that the checksum of the bitmap is still the same
+ CPPUNIT_ASSERT_EQUAL(aBitmapChecksumBeforeSwapping, aGraphic.GetBitmapEx().GetChecksum());
+
+ // Byte size shouldn't change
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+}
+
+void GraphicTest::testSwappingAnimationGraphic_GIF_WithoutGfxLink()
+{
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "123_Numbers.gif";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aInputGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ Graphic aGraphic(aInputGraphic.GetAnimation());
+
+ // Check animation graphic
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsAnimated());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(124), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(146), aGraphic.GetSizePixel().Height());
+
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsGfxLink());
+
+ // We loaded the Graphic and made it available
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // Get the declared byte size of the graphic
+ sal_uLong rByteSize = aGraphic.GetSizeBytes();
+ OUString rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
+ CPPUNIT_ASSERT_EQUAL(true, rSwapFileURL.isEmpty());
+
+ // SWAP OUT
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+ // Byte size doesn't change when we swapped out
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+
+ // Let's check the swap file
+ rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
+ CPPUNIT_ASSERT_EQUAL(true, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
+
+ {
+ // Check the swap file content
+ std::unique_ptr<SvStream> xStream = createStream(rSwapFileURL);
+ CPPUNIT_ASSERT_EQUAL(true, bool(xStream));
+
+ // Check size of the stream
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(15139), xStream->remainingSize());
+
+ std::vector<unsigned char> aHash = calculateHash(xStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("ecae5354edd9cf98553eb3153e44181f56d35338"),
+ toHexString(aHash));
+ }
+
+ // SWAP IN
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
+ CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
+
+ // File shouldn't be available anymore
+ CPPUNIT_ASSERT_EQUAL(false, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
+
+ // Check the bitmap
+ CPPUNIT_ASSERT_EQUAL(tools::Long(124), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(146), aGraphic.GetSizePixel().Height());
+
+ // Byte size is still the same
+ CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
+}
+
+void GraphicTest::testLoadMET()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.met");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::GdiMetafile, aGraphic.GetType());
+}
+
+void GraphicTest::testLoadBMP()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.bmp");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testLoadPSD()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.psd");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testLoadTGA()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.tga");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testLoadXBM()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.xbm");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testLoadXPM()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.xpm");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testLoadPCX()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.pcx");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testLoadEPS()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.eps");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::GdiMetafile, aGraphic.GetType());
+}
+
+void GraphicTest::testLoadWEBP()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.webp");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Height());
+}
+
+void GraphicTest::testAvailableThreaded()
+{
+ Graphic jpgGraphic1 = importUnloadedGraphic(u"TypeDetectionExample.jpg");
+ Graphic jpgGraphic2 = importUnloadedGraphic(u"Exif1.jpg");
+ Graphic pngGraphic1 = importUnloadedGraphic(u"TypeDetectionExample.png");
+ Graphic pngGraphic2 = importUnloadedGraphic(u"testBasicMorphology.png");
+ std::vector<Graphic*> graphics = { &jpgGraphic1, &jpgGraphic2, &pngGraphic1, &pngGraphic2 };
+ std::vector<Size> sizes;
+ for (auto& graphic : graphics)
+ {
+ CPPUNIT_ASSERT(!graphic->isAvailable());
+ sizes.push_back(graphic->GetSizePixel());
+ }
+ GraphicFilter& graphicFilter = GraphicFilter::GetGraphicFilter();
+ graphicFilter.MakeGraphicsAvailableThreaded(graphics);
+ int i = 0;
+ for (auto& graphic : graphics)
+ {
+ CPPUNIT_ASSERT(graphic->isAvailable());
+ CPPUNIT_ASSERT_EQUAL(sizes[i], graphic->GetSizePixel());
+ ++i;
+ }
+}
+
+void GraphicTest::testColorChangeToTransparent()
+{
+ Graphic aGraphic = importUnloadedGraphic(u"testColorChange-red-linear-gradient.png");
+
+ auto xGraphic = aGraphic.GetXGraphic();
+ uno::Reference<graphic::XGraphicTransformer> xGraphicTransformer{ xGraphic, uno::UNO_QUERY };
+ ::Color nColorFrom{ ColorTransparency, 0x00, 0xFF, 0x00, 0x00 };
+ ::Color nColorTo{ ColorTransparency, 0xFF, 0xFF, 0x00, 0x00 };
+ sal_uInt8 nTolerance{ 15 };
+
+ auto xGraphicAfter = xGraphicTransformer->colorChange(
+ xGraphic, static_cast<sal_Int32>(nColorFrom), nTolerance, static_cast<sal_Int32>(nColorTo),
+ static_cast<sal_Int8>(nColorTo.GetAlpha()));
+
+ Graphic aGraphicAfter{ xGraphicAfter };
+ const BitmapEx& rBitmapAfter = aGraphicAfter.GetBitmapExRef();
+ const BitmapEx& rBitmapBefore = aGraphic.GetBitmapExRef();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: rgba[ff000000]
+ // - Actual : rgba[f00000ff]
+ // i.e. the color change to transparent didn't apply correctly
+ CPPUNIT_ASSERT_EQUAL(nColorTo, rBitmapAfter.GetPixelColor(386, 140));
+
+ // Test if color stayed same on 410,140
+ // colorChange with nTolerance 15 shouldn't change this pixel.
+ CPPUNIT_ASSERT_EQUAL(rBitmapBefore.GetPixelColor(410, 140),
+ rBitmapAfter.GetPixelColor(410, 140));
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(GraphicTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/PDFDocumentTest.cxx b/vcl/qa/cppunit/PDFDocumentTest.cxx
new file mode 100644
index 000000000..35af8e66c
--- /dev/null
+++ b/vcl/qa/cppunit/PDFDocumentTest.cxx
@@ -0,0 +1,600 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+
+#include <vcl/filter/pdfdocument.hxx>
+
+class PDFDocumentTest : public test::BootstrapFixture, public unotest::MacrosTest
+{
+public:
+ PDFDocumentTest() = default;
+};
+
+constexpr OUStringLiteral DATA_DIRECTORY = u"/vcl/qa/cppunit/data/";
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseBasicPDF)
+{
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "basic.pdf";
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(aURL, StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
+
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+
+ vcl::filter::PDFObjectElement* pTest = pResources->LookupObject("Test");
+ CPPUNIT_ASSERT(pTest);
+
+ vcl::filter::PDFObjectElement* pTestArray1 = pTest->LookupObject("TestArray1");
+ CPPUNIT_ASSERT(pTestArray1);
+ {
+ CPPUNIT_ASSERT_EQUAL(size_t(5), pTestArray1->GetArray()->GetElements().size());
+ }
+
+ vcl::filter::PDFObjectElement* pTestArray2 = pTest->LookupObject("TestArray2");
+ CPPUNIT_ASSERT(pTestArray2);
+ {
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pTestArray2->GetArray()->GetElements().size());
+ }
+
+ vcl::filter::PDFObjectElement* pTestDictionary = pTest->LookupObject("TestDictionary");
+ {
+ sal_uInt64 nOffset = pTestDictionary->GetDictionaryOffset();
+ sal_uInt64 nLength = pTestDictionary->GetDictionaryLength();
+
+ aStream.Seek(nOffset);
+ std::vector<char> aBuffer(nLength + 1, 0);
+ aStream.ReadBytes(aBuffer.data(), nLength);
+ OString aString(aBuffer.data());
+
+ CPPUNIT_ASSERT_EQUAL(
+ OString("/TestReference 7 0 R/TestNumber "
+ "123/TestName/SomeName/TestDictionary<</Key/Value>>/TestArray[1 2 3]"),
+ aString);
+ }
+
+ CPPUNIT_ASSERT(pTestDictionary);
+ {
+ auto const& rItems = pTestDictionary->GetDictionaryItems();
+ CPPUNIT_ASSERT_EQUAL(size_t(5), rItems.size());
+ auto* pReference = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+ pTestDictionary->Lookup("TestReference"));
+ CPPUNIT_ASSERT(pReference);
+ CPPUNIT_ASSERT_EQUAL(7, pReference->GetObjectValue());
+
+ auto* pNumber
+ = dynamic_cast<vcl::filter::PDFNumberElement*>(pTestDictionary->Lookup("TestNumber"));
+ CPPUNIT_ASSERT(pNumber);
+ CPPUNIT_ASSERT_EQUAL(123.0, pNumber->GetValue());
+
+ auto* pName
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pTestDictionary->Lookup("TestName"));
+ CPPUNIT_ASSERT(pName);
+ CPPUNIT_ASSERT_EQUAL(OString("SomeName"), pName->GetValue());
+
+ auto* pDictionary = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pTestDictionary->Lookup("TestDictionary"));
+ CPPUNIT_ASSERT(pDictionary);
+
+ auto* pArray
+ = dynamic_cast<vcl::filter::PDFArrayElement*>(pTestDictionary->Lookup("TestArray"));
+ CPPUNIT_ASSERT(pArray);
+
+ // Check offsets and lengths
+ {
+ sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestReference");
+ sal_uInt64 nLength
+ = pTestDictionary->GetDictionary()->GetKeyValueLength("TestReference");
+
+ aStream.Seek(nOffset);
+ std::vector<char> aBuffer(nLength + 1, 0);
+ aStream.ReadBytes(aBuffer.data(), nLength);
+ OString aString(aBuffer.data());
+
+ CPPUNIT_ASSERT_EQUAL(OString("TestReference 7 0 R"), aString);
+ }
+ {
+ sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestNumber");
+ sal_uInt64 nLength = pTestDictionary->GetDictionary()->GetKeyValueLength("TestNumber");
+
+ aStream.Seek(nOffset);
+ std::vector<char> aBuffer(nLength + 1, 0);
+ aStream.ReadBytes(aBuffer.data(), nLength);
+ OString aString(aBuffer.data());
+
+ CPPUNIT_ASSERT_EQUAL(OString("TestNumber 123"), aString);
+ }
+ {
+ sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestName");
+ sal_uInt64 nLength = pTestDictionary->GetDictionary()->GetKeyValueLength("TestName");
+
+ aStream.Seek(nOffset);
+ std::vector<char> aBuffer(nLength + 1, 0);
+ aStream.ReadBytes(aBuffer.data(), nLength);
+ OString aString(aBuffer.data());
+
+ CPPUNIT_ASSERT_EQUAL(OString("TestName/SomeName"), aString);
+ }
+ {
+ sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestDictionary");
+ sal_uInt64 nLength
+ = pTestDictionary->GetDictionary()->GetKeyValueLength("TestDictionary");
+
+ aStream.Seek(nOffset);
+ std::vector<char> aBuffer(nLength + 1, 0);
+ aStream.ReadBytes(aBuffer.data(), nLength);
+ OString aString(aBuffer.data());
+
+ CPPUNIT_ASSERT_EQUAL(OString("TestDictionary<</Key/Value>>"), aString);
+ }
+ {
+ sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestArray");
+ sal_uInt64 nLength = pTestDictionary->GetDictionary()->GetKeyValueLength("TestArray");
+
+ aStream.Seek(nOffset);
+ std::vector<char> aBuffer(nLength + 1, 0);
+ aStream.ReadBytes(aBuffer.data(), nLength);
+ OString aString(aBuffer.data());
+
+ CPPUNIT_ASSERT_EQUAL(OString("TestArray[1 2 3]"), aString);
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseDocumentWithNullAsWhitespace)
+{
+ // tdf#140606
+ // Bug document contained a null, which cause the parser to panic,
+ // but other PDF readers can handle the file well.
+
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "DocumentWithNull.pdf";
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(aURL, StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+}
+
+namespace
+{
+vcl::filter::PDFObjectElement*
+addObjectElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+ vcl::filter::PDFDocument& rDocument, int nObjectNumber, int nGenerationNumber)
+{
+ auto pObject = std::make_unique<vcl::filter::PDFObjectElement>(rDocument, nObjectNumber,
+ nGenerationNumber);
+ auto pObjectPtr = pObject.get();
+ rElements.push_back(std::move(pObject));
+ return pObjectPtr;
+}
+
+vcl::filter::PDFTrailerElement*
+addTrailerObjectElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+ vcl::filter::PDFDocument& rDocument)
+{
+ auto pTrailer = std::make_unique<vcl::filter::PDFTrailerElement>(rDocument);
+ auto pTrailerPtr = pTrailer.get();
+ rElements.push_back(std::move(pTrailer));
+ return pTrailerPtr;
+}
+void addEndObjectElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements)
+{
+ rElements.push_back(std::make_unique<vcl::filter::PDFEndObjectElement>());
+}
+
+void addDictionaryElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements)
+{
+ rElements.push_back(std::make_unique<vcl::filter::PDFDictionaryElement>());
+}
+
+void addEndDictionaryElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements)
+{
+ rElements.push_back(std::make_unique<vcl::filter::PDFEndDictionaryElement>());
+}
+
+void addNameElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+ OString const& rName)
+{
+ auto pNameElement = std::make_unique<vcl::filter::PDFNameElement>();
+ pNameElement->SetValue(rName);
+ rElements.push_back(std::move(pNameElement));
+}
+
+vcl::filter::PDFNumberElement*
+addNumberElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements, double fNumber)
+{
+ auto pNumberElement = std::make_unique<vcl::filter::PDFNumberElement>();
+ auto pNumberElementPtr = pNumberElement.get();
+ pNumberElement->SetValue(fNumber);
+ rElements.push_back(std::move(pNumberElement));
+ return pNumberElementPtr;
+}
+
+void addReferenceElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+ vcl::filter::PDFDocument& rDocument,
+ vcl::filter::PDFNumberElement* pNumber1,
+ vcl::filter::PDFNumberElement* pNumber2)
+{
+ auto pReferenceElement
+ = std::make_unique<vcl::filter::PDFReferenceElement>(rDocument, *pNumber1, *pNumber2);
+ rElements.push_back(std::move(pReferenceElement));
+}
+
+void addArrayElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+ vcl::filter::PDFObjectElement* pObjectPointer)
+{
+ auto pArray = std::make_unique<vcl::filter::PDFArrayElement>(pObjectPointer);
+ rElements.push_back(std::move(pArray));
+}
+
+void addEndArrayElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements)
+{
+ rElements.push_back(std::make_unique<vcl::filter::PDFEndArrayElement>());
+}
+
+} // end anonymous namespace
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseEmptyDictionary)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+ addObjectElement(aElements, aDocument, 1, 0);
+ addDictionaryElement(aElements);
+ addEndDictionaryElement(aElements);
+ addEndObjectElement(aElements);
+
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pObject);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pObject);
+
+ CPPUNIT_ASSERT(pObject->GetDictionary());
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pObject->GetDictionary()->GetItems().size());
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseDictionaryWithName)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+ {
+ addObjectElement(aElements, aDocument, 1, 0);
+ addDictionaryElement(aElements);
+ addNameElement(aElements, "Test");
+ addNumberElement(aElements, 30.0);
+ addEndDictionaryElement(aElements);
+ addEndObjectElement(aElements);
+ }
+
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pObject);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pObject);
+
+ CPPUNIT_ASSERT(pObject->GetDictionary());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pObject->GetDictionary()->GetItems().size());
+ auto& rItems = pObject->GetDictionary()->GetItems();
+ auto pNumberElement = dynamic_cast<vcl::filter::PDFNumberElement*>(rItems.at("Test"));
+ CPPUNIT_ASSERT(pNumberElement);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(30.0, pNumberElement->GetValue(), 1e-4);
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseDictionaryNested)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+ {
+ addObjectElement(aElements, aDocument, 1, 0);
+ addDictionaryElement(aElements);
+
+ addNameElement(aElements, "Nested1");
+ addDictionaryElement(aElements);
+ {
+ addNameElement(aElements, "Nested2");
+ addDictionaryElement(aElements);
+ {
+ addNameElement(aElements, "SomeOtherKey");
+ addNameElement(aElements, "SomeOtherValue");
+ }
+ addEndDictionaryElement(aElements);
+ }
+ addEndDictionaryElement(aElements);
+
+ addNameElement(aElements, "SomeOtherKey");
+ addNameElement(aElements, "SomeOtherValue");
+
+ addEndObjectElement(aElements);
+ }
+
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pObject);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pObject);
+
+ CPPUNIT_ASSERT(pObject->GetDictionary());
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pObject->GetDictionary()->GetItems().size());
+ CPPUNIT_ASSERT(pObject->Lookup("Nested1"));
+ CPPUNIT_ASSERT(pObject->Lookup("SomeOtherKey"));
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseEmptyArray)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+ {
+ auto pObjectPtr = addObjectElement(aElements, aDocument, 1, 0);
+ addArrayElement(aElements, pObjectPtr);
+ addEndArrayElement(aElements);
+ addEndObjectElement(aElements);
+ }
+
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pObject);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pObject);
+
+ CPPUNIT_ASSERT(pObject->GetArray());
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pObject->GetArray()->GetElements().size());
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseArrayWithSimpleElements)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+
+ {
+ auto pObjectPtr = addObjectElement(aElements, aDocument, 1, 0);
+ addArrayElement(aElements, pObjectPtr);
+ addNameElement(aElements, "Test");
+ addNumberElement(aElements, 30.0);
+ addEndArrayElement(aElements);
+ addEndObjectElement(aElements);
+ }
+
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pObject);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pObject);
+
+ CPPUNIT_ASSERT(pObject->GetArray());
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pObject->GetArray()->GetElements().size());
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseArrayNestedWithNumbers)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+
+ // [ 1 [ 10 ] 2 ]
+ {
+ auto pObjectPtr = addObjectElement(aElements, aDocument, 1, 0);
+ addArrayElement(aElements, pObjectPtr);
+ {
+ addNumberElement(aElements, 1.0);
+ addArrayElement(aElements, pObjectPtr);
+ addNumberElement(aElements, 10.0);
+ addEndArrayElement(aElements);
+ addNumberElement(aElements, 2.0);
+ }
+ addEndArrayElement(aElements);
+ addEndObjectElement(aElements);
+ }
+
+ // Assert
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pObject);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pObject);
+
+ CPPUNIT_ASSERT(pObject->GetArray());
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pObject->GetArray()->GetElements().size());
+ auto pRootArray = pObject->GetArray();
+
+ auto pNumber1 = dynamic_cast<vcl::filter::PDFNumberElement*>(pRootArray->GetElement(0));
+ CPPUNIT_ASSERT(pNumber1);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, pNumber1->GetValue(), 1e-4);
+
+ auto pArray3 = dynamic_cast<vcl::filter::PDFArrayElement*>(pRootArray->GetElement(1));
+ CPPUNIT_ASSERT(pArray3);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pArray3->GetElements().size());
+
+ auto pNumber2 = dynamic_cast<vcl::filter::PDFNumberElement*>(pRootArray->GetElement(2));
+ CPPUNIT_ASSERT(pNumber1);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, pNumber2->GetValue(), 1e-4);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseArrayNestedWithNames)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+
+ // [/Inner1/Inner2[/Inner31][/Inner41/Inner42[/Inner431/Inner432]][/Inner51[/Inner521]]]
+
+ {
+ auto pObjectPtr = addObjectElement(aElements, aDocument, 1, 0);
+ addArrayElement(aElements, pObjectPtr);
+ {
+ addNameElement(aElements, "Inner1");
+ addNameElement(aElements, "Inner2");
+
+ addArrayElement(aElements, pObjectPtr);
+ {
+ addNameElement(aElements, "Inner31");
+ }
+ addEndArrayElement(aElements);
+
+ addArrayElement(aElements, pObjectPtr);
+ {
+ addNameElement(aElements, "Inner41");
+ addNameElement(aElements, "Inner42");
+ addArrayElement(aElements, pObjectPtr);
+ {
+ addNameElement(aElements, "Inner431");
+ addNameElement(aElements, "Inner432");
+ }
+ addEndArrayElement(aElements);
+ }
+ addEndArrayElement(aElements);
+
+ addArrayElement(aElements, pObjectPtr);
+ {
+ addNameElement(aElements, "Inner51");
+ addArrayElement(aElements, pObjectPtr);
+ {
+ addNameElement(aElements, "Inner521");
+ }
+ addEndArrayElement(aElements);
+ }
+ addEndArrayElement(aElements);
+ }
+ addEndArrayElement(aElements);
+ addEndObjectElement(aElements);
+ }
+
+ // Assert
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pObject);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pObject);
+
+ CPPUNIT_ASSERT(pObject->GetArray());
+ CPPUNIT_ASSERT_EQUAL(size_t(5), pObject->GetArray()->GetElements().size());
+ auto pRootArray = pObject->GetArray();
+
+ auto pName1 = dynamic_cast<vcl::filter::PDFNameElement*>(pRootArray->GetElement(0));
+ CPPUNIT_ASSERT(pName1);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner1"), pName1->GetValue());
+
+ auto pName2 = dynamic_cast<vcl::filter::PDFNameElement*>(pRootArray->GetElement(1));
+ CPPUNIT_ASSERT(pName2);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner2"), pName2->GetValue());
+
+ auto pArray3 = dynamic_cast<vcl::filter::PDFArrayElement*>(pRootArray->GetElement(2));
+ CPPUNIT_ASSERT(pArray3);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pArray3->GetElements().size());
+
+ auto pInner31 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray3->GetElement(0));
+ CPPUNIT_ASSERT(pInner31);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner31"), pInner31->GetValue());
+
+ auto pArray4 = dynamic_cast<vcl::filter::PDFArrayElement*>(pRootArray->GetElement(3));
+ CPPUNIT_ASSERT(pArray4);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pArray4->GetElements().size());
+
+ auto pInner41 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray4->GetElement(0));
+ CPPUNIT_ASSERT(pInner41);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner41"), pInner41->GetValue());
+
+ auto pInner42 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray4->GetElement(1));
+ CPPUNIT_ASSERT(pInner42);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner42"), pInner42->GetValue());
+
+ auto pArray43 = dynamic_cast<vcl::filter::PDFArrayElement*>(pArray4->GetElement(2));
+ CPPUNIT_ASSERT(pArray43);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pArray43->GetElements().size());
+
+ auto pInner431 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray43->GetElement(0));
+ CPPUNIT_ASSERT(pInner431);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner431"), pInner431->GetValue());
+
+ auto pInner432 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray43->GetElement(1));
+ CPPUNIT_ASSERT(pInner432);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner432"), pInner432->GetValue());
+
+ auto pArray5 = dynamic_cast<vcl::filter::PDFArrayElement*>(pRootArray->GetElement(4));
+ CPPUNIT_ASSERT(pArray5);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pArray5->GetElements().size());
+
+ auto pInner51 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray5->GetElement(0));
+ CPPUNIT_ASSERT(pInner51);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner51"), pInner51->GetValue());
+
+ auto pArray52 = dynamic_cast<vcl::filter::PDFArrayElement*>(pArray5->GetElement(1));
+ CPPUNIT_ASSERT(pArray52);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pArray52->GetElements().size());
+
+ auto pInner521 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray52->GetElement(0));
+ CPPUNIT_ASSERT(pInner521);
+ CPPUNIT_ASSERT_EQUAL(OString("Inner521"), pInner521->GetValue());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseTrailer)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+
+ {
+ addTrailerObjectElement(aElements, aDocument);
+ addDictionaryElement(aElements);
+ addNameElement(aElements, "Size");
+ addNumberElement(aElements, 11.0);
+ addEndDictionaryElement(aElements);
+ }
+ {
+ auto pTrailer = dynamic_cast<vcl::filter::PDFTrailerElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pTrailer);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pTrailer);
+
+ CPPUNIT_ASSERT(pTrailer->GetDictionary());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pTrailer->GetDictionary()->GetItems().size());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseTrailerWithReference)
+{
+ std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+ vcl::filter::PDFDocument aDocument;
+
+ {
+ addTrailerObjectElement(aElements, aDocument);
+ addDictionaryElement(aElements);
+ addNameElement(aElements, "Reference");
+ auto pNumberElement1 = addNumberElement(aElements, 11.0);
+ auto pNumberElement2 = addNumberElement(aElements, 0.0);
+ addReferenceElement(aElements, aDocument, pNumberElement1, pNumberElement2);
+ addEndDictionaryElement(aElements);
+ }
+ {
+ auto pTrailer = dynamic_cast<vcl::filter::PDFTrailerElement*>(aElements[0].get());
+ CPPUNIT_ASSERT(pTrailer);
+
+ vcl::filter::PDFObjectParser aParser(aElements);
+ aParser.parse(pTrailer);
+
+ CPPUNIT_ASSERT(pTrailer->GetDictionary());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pTrailer->GetDictionary()->GetItems().size());
+ auto pElement = pTrailer->Lookup("Reference");
+ CPPUNIT_ASSERT(pElement);
+ auto pReference = dynamic_cast<vcl::filter::PDFReferenceElement*>(pElement);
+ CPPUNIT_ASSERT(pReference);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(11.0, pReference->GetObjectValue(), 1e-4);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, pReference->GetGenerationValue(), 1e-4);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/PDFiumLibraryTest.cxx b/vcl/qa/cppunit/PDFiumLibraryTest.cxx
new file mode 100644
index 000000000..1f82f24ac
--- /dev/null
+++ b/vcl/qa/cppunit/PDFiumLibraryTest.cxx
@@ -0,0 +1,454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <string_view>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <unotest/bootstrapfixturebase.hxx>
+#include <unotest/directories.hxx>
+#include <unotools/datetime.hxx>
+
+#include <com/sun/star/util/DateTime.hpp>
+
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+
+#include <vcl/filter/PDFiumLibrary.hxx>
+#include <vcl/pdfread.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+
+class PDFiumLibraryTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/data/") + sFileName;
+ }
+
+ void testDocument();
+ void testPages();
+ void testPageObjects();
+ void testAnnotationsMadeInEvince();
+ void testAnnotationsMadeInAcrobat();
+ void testAnnotationsDifferentTypes();
+ void testTools();
+ void testFormFields();
+
+ CPPUNIT_TEST_SUITE(PDFiumLibraryTest);
+ CPPUNIT_TEST(testDocument);
+ CPPUNIT_TEST(testPages);
+ CPPUNIT_TEST(testPageObjects);
+ CPPUNIT_TEST(testAnnotationsMadeInEvince);
+ CPPUNIT_TEST(testAnnotationsMadeInAcrobat);
+ CPPUNIT_TEST(testAnnotationsDifferentTypes);
+ CPPUNIT_TEST(testTools);
+ CPPUNIT_TEST(testFormFields);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void PDFiumLibraryTest::testDocument()
+{
+ OUString aURL = getFullUrl(u"Pangram.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ auto pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
+
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ CPPUNIT_ASSERT(pPdfium);
+ auto pDocument
+ = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
+ CPPUNIT_ASSERT(pDocument);
+
+ CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
+
+ auto aSize = pDocument->getPageSize(0);
+ CPPUNIT_ASSERT_EQUAL(612.0, aSize.getX());
+ CPPUNIT_ASSERT_EQUAL(792.0, aSize.getY());
+}
+
+void PDFiumLibraryTest::testPages()
+{
+ OUString aURL = getFullUrl(u"Pangram.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ auto pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
+
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ auto pDocument
+ = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
+ CPPUNIT_ASSERT(pDocument);
+
+ CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
+
+ auto pPage = pDocument->openPage(0);
+ CPPUNIT_ASSERT(pPage);
+}
+
+void PDFiumLibraryTest::testPageObjects()
+{
+ OUString aURL = getFullUrl(u"Pangram.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ auto pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
+
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ auto pDocument
+ = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
+ CPPUNIT_ASSERT(pDocument);
+
+ CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
+
+ auto pPage = pDocument->openPage(0);
+ CPPUNIT_ASSERT(pPage);
+
+ CPPUNIT_ASSERT_EQUAL(12, pPage->getObjectCount());
+
+ auto pPageObject = pPage->getObject(0);
+ auto pTextPage = pPage->getTextPage();
+
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Text, pPageObject->getType());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("The quick, brown fox jumps over a lazy dog. DJs flock by when "
+ "MTV ax quiz prog. Junk MTV quiz "),
+ pPageObject->getText(pTextPage));
+
+ CPPUNIT_ASSERT_EQUAL(12.0, pPageObject->getFontSize());
+ CPPUNIT_ASSERT_EQUAL(OUString("Liberation Serif"), pPageObject->getFontName());
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFTextRenderMode::Fill, pPageObject->getTextRenderMode());
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPageObject->getFillColor());
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPageObject->getStrokeColor());
+
+ basegfx::B2DHomMatrix aMatrix = pPageObject->getMatrix();
+ // Ignore translation, ensure there is no rotate/scale.
+ aMatrix.set(0, 2, 0);
+ aMatrix.set(1, 2, 0);
+ CPPUNIT_ASSERT_EQUAL(true, aMatrix.isIdentity());
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(057.01, pPageObject->getBounds().getMinX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(721.51, pPageObject->getBounds().getMinY(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(539.48, pPageObject->getBounds().getMaxX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(732.54, pPageObject->getBounds().getMaxY(), 1E-2);
+}
+
+void PDFiumLibraryTest::testAnnotationsMadeInEvince()
+{
+ OUString aURL = getFullUrl(u"PangramWithAnnotations.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ auto pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
+
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ auto pDocument
+ = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
+ CPPUNIT_ASSERT(pDocument);
+
+ CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
+
+ auto pPage = pDocument->openPage(0);
+ CPPUNIT_ASSERT(pPage);
+
+ CPPUNIT_ASSERT_EQUAL(2, pPage->getAnnotationCount());
+
+ {
+ auto pAnnotation = pPage->getAnnotation(0);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text, pAnnotation->getSubType());
+
+ OUString aPopupString = pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle);
+ CPPUNIT_ASSERT_EQUAL(OUString("quikee"), aPopupString);
+
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("Annotation test"), aContentsString);
+
+ CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey(vcl::pdf::constDictionaryKeyPopup));
+ auto pPopupAnnotation = pAnnotation->getLinked(vcl::pdf::constDictionaryKeyPopup);
+ CPPUNIT_ASSERT(pPopupAnnotation);
+
+ CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationIndex(pPopupAnnotation));
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pPopupAnnotation->getSubType());
+
+ OUString sDateTimeString
+ = pAnnotation->getString(vcl::pdf::constDictionaryKeyModificationDate);
+ CPPUNIT_ASSERT_EQUAL(OUString("D:20200612201322+02'00"), sDateTimeString);
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(1);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pAnnotation->getSubType());
+ }
+}
+
+void PDFiumLibraryTest::testAnnotationsMadeInAcrobat()
+{
+ OUString aURL = getFullUrl(u"PangramAcrobatAnnotations.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ auto pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
+
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ auto pDocument
+ = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
+ CPPUNIT_ASSERT(pDocument);
+
+ CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
+
+ auto pPage = pDocument->openPage(0);
+ CPPUNIT_ASSERT(pPage);
+
+ CPPUNIT_ASSERT_EQUAL(4, pPage->getAnnotationCount());
+
+ {
+ auto pAnnotation = pPage->getAnnotation(0);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text, pAnnotation->getSubType());
+
+ OUString aPopupString = pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle);
+ CPPUNIT_ASSERT_EQUAL(OUString("quikee"), aPopupString);
+
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("YEEEY"), aContentsString);
+
+ CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey(vcl::pdf::constDictionaryKeyPopup));
+ auto pPopupAnnotation = pAnnotation->getLinked(vcl::pdf::constDictionaryKeyPopup);
+ CPPUNIT_ASSERT(pPopupAnnotation);
+
+ CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationIndex(pPopupAnnotation));
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pPopupAnnotation->getSubType());
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(1);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pAnnotation->getSubType());
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(2);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text, pAnnotation->getSubType());
+
+ OUString aPopupString = pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle);
+ CPPUNIT_ASSERT_EQUAL(OUString("quikee"), aPopupString);
+
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("Note"), aContentsString);
+
+ CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey(vcl::pdf::constDictionaryKeyPopup));
+ auto pPopupAnnotation = pAnnotation->getLinked(vcl::pdf::constDictionaryKeyPopup);
+ CPPUNIT_ASSERT(pPopupAnnotation);
+
+ CPPUNIT_ASSERT_EQUAL(3, pPage->getAnnotationIndex(pPopupAnnotation));
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pPopupAnnotation->getSubType());
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(3);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pAnnotation->getSubType());
+ }
+}
+
+void PDFiumLibraryTest::testFormFields()
+{
+ // Given a document with a form field that looks like plain text:
+ OUString aURL = getFullUrl(u"form-fields.pdf");
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ SvMemoryStream aMemory;
+ aMemory.WriteStream(aFileStream);
+ aMemory.Seek(0);
+
+ // When rendering its first (and only) page to a bitmap:
+ std::vector<BitmapEx> aBitmaps;
+ int nRet = vcl::RenderPDFBitmaps(aMemory.GetData(), aMemory.GetSize(), aBitmaps);
+ CPPUNIT_ASSERT(nRet);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aBitmaps.size());
+
+ // Then make sure the bitmap contains that text:
+ Bitmap aBitmap = aBitmaps[0].GetBitmap();
+ BitmapReadAccess aAccess(aBitmap);
+ Size aSize = aBitmap.GetSizePixel();
+ std::set<sal_uInt32> aColors;
+ for (tools::Long y = 0; y < aSize.Height(); ++y)
+ {
+ for (tools::Long x = 0; x < aSize.Width(); ++x)
+ {
+ aColors.insert(static_cast<sal_uInt32>(aAccess.GetPixel(y, x)));
+ }
+ }
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected greater than: 1
+ // - Actual : 1
+ // i.e. at least black text and white background is expected (possibly more, due to
+ // anti-aliasing), but nothing was rendered.
+ CPPUNIT_ASSERT_GREATER(static_cast<size_t>(1), aColors.size());
+}
+
+void PDFiumLibraryTest::testAnnotationsDifferentTypes()
+{
+ OUString aURL = getFullUrl(u"PangramWithMultipleTypeOfAnnotations.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ auto pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
+
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ auto pDocument
+ = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
+ CPPUNIT_ASSERT(pDocument);
+
+ CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
+
+ auto pPage = pDocument->openPage(0);
+ CPPUNIT_ASSERT(pPage);
+
+ CPPUNIT_ASSERT_EQUAL(6, pPage->getAnnotationCount());
+
+ {
+ auto pAnnotation = pPage->getAnnotation(0);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::FreeText, pAnnotation->getSubType());
+ CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("Inline Note"), aContentsString);
+ auto const& rLineGeometry = pAnnotation->getLineGeometry();
+ CPPUNIT_ASSERT_EQUAL(true, rLineGeometry.empty());
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(1);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Ink, pAnnotation->getSubType());
+ CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("Freehand Text"), aContentsString);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pAnnotation->getInkStrokes().size());
+ auto const& aInkStrokes = pAnnotation->getInkStrokes();
+ auto const& aPoints = aInkStrokes[0];
+ CPPUNIT_ASSERT_EQUAL(size_t(74), aPoints.size());
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0f, pAnnotation->getBorderWidth(), 1E-2);
+ auto const& rLineGeometry = pAnnotation->getLineGeometry();
+ CPPUNIT_ASSERT_EQUAL(true, rLineGeometry.empty());
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(2);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Line, pAnnotation->getSubType());
+ CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("Line Text"), aContentsString);
+ auto const& rLineGeometry = pAnnotation->getLineGeometry();
+ CPPUNIT_ASSERT_EQUAL(false, rLineGeometry.empty());
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(3);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Polygon, pAnnotation->getSubType());
+ CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
+ CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey("Vertices"));
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("Polygon Text"), aContentsString);
+ auto const& aVertices = pAnnotation->getVertices();
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aVertices.size());
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0f, pAnnotation->getBorderWidth(), 1E-2);
+ auto const& rLineGeometry = pAnnotation->getLineGeometry();
+ CPPUNIT_ASSERT_EQUAL(true, rLineGeometry.empty());
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(4);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Circle, pAnnotation->getSubType());
+ CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("Ellipse Text"), aContentsString);
+ auto const& rLineGeometry = pAnnotation->getLineGeometry();
+ CPPUNIT_ASSERT_EQUAL(true, rLineGeometry.empty());
+ }
+
+ {
+ auto pAnnotation = pPage->getAnnotation(5);
+ CPPUNIT_ASSERT(pAnnotation);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Square, pAnnotation->getSubType());
+ CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
+ OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
+ CPPUNIT_ASSERT_EQUAL(OUString("Rectangle Text"), aContentsString);
+ CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0xE0, 0x00), pAnnotation->getColor());
+ CPPUNIT_ASSERT_EQUAL(false, pAnnotation->hasKey(vcl::pdf::constDictionaryKeyInteriorColor));
+ auto const& rLineGeometry = pAnnotation->getLineGeometry();
+ CPPUNIT_ASSERT_EQUAL(true, rLineGeometry.empty());
+ }
+}
+
+void PDFiumLibraryTest::testTools()
+{
+ OUString sConverted = vcl::pdf::convertPdfDateToISO8601("D:20200612201322+02'00");
+
+ css::util::DateTime aDateTime;
+ CPPUNIT_ASSERT(utl::ISO8601parseDateTime(sConverted, aDateTime));
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(2020), aDateTime.Year);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), aDateTime.Month);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(12), aDateTime.Day);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(20), aDateTime.Hours);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(13), aDateTime.Minutes);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(22), aDateTime.Seconds);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), aDateTime.NanoSeconds);
+ CPPUNIT_ASSERT_EQUAL(false, bool(aDateTime.IsUTC));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PDFiumLibraryTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/ScanlineToolsTest.cxx b/vcl/qa/cppunit/ScanlineToolsTest.cxx
new file mode 100644
index 000000000..c6751b827
--- /dev/null
+++ b/vcl/qa/cppunit/ScanlineToolsTest.cxx
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <bitmap/ScanlineTools.hxx>
+
+namespace
+{
+class ScanlineToolsTest : public CppUnit::TestFixture
+{
+ void ScanlineTransformer_32_ARGB();
+ void ScanlineTransformer_24_BGR();
+ void ScanlineTransformer_8bit_Palette();
+ void ScanlineTransformer_4bit_Palette();
+ void ScanlineTransformer_1bit_Palette();
+
+ CPPUNIT_TEST_SUITE(ScanlineToolsTest);
+ CPPUNIT_TEST(ScanlineTransformer_32_ARGB);
+ CPPUNIT_TEST(ScanlineTransformer_24_BGR);
+ CPPUNIT_TEST(ScanlineTransformer_8bit_Palette);
+ CPPUNIT_TEST(ScanlineTransformer_4bit_Palette);
+ CPPUNIT_TEST(ScanlineTransformer_1bit_Palette);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void ScanlineToolsTest::ScanlineTransformer_32_ARGB()
+{
+ BitmapPalette aPalette;
+ std::unique_ptr<vcl::bitmap::ScanlineTransformer> pScanlineTransformer
+ = vcl::bitmap::getScanlineTransformer(32, aPalette);
+
+ std::vector<sal_uInt8> aScanLine(5 * 4, 0); // 5 * 4 BytesPerPixel
+ pScanlineTransformer->startLine(aScanLine.data());
+
+ std::vector<Color> aColors{
+ Color(ColorTransparency, 0, 10, 250, 120), Color(ColorTransparency, 50, 30, 230, 110),
+ Color(ColorTransparency, 100, 50, 210, 100), Color(ColorTransparency, 150, 70, 190, 90),
+ Color(ColorTransparency, 200, 90, 170, 80),
+ };
+
+ for (Color const& aColor : aColors)
+ {
+ pScanlineTransformer->writePixel(aColor);
+ }
+
+ std::vector<sal_uInt8> aExpectedBytes{ 0, 10, 250, 120, 50, 30, 230, 110, 100, 50,
+ 210, 100, 150, 70, 190, 90, 200, 90, 170, 80 };
+
+ for (size_t i = 0; i < aScanLine.size(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(int(aExpectedBytes[i]), int(aScanLine[i]));
+ }
+}
+
+void ScanlineToolsTest::ScanlineTransformer_24_BGR()
+{
+ BitmapPalette aPalette;
+ std::unique_ptr<vcl::bitmap::ScanlineTransformer> pScanlineTransformer
+ = vcl::bitmap::getScanlineTransformer(24, aPalette);
+
+ std::vector<sal_uInt8> aScanLine(5 * 3, 0); // 5 * 3 BytesPerPixel
+ pScanlineTransformer->startLine(aScanLine.data());
+
+ std::vector<Color> aColors{
+ Color(ColorTransparency, 0, 10, 250, 120), Color(ColorTransparency, 50, 30, 230, 110),
+ Color(ColorTransparency, 100, 50, 210, 100), Color(ColorTransparency, 150, 70, 190, 90),
+ Color(ColorTransparency, 200, 90, 170, 80),
+ };
+
+ for (Color const& aColor : aColors)
+ {
+ pScanlineTransformer->writePixel(aColor);
+ }
+
+ std::vector<sal_uInt8> aExpectedBytes{ 120, 250, 10, 110, 230, 30, 100, 210,
+ 50, 90, 190, 70, 80, 170, 90 };
+
+ for (size_t i = 0; i < aScanLine.size(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(int(aExpectedBytes[i]), int(aScanLine[i]));
+ }
+}
+
+void ScanlineToolsTest::ScanlineTransformer_8bit_Palette()
+{
+ std::vector<Color> aColors{
+ Color(ColorTransparency, 0, 10, 250, 120), Color(ColorTransparency, 50, 30, 230, 110),
+ Color(ColorTransparency, 100, 50, 210, 100), Color(ColorTransparency, 150, 70, 190, 90),
+ Color(ColorTransparency, 200, 90, 170, 80),
+ };
+
+ BitmapPalette aPalette(256);
+ for (size_t i = 0; i < aColors.size(); ++i)
+ aPalette[i] = aColors[i];
+
+ std::unique_ptr<vcl::bitmap::ScanlineTransformer> pScanlineTransformer
+ = vcl::bitmap::getScanlineTransformer(8, aPalette);
+
+ std::vector<sal_uInt8> aScanLine(5, 0); // 5 * 1 BytesPerPixel
+ pScanlineTransformer->startLine(aScanLine.data());
+
+ for (Color const& aColor : aColors)
+ {
+ pScanlineTransformer->writePixel(aColor);
+ }
+
+ std::vector<sal_uInt8> aExpectedBytes{ 0, 1, 2, 3, 4 };
+
+ for (size_t i = 0; i < aScanLine.size(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(int(aExpectedBytes[i]), int(aScanLine[i]));
+ }
+
+ pScanlineTransformer->startLine(aScanLine.data());
+
+ for (size_t i = 0; i < aColors.size(); ++i)
+ {
+ Color aColor = pScanlineTransformer->readPixel();
+ CPPUNIT_ASSERT_EQUAL(aColors[i], aColor);
+ }
+}
+
+void ScanlineToolsTest::ScanlineTransformer_4bit_Palette()
+{
+ std::vector<Color> aColors{
+ Color(10, 250, 120), Color(30, 230, 110), Color(50, 210, 100),
+ Color(70, 190, 90), Color(90, 170, 80), Color(110, 150, 70),
+ };
+
+ BitmapPalette aPalette(16);
+ for (size_t i = 0; i < aColors.size(); ++i)
+ {
+ aPalette[i] = aColors[i];
+ }
+
+ std::unique_ptr<vcl::bitmap::ScanlineTransformer> pScanlineTransformer
+ = vcl::bitmap::getScanlineTransformer(4, aPalette);
+
+ std::vector<sal_uInt8> aScanLine(3, 0); // 6 * 0.5 BytesPerPixel
+ pScanlineTransformer->startLine(aScanLine.data());
+
+ for (Color const& aColor : aColors)
+ {
+ pScanlineTransformer->writePixel(aColor);
+ }
+
+ std::vector<sal_uInt8> aExpectedBytes{ 0x01, 0x23, 0x45 };
+
+ for (size_t i = 0; i < aScanLine.size(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(int(aExpectedBytes[i]), int(aScanLine[i]));
+ }
+
+ pScanlineTransformer->startLine(aScanLine.data());
+
+ for (size_t i = 0; i < aColors.size(); ++i)
+ {
+ Color aColor = pScanlineTransformer->readPixel();
+ CPPUNIT_ASSERT_EQUAL(aColors[i], aColor);
+ }
+}
+
+void ScanlineToolsTest::ScanlineTransformer_1bit_Palette()
+{
+ std::vector<Color> aColors{
+ Color(10, 250, 120), Color(30, 230, 110), Color(50, 210, 100), Color(70, 190, 90),
+ Color(90, 170, 80), Color(110, 150, 70), Color(130, 130, 60), Color(150, 110, 50),
+ Color(170, 90, 40), Color(190, 70, 30), Color(210, 50, 20), Color(230, 30, 10),
+ Color(250, 10, 0),
+ };
+
+ BitmapPalette aPalette(2);
+ aPalette[0] = Color(10, 250, 120);
+ aPalette[1] = Color(110, 150, 70);
+
+ std::unique_ptr<vcl::bitmap::ScanlineTransformer> pScanlineTransformer
+ = vcl::bitmap::getScanlineTransformer(1, aPalette);
+
+ std::vector<sal_uInt8> aScanLine(2, 0); // 13 * 1/8 BytesPerPixel
+ pScanlineTransformer->startLine(aScanLine.data());
+
+ for (Color const& aColor : aColors)
+ {
+ pScanlineTransformer->writePixel(aColor);
+ }
+
+ std::vector<sal_uInt8> aExpectedBytes{
+ // We expect 3x index 0 and 10x index 1 => 000 111111111
+ 0x1f, // 0001 1111
+ 0xf8 // 1111 1000
+ };
+
+ for (size_t i = 0; i < aScanLine.size(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(int(aExpectedBytes[i]), int(aScanLine[i]));
+ }
+
+ pScanlineTransformer->startLine(aScanLine.data());
+
+ std::vector<Color> aColorsExpected{
+ Color(10, 250, 120), Color(10, 250, 120), Color(10, 250, 120), Color(110, 150, 70),
+ Color(110, 150, 70), Color(110, 150, 70), Color(110, 150, 70), Color(110, 150, 70),
+ Color(110, 150, 70), Color(110, 150, 70), Color(110, 150, 70), Color(110, 150, 70),
+ Color(110, 150, 70),
+ };
+
+ for (size_t i = 0; i < aColors.size(); ++i)
+ {
+ Color aColor = pScanlineTransformer->readPixel();
+ CPPUNIT_ASSERT_EQUAL(aColorsExpected[i], aColor);
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ScanlineToolsTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/TypeSerializerTest.cxx b/vcl/qa/cppunit/TypeSerializerTest.cxx
new file mode 100644
index 000000000..1c7b93d25
--- /dev/null
+++ b/vcl/qa/cppunit/TypeSerializerTest.cxx
@@ -0,0 +1,393 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <config_oox.h>
+#include <config_features.h>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <unotest/directories.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/gdimtf.hxx>
+#include <comphelper/hash.hxx>
+#include <tools/vcompat.hxx>
+#include <comphelper/fileformat.h>
+#include <tools/fract.hxx>
+
+#include <vcl/TypeSerializer.hxx>
+
+#if USE_TLS_NSS
+#include <nss.h>
+#endif
+
+namespace
+{
+constexpr OUStringLiteral DATA_DIRECTORY = u"/vcl/qa/cppunit/data/";
+
+std::vector<unsigned char> calculateHash(SvStream& rStream)
+{
+ rStream.Seek(STREAM_SEEK_TO_BEGIN);
+ comphelper::Hash aHashEngine(comphelper::HashType::SHA1);
+ const sal_uInt32 nSize(rStream.remainingSize());
+ std::vector<sal_uInt8> aData(nSize);
+ aHashEngine.update(aData.data(), nSize);
+ return aHashEngine.finalize();
+}
+
+std::string toHexString(const std::vector<unsigned char>& a)
+{
+ std::stringstream aStrm;
+ for (auto& i : a)
+ {
+ aStrm << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(i);
+ }
+
+ return aStrm.str();
+}
+
+class TypeSerializerTest : public CppUnit::TestFixture
+{
+public:
+ ~TypeSerializerTest();
+
+private:
+ void testGradient();
+ void testGraphic_Vector();
+ void testGraphic_Bitmap_NoGfxLink();
+ void testGraphic_Animation();
+ void testGraphic_GDIMetaFile();
+ void testMapMode();
+
+ CPPUNIT_TEST_SUITE(TypeSerializerTest);
+ CPPUNIT_TEST(testGradient);
+ CPPUNIT_TEST(testGraphic_Vector);
+ CPPUNIT_TEST(testGraphic_Bitmap_NoGfxLink);
+ CPPUNIT_TEST(testGraphic_Animation);
+ CPPUNIT_TEST(testGraphic_GDIMetaFile);
+ CPPUNIT_TEST(testMapMode);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+TypeSerializerTest::~TypeSerializerTest()
+{
+#if USE_TLS_NSS
+ NSS_Shutdown();
+#endif
+}
+
+void TypeSerializerTest::testGradient()
+{
+ Gradient aGradient(GradientStyle::Radial, Color(0xFF, 0x00, 0x00), Color(0x00, 0xFF, 0x00));
+ aGradient.SetAngle(900_deg10);
+ aGradient.SetBorder(5);
+ aGradient.SetOfsX(11);
+ aGradient.SetOfsY(12);
+ aGradient.SetStartIntensity(21);
+ aGradient.SetEndIntensity(22);
+ aGradient.SetSteps(30);
+
+ SvMemoryStream aStream;
+ TypeSerializer aSerializer(aStream);
+ aSerializer.writeGradient(aGradient);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ Gradient aReadGradient;
+ aSerializer.readGradient(aReadGradient);
+ CPPUNIT_ASSERT_EQUAL(GradientStyle::Radial, aReadGradient.GetStyle());
+ CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0x00, 0x00), aReadGradient.GetStartColor());
+ CPPUNIT_ASSERT_EQUAL(Color(0x00, 0xFF, 0x00), aReadGradient.GetEndColor());
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(900), aReadGradient.GetAngle().get());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(5), aReadGradient.GetBorder());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(11), aReadGradient.GetOfsX());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(12), aReadGradient.GetOfsY());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(21), aReadGradient.GetStartIntensity());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(22), aReadGradient.GetEndIntensity());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(30), aReadGradient.GetSteps());
+}
+
+void TypeSerializerTest::testGraphic_Vector()
+{
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "SimpleExample.svg";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+ BitmapChecksum aChecksum = aGraphic.getVectorGraphicData()->GetChecksum();
+
+ // Test TypeSerializer - Native Format 5
+ {
+ SvMemoryStream aMemoryStream;
+ aMemoryStream.SetVersion(SOFFICE_FILEFORMAT_50);
+ aMemoryStream.SetCompressMode(SvStreamCompressFlags::NATIVE);
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.writeGraphic(aGraphic);
+ }
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(290), aMemoryStream.remainingSize());
+ std::vector<unsigned char> aHash = calculateHash(aMemoryStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("ee55ab6faa73b61b68bc3d5628d95f0d3c528e2a"),
+ toHexString(aHash));
+
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ sal_uInt32 nType;
+ aMemoryStream.ReadUInt32(nType);
+ CPPUNIT_ASSERT_EQUAL(COMPAT_FORMAT('N', 'A', 'T', '5'), nType);
+
+ // Read it back
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ Graphic aNewGraphic;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.readGraphic(aNewGraphic);
+ }
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aNewGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(aChecksum, aNewGraphic.getVectorGraphicData()->GetChecksum());
+ }
+
+ // Test TypeSerializer - Normal
+ {
+ SvMemoryStream aMemoryStream;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.writeGraphic(aGraphic);
+ }
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(233), aMemoryStream.remainingSize());
+ std::vector<unsigned char> aHash = calculateHash(aMemoryStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("c2bed2099ce617f1cc035701de5186f0d43e3064"),
+ toHexString(aHash));
+
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ sal_uInt32 nType;
+ aMemoryStream.ReadUInt32(nType);
+ CPPUNIT_ASSERT_EQUAL(createMagic('s', 'v', 'g', '0'), nType);
+
+ // Read it back
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ Graphic aNewGraphic;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.readGraphic(aNewGraphic);
+ }
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aNewGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(aChecksum, aNewGraphic.getVectorGraphicData()->GetChecksum());
+ }
+}
+
+void TypeSerializerTest::testGraphic_Bitmap_NoGfxLink()
+{
+ Bitmap aBitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ aBitmap.Erase(COL_LIGHTGRAYBLUE);
+ BitmapEx aBitmapEx(aBitmap);
+ Graphic aGraphic(aBitmapEx);
+
+ // Test TypeSerializer
+ {
+ SvMemoryStream aMemoryStream;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.writeGraphic(aGraphic);
+ }
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(383), aMemoryStream.remainingSize());
+ std::vector<unsigned char> aHash = calculateHash(aMemoryStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("da831418499146d51bf245fadf60b9111faa76c2"),
+ toHexString(aHash));
+
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ sal_uInt16 nType;
+ aMemoryStream.ReadUInt16(nType);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(0x4D42), nType); // Magic written with WriteDIBBitmapEx
+
+ // Read it back
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ Graphic aNewGraphic;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.readGraphic(aNewGraphic);
+ }
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aNewGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(aBitmapEx.GetChecksum(), aNewGraphic.GetBitmapExRef().GetChecksum());
+ }
+}
+
+void TypeSerializerTest::testGraphic_Animation()
+{
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "123_Numbers.gif";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsAnimated());
+
+ // Test TypeSerializer
+ {
+ SvMemoryStream aMemoryStream;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.writeGraphic(aGraphic);
+ }
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(15123), aMemoryStream.remainingSize());
+ std::vector<unsigned char> aHash = calculateHash(aMemoryStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("86e02d37ab5e9c96fbeda717f62bc6e35dec3a70"),
+ toHexString(aHash));
+
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ sal_uInt16 nType;
+ aMemoryStream.ReadUInt16(nType);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(0x4D42), nType);
+
+ // Read it back
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ Graphic aNewGraphic;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.readGraphic(aNewGraphic);
+ }
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aNewGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aNewGraphic.IsAnimated());
+ }
+
+ // Test TypeSerializer - Native Format 5
+ {
+ SvMemoryStream aMemoryStream;
+ aMemoryStream.SetVersion(SOFFICE_FILEFORMAT_50);
+ aMemoryStream.SetCompressMode(SvStreamCompressFlags::NATIVE);
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.writeGraphic(aGraphic);
+ }
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(1582), aMemoryStream.remainingSize());
+ std::vector<unsigned char> aHash = calculateHash(aMemoryStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("da3b9600340fa80a895f2107357e4ab65a9292eb"),
+ toHexString(aHash));
+
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ sal_uInt32 nType;
+ aMemoryStream.ReadUInt32(nType);
+ CPPUNIT_ASSERT_EQUAL(COMPAT_FORMAT('N', 'A', 'T', '5'), nType);
+
+ // Read it back
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ Graphic aNewGraphic;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.readGraphic(aNewGraphic);
+ }
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aNewGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(true, aNewGraphic.IsAnimated());
+ }
+}
+
+void TypeSerializerTest::testGraphic_GDIMetaFile()
+{
+ GDIMetaFile aGDIMetaFile;
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ pVirtualDev->SetConnectMetaFile(&aGDIMetaFile);
+ Size aVDSize(10, 10);
+ pVirtualDev->SetOutputSizePixel(aVDSize);
+ pVirtualDev->SetBackground(Wallpaper(COL_LIGHTRED));
+ pVirtualDev->Erase();
+ pVirtualDev->DrawPixel(Point(4, 4));
+ }
+ Graphic aGraphic(aGDIMetaFile);
+ CPPUNIT_ASSERT_EQUAL(GraphicType::GdiMetafile, aGraphic.GetType());
+
+ // Test TypeSerializer
+ {
+ SvMemoryStream aMemoryStream;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.writeGraphic(aGraphic);
+ }
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(229), aMemoryStream.remainingSize());
+ std::vector<unsigned char> aHash = calculateHash(aMemoryStream);
+ CPPUNIT_ASSERT_EQUAL(std::string("144c518e5149d61ab4bc34643df820372405d61d"),
+ toHexString(aHash));
+
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ char aIdCharArray[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ aMemoryStream.ReadBytes(aIdCharArray, 6);
+ OString sID(aIdCharArray);
+ CPPUNIT_ASSERT_EQUAL(OString("VCLMTF"), sID);
+
+ // Read it back
+ aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+ Graphic aNewGraphic;
+ {
+ TypeSerializer aSerializer(aMemoryStream);
+ aSerializer.readGraphic(aNewGraphic);
+ }
+ CPPUNIT_ASSERT_EQUAL(GraphicType::GdiMetafile, aNewGraphic.GetType());
+ }
+}
+
+void TypeSerializerTest::testMapMode()
+{
+ { // "simple" case - only map unit is set, IsSimple = true
+ MapMode aMapMode(MapUnit::Map100thMM);
+
+ SvMemoryStream aStream;
+ TypeSerializer aSerializer(aStream);
+ aSerializer.writeMapMode(aMapMode);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ MapMode aReadMapMode;
+ aSerializer.readMapMode(aReadMapMode);
+ CPPUNIT_ASSERT_EQUAL(MapUnit::Map100thMM, aReadMapMode.GetMapUnit());
+ CPPUNIT_ASSERT_EQUAL(true, aReadMapMode.IsSimple());
+ }
+ { // "complex" case - map unit, origin and scale are set, IsSimple = false
+ MapMode aMapMode(MapUnit::MapTwip, Point(5, 10), Fraction(1, 2), Fraction(2, 3));
+
+ SvMemoryStream aStream;
+ TypeSerializer aSerializer(aStream);
+ aSerializer.writeMapMode(aMapMode);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ MapMode aReadMapMode;
+ aSerializer.readMapMode(aReadMapMode);
+ CPPUNIT_ASSERT_EQUAL(MapUnit::MapTwip, aReadMapMode.GetMapUnit());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(5), aReadMapMode.GetOrigin().X());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aReadMapMode.GetOrigin().Y());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aReadMapMode.GetScaleX().GetNumerator());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aReadMapMode.GetScaleX().GetDenominator());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aReadMapMode.GetScaleY().GetNumerator());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aReadMapMode.GetScaleY().GetDenominator());
+ CPPUNIT_ASSERT_EQUAL(false, aReadMapMode.IsSimple());
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TypeSerializerTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/VectorGraphicSearchTest.cxx b/vcl/qa/cppunit/VectorGraphicSearchTest.cxx
new file mode 100644
index 000000000..684493e9c
--- /dev/null
+++ b/vcl/qa/cppunit/VectorGraphicSearchTest.cxx
@@ -0,0 +1,288 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <config_features.h>
+
+#include <string_view>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <unotest/bootstrapfixturebase.hxx>
+#include <unotest/directories.hxx>
+
+#include <vcl/VectorGraphicSearch.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+
+class VectorGraphicSearchTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/data/") + sFileName;
+ }
+
+ void test();
+ void testNextPrevious();
+ void testSearchStringChange();
+ void testSearchMatchWholeWord();
+ void testSearchMatchCase();
+
+ CPPUNIT_TEST_SUITE(VectorGraphicSearchTest);
+ CPPUNIT_TEST(test);
+ CPPUNIT_TEST(testNextPrevious);
+ CPPUNIT_TEST(testSearchStringChange);
+ CPPUNIT_TEST(testSearchMatchWholeWord);
+ CPPUNIT_TEST(testSearchMatchCase);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VectorGraphicSearchTest::test()
+{
+ OUString aURL = getFullUrl(u"Pangram.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ VectorGraphicSearch aSearch(aGraphic);
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("lazy"));
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(34, aSearch.index());
+
+ basegfx::B2DSize aSize = aSearch.pageSize();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(21590.00, aSize.getX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(27940.00, aSize.getY(), 1E-2);
+
+ auto aRectangles = aSearch.getTextRectangles();
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aRectangles.size());
+
+ // Check first and last
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8078.61, aRectangles[0].getMinX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8179.36, aRectangles[0].getMaxX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2101.56, aRectangles[0].getMinY(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2395.36, aRectangles[0].getMaxY(), 1E-2);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8565.86, aRectangles[3].getMinX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8770.76, aRectangles[3].getMaxX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2201.05, aRectangles[3].getMinY(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2486.37, aRectangles[3].getMaxY(), 1E-2);
+
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(817, aSearch.index());
+
+ aRectangles = aSearch.getTextRectangles();
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aRectangles.size());
+
+ // Check first and last
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6562.23, aRectangles[0].getMinX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6662.98, aRectangles[0].getMaxX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(5996.23, aRectangles[0].getMinY(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6290.02, aRectangles[0].getMaxY(), 1E-2);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(7049.48, aRectangles[3].getMinX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(7254.38, aRectangles[3].getMaxX(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6095.71, aRectangles[3].getMinY(), 1E-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6381.04, aRectangles[3].getMaxY(), 1E-2);
+}
+
+// Test next and previous work as expected to move
+// between search matches.
+void VectorGraphicSearchTest::testNextPrevious()
+{
+ OUString aURL = getFullUrl(u"Pangram.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ { // Start from the beginning of the page
+ VectorGraphicSearch aSearch(aGraphic);
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("lazy"));
+
+ // no previous - we are at the begin
+ CPPUNIT_ASSERT_EQUAL(false, aSearch.previous());
+ CPPUNIT_ASSERT_EQUAL(0, aSearch.index()); // nothing was yet found, so it is 0
+
+ // next - first position found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(34, aSearch.index());
+
+ // next - second position found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(817, aSearch.index());
+
+ // next - not found, index unchanged
+ CPPUNIT_ASSERT_EQUAL(false, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(817, aSearch.index());
+
+ // previous - first position
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.previous());
+ CPPUNIT_ASSERT_EQUAL(34, aSearch.index());
+
+ // previous - not found, index unchanged
+ CPPUNIT_ASSERT_EQUAL(false, aSearch.previous());
+ CPPUNIT_ASSERT_EQUAL(34, aSearch.index());
+
+ // next - second position found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(817, aSearch.index());
+ }
+
+ { // Start from the end of the page
+ VectorGraphicSearch aSearch(aGraphic);
+ CPPUNIT_ASSERT_EQUAL(true,
+ aSearch.search("lazy", { SearchStartPosition::End, false, false }));
+
+ // no next - we are at the end
+ CPPUNIT_ASSERT_EQUAL(false, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(0, aSearch.index()); // nothing was yet found, so it is 0
+
+ // previous - second position found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.previous());
+ CPPUNIT_ASSERT_EQUAL(817, aSearch.index());
+
+ // previous - first position found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.previous());
+ CPPUNIT_ASSERT_EQUAL(34, aSearch.index());
+
+ // previous - not found, index unchanged
+ CPPUNIT_ASSERT_EQUAL(false, aSearch.previous());
+ CPPUNIT_ASSERT_EQUAL(34, aSearch.index());
+
+ // next - second position
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(817, aSearch.index());
+
+ // next - not found, index unchanged
+ CPPUNIT_ASSERT_EQUAL(false, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(817, aSearch.index());
+
+ // previous - first match found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.previous());
+ CPPUNIT_ASSERT_EQUAL(34, aSearch.index());
+ }
+}
+
+void VectorGraphicSearchTest::testSearchStringChange()
+{
+ OUString aURL = getFullUrl(u"Pangram.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ VectorGraphicSearch aSearch(aGraphic);
+
+ // Set search to "lazy"
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("lazy"));
+
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(34, aSearch.index());
+
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(817, aSearch.index());
+
+ // Change search to "fox"
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("fox"));
+
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(822, aSearch.index());
+
+ // Change search to "Quick"
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("Quick"));
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.previous());
+ CPPUNIT_ASSERT_EQUAL(784, aSearch.index());
+}
+
+void VectorGraphicSearchTest::testSearchMatchWholeWord()
+{
+ OUString aURL = getFullUrl(u"Pangram.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ {
+ VectorGraphicSearch aSearch(aGraphic);
+ // Search, whole word disabled - "Flummoxed" - found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("Flummoxed"));
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(618, aSearch.index());
+ }
+ {
+ VectorGraphicSearch aSearch(aGraphic);
+ // Search, whole word disabled - "Flummo" - found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("Flummo"));
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(618, aSearch.index());
+ }
+ {
+ VectorGraphicSearch aSearch(aGraphic);
+ // Search, whole word enabled - "Flummoxed" - found
+ CPPUNIT_ASSERT_EQUAL(
+ true, aSearch.search("Flummoxed", { SearchStartPosition::Begin, false, true }));
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(618, aSearch.index());
+ }
+ {
+ VectorGraphicSearch aSearch(aGraphic);
+ // Search, whole word enabled - "Flummo" - not found
+ CPPUNIT_ASSERT_EQUAL(true,
+ aSearch.search("Flummo", { SearchStartPosition::Begin, false, true }));
+ CPPUNIT_ASSERT_EQUAL(false, aSearch.next());
+ }
+}
+
+void VectorGraphicSearchTest::testSearchMatchCase()
+{
+ OUString aURL = getFullUrl(u"Pangram.pdf");
+ SvFileStream aStream(aURL, StreamMode::READ);
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+ aGraphic.makeAvailable();
+
+ {
+ VectorGraphicSearch aSearch(aGraphic);
+ // Search "Flummoxed" - case insensitive - found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("Flummoxed"));
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(618, aSearch.index());
+ }
+
+ {
+ VectorGraphicSearch aSearch(aGraphic);
+ // Search "FLUMMOXED" - case insensitive - found
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.search("FLUMMOXED"));
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(618, aSearch.index());
+ }
+
+ {
+ VectorGraphicSearch aSearch(aGraphic);
+ // Search "Flummoxed" - case sensitive - found
+ CPPUNIT_ASSERT_EQUAL(
+ true, aSearch.search("Flummoxed", { SearchStartPosition::Begin, true, false }));
+ CPPUNIT_ASSERT_EQUAL(true, aSearch.next());
+ CPPUNIT_ASSERT_EQUAL(618, aSearch.index());
+ }
+
+ {
+ VectorGraphicSearch aSearch(aGraphic);
+ // Search to "FLUMMOXED" - case sensitive - not found
+ CPPUNIT_ASSERT_EQUAL(
+ true, aSearch.search("FLUMMOXED", { SearchStartPosition::Begin, true, false }));
+ CPPUNIT_ASSERT_EQUAL(false, aSearch.next());
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VectorGraphicSearchTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/XpmFilterTest.cxx b/vcl/qa/cppunit/XpmFilterTest.cxx
new file mode 100644
index 000000000..1c24de1e1
--- /dev/null
+++ b/vcl/qa/cppunit/XpmFilterTest.cxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/bitmapex.hxx>
+#include <tools/stream.hxx>
+#include <filter/XpmReader.hxx>
+#include <unotools/tempfile.hxx>
+
+class XpmFilterTest : public test::BootstrapFixture
+{
+public:
+ OUString maDataUrl;
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(maDataUrl) + sFileName;
+ }
+ XpmFilterTest()
+ : maDataUrl(u"/vcl/qa/cppunit/data/")
+ {
+ }
+};
+
+CPPUNIT_TEST_FIXTURE(XpmFilterTest, testXPM_8bit)
+{
+ SvFileStream aFileStream(getFullUrl(u"XPM_8.xpm"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(ImportXPM(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(XpmFilterTest, testXPM_4bit)
+{
+ SvFileStream aFileStream(getFullUrl(u"XPM_4.xpm"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(ImportXPM(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aBitmap.GetPixelColor(2, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aBitmap.GetPixelColor(0, 2));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
+}
+
+CPPUNIT_TEST_FIXTURE(XpmFilterTest, testXPM_1bit)
+{
+ SvFileStream aFileStream(getFullUrl(u"XPM_1.xpm"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(ImportXPM(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N1_BPP, aBitmap.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(Color(0xffffff), aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x72d1c8), aBitmap.GetPixelColor(1, 1));
+ CPPUNIT_ASSERT_EQUAL(Color(0x72d1c8), aBitmap.GetPixelColor(8, 8));
+ CPPUNIT_ASSERT_EQUAL(Color(0xffffff), aBitmap.GetPixelColor(9, 9));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/animation.cxx b/vcl/qa/cppunit/animation.cxx
new file mode 100644
index 000000000..e9e308ff7
--- /dev/null
+++ b/vcl/qa/cppunit/animation.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <vcl/animate/Animation.hxx>
+
+class VclAnimationTest : public test::BootstrapFixture
+{
+public:
+ VclAnimationTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testFrameCount();
+ void testDisplaySize();
+
+ CPPUNIT_TEST_SUITE(VclAnimationTest);
+ CPPUNIT_TEST(testFrameCount);
+ CPPUNIT_TEST(testDisplaySize);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclAnimationTest::testFrameCount()
+{
+ Animation aAnimation;
+
+ CPPUNIT_ASSERT_EQUAL(size_t(0), aAnimation.Count());
+
+ aAnimation.Insert(
+ AnimationBitmap(BitmapEx(Size(3, 4), vcl::PixelFormat::N24_BPP), Point(0, 0), Size(3, 4)));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aAnimation.Count());
+
+ aAnimation.Insert(AnimationBitmap(BitmapEx(Size(3, 3), vcl::PixelFormat::N24_BPP), Point(0, 0),
+ Size(10, 10)));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), aAnimation.Count());
+
+ aAnimation.Clear();
+ CPPUNIT_ASSERT_EQUAL(size_t(0), aAnimation.Count());
+}
+
+void VclAnimationTest::testDisplaySize()
+{
+ Animation aAnimation;
+ CPPUNIT_ASSERT_EQUAL(Size(0, 0), aAnimation.GetDisplaySizePixel());
+
+ aAnimation.Insert(
+ AnimationBitmap(BitmapEx(Size(3, 4), vcl::PixelFormat::N24_BPP), Point(0, 0), Size(3, 4)));
+ CPPUNIT_ASSERT_EQUAL(Size(3, 4), aAnimation.GetDisplaySizePixel());
+
+ aAnimation.Insert(AnimationBitmap(BitmapEx(Size(10, 10), vcl::PixelFormat::N24_BPP),
+ Point(0, 0), Size(10, 10)));
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), aAnimation.GetDisplaySizePixel());
+
+ aAnimation.Clear();
+ CPPUNIT_ASSERT_EQUAL(Size(0, 0), aAnimation.GetDisplaySizePixel());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclAnimationTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/app/test_IconThemeInfo.cxx b/vcl/qa/cppunit/app/test_IconThemeInfo.cxx
new file mode 100644
index 000000000..ff1ad985b
--- /dev/null
+++ b/vcl/qa/cppunit/app/test_IconThemeInfo.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdexcept>
+
+#include <rtl/ustring.hxx>
+#include <vcl/IconThemeInfo.hxx>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace vcl;
+
+class IconThemeInfoTest : public CppUnit::TestFixture
+{
+ void
+ UpperCaseDisplayNameIsReturnedForNonDefaultId();
+
+ void
+ ImagesZipIsNotValid();
+
+ void
+ ImagesColibreZipIsValid();
+
+ void
+ ThemeIdIsDetectedFromFileNameWithUnderscore();
+
+ void
+ ExceptionIsThrownWhenIdCannotBeDetermined1();
+
+ void
+ ExceptionIsThrownWhenIdCannotBeDetermined2();
+
+ // Adds code needed to register the test suite
+ CPPUNIT_TEST_SUITE(IconThemeInfoTest);
+ CPPUNIT_TEST(UpperCaseDisplayNameIsReturnedForNonDefaultId);
+ CPPUNIT_TEST(ThemeIdIsDetectedFromFileNameWithUnderscore);
+ CPPUNIT_TEST(ImagesZipIsNotValid);
+ CPPUNIT_TEST(ImagesColibreZipIsValid);
+ CPPUNIT_TEST(ExceptionIsThrownWhenIdCannotBeDetermined1);
+ CPPUNIT_TEST(ExceptionIsThrownWhenIdCannotBeDetermined2);
+
+ // End of test suite definition
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void
+IconThemeInfoTest::UpperCaseDisplayNameIsReturnedForNonDefaultId()
+{
+ OUString displayName = vcl::IconThemeInfo::ThemeIdToDisplayName("katze");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("theme id is properly uppercased", OUString("Katze"), displayName);
+}
+
+void
+IconThemeInfoTest::ImagesZipIsNotValid()
+{
+ bool valid = vcl::IconThemeInfo::UrlCanBeParsed(u"file://images.zip");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("images.zip is not a valid theme name", false, valid);
+}
+
+void
+IconThemeInfoTest::ImagesColibreZipIsValid()
+{
+ bool valid = vcl::IconThemeInfo::UrlCanBeParsed(u"file://images_colibre.zip");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("images_colibre.zip is a valid theme name", true, valid);
+}
+
+void
+IconThemeInfoTest::ThemeIdIsDetectedFromFileNameWithUnderscore()
+{
+ OUString sname = vcl::IconThemeInfo::FileNameToThemeId(u"images_colibre.zip");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'colibre' theme id is returned for 'images_colibre.zip'", OUString("colibre"), sname);
+}
+
+void
+IconThemeInfoTest::ExceptionIsThrownWhenIdCannotBeDetermined1()
+{
+ bool thrown = false;
+ try {
+ vcl::IconThemeInfo::FileNameToThemeId(u"images_colibre");
+ }
+ catch (std::runtime_error&) {
+ thrown = true;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception was thrown",true, thrown);
+}
+
+void
+IconThemeInfoTest::ExceptionIsThrownWhenIdCannotBeDetermined2()
+{
+ bool thrown = false;
+ try {
+ vcl::IconThemeInfo::FileNameToThemeId(u"image_colibre.zip");
+ }
+ catch (std::runtime_error&) {
+ thrown = true;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception was thrown", true, thrown);
+}
+
+// Put the test suite in the registry
+CPPUNIT_TEST_SUITE_REGISTRATION(IconThemeInfoTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/app/test_IconThemeScanner.cxx b/vcl/qa/cppunit/app/test_IconThemeScanner.cxx
new file mode 100644
index 000000000..d02fe752c
--- /dev/null
+++ b/vcl/qa/cppunit/app/test_IconThemeScanner.cxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdexcept>
+
+#include <rtl/ustring.hxx>
+#include <IconThemeScanner.hxx>
+#include <vcl/IconThemeInfo.hxx>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+class IconThemeScannerTest : public CppUnit::TestFixture
+{
+ void
+ AddedThemeIsFoundById();
+
+ void
+ AddedThemeInfoIsReturned();
+
+ void
+ ExceptionIsThrownIfInvalidInfoIsRequested();
+
+ // Adds code needed to register the test suite
+ CPPUNIT_TEST_SUITE(IconThemeScannerTest);
+ CPPUNIT_TEST(AddedThemeIsFoundById);
+ CPPUNIT_TEST(AddedThemeInfoIsReturned);
+ CPPUNIT_TEST(ExceptionIsThrownIfInvalidInfoIsRequested);
+
+ // End of test suite definition
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void
+IconThemeScannerTest::AddedThemeIsFoundById()
+{
+ vcl::IconThemeScanner scanner;
+ scanner.AddIconThemeByPath("file:://images_katze.zip");
+ OUString id = vcl::IconThemeInfo::FileNameToThemeId(u"images_katze.zip");
+ bool found = scanner.IconThemeIsInstalled(id);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("icon theme could be added by url", true, found);
+}
+
+void
+IconThemeScannerTest::AddedThemeInfoIsReturned()
+{
+ vcl::IconThemeScanner scanner;
+ OUString theme("file:://images_katze.zip");
+ scanner.AddIconThemeByPath(theme);
+ OUString id = vcl::IconThemeInfo::FileNameToThemeId(u"images_katze.zip");
+ const vcl::IconThemeInfo& info = scanner.GetIconThemeInfo(id);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'katze' icon theme is found from id", theme, info.GetUrlToFile());
+}
+
+void
+IconThemeScannerTest::ExceptionIsThrownIfInvalidInfoIsRequested()
+{
+ vcl::IconThemeScanner scanner;
+ scanner.AddIconThemeByPath("file:://images_katze.zip");
+ bool thrown = false;
+ try
+ {
+ scanner.GetIconThemeInfo("hund");
+ }
+ catch (const std::runtime_error&)
+ {
+ thrown = true;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception is thrown if invalid theme info is requested", true, thrown);
+}
+
+// Put the test suite in the registry
+CPPUNIT_TEST_SUITE_REGISTRATION(IconThemeScannerTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/app/test_IconThemeSelector.cxx b/vcl/qa/cppunit/app/test_IconThemeSelector.cxx
new file mode 100644
index 000000000..94d53b43d
--- /dev/null
+++ b/vcl/qa/cppunit/app/test_IconThemeSelector.cxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <IconThemeSelector.hxx>
+
+#include <vcl/IconThemeInfo.hxx>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+class IconThemeSelectorTest : public CppUnit::TestFixture
+{
+#ifndef _WIN32 //default theme on Windows is Colibre independently from any desktop environment
+ void BreezeIsReturnedForKde5Desktop();
+ void ElementaryIsReturnedForGnomeDesktop();
+ void ThemeIsOverriddenByPreferredTheme();
+ void ThemeIsOverriddenByHighContrastMode();
+ void NotInstalledThemeDoesNotOverride();
+ void InstalledThemeIsFound();
+ void FirstThemeIsReturnedIfRequestedThemeIsNotFound();
+ void FallbackThemeIsReturnedForEmptyInput();
+ void DifferentPreferredThemesAreInequal();
+ void DifferentHighContrastModesAreInequal();
+ static std::vector<vcl::IconThemeInfo> GetFakeInstalledThemes();
+#endif
+
+ // Adds code needed to register the test suite
+ CPPUNIT_TEST_SUITE(IconThemeSelectorTest);
+
+#ifndef _WIN32
+ CPPUNIT_TEST(BreezeIsReturnedForKde5Desktop);
+ CPPUNIT_TEST(ElementaryIsReturnedForGnomeDesktop);
+ CPPUNIT_TEST(ThemeIsOverriddenByPreferredTheme);
+ CPPUNIT_TEST(ThemeIsOverriddenByHighContrastMode);
+ CPPUNIT_TEST(NotInstalledThemeDoesNotOverride);
+ CPPUNIT_TEST(InstalledThemeIsFound);
+ CPPUNIT_TEST(FirstThemeIsReturnedIfRequestedThemeIsNotFound);
+ CPPUNIT_TEST(FallbackThemeIsReturnedForEmptyInput);
+ CPPUNIT_TEST(DifferentPreferredThemesAreInequal);
+ CPPUNIT_TEST(DifferentHighContrastModesAreInequal);
+#endif
+
+ // End of test suite definition
+ CPPUNIT_TEST_SUITE_END();
+};
+
+#ifndef _WIN32
+
+/*static*/ std::vector<vcl::IconThemeInfo>
+IconThemeSelectorTest::GetFakeInstalledThemes()
+{
+ std::vector<vcl::IconThemeInfo> r;
+ vcl::IconThemeInfo a;
+ a.mThemeId = "breeze";
+ r.push_back(a);
+ a.mThemeId = "elementary";
+ r.push_back(a);
+ a.mThemeId = "colibre";
+ r.push_back(a);
+ a.mThemeId = "sifr";
+ r.push_back(a);
+ return r;
+}
+
+void
+IconThemeSelectorTest::BreezeIsReturnedForKde5Desktop()
+{
+ std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes();
+ vcl::IconThemeSelector s;
+ OUString r = s.SelectIconThemeForDesktopEnvironment(themes, "plasma5");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'breeze' theme is returned for Plasma 5 desktop", OUString("breeze"), r);
+}
+
+void
+IconThemeSelectorTest::ElementaryIsReturnedForGnomeDesktop()
+{
+ std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes();
+ vcl::IconThemeSelector s;
+ OUString r = s.SelectIconThemeForDesktopEnvironment(themes, "gnome");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'elementary' theme is returned for gnome desktop", OUString("elementary"), r);
+}
+
+void
+IconThemeSelectorTest::ThemeIsOverriddenByPreferredTheme()
+{
+ vcl::IconThemeSelector s;
+ OUString preferred("breeze");
+ s.SetPreferredIconTheme(preferred, false);
+ std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes();
+ OUString selected = s.SelectIconThemeForDesktopEnvironment(themes, "gnome");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'elementary' theme is overridden by breeze", preferred, selected);
+}
+
+void
+IconThemeSelectorTest::ThemeIsOverriddenByHighContrastMode()
+{
+ vcl::IconThemeSelector s;
+ s.SetUseHighContrastTheme(true);
+ std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes();
+ OUString selected = s.SelectIconTheme(themes, "breeze");
+ bool sifr = selected.startsWith("sifr");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'breeze' theme is overridden by high contrast mode", true, sifr);
+ s.SetUseHighContrastTheme(false);
+ selected = s.SelectIconTheme(themes, "breeze");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'breeze' theme is no longer overridden by high contrast mode",
+ OUString("breeze"), selected);
+}
+
+void
+IconThemeSelectorTest::NotInstalledThemeDoesNotOverride()
+{
+ vcl::IconThemeSelector s;
+ s.SetPreferredIconTheme("breeze_foo", false);
+ std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes();
+ OUString selected = s.SelectIconTheme(themes, "colibre");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'colibre' theme is not overridden by 'breeze_foo'", OUString("colibre"), selected);
+}
+
+void
+IconThemeSelectorTest::InstalledThemeIsFound()
+{
+ vcl::IconThemeSelector s;
+ std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes();
+ OUString selected = s.SelectIconTheme(themes, "colibre");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'colibre' theme is found", OUString("colibre"), selected);
+}
+
+void
+IconThemeSelectorTest::FirstThemeIsReturnedIfRequestedThemeIsNotFound()
+{
+ vcl::IconThemeSelector s;
+ std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes();
+ OUString selected = s.SelectIconTheme(themes, "breeze_foo");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'breeze' theme is found", themes.front().GetThemeId(), selected);
+}
+
+void
+IconThemeSelectorTest::FallbackThemeIsReturnedForEmptyInput()
+{
+ vcl::IconThemeSelector s;
+ OUString selected = s.SelectIconTheme(std::vector<vcl::IconThemeInfo>(), "colibre");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("fallback is returned for empty input",
+ OUString(vcl::IconThemeSelector::FALLBACK_ICON_THEME_ID), selected);
+}
+
+void
+IconThemeSelectorTest::DifferentHighContrastModesAreInequal()
+{
+ vcl::IconThemeSelector s1;
+ vcl::IconThemeSelector s2;
+ s1.SetUseHighContrastTheme(true);
+ s2.SetUseHighContrastTheme(false);
+ bool equal = (s1 == s2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Different high contrast modes are detected as inequal", false, equal);
+}
+
+void
+IconThemeSelectorTest::DifferentPreferredThemesAreInequal()
+{
+ vcl::IconThemeSelector s1;
+ vcl::IconThemeSelector s2;
+ s1.SetPreferredIconTheme("breeze", false);
+ s2.SetUseHighContrastTheme(true);
+ bool equal = (s1 == s2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Different preferred themes are detected as inequal", false, equal);
+}
+
+#endif
+
+// Put the test suite in the registry
+CPPUNIT_TEST_SUITE_REGISTRATION(IconThemeSelectorTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/bitmapcolor.cxx b/vcl/qa/cppunit/bitmapcolor.cxx
new file mode 100644
index 000000000..f62e19dab
--- /dev/null
+++ b/vcl/qa/cppunit/bitmapcolor.cxx
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// bootstrap stuff
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/BitmapColor.hxx>
+
+namespace
+{
+class BitmapColorTest : public test::BootstrapFixture
+{
+public:
+ BitmapColorTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void defaultConstructor();
+ void colorValueConstructor();
+ void colorClassConstructor();
+ void setValue();
+ void invert();
+ void getLuminance();
+
+ CPPUNIT_TEST_SUITE(BitmapColorTest);
+ CPPUNIT_TEST(defaultConstructor);
+ CPPUNIT_TEST(colorValueConstructor);
+ CPPUNIT_TEST(colorClassConstructor);
+ CPPUNIT_TEST(setValue);
+ CPPUNIT_TEST(invert);
+ CPPUNIT_TEST(getLuminance);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void BitmapColorTest::defaultConstructor()
+{
+ BitmapColor aBmpColor;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red wrong", static_cast<sal_uInt8>(0), aBmpColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green wrong", static_cast<sal_uInt8>(0), aBmpColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue wrong", static_cast<sal_uInt8>(0), aBmpColor.GetBlue());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Transparency wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetAlpha());
+}
+
+void BitmapColorTest::colorValueConstructor()
+{
+ {
+ BitmapColor aBmpColor(0, 0, 0);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red wrong", static_cast<sal_uInt8>(0), aBmpColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green wrong", static_cast<sal_uInt8>(0),
+ aBmpColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue wrong", static_cast<sal_uInt8>(0), aBmpColor.GetBlue());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Transparency wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetAlpha());
+ }
+
+ {
+ BitmapColor aBmpColor(128, 128, 128);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red wrong", static_cast<sal_uInt8>(128), aBmpColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green wrong", static_cast<sal_uInt8>(128),
+ aBmpColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue wrong", static_cast<sal_uInt8>(128),
+ aBmpColor.GetBlue());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Transparency wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetAlpha());
+ }
+
+ {
+ BitmapColor aBmpColor(255, 255, 255);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red wrong", static_cast<sal_uInt8>(255), aBmpColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetBlue());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Transparency wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetAlpha());
+ }
+}
+
+void BitmapColorTest::colorClassConstructor()
+{
+ {
+ BitmapColor aBmpColor(Color(0, 0, 0));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red wrong", static_cast<sal_uInt8>(0), aBmpColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green wrong", static_cast<sal_uInt8>(0),
+ aBmpColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue wrong", static_cast<sal_uInt8>(0), aBmpColor.GetBlue());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Transparency wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetAlpha());
+ }
+
+ {
+ BitmapColor aBmpColor(Color(127, 127, 127));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red wrong", static_cast<sal_uInt8>(127), aBmpColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green wrong", static_cast<sal_uInt8>(127),
+ aBmpColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue wrong", static_cast<sal_uInt8>(127),
+ aBmpColor.GetBlue());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Transparency wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetAlpha());
+ }
+
+ {
+ BitmapColor aBmpColor(Color(255, 255, 255));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red wrong", static_cast<sal_uInt8>(255), aBmpColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetBlue());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Transparency wrong", static_cast<sal_uInt8>(255),
+ aBmpColor.GetAlpha());
+ }
+
+ // Transparency / Alpha
+ {
+ BitmapColor aBmpColor(Color(ColorTransparency, 255, 128, 64, 0));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Red wrong", static_cast<sal_uInt8>(128), aBmpColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Green wrong", static_cast<sal_uInt8>(64),
+ aBmpColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue wrong", static_cast<sal_uInt8>(0), aBmpColor.GetBlue());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Transparency wrong", static_cast<sal_uInt8>(0),
+ aBmpColor.GetAlpha());
+ }
+}
+
+void BitmapColorTest::setValue()
+{
+ BitmapColor aBmpColor;
+
+ aBmpColor.SetRed(127);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(127), aBmpColor.GetRed());
+
+ aBmpColor.SetGreen(127);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(127), aBmpColor.GetGreen());
+
+ aBmpColor.SetBlue(127);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(127), aBmpColor.GetBlue());
+}
+
+void BitmapColorTest::invert()
+{
+ BitmapColor aBmpColor(255, 255, 255);
+ BitmapColor aInvertedColor(aBmpColor);
+ aInvertedColor.Invert();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(0), aInvertedColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(0), aInvertedColor.GetGreen());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(0), aInvertedColor.GetBlue());
+}
+
+void BitmapColorTest::getLuminance()
+{
+ {
+ BitmapColor aBmpColor(COL_BLACK);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(0), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_BLUE);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(14), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_GREEN);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(75), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_CYAN);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(90), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_RED);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(38), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_MAGENTA);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(52), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_BROWN);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(113), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_GRAY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(128), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_LIGHTGRAY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(192), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_LIGHTBLUE);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(28), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_LIGHTGREEN);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(150), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_LIGHTCYAN);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(179), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_LIGHTRED);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(75), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_LIGHTMAGENTA);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(104), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_YELLOW);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(226), aBmpColor.GetLuminance());
+ }
+
+ {
+ BitmapColor aBmpColor(COL_WHITE);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(255), aBmpColor.GetLuminance());
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BitmapColorTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx b/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx
new file mode 100644
index 000000000..26c1136cb
--- /dev/null
+++ b/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx
@@ -0,0 +1,286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/virdev.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/svapp.hxx>
+
+#include <tools/stream.hxx>
+
+#include <vcl/graphicfilter.hxx>
+#include <vcl/filter/PngImageReader.hxx>
+
+#include <svdata.hxx>
+#include <salinst.hxx>
+
+constexpr OUStringLiteral gaDataUrl = u"/vcl/qa/cppunit/bitmaprender/data/";
+
+class BitmapRenderTest : public test::BootstrapFixture
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(gaDataUrl) + sFileName;
+ }
+
+public:
+ BitmapRenderTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testTdf104141();
+ void testTdf113918();
+ void testDrawAlphaBitmapEx();
+ void testAlphaVirtualDevice();
+ void testTdf116888();
+
+ CPPUNIT_TEST_SUITE(BitmapRenderTest);
+ CPPUNIT_TEST(testTdf104141);
+ CPPUNIT_TEST(testTdf113918);
+ CPPUNIT_TEST(testDrawAlphaBitmapEx);
+ CPPUNIT_TEST(testAlphaVirtualDevice);
+ CPPUNIT_TEST(testTdf116888);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void BitmapRenderTest::testTdf104141()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ pVDev->SetOutputSizePixel(Size(400, 400));
+ pVDev->SetBackground(Wallpaper(COL_GREEN));
+ pVDev->Erase();
+
+ // Load animated GIF and draw it on green background
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ const OUString aURL(getFullUrl(u"tdf104141.gif"));
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ BitmapEx aBitmap = aGraphic.GetBitmapEx();
+ pVDev->DrawBitmapEx(Point(20, 20), aBitmap);
+
+ // Check drawing results: ensure that it contains transparent
+ // (greenish) pixels
+ const Color aColor = pVDev->GetPixel(Point(21, 21));
+ CPPUNIT_ASSERT(aColor.GetGreen() > 10 * aColor.GetRed());
+ CPPUNIT_ASSERT(aColor.GetGreen() > 10 * aColor.GetBlue());
+}
+
+void BitmapRenderTest::testTdf113918()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ pVDev->SetOutputSizePixel(Size(2480, 3508));
+ pVDev->SetBackground(Wallpaper(COL_GREEN));
+ pVDev->Erase();
+
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ const OUString aURL(getFullUrl(u"tdf113918.png"));
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ BitmapEx aBitmap = aGraphic.GetBitmapEx();
+ pVDev->DrawBitmapEx(Point(0, 0), aBitmap);
+
+ // Ensure that image is drawn with white background color from palette
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(21, 21)));
+
+ // Ensure that image is drawn with gray text color from palette
+ const Color aColor = pVDev->GetPixel(Point(1298, 1368));
+ CPPUNIT_ASSERT_EQUAL(aColor.GetGreen(), aColor.GetRed());
+ CPPUNIT_ASSERT_EQUAL(aColor.GetGreen(), aColor.GetBlue());
+ CPPUNIT_ASSERT(aColor.GetGreen() > 100);
+}
+
+#if defined(_WIN32) || defined(IOS)
+
+namespace
+{
+int deltaColor(BitmapColor aColor1, BitmapColor aColor2)
+{
+ int deltaR = std::abs(aColor1.GetRed() - aColor2.GetRed());
+ int deltaG = std::abs(aColor1.GetGreen() - aColor2.GetGreen());
+ int deltaB = std::abs(aColor1.GetBlue() - aColor2.GetBlue());
+
+ return std::max(std::max(deltaR, deltaG), deltaB);
+}
+}
+
+#endif
+
+void BitmapRenderTest::testDrawAlphaBitmapEx()
+{
+// TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
+#ifndef MACOSX
+ if (getDefaultDeviceBitCount() < 24)
+ return;
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ pVDev->SetOutputSizePixel(Size(8, 8));
+ pVDev->SetBackground(Wallpaper(COL_WHITE));
+ pVDev->Erase();
+
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(1, 1)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(2, 2)));
+
+ SvFileStream aFileStream(getFullUrl(u"ImageRGBA.png"), StreamMode::READ);
+
+ vcl::PngImageReader aPngReader(aFileStream);
+ BitmapEx aBitmapEx;
+ aPngReader.read(aBitmapEx);
+
+ // Check backend capabilities, if the backend support 32-bit bitmap
+ if (ImplGetSVData()->mpDefInst->supportsBitmap32())
+ {
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N32_BPP, aBitmapEx.GetBitmap().getPixelFormat());
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmapEx.GetBitmap().getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(true, aBitmapEx.IsAlpha());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmapEx.GetAlpha().getPixelFormat());
+ }
+
+ // Check the bitmap has pixels we expect
+ CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xFF, 0x00, 0x00, 0x00),
+ aBitmapEx.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0x00, 0xFF, 0xFF, 0x00),
+ aBitmapEx.GetPixelColor(1, 1));
+ CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0x7F, 0x00, 0xFF, 0x00),
+ aBitmapEx.GetPixelColor(2, 2));
+
+ pVDev->DrawBitmapEx(Point(), aBitmapEx);
+
+ CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0xFF, 0xFF), pVDev->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0xFF, 0x00), pVDev->GetPixel(Point(1, 1)));
+
+#if defined(_WIN32) || defined(MACOSX) || defined(IOS)
+ // sometimes on Windows we get rounding error in blending so let's ignore this on Windows for now.
+ CPPUNIT_ASSERT_LESS(2, deltaColor(Color(0x7F, 0xFF, 0x7F), pVDev->GetPixel(Point(2, 2))));
+#else
+ CPPUNIT_ASSERT_EQUAL(Color(0x7F, 0xFF, 0x7F), pVDev->GetPixel(Point(2, 2)));
+#endif
+#endif
+}
+
+void BitmapRenderTest::testAlphaVirtualDevice()
+{
+// TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
+#ifndef MACOSX
+ // Create an alpha virtual device
+ ScopedVclPtr<VirtualDevice> pAlphaVirtualDevice(VclPtr<VirtualDevice>::Create(
+ *Application::GetDefaultDevice(), DeviceFormat::DEFAULT, DeviceFormat::DEFAULT));
+
+ // Set it up
+ pAlphaVirtualDevice->SetOutputSizePixel(Size(4, 4));
+ pAlphaVirtualDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
+ pAlphaVirtualDevice->Erase();
+
+ // Get a BitmapEx from the VirDev -> Colors should have alpha
+ BitmapEx aBitmap = pAlphaVirtualDevice->GetBitmapEx(Point(), Size(4, 4));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+ Color aColor = aBitmap.GetPixelColor(1, 1);
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, aColor);
+
+ // Draw an opaque pixel to the VirDev
+ pAlphaVirtualDevice->DrawPixel(Point(1, 1), Color(0x0022ff55));
+
+ aColor = pAlphaVirtualDevice->GetPixel(Point(1, 1));
+ // Read back the opaque pixel
+#if defined _WIN32
+ CPPUNIT_ASSERT_LESS(6, deltaColor(Color(0x0022ff55), aColor));
+#else
+ CPPUNIT_ASSERT_EQUAL(Color(0x0022ff55), aColor);
+#endif
+
+ // Read back the BitmapEx and check the opaque pixel
+ aBitmap = pAlphaVirtualDevice->GetBitmapEx(Point(), Size(4, 4));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+
+ aColor = aBitmap.GetPixelColor(1, 1);
+#if defined _WIN32
+ CPPUNIT_ASSERT_LESS(6, deltaColor(Color(0x0022ff55), aColor));
+#else
+ CPPUNIT_ASSERT_EQUAL(Color(0x0022ff55), aColor);
+#endif
+
+ // Draw an semi-transparent pixel
+ pAlphaVirtualDevice->DrawPixel(Point(0, 0), Color(ColorTransparency, 0x44, 0x22, 0xff, 0x55));
+
+ aColor = pAlphaVirtualDevice->GetPixel(Point(0, 0));
+ // Read back the semi-transparent pixel
+#if defined _WIN32
+ CPPUNIT_ASSERT_LESS(6, deltaColor(Color(ColorTransparency, 0x4422FF55), aColor));
+#else
+ CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0x4422FF55), aColor);
+#endif
+
+ // Read back the BitmapEx and check the semi-transparent pixel
+ aBitmap = pAlphaVirtualDevice->GetBitmapEx(Point(), Size(4, 4));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), aBitmap.GetSizePixel().Height());
+
+ aColor = aBitmap.GetPixelColor(0, 0);
+#if defined _WIN32
+ CPPUNIT_ASSERT_LESS(6, deltaColor(Color(ColorTransparency, 0x4422FF55), aColor));
+#else
+ CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0x4422FF55), aColor);
+#endif
+#endif
+}
+
+void BitmapRenderTest::testTdf116888()
+{
+ // The image is a 8bit image with a non-grayscale palette. In OpenGL mode
+ // pdf export of the image was broken, because OpenGLSalBitmap::ReadTexture()
+ // didn't handle 8bit non-grayscale and moreover OpenGLSalBitmap::AcquireBuffer()
+ // didn't properly release mpUserBuffer after ReadTexture() failure.
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ const OUString aURL(getFullUrl(u"tdf116888.gif"));
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ CPPUNIT_ASSERT(!aBitmap.IsEmpty());
+ aBitmap.Scale(0.8, 0.8); // This scaling discards mpUserData,
+ Bitmap::ScopedReadAccess pAccess(aBitmap); // forcing ReadTexture() here.
+ // Check that there is mpUserBuffer content.
+ CPPUNIT_ASSERT(pAccess);
+ const ScanlineFormat eFormat = pAccess->GetScanlineFormat();
+ CPPUNIT_ASSERT_EQUAL(ScanlineFormat::N8BitPal, eFormat);
+ CPPUNIT_ASSERT(!aBitmap.HasGreyPaletteAny());
+ // HACK: Some rendering backends change white to #FEFEFE while scaling for some reason.
+ // That is pretty much white too in practice, so adjust for that.
+ BitmapColor white(COL_WHITE);
+ if (pAccess->GetColor(0, 0) == Color(0xfe, 0xfe, 0xfe))
+ white = Color(0xfe, 0xfe, 0xfe);
+ // Check that the image contents are also valid.
+ CPPUNIT_ASSERT_EQUAL(white, pAccess->GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(white, pAccess->GetColor(0, pAccess->Width() - 1));
+ CPPUNIT_ASSERT_EQUAL(white, pAccess->GetColor(pAccess->Height() - 1, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK),
+ pAccess->GetColor(pAccess->Height() - 1, pAccess->Width() - 1));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BitmapRenderTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/bitmaprender/data/ImageRGBA.png b/vcl/qa/cppunit/bitmaprender/data/ImageRGBA.png
new file mode 100644
index 000000000..7a8399293
--- /dev/null
+++ b/vcl/qa/cppunit/bitmaprender/data/ImageRGBA.png
Binary files differ
diff --git a/vcl/qa/cppunit/bitmaprender/data/tdf104141.gif b/vcl/qa/cppunit/bitmaprender/data/tdf104141.gif
new file mode 100644
index 000000000..d6390fdaa
--- /dev/null
+++ b/vcl/qa/cppunit/bitmaprender/data/tdf104141.gif
Binary files differ
diff --git a/vcl/qa/cppunit/bitmaprender/data/tdf113918.png b/vcl/qa/cppunit/bitmaprender/data/tdf113918.png
new file mode 100644
index 000000000..dd49897d9
--- /dev/null
+++ b/vcl/qa/cppunit/bitmaprender/data/tdf113918.png
Binary files differ
diff --git a/vcl/qa/cppunit/bitmaprender/data/tdf116888.gif b/vcl/qa/cppunit/bitmaprender/data/tdf116888.gif
new file mode 100644
index 000000000..295310949
--- /dev/null
+++ b/vcl/qa/cppunit/bitmaprender/data/tdf116888.gif
Binary files differ
diff --git a/vcl/qa/cppunit/blocklistparsertest.cxx b/vcl/qa/cppunit/blocklistparsertest.cxx
new file mode 100644
index 000000000..689e8d9c9
--- /dev/null
+++ b/vcl/qa/cppunit/blocklistparsertest.cxx
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/types.h>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <unotest/bootstrapfixturebase.hxx>
+
+#include <driverblocklist.hxx>
+
+using namespace DriverBlocklist;
+
+namespace
+{
+
+class BlocklistParserTest : public test::BootstrapFixtureBase
+{
+ void testParse();
+ void testEvaluate();
+ void testVulkan();
+
+ CPPUNIT_TEST_SUITE(BlocklistParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST(testEvaluate);
+ CPPUNIT_TEST(testVulkan);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void BlocklistParserTest::testParse()
+{
+ std::vector<DriverInfo> aDriveInfos;
+
+ Parser aBlocklistParser(m_directories.getURLFromSrc(u"vcl/qa/cppunit/") + "test_blocklist_parse.xml",
+ aDriveInfos, VersionType::OpenGL);
+ aBlocklistParser.parse();
+
+ size_t const n = aDriveInfos.size();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(16), n);
+
+ size_t i = 0;
+
+ for (bool bIsAllowlisted : {true, false})
+ {
+ DriverInfo& aDriveInfo = aDriveInfos[i++];
+ CPPUNIT_ASSERT_EQUAL(bIsAllowlisted, aDriveInfo.mbAllowlisted);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor); // "all"
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_LESS_THAN, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(OpenGLVersion(10,20,30,40), aDriveInfo.mnDriverVersion);
+
+ aDriveInfo = aDriveInfos[i++];
+ CPPUNIT_ASSERT_EQUAL(bIsAllowlisted, aDriveInfo.mbAllowlisted);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorNVIDIA), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_EQUAL, aDriveInfo.meComparisonOp);
+
+ aDriveInfo = aDriveInfos[i++];
+ CPPUNIT_ASSERT_EQUAL(bIsAllowlisted, aDriveInfo.mbAllowlisted);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorMicrosoft), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_NOT_EQUAL, aDriveInfo.meComparisonOp);
+
+ aDriveInfo = aDriveInfos[i++];
+ CPPUNIT_ASSERT_EQUAL(bIsAllowlisted, aDriveInfo.mbAllowlisted);
+ CPPUNIT_ASSERT_EQUAL(OUString("0xcafe"), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_NOT_EQUAL, aDriveInfo.meComparisonOp);
+
+ aDriveInfo = aDriveInfos[i++];
+ CPPUNIT_ASSERT_EQUAL(bIsAllowlisted, aDriveInfo.mbAllowlisted);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_BETWEEN_EXCLUSIVE, aDriveInfo.meComparisonOp);
+
+ aDriveInfo = aDriveInfos[i++];
+ CPPUNIT_ASSERT_EQUAL(bIsAllowlisted, aDriveInfo.mbAllowlisted);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_BETWEEN_INCLUSIVE, aDriveInfo.meComparisonOp);
+
+ aDriveInfo = aDriveInfos[i++];
+ CPPUNIT_ASSERT_EQUAL(bIsAllowlisted, aDriveInfo.mbAllowlisted);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_BETWEEN_INCLUSIVE_START, aDriveInfo.meComparisonOp);
+
+ aDriveInfo = aDriveInfos[i++];
+ CPPUNIT_ASSERT_EQUAL(bIsAllowlisted, aDriveInfo.mbAllowlisted);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_COMPARISON_IGNORED, aDriveInfo.meComparisonOp);
+ }
+}
+
+void BlocklistParserTest::testEvaluate()
+{
+ std::vector<DriverInfo> aDriveInfos;
+
+ Parser aBlocklistParser(m_directories.getURLFromSrc(u"vcl/qa/cppunit/") + "test_blocklist_evaluate.xml",
+ aDriveInfos, VersionType::OpenGL);
+ aBlocklistParser.parse();
+
+ OUString vendorAMD = GetVendorId(VendorAMD);
+ OUString vendorNVIDIA = GetVendorId(VendorNVIDIA);
+ OUString vendorIntel = GetVendorId(VendorIntel);
+ OUString vendorMicrosoft = GetVendorId(VendorMicrosoft);
+
+ // Check OS
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.40", vendorNVIDIA, "all", DRIVER_OS_WINDOWS_7));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.40", vendorNVIDIA, "all", DRIVER_OS_WINDOWS_8));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.40", vendorNVIDIA, "all", DRIVER_OS_WINDOWS_10));
+
+ // Check generic OS
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.50", vendorMicrosoft, "all", DRIVER_OS_WINDOWS_10));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.50", vendorMicrosoft, "all", DRIVER_OS_LINUX));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.50", vendorMicrosoft, "all", DRIVER_OS_OSX_10_7));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.50", vendorMicrosoft, "all", DRIVER_OS_OSX_10_8));
+
+ // Check Vendors
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.40", vendorMicrosoft, "all", DRIVER_OS_WINDOWS_7));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.40", vendorMicrosoft, "all", DRIVER_OS_WINDOWS_10));
+
+ // Check Versions
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.39", vendorAMD, "all", DRIVER_OS_WINDOWS_7));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.40", vendorAMD, "all", DRIVER_OS_WINDOWS_7));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"10.20.30.41", vendorAMD, "all", DRIVER_OS_WINDOWS_7));
+
+ // Check
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::OpenGL, u"9.17.10.4229", vendorIntel, "all", DRIVER_OS_WINDOWS_7));
+
+
+}
+
+void BlocklistParserTest::testVulkan()
+{
+ std::vector<DriverInfo> aDriveInfos;
+
+ Parser aBlocklistParser(m_directories.getURLFromSrc(u"vcl/qa/cppunit/") + "test_blocklist_vulkan.xml",
+ aDriveInfos, VersionType::Vulkan);
+ aBlocklistParser.parse();
+
+ OUString vendorAMD = GetVendorId(VendorAMD);
+
+ // Check Versions
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::Vulkan, u"1.2.3", vendorAMD, "all", DRIVER_OS_ALL));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::Vulkan, u"1.2.2", vendorAMD, "all", DRIVER_OS_ALL));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, VersionType::Vulkan, u"1.2.20", vendorAMD, "all", DRIVER_OS_ALL));
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BlocklistParserTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/builder/demo.ui b/vcl/qa/cppunit/builder/demo.ui
new file mode 100644
index 000000000..28d6fddb9
--- /dev/null
+++ b/vcl/qa/cppunit/builder/demo.ui
@@ -0,0 +1,1883 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.1 -->
+<interface domain="vcl">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkListStore" id="liststore1">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0">[None]</col>
+ </row>
+ <row>
+ <col id="0">Normal</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="liststore2">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0">1</col>
+ </row>
+ <row>
+ <col id="0">2</col>
+ </row>
+ <row>
+ <col id="0">3</col>
+ </row>
+ <row>
+ <col id="0">4</col>
+ </row>
+ <row>
+ <col id="0">5</col>
+ </row>
+ <row>
+ <col id="0">6</col>
+ </row>
+ <row>
+ <col id="0">7</col>
+ </row>
+ <row>
+ <col id="0">8</col>
+ </row>
+ <row>
+ <col id="0">9</col>
+ </row>
+ <row>
+ <col id="0">10</col>
+ </row>
+ <row>
+ <col id="0">1 - 10</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkDialog" id="dialog1">
+ <property name="can-focus">False</property>
+ <property name="border-width">5</property>
+ <property name="type-hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can-focus">False</property>
+ <property name="layout-style">end</property>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="notebook1">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <!-- n-columns=3 n-rows=3 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">4</property>
+ <property name="column-spacing">2</property>
+ <property name="row-homogeneous">True</property>
+ <property name="column-homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="labelfoo">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">cell 1.1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">cell 3.3</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">2</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">A label that spans three rows</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton1">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combobox1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkButton" id="button4">
+ <property name="label">EXPAND</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="tooltip-text">A tooltip example</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button5">
+ <property name="label">FILL</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkButton" id="button3">
+ <property name="label">button</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton1">
+ <property name="label">radiobutton</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton1">
+ <property name="label">checkbutton</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">left</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">right</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry1">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="text">an edit control</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Frame Label</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Tab1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">page 1</property>
+ </object>
+ <packing>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=4 n-rows=5 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="column-spacing">5</property>
+ <property name="row-homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">_Number of title pages</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">NF_PAGE_COUNT</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Place title pages at</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">pages</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">2</property>
+ <property name="top-attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="NF_PAGE_COUNT">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="NF_PAGE_START">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can-focus">True</property>
+ <property name="numeric">True</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="RB_PAGE_START"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left-attach">2</property>
+ <property name="top-attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_USE_EXISTING_PAGES">
+ <property name="label">Converting existing pages to title pages</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">RB_INSERT_NEW_PAGES</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_INSERT_NEW_PAGES">
+ <property name="label">Insert new title pages</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">RB_USE_EXISTING_PAGES</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_DOCUMENT_START">
+ <property name="label">Document Start</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">RB_PAGE_START</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_PAGE_START">
+ <property name="label">Page</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">RB_DOCUMENT_START</property>
+ <accessibility>
+ <relation type="label-for" target="NF_PAGE_START"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Make Title Pages</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="orientation">vertical</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_RESTART_NUMBERING">
+ <property name="label">Reset Page Numbering after title pages</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box8">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkLabel" id="FT_PAGE_COUNT">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Page number</property>
+ <accessibility>
+ <relation type="label-for" target="NF_RESTART_NUMBERING"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="NF_RESTART_NUMBERING">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can-focus">True</property>
+ <property name="numeric">True</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="FT_PAGE_COUNT"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_SET_PAGE_NUMBER">
+ <property name="label">Set Page Number for first title page</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box9">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkLabel" id="FT_PAGE_PAGES">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Page number</property>
+ <accessibility>
+ <relation type="label-for" target="NF_SET_PAGE_NUMBER"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="NF_SET_PAGE_NUMBER">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can-focus">True</property>
+ <property name="numeric">True</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="FT_PAGE_PAGES"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Page Numbering</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box10">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <child>
+ <object class="GtkComboBox" id="LB_PAGE_PROPERTIES">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="PB_PAGE_PROPERTIES">
+ <property name="label">Edit...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Edit Page Properties</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Tab2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">page 2</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box11">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkRadioButton" id="2">
+ <property name="label">Line break</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="3">
+ <property name="label">Column break</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">2</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="1">
+ <property name="label">Page break</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">2</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Style</property>
+ <property name="mnemonic-widget">5</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="model">liststore1</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="7">
+ <property name="label">Change page number</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <accessibility>
+ <relation type="label-for" target="8"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box12">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkSpinButton" id="8">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="7"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Type</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Tab3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">page 3</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box13">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkFrame" id="frame6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box14">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkRadioButton" id="15">
+ <property name="label">Optimal</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="16">
+ <property name="label">Fit width and height</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">15</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="17">
+ <property name="label">Fit width</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">15</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="18">
+ <property name="label">100%</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">15</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box15">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkRadioButton" id="19">
+ <property name="label">Variable</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">15</property>
+ <accessibility>
+ <relation type="label-for" target="20"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="20">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="19"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="14">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Zoom Factor</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box16">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkRadioButton" id="22">
+ <property name="label">Automatic</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="23">
+ <property name="label">Single page</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">22</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box17">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkRadioButton" id="24">
+ <property name="label">Columns</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">22</property>
+ <accessibility>
+ <relation type="label-for" target="25"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="25">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="24"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="26">
+ <property name="label">Book mode</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="margin-start">10</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="21">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">View Layout</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">page 4</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box18">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">10</property>
+ <property name="margin-end">10</property>
+ <child>
+ <object class="GtkFrame" id="frame8">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkTreeView" id="treeview1">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="margin-start">12</property>
+ <property name="model">liststore2</property>
+ <property name="headers-visible">False</property>
+ <property name="search-column">0</property>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Level</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame9">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box19">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox" id="box20">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <!-- n-columns=2 n-rows=9 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="column-spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="label16">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Paragraph Style</property>
+ <property name="mnemonic-widget">combobox2</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combobox2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label17">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Number</property>
+ <property name="mnemonic-widget">combobox3</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label18">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Character Style</property>
+ <property name="mnemonic-widget">combobox4</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label19">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Show sublevels</property>
+ <property name="mnemonic-widget">spinbutton2</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label20">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Separator</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combobox3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combobox4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton2">
+ <property name="visible">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="can-focus">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry2">
+ <property name="visible">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="can-focus">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry3">
+ <property name="visible">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="can-focus">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton3">
+ <property name="visible">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="can-focus">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label23">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Start at</property>
+ <property name="mnemonic-widget">spinbutton3</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label22">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">20</property>
+ <property name="label">After</property>
+ <property name="mnemonic-widget">entry3</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label21">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">20</property>
+ <property name="label">Before</property>
+ <property name="mnemonic-widget">entry2</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="drawingarea1">
+ <property name="width-request">150</property>
+ <property name="height-request">200</property>
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label24">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Numbering</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">page 5</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box21">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">10</property>
+ <property name="margin-end">10</property>
+ <child>
+ <object class="GtkFrame" id="frame10">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkTreeView" id="treeview2">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="margin-start">12</property>
+ <property name="model">liststore2</property>
+ <property name="headers-visible">False</property>
+ <property name="search-column">0</property>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label26">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Level</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame11">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=6 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="row-spacing">10</property>
+ <property name="column-spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="label27">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Numbering followed by</property>
+ <property name="mnemonic-widget">combobox5</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label28">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Numbering Alignment</property>
+ <property name="mnemonic-widget">combobox6</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label29">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Aligned at</property>
+ <property name="mnemonic-widget">spinbutton6</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label30">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Indent at</property>
+ <property name="mnemonic-widget">spinbutton4</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combobox5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton4">
+ <property name="visible">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="can-focus">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label31">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">at</property>
+ <property name="mnemonic-widget">spinbutton5</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton5">
+ <property name="visible">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="can-focus">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton6">
+ <property name="visible">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="can-focus">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combobox6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="drawingarea2">
+ <property name="width-request">300</property>
+ <property name="height-request">150</property>
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button6">
+ <property name="label">Default</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="valign">end</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label32">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Position and Spacing</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label25">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">page 6</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkExpander" id="expander1">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="resize-toplevel">True</property>
+ <child>
+ <!-- n-columns=2 n-rows=3 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">200</property>
+ <property name="column-spacing">400</property>
+ <child>
+ <object class="GtkLabel" id="label34">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">label</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label35">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">label</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label36">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">label</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label37">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">label</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label38">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">label</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label39">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">label</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label40">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">Details</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label33">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label">page 7</property>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/vcl/qa/cppunit/canvasbitmaptest.cxx b/vcl/qa/cppunit/canvasbitmaptest.cxx
new file mode 100644
index 000000000..91a5cfed4
--- /dev/null
+++ b/vcl/qa/cppunit/canvasbitmaptest.cxx
@@ -0,0 +1,791 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// bootstrap stuff
+#include <test/bootstrapfixture.hxx>
+
+#include <com/sun/star/util/Endianness.hpp>
+#include <com/sun/star/rendering/ColorComponentTag.hpp>
+#include <com/sun/star/rendering/ColorSpaceType.hpp>
+#include <com/sun/star/rendering/RenderingIntent.hpp>
+#include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
+#include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
+#include <com/sun/star/rendering/XBitmapPalette.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+
+#include <vcl/canvastools.hxx>
+#include <vcl/bitmapex.hxx>
+
+#include <canvasbitmap.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace vcl::unotools;
+
+namespace com::sun::star::rendering
+{
+
+static bool operator==( const RGBColor& rLHS, const ARGBColor& rRHS )
+{
+ return rLHS.Red == rRHS.Red && rLHS.Green == rRHS.Green && rLHS.Blue == rRHS.Blue;
+}
+
+}
+
+namespace
+{
+
+class CanvasBitmapTest : public test::BootstrapFixture
+{
+public:
+ CanvasBitmapTest() : BootstrapFixture(true, false) {}
+
+ void runTest();
+
+ CPPUNIT_TEST_SUITE(CanvasBitmapTest);
+ CPPUNIT_TEST(runTest);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool rangeCheck( const rendering::RGBColor& rColor )
+{
+ return rColor.Red < 0.0 || rColor.Red > 1.0 ||
+ rColor.Green < 0.0 || rColor.Green > 1.0 ||
+ rColor.Blue < 0.0 || rColor.Blue > 1.0;
+}
+
+void checkCanvasBitmap( const rtl::Reference<VclCanvasBitmap>& xBmp,
+ const char* msg,
+ int nOriginalDepth )
+{
+ SAL_INFO("vcl", "Testing " << msg << ", with depth " << nOriginalDepth);
+
+ BitmapEx aContainedBmpEx( xBmp->getBitmapEx() );
+ Bitmap aContainedBmp( aContainedBmpEx.GetBitmap() );
+ int nDepth = nOriginalDepth;
+ int extraBpp = 0;
+
+ {
+ Bitmap::ScopedReadAccess pAcc( aContainedBmp );
+ nDepth = pAcc->GetBitCount();
+ if( pAcc->GetScanlineFormat() == ScanlineFormat::N32BitTcMask )
+ extraBpp = 8; // the format has 8 unused bits
+ }
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Original bitmap size not (200,200)",
+ Size(200,200), aContainedBmp.GetSizePixel());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Original bitmap size via API not (200,200)",
+ sal_Int32(200), xBmp->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Original bitmap size via API not (200,200)",
+ sal_Int32(200), xBmp->getSize().Height);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "alpha state mismatch",
+ aContainedBmpEx.IsAlpha(), bool(xBmp->hasAlpha()));
+
+ CPPUNIT_ASSERT_MESSAGE( "getScaledBitmap() failed",
+ xBmp->getScaledBitmap( geometry::RealSize2D(500,500), false ).is());
+
+ rendering::IntegerBitmapLayout aLayout;
+ uno::Sequence<sal_Int8> aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,1,1));
+
+ const sal_Int32 nExpectedBitsPerPixel(
+ (aContainedBmpEx.IsAlpha() ? std::max(8,nDepth)+8 : nDepth) + extraBpp);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "# scanlines not 1",
+ static_cast<sal_Int32>(1), aLayout.ScanLines);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "# scanline bytes mismatch",
+ static_cast<sal_Int32>((nExpectedBitsPerPixel+7)/8), aLayout.ScanLineBytes);
+ CPPUNIT_ASSERT_MESSAGE( "# scanline stride mismatch",
+ aLayout.ScanLineStride == (nExpectedBitsPerPixel+7)/8 ||
+ aLayout.ScanLineStride == -(nExpectedBitsPerPixel+7)/8);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "# plane stride not 0",
+ static_cast<sal_Int32>(0), aLayout.PlaneStride);
+
+ CPPUNIT_ASSERT_MESSAGE( "Color space not there",
+ aLayout.ColorSpace.is());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Palette existence does not conform to bitmap",
+ (nDepth <= 8), aLayout.Palette.is());
+
+ uno::Sequence<sal_Int8> aPixelData2 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(0,0) );
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "getData and getPixel did not return same amount of data",
+ aPixelData.getLength(), aPixelData2.getLength());
+
+ aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,200,1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "# scanlines not 1 for getPixel",
+ static_cast<sal_Int32>(1), aLayout.ScanLines);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "# scanline bytes mismatch for getPixel",
+ static_cast<sal_Int32>((200*nExpectedBitsPerPixel+7)/8), aLayout.ScanLineBytes);
+ CPPUNIT_ASSERT_MESSAGE( "# scanline stride mismatch for getPixel",
+ aLayout.ScanLineStride == (200*nExpectedBitsPerPixel+7)/8 ||
+ aLayout.ScanLineStride == -(200*nExpectedBitsPerPixel+7)/8);
+
+ uno::Sequence< rendering::RGBColor > aRGBColors = xBmp->convertIntegerToRGB( aPixelData );
+ uno::Sequence< rendering::ARGBColor > aARGBColors = xBmp->convertIntegerToARGB( aPixelData );
+
+ const rendering::RGBColor* pRGBStart ( aRGBColors.getConstArray() );
+ const rendering::RGBColor* pRGBEnd ( aRGBColors.getConstArray()+aRGBColors.getLength() );
+ const rendering::ARGBColor* pARGBStart( aARGBColors.getConstArray() );
+ std::pair<const rendering::RGBColor*,
+ const rendering::ARGBColor*> aRes = std::mismatch( pRGBStart, pRGBEnd, pARGBStart );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "argb and rgb colors are not equal",
+ pRGBEnd, aRes.first);
+
+ CPPUNIT_ASSERT_MESSAGE( "rgb colors are not within [0,1] range",
+ std::none_of(pRGBStart,pRGBEnd,&rangeCheck));
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "First pixel is not white", 1.0, pRGBStart[0].Red, 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "First pixel is not white", 1.0, pRGBStart[0].Green, 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "First pixel is not white", 1.0, pRGBStart[0].Blue, 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "Second pixel is not opaque", 1.0, pARGBStart[1].Alpha, 1E-12);
+ if( aContainedBmpEx.IsAlpha() )
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "First pixel is not fully transparent",
+ 0.0, pARGBStart[0].Alpha);
+ }
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Second pixel is not black",
+ 0.0, pRGBStart[1].Red);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Second pixel is not black",
+ 0.0, pRGBStart[1].Green);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Second pixel is not black",
+ 0.0, pRGBStart[1].Blue);
+
+ if( nOriginalDepth > 8 )
+ {
+ const Color aCol(COL_GREEN);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Sixth pixel is not green (red component)",
+ vcl::unotools::toDoubleColor(aCol.GetRed()), pRGBStart[5].Red);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Sixth pixel is not green (green component)",
+ vcl::unotools::toDoubleColor(aCol.GetGreen()), pRGBStart[5].Green);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Sixth pixel is not green (blue component)",
+ vcl::unotools::toDoubleColor(aCol.GetBlue()), pRGBStart[5].Blue);
+ }
+ else if( nDepth <= 8 )
+ {
+ uno::Reference<rendering::XBitmapPalette> xPal = xBmp->getPalette();
+ CPPUNIT_ASSERT_MESSAGE( "8bit or less: missing palette",
+ xPal.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Palette incorrect entry count",
+ static_cast<sal_Int32>(1 << nOriginalDepth), xPal->getNumberOfEntries());
+ uno::Sequence<double> aIndex;
+ CPPUNIT_ASSERT_MESSAGE( "Palette is not read-only",
+ !xPal->setIndex(aIndex,true,0));
+ CPPUNIT_ASSERT_MESSAGE( "Palette entry 0 is not opaque",
+ xPal->getIndex(aIndex,0));
+ CPPUNIT_ASSERT_MESSAGE( "Palette has no valid color space",
+ xPal->getColorSpace().is());
+ }
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "150th pixel is not white", 1.0, pRGBStart[150].Red, 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "150th pixel is not white", 1.0, pRGBStart[150].Green, 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "150th pixel is not white", 1.0, pRGBStart[150].Blue, 1E-12);
+
+ if( nOriginalDepth <= 8 )
+ return;
+
+ uno::Sequence<sal_Int8> aPixel3, aPixel4;
+
+ const Color aCol(COL_GREEN);
+ uno::Sequence<rendering::ARGBColor> aARGBColor
+ {
+ {
+ 1.0,
+ vcl::unotools::toDoubleColor(aCol.GetRed()),
+ vcl::unotools::toDoubleColor(aCol.GetGreen()),
+ vcl::unotools::toDoubleColor(aCol.GetBlue())
+ }
+ };
+
+ uno::Sequence<rendering::RGBColor> aRGBColor
+ {
+ {
+ vcl::unotools::toDoubleColor(aCol.GetRed()),
+ vcl::unotools::toDoubleColor(aCol.GetGreen()),
+ vcl::unotools::toDoubleColor(aCol.GetBlue())
+ }
+ };
+
+ aPixel3 = xBmp->convertIntegerFromARGB( aARGBColor );
+ aPixel4 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(5,0) );
+ CPPUNIT_ASSERT_MESSAGE( "Green pixel from bitmap mismatch with manually converted green pixel",
+ bool(aPixel3 == aPixel4));
+
+ if( !aContainedBmpEx.IsAlpha() )
+ {
+ aPixel3 = xBmp->convertIntegerFromRGB( aRGBColor );
+ CPPUNIT_ASSERT_MESSAGE( "Green pixel from bitmap mismatch with manually RGB-converted green pixel",
+ bool(aPixel3 == aPixel4));
+ }
+
+}
+
+class TestBitmap : public cppu::WeakImplHelper< rendering::XIntegerReadOnlyBitmap,
+ rendering::XBitmapPalette,
+ rendering::XIntegerBitmapColorSpace >
+{
+private:
+ geometry::IntegerSize2D maSize;
+ uno::Sequence<sal_Int8> maComponentTags;
+ uno::Sequence<sal_Int32> maComponentBitCounts;
+ rendering::IntegerBitmapLayout maLayout;
+ const sal_Int32 mnBitsPerPixel;
+
+ // XBitmap
+ virtual geometry::IntegerSize2D SAL_CALL getSize() override { return maSize; }
+ virtual sal_Bool SAL_CALL hasAlpha( ) override { return mnBitsPerPixel != 8; }
+ virtual uno::Reference< rendering::XBitmap > SAL_CALL getScaledBitmap( const geometry::RealSize2D&,
+ sal_Bool ) override { return this; }
+
+ // XIntegerReadOnlyBitmap
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL getData( rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerRectangle2D& rect ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "X1 out of bounds", rect.X1 >= 0 );
+ CPPUNIT_ASSERT_MESSAGE( "Y1 out of bounds", rect.Y1 >= 0 );
+ CPPUNIT_ASSERT_MESSAGE( "X2 out of bounds", rect.X2 <= maSize.Width );
+ CPPUNIT_ASSERT_MESSAGE( "Y2 out of bounds", rect.Y2 <= maSize.Height );
+
+ bitmapLayout = getMemoryLayout();
+
+ const sal_Int32 nWidth = rect.X2-rect.X1;
+ const sal_Int32 nHeight = rect.Y2-rect.Y1;
+ const sal_Int32 nScanlineLen = (nWidth * mnBitsPerPixel + 7)/8;
+ uno::Sequence<sal_Int8> aRes( nScanlineLen * nHeight );
+ sal_Int8* pOut = aRes.getArray();
+
+ bitmapLayout.ScanLines = nHeight;
+ bitmapLayout.ScanLineBytes =
+ bitmapLayout.ScanLineStride= nScanlineLen;
+
+ if( mnBitsPerPixel == 8 )
+ {
+ for( sal_Int32 y=0; y<nHeight; ++y )
+ {
+ for( sal_Int32 x=0; x<nWidth; ++x )
+ pOut[ y*nScanlineLen + x ] = sal_Int8(x);
+ }
+ }
+ else
+ {
+ for( sal_Int32 y=0; y<nHeight; ++y )
+ {
+ for( sal_Int32 x=0; x<nWidth; ++x )
+ {
+ pOut[ y*nScanlineLen + 4*x ] = sal_Int8(rect.X1);
+ pOut[ y*nScanlineLen + 4*x + 1 ] = sal_Int8(rect.Y2);
+ pOut[ y*nScanlineLen + 4*x + 2 ] = sal_Int8(x);
+ pOut[ y*nScanlineLen + 4*x + 3 ] = sal_Int8(rect.Y1);
+ }
+ }
+ }
+
+ return aRes;
+ }
+
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL getPixel( rendering::IntegerBitmapLayout&,
+ const geometry::IntegerPoint2D& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("getPixel: method not implemented", false);
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ /// @throws uno::RuntimeException
+ uno::Reference< rendering::XBitmapPalette > getPalette( )
+ {
+ uno::Reference< XBitmapPalette > aRet;
+ if( mnBitsPerPixel == 8 )
+ aRet.set(this);
+ return aRet;
+ }
+
+ virtual rendering::IntegerBitmapLayout SAL_CALL getMemoryLayout( ) override
+ {
+ rendering::IntegerBitmapLayout aLayout( maLayout );
+
+ const sal_Int32 nScanlineLen = (maSize.Width * mnBitsPerPixel + 7)/8;
+
+ aLayout.ScanLines = maSize.Height;
+ aLayout.ScanLineBytes =
+ aLayout.ScanLineStride= nScanlineLen;
+ aLayout.Palette = getPalette();
+ aLayout.ColorSpace.set( this );
+
+ return aLayout;
+ }
+
+ // XBitmapPalette
+ virtual sal_Int32 SAL_CALL getNumberOfEntries() override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "Got palette getNumberOfEntries interface call without handing out palette",
+ getPalette().is() );
+
+ return 255;
+ }
+
+ virtual sal_Bool SAL_CALL getIndex( uno::Sequence< double >& entry,
+ ::sal_Int32 nIndex ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "Got palette getIndex interface call without handing out palette",
+ getPalette().is() );
+ CPPUNIT_ASSERT_MESSAGE( "getIndex: index out of range",
+ nIndex >= 0 );
+ CPPUNIT_ASSERT_MESSAGE( "getIndex: index out of range",
+ nIndex < 256 );
+ entry = colorToStdColorSpaceSequence(
+ Color(sal_uInt8(nIndex),
+ sal_uInt8(nIndex),
+ sal_uInt8(nIndex)) );
+
+ return true; // no palette transparency here.
+ }
+
+ virtual sal_Bool SAL_CALL setIndex( const uno::Sequence< double >&,
+ sal_Bool,
+ ::sal_Int32 nIndex ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "Got palette setIndex interface call without handing out palette",
+ getPalette().is());
+ CPPUNIT_ASSERT_MESSAGE( "setIndex: index out of range",
+ nIndex >= 0);
+ CPPUNIT_ASSERT_MESSAGE( "setIndex: index out of range",
+ nIndex < 256);
+ return false;
+ }
+
+ struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
+ PaletteColorSpaceHolder>
+ {
+ uno::Reference<rendering::XColorSpace> operator()()
+ {
+ return vcl::unotools::createStandardColorSpace();
+ }
+ };
+
+ virtual uno::Reference< rendering::XColorSpace > SAL_CALL getColorSpace( ) override
+ {
+ // this is the method from XBitmapPalette. Return palette color
+ // space here
+ return PaletteColorSpaceHolder::get();
+ }
+
+ // XIntegerBitmapColorSpace
+ virtual ::sal_Int8 SAL_CALL getType( ) override
+ {
+ return rendering::ColorSpaceType::RGB;
+ }
+
+ virtual uno::Sequence< sal_Int8 > SAL_CALL getComponentTags( ) override
+ {
+ return maComponentTags;
+ }
+
+ virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) override
+ {
+ return rendering::RenderingIntent::PERCEPTUAL;
+ }
+
+ virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties() override
+ {
+ CPPUNIT_ASSERT_MESSAGE("getProperties: method not implemented", false );
+ return uno::Sequence< ::beans::PropertyValue >();
+ }
+
+ virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >&,
+ const uno::Reference< rendering::XColorSpace >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertColorSpace: method not implemented", false);
+ return uno::Sequence< double >();
+ }
+
+ virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertToRGB: method not implemented", false);
+ return uno::Sequence< rendering::RGBColor >();
+ }
+
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertToARGB: method not implemented", false);
+ return uno::Sequence< rendering::ARGBColor >();
+ }
+
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertToPARGB: method not implemented", false);
+ return uno::Sequence< rendering::ARGBColor >();
+ }
+
+ virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertFromRGB: method not implemented", false);
+ return uno::Sequence< double >();
+ }
+
+ virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertFromARGB: this method is not expected to be called!", false);
+ return uno::Sequence< double >();
+ }
+
+ virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertFromPARGB: this method is not expected to be called!", false);
+ return uno::Sequence< double >();
+ }
+
+ virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) override
+ {
+ return mnBitsPerPixel;
+ }
+
+ virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) override
+ {
+ return maComponentBitCounts;
+ }
+
+ virtual ::sal_Int8 SAL_CALL getEndianness( ) override
+ {
+ return util::Endianness::LITTLE;
+ }
+
+ virtual uno::Sequence< double > SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& ,
+ const uno::Reference< rendering::XColorSpace >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertFromIntegerColorSpace: method not implemented", false);
+ return uno::Sequence< double >();
+ }
+
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& ,
+ const uno::Reference< rendering::XIntegerBitmapColorSpace >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertToIntegerColorSpace: method not implemented", false);
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) override
+ {
+ const uno::Sequence< rendering::ARGBColor > aTemp( convertIntegerToARGB(deviceColor) );
+ uno::Sequence< rendering::RGBColor > aRes( aTemp.getLength() );
+ std::transform(aTemp.begin(), aTemp.end(), aRes.getArray(),
+ [](const rendering::ARGBColor& rColor) {
+ return rendering::RGBColor(rColor.Red,
+ rColor.Green,
+ rColor.Blue);
+ });
+
+ return aRes;
+ }
+
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) override
+ {
+ const std::size_t nLen( deviceColor.getLength() );
+ const sal_Int32 nBytesPerPixel(mnBitsPerPixel == 8 ? 1 : 4);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("number of channels no multiple of pixel element count",
+ 0, static_cast<int>(nLen%nBytesPerPixel));
+
+ uno::Sequence< rendering::ARGBColor > aRes( nLen / nBytesPerPixel );
+
+ if( getPalette().is() )
+ {
+ std::transform(deviceColor.begin(), deviceColor.end(), aRes.getArray(),
+ [](sal_Int8 nIn) {
+ auto fColor = vcl::unotools::toDoubleColor(nIn);
+ return rendering::ARGBColor(1.0, fColor, fColor, fColor);
+ });
+ }
+ else
+ {
+ rendering::ARGBColor* pOut( aRes.getArray() );
+ for( std::size_t i=0; i<nLen; i+=4 )
+ {
+ *pOut++ = rendering::ARGBColor(
+ vcl::unotools::toDoubleColor(deviceColor[i+3]),
+ vcl::unotools::toDoubleColor(deviceColor[i+0]),
+ vcl::unotools::toDoubleColor(deviceColor[i+1]),
+ vcl::unotools::toDoubleColor(deviceColor[i+2]));
+ }
+ }
+
+ return aRes;
+ }
+
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB(
+ const uno::Sequence< ::sal_Int8 >& deviceColor) override
+ {
+ const std::size_t nLen( deviceColor.getLength() );
+ const sal_Int32 nBytesPerPixel(mnBitsPerPixel == 8 ? 1 : 4);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("number of channels no multiple of pixel element count",
+ 0, static_cast<int>(nLen%nBytesPerPixel));
+
+ uno::Sequence< rendering::ARGBColor > aRes( nLen / nBytesPerPixel );
+
+ if( getPalette().is() )
+ {
+ std::transform(deviceColor.begin(), deviceColor.end(), aRes.getArray(),
+ [](sal_Int8 nIn) {
+ auto fColor = vcl::unotools::toDoubleColor(nIn);
+ return rendering::ARGBColor(1.0, fColor, fColor, fColor);
+ });
+ }
+ else
+ {
+ rendering::ARGBColor* pOut( aRes.getArray() );
+ for( std::size_t i=0; i<nLen; i+=4 )
+ {
+ const double fAlpha=vcl::unotools::toDoubleColor(deviceColor[i+3]);
+ *pOut++ = rendering::ARGBColor(
+ fAlpha,
+ fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+0]),
+ fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+1]),
+ fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+2]));
+ }
+ }
+
+ return aRes;
+ }
+
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB(
+ const uno::Sequence< rendering::RGBColor >&) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertIntegerFromRGB: method not implemented", false);
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertIntegerFromARGB: method not implemented", false);
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE("convertIntegerFromPARGB: method not implemented", false);
+ return uno::Sequence< sal_Int8 >();
+ }
+
+public:
+ TestBitmap( const geometry::IntegerSize2D& rSize, bool bPalette ) :
+ maSize(rSize),
+ maComponentTags(),
+ maComponentBitCounts(),
+ maLayout(),
+ mnBitsPerPixel( bPalette ? 8 : 32 )
+ {
+ if( bPalette )
+ {
+ maComponentTags = { rendering::ColorComponentTag::INDEX };
+ maComponentBitCounts = { 8 };
+ }
+ else
+ {
+ maComponentTags.realloc(4);
+ sal_Int8* pTags = maComponentTags.getArray();
+ pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
+ pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
+ pTags[2] = rendering::ColorComponentTag::RGB_RED;
+ pTags[3] = rendering::ColorComponentTag::ALPHA;
+
+ maComponentBitCounts.realloc(4);
+ sal_Int32* pCounts = maComponentBitCounts.getArray();
+ pCounts[0] = 8;
+ pCounts[1] = 8;
+ pCounts[2] = 8;
+ pCounts[3] = 8;
+ }
+
+ maLayout.ScanLines = 0;
+ maLayout.ScanLineBytes = 0;
+ maLayout.ScanLineStride = 0;
+ maLayout.PlaneStride = 0;
+ maLayout.ColorSpace.clear();
+ maLayout.Palette.clear();
+ maLayout.IsMsbFirst = false;
+ }
+};
+
+void CanvasBitmapTest::runTest()
+{
+ static vcl::PixelFormat ePixelFormatArray[] =
+ {
+ vcl::PixelFormat::N1_BPP,
+ vcl::PixelFormat::N8_BPP,
+ vcl::PixelFormat::N24_BPP
+ };
+
+ // Testing VclCanvasBitmap wrapper
+
+ for (auto const pixelFormat : ePixelFormatArray)
+ {
+ const sal_uInt16 nDepth = sal_uInt16(pixelFormat);
+ Bitmap aBitmap(Size(200,200), pixelFormat);
+ aBitmap.Erase(COL_WHITE);
+ {
+ BitmapScopedWriteAccess pAcc(aBitmap);
+ if( pAcc.get() )
+ {
+ BitmapColor aBlack(0);
+ BitmapColor aWhite(0);
+ if( pAcc->HasPalette() )
+ {
+ aBlack.SetIndex( sal::static_int_cast<sal_Int8>(pAcc->GetBestPaletteIndex(BitmapColor(0,0,0))) );
+ aWhite.SetIndex( sal::static_int_cast<sal_Int8>(pAcc->GetBestPaletteIndex(BitmapColor(255,255,255))) );
+ }
+ else
+ {
+ aBlack = COL_BLACK;
+ aWhite = COL_WHITE;
+ }
+ pAcc->SetFillColor(COL_GREEN);
+ pAcc->FillRect(tools::Rectangle(0,0,100,100));
+ pAcc->SetPixel(0,0,aWhite);
+ pAcc->SetPixel(0,1,aBlack);
+ pAcc->SetPixel(0,2,aWhite);
+ }
+ }
+
+ rtl::Reference<VclCanvasBitmap> xBmp( new VclCanvasBitmap(BitmapEx(aBitmap)) );
+
+ checkCanvasBitmap( xBmp, "single bitmap", nDepth );
+
+ Bitmap aMask(Size(200,200), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256));
+ aMask.Erase(COL_WHITE);
+ {
+ BitmapScopedWriteAccess pAcc(aMask);
+ if( pAcc.get() )
+ {
+ pAcc->SetFillColor(COL_BLACK);
+ pAcc->FillRect(tools::Rectangle(0,0,100,100));
+ pAcc->SetPixel(0,0,BitmapColor(255));
+ pAcc->SetPixel(0,1,BitmapColor(0));
+ pAcc->SetPixel(0,2,BitmapColor(255));
+ }
+ }
+
+ xBmp.set( new VclCanvasBitmap(BitmapEx(aBitmap,aMask)) );
+
+ checkCanvasBitmap( xBmp, "masked bitmap", nDepth );
+
+ AlphaMask aAlpha(Size(200,200));
+ aAlpha.Erase(255);
+ {
+ BitmapWriteAccess* pAcc = aAlpha.AcquireWriteAccess();
+ if( pAcc )
+ {
+ pAcc->SetFillColor(COL_BLACK);
+ pAcc->FillRect(tools::Rectangle(0,0,100,100));
+ pAcc->SetPixel(0,0,BitmapColor(255));
+ pAcc->SetPixel(0,1,BitmapColor(0));
+ pAcc->SetPixel(0,2,BitmapColor(255));
+ aAlpha.ReleaseAccess(pAcc);
+ }
+ }
+
+ xBmp.set( new VclCanvasBitmap(BitmapEx(aBitmap,aAlpha)) );
+
+ checkCanvasBitmap( xBmp, "alpha bitmap", nDepth );
+ }
+
+ // Testing XBitmap import
+
+ uno::Reference< rendering::XIntegerReadOnlyBitmap > xTestBmp(
+ new TestBitmap( geometry::IntegerSize2D(10,10), true ));
+
+ BitmapEx aBmp = vcl::unotools::bitmapExFromXBitmap(xTestBmp);
+ CPPUNIT_ASSERT_MESSAGE( "Palette bitmap is alpha",
+ !aBmp.IsAlpha());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Bitmap does not have size (10,10)",
+ Size(10,10), aBmp.GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Bitmap does not have the expected pixel format",
+ vcl::PixelFormat::N8_BPP, aBmp.getPixelFormat());
+ {
+ Bitmap aBitmap = aBmp.GetBitmap();
+ BitmapReadAccess* pBmpAcc = aBitmap.AcquireReadAccess();
+
+ CPPUNIT_ASSERT_MESSAGE( "Bitmap has invalid BitmapReadAccess",
+ pBmpAcc );
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(0,0) incorrect content",
+ BitmapColor(0), pBmpAcc->GetPixel(0,0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(2,2) incorrect content",
+ BitmapColor(2), pBmpAcc->GetPixel(2,2));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(9,2) incorrect content",
+ BitmapColor(9), pBmpAcc->GetPixel(2,9));
+
+ Bitmap::ReleaseAccess(pBmpAcc);
+ }
+
+ xTestBmp.set( new TestBitmap( geometry::IntegerSize2D(10,10), false ));
+
+ aBmp = vcl::unotools::bitmapExFromXBitmap(xTestBmp);
+ CPPUNIT_ASSERT_MESSAGE( "Palette bitmap has no alpha",
+ aBmp.IsAlpha());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Bitmap does not have size (10,10)",
+ Size(10,10), aBmp.GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Bitmap does not have the expected pixel format",
+ vcl::PixelFormat::N24_BPP, aBmp.getPixelFormat());
+ {
+ Bitmap aBitmap = aBmp.GetBitmap();
+ BitmapReadAccess* pBmpAcc = aBitmap.AcquireReadAccess();
+ BitmapReadAccess* pAlphaAcc = aBmp.GetAlpha().AcquireReadAccess();
+
+ CPPUNIT_ASSERT_MESSAGE( "Bitmap has invalid BitmapReadAccess",
+ pBmpAcc);
+ CPPUNIT_ASSERT_MESSAGE( "Bitmap has invalid alpha BitmapReadAccess",
+ pAlphaAcc);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(0,0) incorrect content",
+ BitmapColor(0,1,0), pBmpAcc->GetPixel(0,0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(0,0) incorrect alpha content",
+ BitmapColor(255), pAlphaAcc->GetPixel(0,0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(2,2) incorrect content",
+ BitmapColor(0,3,2), pBmpAcc->GetPixel(2,2));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(2,2) incorrect alpha content",
+ BitmapColor(253), pAlphaAcc->GetPixel(2,2));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(9,2) incorrect content",
+ BitmapColor(0,3,9), pBmpAcc->GetPixel(2,9));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(9,2) correct alpha content",
+ BitmapColor(253), pAlphaAcc->GetPixel(2,9));
+
+ aBmp.GetAlpha().ReleaseAccess(pAlphaAcc);
+ Bitmap::ReleaseAccess(pBmpAcc);
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(CanvasBitmapTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx
new file mode 100644
index 000000000..3bf69cd3a
--- /dev/null
+++ b/vcl/qa/cppunit/complextext.cxx
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <config_features.h>
+#include <config_fonts.h>
+
+#include <ostream>
+#include <vector>
+#include <tools/long.hxx>
+#include <vcl/glyphitemcache.hxx>
+
+#if HAVE_MORE_FONTS
+// must be declared before inclusion of test/bootstrapfixture.hxx
+static std::ostream& operator<<(std::ostream& rStream, const std::vector<sal_Int32>& rVec);
+#endif
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/wrkwin.hxx>
+#include <vcl/virdev.hxx>
+// workaround MSVC2015 issue with std::unique_ptr
+#include <sallayout.hxx>
+#include <salgdi.hxx>
+
+
+#include <ImplLayoutArgs.hxx>
+
+#if HAVE_MORE_FONTS
+static std::ostream& operator<<(std::ostream& rStream, const std::vector<sal_Int32>& rVec)
+{
+ rStream << "{ ";
+ for (size_t i = 0; i < rVec.size() - 1; i++)
+ rStream << rVec[i] << ", ";
+ rStream << rVec.back();
+ rStream << " }";
+ return rStream;
+}
+#endif
+
+class VclComplexTextTest : public test::BootstrapFixture
+{
+public:
+ VclComplexTextTest() : BootstrapFixture(true, false) {}
+
+ /// Play with font measuring etc.
+ void testArabic();
+ void testKashida();
+ void testTdf95650(); // Windows-only issue
+ void testCaching();
+ void testCachingSubstring();
+
+ CPPUNIT_TEST_SUITE(VclComplexTextTest);
+ CPPUNIT_TEST(testArabic);
+ CPPUNIT_TEST(testKashida);
+ CPPUNIT_TEST(testTdf95650);
+ CPPUNIT_TEST(testCaching);
+ CPPUNIT_TEST(testCachingSubstring);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclComplexTextTest::testArabic()
+{
+#if HAVE_MORE_FONTS
+ OUString aOneTwoThree(u"واحِدْ إثٍنين ثلاثةٌ");
+ ScopedVclPtrInstance<WorkWindow> pWin(static_cast<vcl::Window *>(nullptr));
+ CPPUNIT_ASSERT( pWin );
+
+ vcl::Font aFont("DejaVu Sans", "Book", Size(0, 12));
+
+ OutputDevice *pOutDev = pWin->GetOutDev();
+ pOutDev->SetFont( aFont );
+
+ // absolute character widths AKA text array.
+ std::vector<sal_Int32> aRefCharWidths {6, 9, 16, 16, 22, 22, 26, 29, 32, 32,
+ 36, 40, 49, 53, 56, 63, 63, 66, 72, 72};
+ std::vector<sal_Int32> aCharWidths(aOneTwoThree.getLength(), 0);
+ tools::Long nTextWidth = pOutDev->GetTextArray(aOneTwoThree, &aCharWidths);
+
+ CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths);
+ // this sporadically returns 75 or 74 on some of the windows tinderboxes eg. tb73
+ CPPUNIT_ASSERT_EQUAL(tools::Long(72), nTextWidth);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
+
+ // text advance width and line height
+ CPPUNIT_ASSERT_EQUAL(tools::Long(72), pOutDev->GetTextWidth(aOneTwoThree));
+ CPPUNIT_ASSERT_EQUAL(tools::Long(14), pOutDev->GetTextHeight());
+
+ // exact bounding rectangle, not essentially the same as text width/height
+ tools::Rectangle aBoundRect;
+ pOutDev->GetTextBoundRect(aBoundRect, aOneTwoThree);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0, aBoundRect.Left(), 1); // This sometimes equals to 1
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1, aBoundRect.Top(), 1);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(71, aBoundRect.getWidth(), 1); // This sometimes equals to 70
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(15, aBoundRect.getHeight(), 1);
+
+#if 0
+ // FIXME: This seems to be wishful thinking, GetTextRect() does not take
+ // rotation into account.
+
+ // normal orientation
+ tools::Rectangle aInput;
+ tools::Rectangle aRect = pOutDev->GetTextRect( aInput, aOneTwoThree );
+
+ // now rotate 270 degrees
+ vcl::Font aRotated( aFont );
+ aRotated.SetOrientation( 2700 );
+ pOutDev->SetFont( aRotated );
+ tools::Rectangle aRectRot = pOutDev->GetTextRect( aInput, aOneTwoThree );
+
+ // Check that we did do the rotation...
+ fprintf( stderr, "%" SAL_PRIdINT64 " %" SAL_PRIdINT64 " %" SAL_PRIdINT64 " %" SAL_PRIdINT64 "\n",
+ sal_Int64(aRect.GetWidth()), sal_Int64(aRect.GetHeight()),
+ sal-Int64(aRectRot.GetWidth()), sal_Int64(aRectRot.GetHeight()) );
+ CPPUNIT_ASSERT( aRectRot.GetWidth() == aRect.GetHeight() );
+ CPPUNIT_ASSERT( aRectRot.GetHeight() == aRect.GetWidth() );
+#endif
+#endif
+}
+
+void VclComplexTextTest::testKashida()
+{
+#if HAVE_MORE_FONTS
+ // Cache the glyph list of some Arabic text.
+ ScopedVclPtrInstance<VirtualDevice> pOutputDevice;
+ auto aText
+ = OUString(u"عنصر الفوسفور عنصر فلزي صلب. تتكون الدورة الرابعة من 15 عنصرا.");
+ std::unique_ptr<SalLayout> pLayout = pOutputDevice->ImplLayout(
+ aText, 0, aText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ SalLayoutGlyphs aGlyphs = pLayout->GetGlyphs();
+ CPPUNIT_ASSERT(aGlyphs.IsValid());
+ CPPUNIT_ASSERT(aGlyphs.Impl(0) != nullptr);
+
+ // Now lay it out using the cached glyph list.
+ vcl::text::ImplLayoutArgs aLayoutArgs(aText, 0, aText.getLength(), SalLayoutFlags::NONE,
+ pOutputDevice->GetFont().GetLanguageTag(), nullptr);
+ pLayout = pOutputDevice->GetGraphics()->GetTextLayout(0);
+ CPPUNIT_ASSERT(pLayout->LayoutText(aLayoutArgs, aGlyphs.Impl(0)));
+
+ // Without the accompanying fix in place, this test would have failed with 'assertion failed'.
+ // The kashida justification flag was lost when going via the glyph cache.
+ CPPUNIT_ASSERT(aLayoutArgs.mnFlags & SalLayoutFlags::KashidaJustification);
+#endif
+}
+
+void VclComplexTextTest::testTdf95650()
+{
+ static constexpr OUStringLiteral aTxt =
+ u"\u0131\u0302\u0504\u4E44\u3031\u3030\u3531\u2D30"
+ "\u3037\u0706\u0908\u0B0A\u0D0C\u0F0E\u072E\u100A"
+ "\u0D11\u1312\u0105\u020A\u0512\u1403\u030C\u1528"
+ "\u2931\u632E\u7074\u0D20\u0E0A\u100A\uF00D\u0D20"
+ "\u030A\u0C0B\u20E0\u0A0D";
+ ScopedVclPtrInstance<WorkWindow> pWin(static_cast<vcl::Window *>(nullptr));
+ CPPUNIT_ASSERT(pWin);
+
+ OutputDevice *pOutDev = pWin->GetOutDev();
+ // Check that the following executes without failing assertion
+ pOutDev->ImplLayout(aTxt, 9, 1, Point(), 0, {}, SalLayoutFlags::BiDiRtl);
+}
+
+static void checkCompareGlyphs( const SalLayoutGlyphs& aGlyphs1, const SalLayoutGlyphs& aGlyphs2,
+ const std::string& message )
+{
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(message, aGlyphs1.IsValid(), aGlyphs2.IsValid());
+ // And check it's the same.
+ for( int level = 0; level < MAX_FALLBACK; ++level )
+ {
+ const std::string messageLevel = OString(message.c_str()
+ + OString::Concat(", level: ") + OString::number(level)).getStr();
+ if( aGlyphs1.Impl(level) == nullptr)
+ {
+ CPPUNIT_ASSERT_MESSAGE(messageLevel, aGlyphs2.Impl(level) == nullptr);
+ continue;
+ }
+ const SalLayoutGlyphsImpl* g1 = aGlyphs1.Impl(level);
+ const SalLayoutGlyphsImpl* g2 = aGlyphs2.Impl(level);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(messageLevel, g1->GetFont().get(), g2->GetFont().get());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(messageLevel, g1->size(), g2->size());
+ for( size_t i = 0; i < g1->size(); ++i )
+ {
+ const bool equal = (*g1)[i] == (*g2)[i];
+ CPPUNIT_ASSERT_MESSAGE(messageLevel, equal);
+ }
+ }
+}
+
+static void testCachedGlyphs( const OUString& aText, const OUString& aFontName )
+{
+ const std::string message = OUString("Font: " + aFontName + ", text: '" + aText + "'").toUtf8().getStr();
+ ScopedVclPtrInstance<VirtualDevice> pOutputDevice;
+ vcl::Font aFont( aFontName, Size(0, 12));
+ pOutputDevice->SetFont( aFont );
+ SalLayoutGlyphsCache::self()->clear();
+ // Get the glyphs for the text.
+ std::unique_ptr<SalLayout> pLayout1 = pOutputDevice->ImplLayout(
+ aText, 0, aText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ SalLayoutGlyphs aGlyphs1 = pLayout1->GetGlyphs();
+ // Reuse the cached glyphs to get glyphs again.
+ std::unique_ptr<SalLayout> pLayout2 = pOutputDevice->ImplLayout(
+ aText, 0, aText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly, nullptr, &aGlyphs1);
+ SalLayoutGlyphs aGlyphs2 = pLayout2->GetGlyphs();
+ checkCompareGlyphs(aGlyphs1, aGlyphs2, message + " (reuse)");
+ // Get cached glyphs from SalLayoutGlyphsCache.
+ const SalLayoutGlyphs* aGlyphs3 = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
+ pOutputDevice, aText, 0, aText.getLength(), 0);
+ CPPUNIT_ASSERT_MESSAGE(message, aGlyphs3 != nullptr);
+ checkCompareGlyphs(aGlyphs1, *aGlyphs3, message + " (cache)");
+}
+
+// Check that caching using SalLayoutGlyphs gives same results as without caching.
+// This should preferably use fonts that come with LO.
+void VclComplexTextTest::testCaching()
+{
+ // Just something basic, no font fallback.
+ testCachedGlyphs( "test", "Dejavu Sans" );
+ // This font does not have latin characters, will need fallback.
+ testCachedGlyphs( "test", "KacstBook" );
+}
+
+static void testCachedGlyphsSubstring( const OUString& aText, const OUString& aFontName, bool rtl )
+{
+ const std::string prefix = OUString("Font: " + aFontName + ", text: '" + aText + "'").toUtf8().getStr();
+ ScopedVclPtrInstance<VirtualDevice> pOutputDevice;
+ // BiDiStrong is needed, otherwise SalLayoutGlyphsImpl::cloneCharRange() will not do anything.
+ vcl::text::ComplexTextLayoutFlags layoutFlags = vcl::text::ComplexTextLayoutFlags::BiDiStrong;
+ if(rtl)
+ layoutFlags |= vcl::text::ComplexTextLayoutFlags::BiDiRtl;
+ pOutputDevice->SetLayoutMode( layoutFlags );
+ vcl::Font aFont( aFontName, Size(0, 12));
+ pOutputDevice->SetFont( aFont );
+ SalLayoutGlyphsCache::self()->clear();
+ // Get the glyphs for the entire text once, to ensure the cache can built subsets from it.
+ pOutputDevice->ImplLayout( aText, 0, aText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ // Now check for all subsets. Some of them possibly do not make sense in practice, but the code
+ // should cope with them.
+ for( sal_Int32 len = 1; len <= aText.getLength(); ++len )
+ for( sal_Int32 pos = 0; pos < aText.getLength() - len; ++pos )
+ {
+ std::string message = prefix + " (" + std::to_string(pos) + "/" + std::to_string(len) + ")";
+ std::unique_ptr<SalLayout> pLayout1 = pOutputDevice->ImplLayout(
+ aText, pos, len, Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ SalLayoutGlyphs aGlyphs1 = pLayout1->GetGlyphs();
+ const SalLayoutGlyphs* aGlyphs2 = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
+ pOutputDevice, aText, pos, len, 0);
+ CPPUNIT_ASSERT_MESSAGE(message, aGlyphs2 != nullptr);
+ checkCompareGlyphs(aGlyphs1, *aGlyphs2, message);
+ }
+
+}
+
+// Check that SalLayoutGlyphsCache works properly when it builds a subset
+// of glyphs using SalLayoutGlyphsImpl::cloneCharRange().
+// This should preferably use fonts that come with LO.
+void VclComplexTextTest::testCachingSubstring()
+{
+ // Just something basic.
+ testCachedGlyphsSubstring( "test", "Dejavu Sans", false );
+ // And complex arabic text, taken from tdf104649.docx .
+ OUString text(u"فصل (پاره 2): درخواست حاجت از ديگران و برآوردن حاجت ديگران 90");
+ testCachedGlyphsSubstring( text, "Dejavu Sans", true );
+ // The text is RTL, but Writer will sometimes try to lay it out as LTR, for whatever reason
+ // (tdf#149264)./ So make sure that gets handled properly too (SalLayoutGlyphsCache should
+ // not use glyph subsets in that case).
+ testCachedGlyphsSubstring( text, "Dejavu Sans", false );
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclComplexTextTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/data/123_Numbers.gif b/vcl/qa/cppunit/data/123_Numbers.gif
new file mode 100644
index 000000000..2e47e28cb
--- /dev/null
+++ b/vcl/qa/cppunit/data/123_Numbers.gif
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_8bit_RLE.bmp b/vcl/qa/cppunit/data/BMP_8bit_RLE.bmp
new file mode 100644
index 000000000..de20e4f2b
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_8bit_RLE.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_A8R8G8B8.bmp b/vcl/qa/cppunit/data/BMP_A8R8G8B8.bmp
new file mode 100644
index 000000000..9e789b798
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_A8R8G8B8.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_Paint_1bit.bmp b/vcl/qa/cppunit/data/BMP_Paint_1bit.bmp
new file mode 100644
index 000000000..1112bd67e
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_Paint_1bit.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_Paint_24bit.bmp b/vcl/qa/cppunit/data/BMP_Paint_24bit.bmp
new file mode 100644
index 000000000..41a2eb245
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_Paint_24bit.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_Paint_4bit.bmp b/vcl/qa/cppunit/data/BMP_Paint_4bit.bmp
new file mode 100644
index 000000000..69c91a635
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_Paint_4bit.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_Paint_8bit.bmp b/vcl/qa/cppunit/data/BMP_Paint_8bit.bmp
new file mode 100644
index 000000000..eb48327ef
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_Paint_8bit.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_R5G6B5.bmp b/vcl/qa/cppunit/data/BMP_R5G6B5.bmp
new file mode 100644
index 000000000..ac5531c14
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_R5G6B5.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_R8G8B8.bmp b/vcl/qa/cppunit/data/BMP_R8G8B8.bmp
new file mode 100644
index 000000000..5197e42a7
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_R8G8B8.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_RLE.bmp b/vcl/qa/cppunit/data/BMP_RLE.bmp
new file mode 100644
index 000000000..ceb843988
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_RLE.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_RLE_V2.bmp b/vcl/qa/cppunit/data/BMP_RLE_V2.bmp
new file mode 100644
index 000000000..a50076140
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_RLE_V2.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/BMP_RLE_V3.bmp b/vcl/qa/cppunit/data/BMP_RLE_V3.bmp
new file mode 100644
index 000000000..870b8d563
--- /dev/null
+++ b/vcl/qa/cppunit/data/BMP_RLE_V3.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/DocumentWithNull.pdf b/vcl/qa/cppunit/data/DocumentWithNull.pdf
new file mode 100644
index 000000000..f6d926957
--- /dev/null
+++ b/vcl/qa/cppunit/data/DocumentWithNull.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/data/Exif1.jpg b/vcl/qa/cppunit/data/Exif1.jpg
new file mode 100644
index 000000000..a81425e75
--- /dev/null
+++ b/vcl/qa/cppunit/data/Exif1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/data/Exif1_090CW.jpg b/vcl/qa/cppunit/data/Exif1_090CW.jpg
new file mode 100644
index 000000000..bb8a81a16
--- /dev/null
+++ b/vcl/qa/cppunit/data/Exif1_090CW.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/data/Exif1_180.jpg b/vcl/qa/cppunit/data/Exif1_180.jpg
new file mode 100644
index 000000000..b18b70f13
--- /dev/null
+++ b/vcl/qa/cppunit/data/Exif1_180.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/data/Exif1_270CW.jpg b/vcl/qa/cppunit/data/Exif1_270CW.jpg
new file mode 100644
index 000000000..f10764114
--- /dev/null
+++ b/vcl/qa/cppunit/data/Exif1_270CW.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/data/Pangram.pdf b/vcl/qa/cppunit/data/Pangram.pdf
new file mode 100644
index 000000000..0714fda4e
--- /dev/null
+++ b/vcl/qa/cppunit/data/Pangram.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/data/PangramAcrobatAnnotations.pdf b/vcl/qa/cppunit/data/PangramAcrobatAnnotations.pdf
new file mode 100644
index 000000000..f97003a7f
--- /dev/null
+++ b/vcl/qa/cppunit/data/PangramAcrobatAnnotations.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/data/PangramWithAnnotations.pdf b/vcl/qa/cppunit/data/PangramWithAnnotations.pdf
new file mode 100644
index 000000000..f69ddd987
--- /dev/null
+++ b/vcl/qa/cppunit/data/PangramWithAnnotations.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/data/PangramWithMultipleTypeOfAnnotations.pdf b/vcl/qa/cppunit/data/PangramWithMultipleTypeOfAnnotations.pdf
new file mode 100644
index 000000000..68037d0a2
--- /dev/null
+++ b/vcl/qa/cppunit/data/PangramWithMultipleTypeOfAnnotations.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/data/SimpleExample.svg b/vcl/qa/cppunit/data/SimpleExample.svg
new file mode 100644
index 000000000..6890b5456
--- /dev/null
+++ b/vcl/qa/cppunit/data/SimpleExample.svg
@@ -0,0 +1,4 @@
+<svg width="50" height="50" version="1.1" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
+ <rect x="0" y="0" width="50" height="50" fill="#aaaaaa"/>
+ <rect x="5" y="5" width="40" height="40" fill="#ff44aa"/>
+</svg>
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.bmp b/vcl/qa/cppunit/data/TypeDetectionExample.bmp
new file mode 100644
index 000000000..5197e42a7
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.emf b/vcl/qa/cppunit/data/TypeDetectionExample.emf
new file mode 100644
index 000000000..571a25c81
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.emf
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.emz b/vcl/qa/cppunit/data/TypeDetectionExample.emz
new file mode 100644
index 000000000..dd3b3b2f1
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.emz
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.eps b/vcl/qa/cppunit/data/TypeDetectionExample.eps
new file mode 100644
index 000000000..7f0db47bc
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.eps
@@ -0,0 +1,82 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: cairo 1.16.0 (https://cairographics.org)
+%%CreationDate: Sat May 2 14:29:27 2020
+%%Pages: 1
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%BoundingBox: 0 1 7 8
+%%EndComments
+%%BeginProlog
+50 dict begin
+/q { gsave } bind def
+/Q { grestore } bind def
+/cm { 6 array astore concat } bind def
+/w { setlinewidth } bind def
+/J { setlinecap } bind def
+/j { setlinejoin } bind def
+/M { setmiterlimit } bind def
+/d { setdash } bind def
+/m { moveto } bind def
+/l { lineto } bind def
+/c { curveto } bind def
+/h { closepath } bind def
+/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto
+ 0 exch rlineto 0 rlineto closepath } bind def
+/S { stroke } bind def
+/f { fill } bind def
+/f* { eofill } bind def
+/n { newpath } bind def
+/W { clip } bind def
+/W* { eoclip } bind def
+/BT { } bind def
+/ET { } bind def
+/BDC { mark 3 1 roll /BDC pdfmark } bind def
+/EMC { mark /EMC pdfmark } bind def
+/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def
+/Tj { show currentpoint cairo_store_point } bind def
+/TJ {
+ {
+ dup
+ type /stringtype eq
+ { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse
+ } forall
+ currentpoint cairo_store_point
+} bind def
+/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore
+ cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def
+/Tf { pop /cairo_font exch def /cairo_font_matrix where
+ { pop cairo_selectfont } if } bind def
+/Td { matrix translate cairo_font_matrix matrix concatmatrix dup
+ /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point
+ /cairo_font where { pop cairo_selectfont } if } bind def
+/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def
+ cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def
+/g { setgray } bind def
+/rg { setrgbcolor } bind def
+/d1 { setcachedevice } bind def
+/cairo_data_source {
+ CairoDataIndex CairoData length lt
+ { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def }
+ { () } ifelse
+} def
+/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def
+/cairo_image { image cairo_flush_ascii85_file } def
+/cairo_imagemask { imagemask cairo_flush_ascii85_file } def
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+%%Page: 1 1
+%%BeginPageSetup
+%%PageBoundingBox: 0 1 7 8
+%%EndPageSetup
+q 0 1 7 7 rectclip
+1 0 0 -1 0 8 cm q
+0.956863 0.831373 0.266667 rg
+3.75 0.75 m 5.41 0.75 6.75 2.09 6.75 3.75 c 6.75 5.41 5.41 6.75 3.75 6.75
+ c 2.09 6.75 0.75 5.41 0.75 3.75 c 0.75 2.09 2.09 0.75 3.75 0.75 c h
+3.75 0.75 m f
+Q Q
+showpage
+%%Trailer
+end
+%%EOF
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.gif b/vcl/qa/cppunit/data/TypeDetectionExample.gif
new file mode 100644
index 000000000..b33eb4f90
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.gif
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.jpg b/vcl/qa/cppunit/data/TypeDetectionExample.jpg
new file mode 100644
index 000000000..b8436eaa1
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.met b/vcl/qa/cppunit/data/TypeDetectionExample.met
new file mode 100644
index 000000000..7635e841f
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.met
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.pcx b/vcl/qa/cppunit/data/TypeDetectionExample.pcx
new file mode 100644
index 000000000..639323455
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.pcx
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.pdf b/vcl/qa/cppunit/data/TypeDetectionExample.pdf
new file mode 100644
index 000000000..b68bff5e1
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.png b/vcl/qa/cppunit/data/TypeDetectionExample.png
new file mode 100644
index 000000000..f73f5fd74
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.png
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.psd b/vcl/qa/cppunit/data/TypeDetectionExample.psd
new file mode 100644
index 000000000..8282b14fd
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.psd
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.svg b/vcl/qa/cppunit/data/TypeDetectionExample.svg
new file mode 100644
index 000000000..e23e44c23
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.svg
@@ -0,0 +1,4 @@
+<svg width="10" height="10" version="1.1" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
+ <rect x="0" y="0" width="10" height="10" fill="#ffffff"/>
+ <rect x="1" y="1" width="8" height="8" fill="#72d1c8"/>
+</svg>
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.svgz b/vcl/qa/cppunit/data/TypeDetectionExample.svgz
new file mode 100644
index 000000000..17c1bcc3c
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.svgz
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.tga b/vcl/qa/cppunit/data/TypeDetectionExample.tga
new file mode 100644
index 000000000..870c88b10
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.tga
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.tif b/vcl/qa/cppunit/data/TypeDetectionExample.tif
new file mode 100644
index 000000000..dc74dc958
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.tif
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.webp b/vcl/qa/cppunit/data/TypeDetectionExample.webp
new file mode 100644
index 000000000..e85ae1216
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.webp
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.wmf b/vcl/qa/cppunit/data/TypeDetectionExample.wmf
new file mode 100644
index 000000000..7ed706928
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.wmz b/vcl/qa/cppunit/data/TypeDetectionExample.wmz
new file mode 100644
index 000000000..2435f20ba
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.wmz
Binary files differ
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.xbm b/vcl/qa/cppunit/data/TypeDetectionExample.xbm
new file mode 100644
index 000000000..b40d1a45e
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.xbm
@@ -0,0 +1,5 @@
+#define sample_width 10
+#define sample_height 10
+static unsigned char sample_bits[] = {
+ 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,
+ 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00 };
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.xpm b/vcl/qa/cppunit/data/TypeDetectionExample.xpm
new file mode 100644
index 000000000..7b9b94359
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.xpm
@@ -0,0 +1,15 @@
+/* XPM */
+static char * sample_xpm[] = {
+"10 10 2 1",
+" c #FFFFFF",
+". c #72D1C8",
+" ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" "};
diff --git a/vcl/qa/cppunit/data/XPM_1.xpm b/vcl/qa/cppunit/data/XPM_1.xpm
new file mode 100644
index 000000000..7b9b94359
--- /dev/null
+++ b/vcl/qa/cppunit/data/XPM_1.xpm
@@ -0,0 +1,15 @@
+/* XPM */
+static char * sample_xpm[] = {
+"10 10 2 1",
+" c #FFFFFF",
+". c #72D1C8",
+" ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" ........ ",
+" "};
diff --git a/vcl/qa/cppunit/data/XPM_4.xpm b/vcl/qa/cppunit/data/XPM_4.xpm
new file mode 100644
index 000000000..f958aa9a1
--- /dev/null
+++ b/vcl/qa/cppunit/data/XPM_4.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * XPM_4_xpm[] = {
+"4 4 16 1",
+" c #000000",
+". c #800000",
+"+ c #008000",
+"@ c #808000",
+"# c #000080",
+"$ c #800080",
+"% c #008080",
+"& c #808080",
+"* c #C0C0C0",
+"= c #FF0000",
+"- c #00FF00",
+"; c #FFFF00",
+"> c #0000FF",
+", c #FF00FF",
+"' c #00FFFF",
+") c #FFFFFF",
+">>==",
+">>==",
+";;--",
+";;--"};
diff --git a/vcl/qa/cppunit/data/XPM_8.xpm b/vcl/qa/cppunit/data/XPM_8.xpm
new file mode 100644
index 000000000..82c354dfd
--- /dev/null
+++ b/vcl/qa/cppunit/data/XPM_8.xpm
@@ -0,0 +1,263 @@
+/* XPM */
+static char * XPM_4_xpm[] = {
+"4 4 256 2",
+" c #000000",
+". c #800000",
+"+ c #008000",
+"@ c #808000",
+"# c #000080",
+"$ c #800080",
+"% c #008080",
+"& c #C0C0C0",
+"* c #C0DCC0",
+"= c #A6CAF0",
+"- c #402000",
+"; c #602000",
+"> c #802000",
+", c #A02000",
+"' c #C02000",
+") c #E02000",
+"! c #004000",
+"~ c #204000",
+"{ c #404000",
+"] c #604000",
+"^ c #804000",
+"/ c #A04000",
+"( c #C04000",
+"_ c #E04000",
+": c #006000",
+"< c #206000",
+"[ c #406000",
+"} c #606000",
+"| c #806000",
+"1 c #A06000",
+"2 c #C06000",
+"3 c #E06000",
+"4 c #008000",
+"5 c #208000",
+"6 c #408000",
+"7 c #608000",
+"8 c #808000",
+"9 c #A08000",
+"0 c #C08000",
+"a c #E08000",
+"b c #00A000",
+"c c #20A000",
+"d c #40A000",
+"e c #60A000",
+"f c #80A000",
+"g c #A0A000",
+"h c #C0A000",
+"i c #E0A000",
+"j c #00C000",
+"k c #20C000",
+"l c #40C000",
+"m c #60C000",
+"n c #80C000",
+"o c #A0C000",
+"p c #C0C000",
+"q c #E0C000",
+"r c #00E000",
+"s c #20E000",
+"t c #40E000",
+"u c #60E000",
+"v c #80E000",
+"w c #A0E000",
+"x c #C0E000",
+"y c #E0E000",
+"z c #000040",
+"A c #200040",
+"B c #400040",
+"C c #600040",
+"D c #800040",
+"E c #A00040",
+"F c #C00040",
+"G c #E00040",
+"H c #002040",
+"I c #202040",
+"J c #402040",
+"K c #602040",
+"L c #802040",
+"M c #A02040",
+"N c #C02040",
+"O c #E02040",
+"P c #004040",
+"Q c #204040",
+"R c #404040",
+"S c #604040",
+"T c #804040",
+"U c #A04040",
+"V c #C04040",
+"W c #E04040",
+"X c #006040",
+"Y c #206040",
+"Z c #406040",
+"` c #606040",
+" . c #806040",
+".. c #A06040",
+"+. c #C06040",
+"@. c #E06040",
+"#. c #008040",
+"$. c #208040",
+"%. c #408040",
+"&. c #608040",
+"*. c #808040",
+"=. c #A08040",
+"-. c #C08040",
+";. c #E08040",
+">. c #00A040",
+",. c #20A040",
+"'. c #40A040",
+"). c #60A040",
+"!. c #80A040",
+"~. c #A0A040",
+"{. c #C0A040",
+"]. c #E0A040",
+"^. c #00C040",
+"/. c #20C040",
+"(. c #40C040",
+"_. c #60C040",
+":. c #80C040",
+"<. c #A0C040",
+"[. c #C0C040",
+"}. c #E0C040",
+"|. c #00E040",
+"1. c #20E040",
+"2. c #40E040",
+"3. c #60E040",
+"4. c #80E040",
+"5. c #A0E040",
+"6. c #C0E040",
+"7. c #E0E040",
+"8. c #000080",
+"9. c #200080",
+"0. c #400080",
+"a. c #600080",
+"b. c #800080",
+"c. c #A00080",
+"d. c #C00080",
+"e. c #E00080",
+"f. c #002080",
+"g. c #202080",
+"h. c #402080",
+"i. c #602080",
+"j. c #802080",
+"k. c #A02080",
+"l. c #C02080",
+"m. c #E02080",
+"n. c #004080",
+"o. c #204080",
+"p. c #404080",
+"q. c #604080",
+"r. c #804080",
+"s. c #A04080",
+"t. c #C04080",
+"u. c #E04080",
+"v. c #006080",
+"w. c #206080",
+"x. c #406080",
+"y. c #606080",
+"z. c #806080",
+"A. c #A06080",
+"B. c #C06080",
+"C. c #E06080",
+"D. c #008080",
+"E. c #208080",
+"F. c #408080",
+"G. c #608080",
+"H. c #808080",
+"I. c #A08080",
+"J. c #C08080",
+"K. c #E08080",
+"L. c #00A080",
+"M. c #20A080",
+"N. c #40A080",
+"O. c #60A080",
+"P. c #80A080",
+"Q. c #A0A080",
+"R. c #C0A080",
+"S. c #E0A080",
+"T. c #00C080",
+"U. c #20C080",
+"V. c #40C080",
+"W. c #60C080",
+"X. c #80C080",
+"Y. c #A0C080",
+"Z. c #C0C080",
+"`. c #E0C080",
+" + c #00E080",
+".+ c #20E080",
+"++ c #40E080",
+"@+ c #60E080",
+"#+ c #80E080",
+"$+ c #A0E080",
+"%+ c #C0E080",
+"&+ c #E0E080",
+"*+ c #0000C0",
+"=+ c #2000C0",
+"-+ c #4000C0",
+";+ c #6000C0",
+">+ c #8000C0",
+",+ c #A000C0",
+"'+ c #C000C0",
+")+ c #E000C0",
+"!+ c #0020C0",
+"~+ c #2020C0",
+"{+ c #4020C0",
+"]+ c #6020C0",
+"^+ c #8020C0",
+"/+ c #A020C0",
+"(+ c #C020C0",
+"_+ c #E020C0",
+":+ c #0040C0",
+"<+ c #2040C0",
+"[+ c #4040C0",
+"}+ c #6040C0",
+"|+ c #8040C0",
+"1+ c #A040C0",
+"2+ c #C040C0",
+"3+ c #E040C0",
+"4+ c #0060C0",
+"5+ c #2060C0",
+"6+ c #4060C0",
+"7+ c #6060C0",
+"8+ c #8060C0",
+"9+ c #A060C0",
+"0+ c #C060C0",
+"a+ c #E060C0",
+"b+ c #0080C0",
+"c+ c #2080C0",
+"d+ c #4080C0",
+"e+ c #6080C0",
+"f+ c #8080C0",
+"g+ c #A080C0",
+"h+ c #C080C0",
+"i+ c #E080C0",
+"j+ c #00A0C0",
+"k+ c #20A0C0",
+"l+ c #40A0C0",
+"m+ c #60A0C0",
+"n+ c #80A0C0",
+"o+ c #A0A0C0",
+"p+ c #C0A0C0",
+"q+ c #E0A0C0",
+"r+ c #00C0C0",
+"s+ c #20C0C0",
+"t+ c #40C0C0",
+"u+ c #60C0C0",
+"v+ c #80C0C0",
+"w+ c #A0C0C0",
+"x+ c #FFFBF0",
+"y+ c #A0A0A4",
+"z+ c #808080",
+"A+ c #FF0000",
+"B+ c #00FF00",
+"C+ c #FFFF00",
+"D+ c #0000FF",
+"E+ c #FF00FF",
+"F+ c #00FFFF",
+"G+ c #FFFFFF",
+"D+D+A+A+",
+"D+D+A+A+",
+"C+C+B+B+",
+"C+C+B+B+"};
diff --git a/vcl/qa/cppunit/data/basic.pdf b/vcl/qa/cppunit/data/basic.pdf
new file mode 100644
index 000000000..0d68be4bf
--- /dev/null
+++ b/vcl/qa/cppunit/data/basic.pdf
@@ -0,0 +1,71 @@
+%PDF-1.2
+%µ¶
+
+1 0 obj
+<</Type/Page/Parent 5 0 R/Resources 3 0 R/Contents 2 0 R>>
+endobj
+
+2 0 obj
+<</Length 57>>
+stream
+BT
+/F1 24 Tf
+1 0 0 1 260 254 Tm
+0.5 g
+(Hello World)Tj
+ET
+
+endstream
+endobj
+
+3 0 obj
+<</ProcSet[/PDF/Text]/Font<</F1 4 0 R>>/Test 7 0 R>>
+endobj
+
+4 0 obj
+<</Type/Font/Subtype/Type1/Name/F1/BaseFont/Helvetica>>
+endobj
+
+5 0 obj
+<</Type/Pages/Kids[1 0 R]/Count 1/MediaBox[0 0 612 446]>>
+endobj
+
+6 0 obj
+<</Type/Catalog/Pages 5 0 R>>
+endobj
+
+7 0 obj
+<</TestArray1 8 0 R/TestArray2 9 0 R/TestDictionary 10 0 R>>
+endobj
+
+8 0 obj
+[/Inner1/Inner2[/Inner31][/Inner41/Inner42[/Inner431/Inner432]][/Inner51[/Inner521]]]
+endobj
+
+9 0 obj
+[/TestReference 7 0 R]
+endobj
+
+10 0 obj
+<</TestReference 7 0 R/TestNumber 123/TestName/SomeName/TestDictionary<</Key/Value>>/TestArray[1 2 3]>>
+endobj
+
+xref
+0 11
+0000000000 65536 f
+0000000016 00000 n
+0000000091 00000 n
+0000000197 00000 n
+0000000266 00000 n
+0000000338 00000 n
+0000000412 00000 n
+0000000458 00000 n
+0000000535 00000 n
+0000000637 00000 n
+0000000676 00000 n
+
+trailer
+<</Size 11/Root 6 0 R>>
+startxref
+797
+%%EOF
diff --git a/vcl/qa/cppunit/data/basicSource.pdf b/vcl/qa/cppunit/data/basicSource.pdf
new file mode 100644
index 000000000..2cde317fc
--- /dev/null
+++ b/vcl/qa/cppunit/data/basicSource.pdf
@@ -0,0 +1,60 @@
+%PDF-1.2
+
+%Fix with "mutool clean vcl/qa/cppunit/data/basicSource.pdf vcl/qa/cppunit/data/basic.pdf"
+
+1 0 obj
+<< /Type /Page /Parent 5 0 R /Resources 3 0 R /Contents 2 0 R>>
+endobj
+
+2 0 obj
+<</Length 57>>
+stream
+BT
+/F1 24 Tf
+1 0 0 1 260 254 Tm
+0.5 g
+(Hello World)Tj
+ET
+endstream
+endobj
+
+3 0 obj
+<<
+/ProcSet [/PDF /Text ]
+/Font << /F1 4 0 R >>
+/Test 7 0 R
+>>
+endobj
+
+4 0 obj
+<< /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Helvetica >>
+endobj
+
+5 0 obj
+<< /Type /Pages /Kids [ 1 0 R ] /Count 1 /MediaBox [ 0 0 612 446 ]>>
+endobj
+
+6 0 obj
+<< /Type /Catalog /Pages 5 0 R>>
+endobj
+
+7 0 obj
+<< /TestArray1 8 0 R /TestArray2 9 0 R /TestDictionary 10 0 R >>
+endobj
+
+8 0 obj
+[ /Inner1 /Inner2 [/Inner31] [/Inner41 /Inner42 [/Inner431 /Inner432] ] [ /Inner51 [/Inner521] ] ]
+endobj
+
+9 0 obj
+[ /TestReference 7 0 R ]
+endobj
+
+10 0 obj
+<< /TestReference 7 0 R /TestNumber 123 /TestName /SomeName /TestDictionary << /Key /Value >> /TestArray [1 2 3] >>
+endobj
+
+trailer
+<</Root 6 0 R>>
+
+%%EOF
diff --git a/vcl/qa/cppunit/data/form-fields.pdf b/vcl/qa/cppunit/data/form-fields.pdf
new file mode 100644
index 000000000..a014b36c9
--- /dev/null
+++ b/vcl/qa/cppunit/data/form-fields.pdf
@@ -0,0 +1,95 @@
+%PDF-1.7
+%
+1 0 obj <<
+ /Type /Catalog
+ /Pages 5 0 R
+>>
+endobj
+
+2 0 obj <<
+ /Length 0
+>>
+stream
+endstream
+endobj
+
+3 0 obj <<
+ /Font <<
+ /TT1 4 0 R
+ >>
+>>
+endobj
+
+4 0 obj <<
+ /Type /Font
+ /Subtype /Type1
+ /Name /TT1
+ /BaseFont/Helvetica
+>>
+endobj
+
+5 0 obj <<
+ /Type /Pages
+ /Kids [6 0 R]
+ /Count 1
+ /MediaBox [ 0 0 612 446 ]
+>>
+endobj
+
+6 0 obj <<
+ /Type /Page
+ /Parent 5 0 R
+ /Resources 3 0 R
+ /Contents 2 0 R
+ /Annots [7 0 R]
+>>
+endobj
+
+7 0 obj <<
+ /Type /Annot
+ /Subtype /Widget
+ /T (T)
+ /V (V)
+ /DA (/Helv 0 Tf 0 g)
+ /Rect [ 0 0 612 446 ]
+ /FT /Tx
+ /AP <<
+ /N 8 0 R
+ >>
+>>
+endobj
+
+8 0 obj <<
+ /Type /XObject
+ /Subtype /Form
+ /Matrix [1.0 0.0 0.0 1.0 0.0 0.0]
+ /Resources 3 0 R
+ /BBox [ 0 0 612 446 ]
+ /Length 55
+>>
+stream
+ BT
+ /TT1 24 Tf
+ 1 0 0 1 260 254 Tm
+ (test)Tj
+ ET
+endstream
+endobj
+xref
+0 9
+0000000000 65535 f
+0000000015 00000 n
+0000000069 00000 n
+0000000121 00000 n
+0000000174 00000 n
+0000000259 00000 n
+0000000351 00000 n
+0000000458 00000 n
+0000000616 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 9
+>>
+startxref
+836
+%%EOF
diff --git a/vcl/qa/cppunit/data/graphic-descriptor-mapmode.bmp b/vcl/qa/cppunit/data/graphic-descriptor-mapmode.bmp
new file mode 100644
index 000000000..f65c10ea2
--- /dev/null
+++ b/vcl/qa/cppunit/data/graphic-descriptor-mapmode.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/inch-size.emf b/vcl/qa/cppunit/data/inch-size.emf
new file mode 100644
index 000000000..ac5a1b805
--- /dev/null
+++ b/vcl/qa/cppunit/data/inch-size.emf
Binary files differ
diff --git a/vcl/qa/cppunit/data/roundtrip.wmf b/vcl/qa/cppunit/data/roundtrip.wmf
new file mode 100644
index 000000000..83210546c
--- /dev/null
+++ b/vcl/qa/cppunit/data/roundtrip.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/data/tdf73523.bmp b/vcl/qa/cppunit/data/tdf73523.bmp
new file mode 100644
index 000000000..f4364ea3e
--- /dev/null
+++ b/vcl/qa/cppunit/data/tdf73523.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/data/testBasicMorphology.png b/vcl/qa/cppunit/data/testBasicMorphology.png
new file mode 100644
index 000000000..5db565779
--- /dev/null
+++ b/vcl/qa/cppunit/data/testBasicMorphology.png
Binary files differ
diff --git a/vcl/qa/cppunit/data/testBasicMorphologyDilated1.png b/vcl/qa/cppunit/data/testBasicMorphologyDilated1.png
new file mode 100644
index 000000000..ba335bab3
--- /dev/null
+++ b/vcl/qa/cppunit/data/testBasicMorphologyDilated1.png
Binary files differ
diff --git a/vcl/qa/cppunit/data/testBasicMorphologyDilated1Eroded1.png b/vcl/qa/cppunit/data/testBasicMorphologyDilated1Eroded1.png
new file mode 100644
index 000000000..3b10a949a
--- /dev/null
+++ b/vcl/qa/cppunit/data/testBasicMorphologyDilated1Eroded1.png
Binary files differ
diff --git a/vcl/qa/cppunit/data/testBasicMorphologyDilated2.png b/vcl/qa/cppunit/data/testBasicMorphologyDilated2.png
new file mode 100644
index 000000000..30d90757e
--- /dev/null
+++ b/vcl/qa/cppunit/data/testBasicMorphologyDilated2.png
Binary files differ
diff --git a/vcl/qa/cppunit/data/testBasicMorphologyDilated2Eroded1.png b/vcl/qa/cppunit/data/testBasicMorphologyDilated2Eroded1.png
new file mode 100644
index 000000000..a506577da
--- /dev/null
+++ b/vcl/qa/cppunit/data/testBasicMorphologyDilated2Eroded1.png
Binary files differ
diff --git a/vcl/qa/cppunit/data/testColorChange-red-linear-gradient.png b/vcl/qa/cppunit/data/testColorChange-red-linear-gradient.png
new file mode 100644
index 000000000..6f2a9d0ab
--- /dev/null
+++ b/vcl/qa/cppunit/data/testColorChange-red-linear-gradient.png
Binary files differ
diff --git a/vcl/qa/cppunit/data/to-wmf.emf b/vcl/qa/cppunit/data/to-wmf.emf
new file mode 100644
index 000000000..e1a7b9f9e
--- /dev/null
+++ b/vcl/qa/cppunit/data/to-wmf.emf
Binary files differ
diff --git a/vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf b/vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf
new file mode 100644
index 000000000..1e7f75b19
--- /dev/null
+++ b/vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/dndtest.cxx b/vcl/qa/cppunit/dndtest.cxx
new file mode 100644
index 000000000..9120c19c0
--- /dev/null
+++ b/vcl/qa/cppunit/dndtest.cxx
@@ -0,0 +1,311 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragSourceListener.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTargetListener.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragGestureListener.hpp>
+
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::datatransfer::clipboard;
+using namespace ::com::sun::star::datatransfer::dnd;
+
+class MyWin : public WorkWindow
+{
+public:
+ MyWin( vcl::Window* pParent, WinBits nWinStyle );
+
+ void MouseMove( const MouseEvent& rMEvt );
+ void MouseButtonDown( const MouseEvent& rMEvt );
+ void MouseButtonUp( const MouseEvent& rMEvt );
+ void KeyInput( const KeyEvent& rKEvt );
+ void KeyUp( const KeyEvent& rKEvt );
+ void Paint( const Rectangle& rRect );
+ void Resize();
+};
+
+class MyDragAndDropListener: public ::cppu::WeakImplHelper < XDropTargetListener, XDragGestureListener, XDragSourceListener >
+{
+ vcl::Window * m_pWindow;
+
+public:
+
+ explicit MyDragAndDropListener( vcl::Window * pWindow ) : m_pWindow( pWindow ) {};
+
+ virtual void SAL_CALL dragGestureRecognized( const DragGestureEvent& dge ) throw(RuntimeException);
+ virtual void SAL_CALL drop( const DropTargetDropEvent& dtde ) throw(RuntimeException);
+ virtual void SAL_CALL dragEnter( const DropTargetDragEnterEvent& dtde ) throw(RuntimeException);
+ virtual void SAL_CALL dragExit( const DropTargetEvent& dte ) throw(RuntimeException);
+ virtual void SAL_CALL dragOver( const DropTargetDragEvent& dtde ) throw(RuntimeException);
+ virtual void SAL_CALL dropActionChanged( const DropTargetDragEvent& dtde ) throw(RuntimeException);
+ virtual void SAL_CALL dragDropEnd( const DragSourceDropEvent& dsde ) throw(RuntimeException);
+ virtual void SAL_CALL dragEnter( const DragSourceDragEvent& dsdee ) throw(RuntimeException);
+ virtual void SAL_CALL dragExit( const DragSourceEvent& dse ) throw(RuntimeException);
+ virtual void SAL_CALL dragOver( const DragSourceDragEvent& dsde ) throw(RuntimeException);
+ virtual void SAL_CALL dropActionChanged( const DragSourceDragEvent& dsde ) throw(RuntimeException);
+ virtual void SAL_CALL disposing( const EventObject& eo ) throw(RuntimeException);
+};
+
+class MyInfoBox : public InfoBox
+{
+
+public:
+
+ explicit MyInfoBox( vcl::Window* pParent );
+};
+
+class MyListBox : public ListBox
+{
+
+public:
+
+ explicit MyListBox( vcl::Window* pParent );
+};
+
+class StringTransferable : public ::cppu::WeakImplHelper< XTransferable >
+{
+ const OUString m_aData;
+ Sequence< DataFlavor > m_aFlavorList;
+
+public:
+ explicit StringTransferable( const OUString& rString ) : m_aData( rString ), m_aFlavorList( 1 )
+ {
+ DataFlavor df;
+
+ df.MimeType = "text/plain;charset=utf-16";
+ df.DataType = cppu::UnoType<OUString>::get();
+
+ m_aFlavorList[0] = df;
+ };
+
+ virtual Any SAL_CALL getTransferData( const DataFlavor& aFlavor ) throw(UnsupportedFlavorException, IOException, RuntimeException);
+ virtual Sequence< DataFlavor > SAL_CALL getTransferDataFlavors( ) throw(RuntimeException);
+ virtual bool SAL_CALL isDataFlavorSupported( const DataFlavor& aFlavor ) throw(RuntimeException);
+};
+
+class VclDnDTest : public test::BootstrapFixture
+{
+public:
+ VclDnDTest() : BootstrapFixture(true, false) {}
+
+ /// Play with drag and drop
+ void testDnD();
+
+ CPPUNIT_TEST_SUITE(VclDnDTest);
+ CPPUNIT_TEST(testDnD);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclDnDTest::testDnD()
+{
+ MyWin aMainWin( NULL, WB_APP | WB_STDWORK );
+ aMainWin.SetText( OUString( "Drag And Drop - Workbench" ) );
+ aMainWin.Show();
+
+ // test the clipboard code
+ Reference< XClipboard > xClipboard = aMainWin.GetClipboard();
+ CPPUNIT_ASSERT_MESSAGE("System clipboard not available",
+ xClipboard.is());
+
+ MyInfoBox aInfoBox( &aMainWin );
+ aInfoBox.Execute();
+
+ MyListBox aListBox( &aMainWin );
+ aListBox.setPosSizePixel( 10, 10, 100, 100 );
+ aListBox.InsertEntry( OUString("TestItem"));
+ aListBox.Show();
+}
+
+MyWin::MyWin( vcl::Window* pParent, WinBits nWinStyle ) :
+ WorkWindow( pParent, nWinStyle )
+{
+ Reference< XDropTargetListener > xListener = new MyDragAndDropListener( this );
+
+ Reference< XDropTarget > xDropTarget = GetDropTarget();
+ if( xDropTarget.is() )
+ {
+ xDropTarget->addDropTargetListener( xListener );
+ xDropTarget->setActive( true );
+ }
+
+ Reference< XDragGestureRecognizer > xRecognizer = GetDragGestureRecognizer();
+ if( xRecognizer.is() )
+ xRecognizer->addDragGestureListener( Reference< XDragGestureListener > ( xListener, UNO_QUERY ) );
+}
+
+void MyWin::MouseMove( const MouseEvent& rMEvt )
+{
+ WorkWindow::MouseMove( rMEvt );
+}
+
+void MyWin::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ WorkWindow::MouseButtonDown( rMEvt );
+}
+
+void MyWin::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ WorkWindow::MouseButtonUp( rMEvt );
+}
+
+void MyWin::KeyInput( const KeyEvent& rKEvt )
+{
+ WorkWindow::KeyInput( rKEvt );
+}
+
+void MyWin::KeyUp( const KeyEvent& rKEvt )
+{
+ WorkWindow::KeyUp( rKEvt );
+}
+
+void MyWin::Paint( const Rectangle& rRect )
+{
+ WorkWindow::Paint( rRect );
+}
+
+void MyWin::Resize()
+{
+ WorkWindow::Resize();
+}
+
+void SAL_CALL MyDragAndDropListener::dragGestureRecognized( const DragGestureEvent& dge ) throw(RuntimeException)
+{
+ Reference< XDragSource > xDragSource( dge.DragSource, UNO_QUERY );
+ xDragSource->startDrag( dge, -1, 0, 0, new StringTransferable( OUString("TestString") ), this );
+}
+
+void SAL_CALL MyDragAndDropListener::drop( const DropTargetDropEvent& dtde ) throw(RuntimeException)
+{
+ dtde.Context->dropComplete( true );
+}
+
+void SAL_CALL MyDragAndDropListener::dragEnter( const DropTargetDragEnterEvent& dtdee ) throw(RuntimeException)
+{
+ dtdee.Context->acceptDrag( dtdee.DropAction );
+}
+
+void SAL_CALL MyDragAndDropListener::dragExit( const DropTargetEvent& ) throw(RuntimeException)
+{
+}
+
+void SAL_CALL MyDragAndDropListener::dragOver( const DropTargetDragEvent& dtde ) throw(RuntimeException)
+{
+ dtde.Context->acceptDrag( dtde.DropAction );
+}
+
+void SAL_CALL MyDragAndDropListener::dropActionChanged( const DropTargetDragEvent& dtde ) throw(RuntimeException)
+{
+ dtde.Context->acceptDrag( dtde.DropAction );
+}
+
+void SAL_CALL MyDragAndDropListener::dragDropEnd( const DragSourceDropEvent& ) throw(RuntimeException)
+{
+}
+
+void SAL_CALL MyDragAndDropListener::dragEnter( const DragSourceDragEvent& ) throw(RuntimeException)
+{
+}
+
+void SAL_CALL MyDragAndDropListener::dragExit( const DragSourceEvent& ) throw(RuntimeException)
+{
+}
+
+void SAL_CALL MyDragAndDropListener::dragOver( const DragSourceDragEvent& ) throw(RuntimeException)
+{
+}
+
+void SAL_CALL MyDragAndDropListener::dropActionChanged( const DragSourceDragEvent& ) throw(RuntimeException)
+{
+}
+
+void SAL_CALL MyDragAndDropListener::disposing( const EventObject& ) throw(RuntimeException)
+{
+}
+
+MyInfoBox::MyInfoBox( vcl::Window* pParent ) : InfoBox( pParent,
+ OUString("dragging over this box should result in another window id in the drag log.") )
+{
+ Reference< XDropTargetListener > xListener = new MyDragAndDropListener( this );
+
+ Reference< XDropTarget > xDropTarget = GetDropTarget();
+ if( xDropTarget.is() )
+ {
+ xDropTarget->addDropTargetListener( xListener );
+ xDropTarget->setActive( true );
+ }
+
+ Reference< XDragGestureRecognizer > xRecognizer = GetDragGestureRecognizer();
+ if( xRecognizer.is() )
+ xRecognizer->addDragGestureListener( Reference< XDragGestureListener > ( xListener, UNO_QUERY ) );
+};
+
+MyListBox::MyListBox( vcl::Window* pParent ) : ListBox( pParent )
+{
+ Reference< XDropTargetListener > xListener = new MyDragAndDropListener( this );
+
+ Reference< XDropTarget > xDropTarget = GetDropTarget();
+ if( xDropTarget.is() )
+ {
+ xDropTarget->addDropTargetListener( xListener );
+ xDropTarget->setActive( true );
+ }
+
+ Reference< XDragGestureRecognizer > xRecognizer = GetDragGestureRecognizer();
+ if( xRecognizer.is() )
+ xRecognizer->addDragGestureListener( Reference< XDragGestureListener > ( xListener, UNO_QUERY ) );
+};
+
+Any SAL_CALL StringTransferable::getTransferData( const DataFlavor& )
+ throw(UnsupportedFlavorException, IOException, RuntimeException)
+{
+ return makeAny( m_aData );
+}
+
+Sequence< DataFlavor > SAL_CALL StringTransferable::getTransferDataFlavors( )
+ throw(RuntimeException)
+{
+ return m_aFlavorList;
+}
+
+bool SAL_CALL StringTransferable::isDataFlavorSupported( const DataFlavor& )
+ throw(RuntimeException)
+{
+ return true;
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclDnDTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/drawmode.cxx b/vcl/qa/cppunit/drawmode.cxx
new file mode 100644
index 000000000..f2b59dc84
--- /dev/null
+++ b/vcl/qa/cppunit/drawmode.cxx
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <tools/color.hxx>
+
+#include <vcl/font.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/settings.hxx>
+
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <drawmode.hxx>
+
+class VclDrawModeTest : public test::BootstrapFixture
+{
+public:
+ VclDrawModeTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testDrawModeLineColor();
+ void testDrawModeFillColor();
+ void testDrawModeHatchColor();
+ void testDrawModeTextColor();
+ void testDrawModeFontColor();
+ void testDrawModeBitmapEx();
+
+ CPPUNIT_TEST_SUITE(VclDrawModeTest);
+
+ CPPUNIT_TEST(testDrawModeLineColor);
+ CPPUNIT_TEST(testDrawModeFillColor);
+ CPPUNIT_TEST(testDrawModeHatchColor);
+ CPPUNIT_TEST(testDrawModeTextColor);
+ CPPUNIT_TEST(testDrawModeFontColor);
+ CPPUNIT_TEST(testDrawModeBitmapEx);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclDrawModeTest::testDrawModeLineColor()
+{
+ const Color aColor = COL_RED;
+ const sal_uInt8 cLum = aColor.GetLuminance();
+ const StyleSettings aStyleSettings;
+
+ CPPUNIT_ASSERT_EQUAL(
+ COL_BLACK, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::BlackLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ COL_WHITE, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::WhiteLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ Color(cLum, cLum, cLum),
+ vcl::drawmode::GetLineColor(aColor, DrawModeFlags::GrayLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aStyleSettings.GetFontColor(),
+ vcl::drawmode::GetLineColor(aColor, DrawModeFlags::SettingsLine, aStyleSettings));
+
+ Color aTransparentRed = COL_RED;
+ aTransparentRed.SetAlpha(100);
+
+ CPPUNIT_ASSERT_EQUAL(
+ aTransparentRed,
+ vcl::drawmode::GetLineColor(aTransparentRed, DrawModeFlags::BlackLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aTransparentRed,
+ vcl::drawmode::GetLineColor(aTransparentRed, DrawModeFlags::WhiteLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aTransparentRed,
+ vcl::drawmode::GetLineColor(aTransparentRed, DrawModeFlags::GrayLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aTransparentRed,
+ vcl::drawmode::GetLineColor(aTransparentRed, DrawModeFlags::SettingsLine, aStyleSettings));
+
+ // noops
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::NoFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::BlackFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::WhiteFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::GrayFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::SettingsFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::BlackText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::WhiteText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::GrayText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::SettingsText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::BlackBitmap, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::WhiteBitmap, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetLineColor(aColor, DrawModeFlags::GrayBitmap, aStyleSettings));
+}
+
+void VclDrawModeTest::testDrawModeFillColor()
+{
+ const Color aColor = COL_RED;
+ const sal_uInt8 cLum = aColor.GetLuminance();
+ const StyleSettings aStyleSettings;
+
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::NoFill,
+ aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ COL_BLACK, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::BlackFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ COL_WHITE, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::WhiteFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ Color(cLum, cLum, cLum),
+ vcl::drawmode::GetFillColor(aColor, DrawModeFlags::GrayFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aStyleSettings.GetWindowColor(),
+ vcl::drawmode::GetFillColor(aColor, DrawModeFlags::SettingsFill, aStyleSettings));
+
+ Color aTransparentRed = COL_RED;
+ aTransparentRed.SetAlpha(100);
+
+ CPPUNIT_ASSERT_EQUAL(
+ aTransparentRed,
+ vcl::drawmode::GetFillColor(aTransparentRed, DrawModeFlags::BlackLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aTransparentRed,
+ vcl::drawmode::GetFillColor(aTransparentRed, DrawModeFlags::WhiteLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aTransparentRed,
+ vcl::drawmode::GetFillColor(aTransparentRed, DrawModeFlags::GrayLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aTransparentRed,
+ vcl::drawmode::GetFillColor(aTransparentRed, DrawModeFlags::SettingsLine, aStyleSettings));
+
+ // noops
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::BlackLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::WhiteLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::GrayLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::SettingsLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::BlackText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::WhiteText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::GrayText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::SettingsText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::BlackBitmap, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::WhiteBitmap, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetFillColor(aColor, DrawModeFlags::GrayBitmap, aStyleSettings));
+}
+
+void VclDrawModeTest::testDrawModeHatchColor()
+{
+ const Color aColor = COL_RED;
+ const sal_uInt8 cLum = aColor.GetLuminance();
+ const StyleSettings aStyleSettings;
+
+ CPPUNIT_ASSERT_EQUAL(
+ COL_BLACK, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::BlackLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ COL_WHITE, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::WhiteLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ Color(cLum, cLum, cLum),
+ vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::GrayLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aStyleSettings.GetFontColor(),
+ vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::SettingsLine, aStyleSettings));
+
+ // noops
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::NoFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::BlackFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::WhiteFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::GrayFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::SettingsFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::BlackText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::WhiteText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::GrayText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::SettingsText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::BlackBitmap, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::WhiteBitmap, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetHatchColor(aColor, DrawModeFlags::GrayBitmap, aStyleSettings));
+}
+
+void VclDrawModeTest::testDrawModeTextColor()
+{
+ const Color aColor = COL_RED;
+ const sal_uInt8 cLum = aColor.GetLuminance();
+ const StyleSettings aStyleSettings;
+
+ CPPUNIT_ASSERT_EQUAL(
+ COL_BLACK, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::BlackText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ COL_WHITE, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::WhiteText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ Color(cLum, cLum, cLum),
+ vcl::drawmode::GetTextColor(aColor, DrawModeFlags::GrayText, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aStyleSettings.GetFontColor(),
+ vcl::drawmode::GetTextColor(aColor, DrawModeFlags::SettingsText, aStyleSettings));
+
+ // noops
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::BlackLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::WhiteLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::GrayLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::SettingsLine, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::NoFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::BlackFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::WhiteFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::GrayFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::SettingsFill, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::BlackBitmap, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::WhiteBitmap, aStyleSettings));
+ CPPUNIT_ASSERT_EQUAL(
+ aColor, vcl::drawmode::GetTextColor(aColor, DrawModeFlags::GrayBitmap, aStyleSettings));
+}
+
+void VclDrawModeTest::testDrawModeFontColor()
+{
+ const StyleSettings aStyleSettings;
+
+ vcl::Font aFont;
+ aFont.SetFillColor(COL_RED);
+
+ // black text and fill
+ aFont.SetTransparent(false);
+ vcl::Font aTestFont = vcl::drawmode::GetFont(
+ aFont, DrawModeFlags::BlackText | DrawModeFlags::BlackFill, aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, aTestFont.GetColor());
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, aTestFont.GetFillColor());
+
+ aFont.SetTransparent(true);
+ aTestFont = vcl::drawmode::GetFont(aFont, DrawModeFlags::BlackText | DrawModeFlags::BlackFill,
+ aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, aTestFont.GetColor());
+ CPPUNIT_ASSERT_EQUAL(COL_RED, aTestFont.GetFillColor());
+
+ // white text and fill
+ aFont.SetTransparent(false);
+ aTestFont = vcl::drawmode::GetFont(aFont, DrawModeFlags::WhiteText | DrawModeFlags::WhiteFill,
+ aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aTestFont.GetColor());
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aTestFont.GetFillColor());
+
+ aFont.SetTransparent(true);
+ aTestFont = vcl::drawmode::GetFont(aFont, DrawModeFlags::WhiteText | DrawModeFlags::WhiteFill,
+ aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aTestFont.GetColor());
+ CPPUNIT_ASSERT_EQUAL(COL_RED, aTestFont.GetFillColor());
+
+ // gray text and fill
+ const sal_uInt8 cTextLum = aFont.GetColor().GetLuminance();
+ const Color aTextGray(cTextLum, cTextLum, cTextLum);
+ const sal_uInt8 cFillLum = aFont.GetFillColor().GetLuminance();
+ const Color aFillGray(cFillLum, cFillLum, cFillLum);
+
+ aFont.SetTransparent(false);
+ aTestFont = vcl::drawmode::GetFont(aFont, DrawModeFlags::GrayText | DrawModeFlags::GrayFill,
+ aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(aTextGray, aTestFont.GetColor());
+ CPPUNIT_ASSERT_EQUAL(aFillGray, aTestFont.GetFillColor());
+
+ aFont.SetTransparent(true);
+ aTestFont = vcl::drawmode::GetFont(aFont, DrawModeFlags::GrayText | DrawModeFlags::GrayFill,
+ aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(aTextGray, aTestFont.GetColor());
+ CPPUNIT_ASSERT_EQUAL(COL_RED, aTestFont.GetFillColor());
+
+ // no text fill
+ aFont.SetTransparent(false);
+ aTestFont = vcl::drawmode::GetFont(aFont, DrawModeFlags::NoFill, aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, aTestFont.GetFillColor());
+
+ aFont.SetTransparent(true);
+ aTestFont = vcl::drawmode::GetFont(aFont, DrawModeFlags::NoFill, aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(COL_RED, aTestFont.GetFillColor());
+
+ // white text and fill
+ aFont.SetTransparent(false);
+ aTestFont = vcl::drawmode::GetFont(
+ aFont, DrawModeFlags::SettingsText | DrawModeFlags::SettingsFill, aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(aStyleSettings.GetFontColor(), aTestFont.GetColor());
+ CPPUNIT_ASSERT_EQUAL(aStyleSettings.GetWindowColor(), aTestFont.GetFillColor());
+
+ aFont.SetTransparent(true);
+ aTestFont = vcl::drawmode::GetFont(
+ aFont, DrawModeFlags::SettingsText | DrawModeFlags::SettingsFill, aStyleSettings);
+ CPPUNIT_ASSERT_EQUAL(aStyleSettings.GetFontColor(), aTestFont.GetColor());
+ CPPUNIT_ASSERT_EQUAL(COL_RED, aTestFont.GetFillColor());
+}
+
+void VclDrawModeTest::testDrawModeBitmapEx()
+{
+ const StyleSettings aStyleSettings;
+
+ Bitmap aBmp(Size(1, 1), vcl::PixelFormat::N24_BPP);
+ BitmapWriteAccess(aBmp).SetPixel(0, 0, BitmapColor(COL_RED));
+
+ BitmapEx aBmpEx(aBmp);
+
+ {
+ BitmapEx aResultBitmapEx(vcl::drawmode::GetBitmapEx(aBmpEx, DrawModeFlags::GrayBitmap));
+ Bitmap aResultBitmap(aResultBitmapEx.GetBitmap());
+ Bitmap::ScopedReadAccess pReadAccess(aResultBitmap);
+
+ const BitmapColor& rColor = pReadAccess->GetColor(0, 0);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x26), sal_Int32(rColor.GetRed()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x26), sal_Int32(rColor.GetGreen()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x26), sal_Int32(rColor.GetBlue()));
+ }
+
+ // any other operation other than DrawModeFlags::GrayBitmap is a noop
+ {
+ BitmapEx aResultBitmapEx(vcl::drawmode::GetBitmapEx(aBmpEx, DrawModeFlags::NoFill));
+ Bitmap aResultBitmap(aResultBitmapEx.GetBitmap());
+ Bitmap::ScopedReadAccess pReadAccess(aResultBitmap);
+
+ const BitmapColor& rColor = pReadAccess->GetColor(0, 0);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x80), sal_Int32(rColor.GetRed()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x00), sal_Int32(rColor.GetGreen()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x00), sal_Int32(rColor.GetBlue()));
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclDrawModeTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/errorhandler.cxx b/vcl/qa/cppunit/errorhandler.cxx
new file mode 100644
index 000000000..21c672ac5
--- /dev/null
+++ b/vcl/qa/cppunit/errorhandler.cxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <vcl/errinf.hxx>
+
+class ErrorHandlerTest;
+
+namespace {
+
+class MockErrorHandler : private ErrorHandler
+{
+ friend ErrorHandlerTest;
+
+protected:
+ virtual bool CreateString(const ErrorInfo *pErrInfo, OUString &rErrString) const override
+ {
+ if (pErrInfo->GetErrorCode().IsDynamic())
+ rErrString = "Dynamic error";
+ else
+ rErrString = "Non-dynamic error";
+
+ return true;
+ }
+};
+
+}
+
+class ErrorHandlerTest : public test::BootstrapFixture
+{
+public:
+ ErrorHandlerTest() : BootstrapFixture(true, false) {}
+
+ void testGetErrorString();
+
+ CPPUNIT_TEST_SUITE(ErrorHandlerTest);
+ CPPUNIT_TEST(testGetErrorString);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void ErrorHandlerTest::testGetErrorString()
+{
+ MockErrorHandler aErrHdlr;
+ std::unique_ptr<ErrorInfo> xErrorInfo;
+ OUString aErrStr;
+
+ CPPUNIT_ASSERT_MESSAGE("GetErrorString(ERRCODE_ABORT, aErrStr) should return false",
+ !ErrorHandler::GetErrorString(ERRCODE_ABORT, aErrStr));
+ // normally protected, but MockErrorHandler is a friend of this class
+ xErrorInfo = ErrorInfo::GetErrorInfo(ERRCODE_ABORT);
+ aErrHdlr.CreateString(xErrorInfo.get(), aErrStr);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("error message should be non-dynamic", OUString("Non-dynamic error"), aErrStr);
+
+ CPPUNIT_ASSERT_MESSAGE("GetErrorString(ERRCODE_NONE, aErrStr) should return false",
+ !ErrorHandler::GetErrorString(ERRCODE_NONE, aErrStr));
+ xErrorInfo = ErrorInfo::GetErrorInfo(ERRCODE_NONE);
+ aErrHdlr.CreateString(xErrorInfo.get(), aErrStr);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("error message should be non-dynamic", OUString("Non-dynamic error"), aErrStr);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ErrorHandlerTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/filter/igif/data/logic-lazy-read.gif b/vcl/qa/cppunit/filter/igif/data/logic-lazy-read.gif
new file mode 100644
index 000000000..3d18891f7
--- /dev/null
+++ b/vcl/qa/cppunit/filter/igif/data/logic-lazy-read.gif
Binary files differ
diff --git a/vcl/qa/cppunit/filter/igif/igif.cxx b/vcl/qa/cppunit/filter/igif/igif.cxx
new file mode 100644
index 000000000..4c730247f
--- /dev/null
+++ b/vcl/qa/cppunit/filter/igif/igif.cxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <test/bootstrapfixture.hxx>
+
+#include <tools/stream.hxx>
+#include <unotest/directories.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+
+using namespace com::sun::star;
+
+namespace
+{
+constexpr OUStringLiteral DATA_DIRECTORY = u"/vcl/qa/cppunit/filter/igif/data/";
+
+/// Covers vcl/source/filter/igif/ fixes.
+class Test : public test::BootstrapFixture
+{
+};
+
+CPPUNIT_TEST_FIXTURE(Test, testLogicLazyRead)
+{
+ GraphicFilter aGraphicFilter;
+ test::Directories aDirectories;
+ OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "logic-lazy-read.gif";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ Graphic aGraphic = aGraphicFilter.ImportUnloadedGraphic(aStream);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 0
+ // - Actual : 10
+ // i.e. the preferred unit was pixels, not mm100.
+ CPPUNIT_ASSERT_EQUAL(MapUnit::Map100thMM, aGraphic.GetPrefMapMode().GetMapUnit());
+}
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/filter/ipdf/data/add-visible-signature-last-page.pdf b/vcl/qa/cppunit/filter/ipdf/data/add-visible-signature-last-page.pdf
new file mode 100644
index 000000000..c321abd09
--- /dev/null
+++ b/vcl/qa/cppunit/filter/ipdf/data/add-visible-signature-last-page.pdf
@@ -0,0 +1,111 @@
+%PDF-1.6
+%äüöß
+2 0 obj
+<</Length 3 0 R/Filter/FlateDecode>>
+stream
+xTn1 ]K/I8Mg\\PԐnf2eڨpBIB2~#QwDɶƿ#gzKkMkRؼ7妁
++Rw 2Q#XQ˲sv`7Vܸ$}dFڜTXI+8+]HN+kC"Tta@+"]9ZY Rq a!O<ҫ
+d\)WiKO.H/\$ώga-/w- !9cDc
+ΩPqe:/ tqi08{{N10\N9UҸAoݵӏZ/_b7F߾ _a_t{!J@ACjl4#}ԍH뭷Gc;2?cQ@
+endstream
+endobj
+
+3 0 obj
+426
+endobj
+
+5 0 obj
+<</Length 6 0 R/Filter/FlateDecode>>
+stream
+x;1 D{qr$ZfO#Q#+r&x #Y Z}>a;zg6
+xn :d8 aQ^D,;7#M3qĵ1 Ɛ$}5+'pΏ5y^qYW]ٶuL#>"B
+endstream
+endobj
+
+6 0 obj
+167
+endobj
+
+8 0 obj
+<<
+>>
+endobj
+
+9 0 obj
+<</Font 8 0 R
+/ProcSet[/PDF/Text]
+>>
+endobj
+
+1 0 obj
+<</Type/Page/Parent 7 0 R/Resources 9 0 R/MediaBox[0 0 612 792]/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 2 0 R>>
+endobj
+
+4 0 obj
+<</Type/Page/Parent 7 0 R/Resources 9 0 R/MediaBox[0 0 612 792]/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 5 0 R>>
+endobj
+
+10 0 obj
+<</Count 2/First 11 0 R/Last 12 0 R
+>>
+endobj
+
+11 0 obj
+<</Count 0/Title<FEFF005000610067006500200031>
+/Dest[1 0 R/XYZ 0 792 0]/Parent 10 0 R/Next 12 0 R>>
+endobj
+
+12 0 obj
+<</Count 0/Title<FEFF005000610067006500200032>
+/Dest[4 0 R/XYZ 0 792 0]/Parent 10 0 R/Prev 11 0 R>>
+endobj
+
+7 0 obj
+<</Type/Pages
+/Resources 9 0 R
+/MediaBox[ 0 0 612 792 ]
+/Kids[ 1 0 R 4 0 R ]
+/Count 2>>
+endobj
+
+13 0 obj
+<</Type/Catalog/Pages 7 0 R
+/OpenAction[1 0 R /XYZ null null 0]
+/Outlines 10 0 R
+>>
+endobj
+
+14 0 obj
+<</Author<FEFF004D0069006B006C006F0073002000560061006A006E0061>
+/Creator<FEFF0044007200610077>
+/Producer<FEFF004C0069006200720065004F0066006600690063006500440065007600200037002E0031>
+/CreationDate(D:20200624113559+02'00')>>
+endobj
+
+xref
+0 15
+0000000000 65535 f
+0000000869 00000 n
+0000000019 00000 n
+0000000516 00000 n
+0000001011 00000 n
+0000000536 00000 n
+0000000774 00000 n
+0000001443 00000 n
+0000000794 00000 n
+0000000816 00000 n
+0000001153 00000 n
+0000001209 00000 n
+0000001326 00000 n
+0000001547 00000 n
+0000001648 00000 n
+trailer
+<</Size 15/Root 13 0 R
+/Info 14 0 R
+/ID [ <F52D3902B7388C216897409EFCC78884>
+<F52D3902B7388C216897409EFCC78884> ]
+/DocChecksum /67E881EB92900640250E0931504CE95E
+>>
+startxref
+1889
+%%EOF
diff --git a/vcl/qa/cppunit/filter/ipdf/data/comment-end.pdf b/vcl/qa/cppunit/filter/ipdf/data/comment-end.pdf
new file mode 100644
index 000000000..6f1ad86f5
--- /dev/null
+++ b/vcl/qa/cppunit/filter/ipdf/data/comment-end.pdf
@@ -0,0 +1,69 @@
+%PDF-1.7
+%
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /MediaBox [0 0 200 300]
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+>>
+endobj
+4 0 obj <<
+ /Length 4
+>>
+stream
+q
+Q
+endstream
+endobj
+xref
+0 5
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000157 00000 n
+0000000226 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 5
+ /Prev 541
+>>
+startxref
+280
+%%EOF %%TEST
+4 0 obj <<
+ /Length 5 0 R
+>>
+stream
+q
+Q
+endstream
+endobj
+5 0 obj
+4
+endobj
+xref
+0 6
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000157 00000 n
+0000000466 00000 n
+0000000524 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 6
+>>
+startxref
+280
+%%EOF
diff --git a/vcl/qa/cppunit/filter/ipdf/data/dict-array-dict.pdf b/vcl/qa/cppunit/filter/ipdf/data/dict-array-dict.pdf
new file mode 100644
index 000000000..73de3117b
--- /dev/null
+++ b/vcl/qa/cppunit/filter/ipdf/data/dict-array-dict.pdf
@@ -0,0 +1,55 @@
+%PDF-1.7
+%
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /MediaBox [0 0 200 300]
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+ /Key[<</InnerKey 42>>]
+>>
+endobj
+4 0 obj <<
+ /Length 188
+>>
+stream
+q
+0 0 0 rg
+0 290 10 10 re B*
+10 150 50 30 re B*
+0 0 1 rg
+190 290 10 10 re B*
+70 232 50 30 re B*
+0 1 0 rg
+190 0 10 10 re B*
+130 150 50 30 re B*
+1 0 0 rg
+0 0 10 10 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+xref
+0 5
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000157 00000 n
+0000000251 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 5
+>>
+startxref
+491
+%%EOF
diff --git a/vcl/qa/cppunit/filter/ipdf/data/real-numbers.pdf b/vcl/qa/cppunit/filter/ipdf/data/real-numbers.pdf
new file mode 100644
index 000000000..409360c54
--- /dev/null
+++ b/vcl/qa/cppunit/filter/ipdf/data/real-numbers.pdf
@@ -0,0 +1,55 @@
+%PDF-1.7
+%
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /MediaBox [0 0 200 300]
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+>>
+endobj
+4 0 obj <<
+ /Length 188
+ /Test [.00 1.00 .00 1.00 .00 1.00]
+>>
+stream
+q
+0 0 0 rg
+0 290 10 10 re B*
+10 150 50 30 re B*
+0 0 1 rg
+190 290 10 10 re B*
+70 232 50 30 re B*
+0 1 0 rg
+190 0 10 10 re B*
+130 150 50 30 re B*
+1 0 0 rg
+0 0 10 10 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+xref
+0 5
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000157 00000 n
+0000000226 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 5
+>>
+startxref
+503
+%%EOF
diff --git a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx
new file mode 100644
index 000000000..c34bb4794
--- /dev/null
+++ b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawView.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <osl/file.hxx>
+#include <unotools/tempfile.hxx>
+#include <sfx2/sfxbasemodel.hxx>
+#include <svx/svdview.hxx>
+#include <sfx2/viewsh.hxx>
+#include <svx/signaturelinehelper.hxx>
+#include <sfx2/objsh.hxx>
+#include <vcl/filter/PDFiumLibrary.hxx>
+#include <vcl/filter/pdfdocument.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+constexpr OUStringLiteral DATA_DIRECTORY = u"/vcl/qa/cppunit/filter/ipdf/data/";
+}
+
+/// Covers vcl/source/filter/ipdf/ fixes.
+class VclFilterIpdfTest : public test::BootstrapFixture, public unotest::MacrosTest
+{
+private:
+ uno::Reference<lang::XComponent> mxComponent;
+ uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer;
+ uno::Reference<xml::crypto::XXMLSecurityContext> mxSecurityContext;
+
+public:
+ void setUp() override;
+ void tearDown() override;
+ uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
+ uno::Reference<xml::crypto::XXMLSecurityContext>& getSecurityContext()
+ {
+ return mxSecurityContext;
+ }
+};
+
+void VclFilterIpdfTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+ MacrosTest::setUpNssGpg(m_directories, "vcl_filter_ipdf");
+
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+ mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext);
+ mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
+}
+
+void VclFilterIpdfTest::tearDown()
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+
+ MacrosTest::tearDownNssGpg();
+ test::BootstrapFixture::tearDown();
+}
+
+CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testPDFAddVisibleSignatureLastPage)
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+ // Given: copy the test document to a temporary file, as it'll be modified.
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString aSourceURL
+ = m_directories.getURLFromSrc(DATA_DIRECTORY) + "add-visible-signature-last-page.pdf";
+ OUString aURL = aTempFile.GetURL();
+ osl::File::RC eRet = osl::File::copy(aSourceURL, aURL);
+ CPPUNIT_ASSERT_EQUAL(osl::File::RC::E_None, eRet);
+
+ // Open it.
+ uno::Sequence<beans::PropertyValue> aArgs = { comphelper::makePropertyValue("ReadOnly", true) };
+ getComponent() = loadFromDesktop(aURL, "com.sun.star.drawing.DrawingDocument", aArgs);
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(getComponent().get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+
+ // Add a signature line to the 2nd page.
+ uno::Reference<lang::XMultiServiceFactory> xFactory(getComponent(), uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xShape(
+ xFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), uno::UNO_QUERY);
+ xShape->setPosition(awt::Point(1000, 15000));
+ xShape->setSize(awt::Size(10000, 10000));
+ uno::Reference<drawing::XDrawPagesSupplier> xSupplier(getComponent(), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPages> xDrawPages = xSupplier->getDrawPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xDrawPages->getCount());
+
+ uno::Reference<frame::XModel> xModel(getComponent(), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawView> xController(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(1), uno::UNO_QUERY);
+ xController->setCurrentPage(xDrawPage);
+ xDrawPage->add(xShape);
+
+ // Select it and assign a certificate.
+ uno::Reference<view::XSelectionSupplier> xSelectionSupplier(pBaseModel->getCurrentController(),
+ uno::UNO_QUERY);
+ xSelectionSupplier->select(uno::Any(xShape));
+ auto xCert = GetValidCertificate(
+ getSecurityContext()->getSecurityEnvironment()->getPersonalCertificates());
+ if (!xCert)
+ {
+ return;
+ }
+ SdrView* pView = SfxViewShell::Current()->GetDrawView();
+ svx::SignatureLineHelper::setShapeCertificate(pView, xCert);
+
+ // When: do the actual signing.
+ pObjectShell->SignDocumentContentUsingCertificate(xCert);
+
+ // Then: count the # of shapes on the signature widget/annotation.
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ return;
+ SvFileStream aFile(aTempFile.GetURL(), StreamMode::READ);
+ SvMemoryStream aMemory;
+ aMemory.WriteStream(aFile);
+ // Last page.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/1);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 1
+ // - Actual : 0
+ // i.e. the signature was there, but it was on the first page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount());
+ std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnot = pPdfPage->getAnnotation(0);
+ CPPUNIT_ASSERT_EQUAL(4, pAnnot->getObjectCount());
+}
+
+CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testDictArrayDict)
+{
+ // Load a file that has markup like this:
+ // 3 0 obj <<
+ // /Key[<</InnerKey 42>>]
+ // >>
+ OUString aSourceURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "dict-array-dict.pdf";
+ SvFileStream aFile(aSourceURL, StreamMode::READ);
+ vcl::filter::PDFDocument aDocument;
+ CPPUNIT_ASSERT(aDocument.Read(aFile));
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT(!aPages.empty());
+ vcl::filter::PDFObjectElement* pPage = aPages[0];
+ auto pKey = dynamic_cast<vcl::filter::PDFArrayElement*>(pPage->Lookup("Key"));
+
+ // Without the accompanying fix in place, this test would have failed, because the value of Key
+ // was a dictionary element, not an array element.
+ CPPUNIT_ASSERT(pKey);
+}
+
+CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testRealNumbers)
+{
+ // Load a file that has markup like this:
+ // 4 0 obj <<
+ // /Test [.00 1.00 .00 1.00 .00 1.00]
+ // >>
+ OUString aSourceURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "real-numbers.pdf";
+ SvFileStream aFile(aSourceURL, StreamMode::READ);
+ vcl::filter::PDFDocument aDocument;
+
+ // Without the accompanying fix in place, this test would have failed, because the parser
+ // stopped when it saw an unexpected "." character.
+ CPPUNIT_ASSERT(aDocument.Read(aFile));
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT(!aPages.empty());
+}
+
+CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testCommentEnd)
+{
+ // Load the test document:
+ // - it has two xrefs
+ // - second xref has an updated page content object with an indirect length
+ // - last startxref refers to the first xref
+ // - first xref has a /Prev to the second xref
+ // - first xref is terminated by a \r, which is not followed by a newline
+ // this means that if reading doesn't stop at the end of the first xref, then we'll try to look
+ // up the offset of the length object, which we don't yet have
+ OUString aSourceURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "comment-end.pdf";
+ SvFileStream aFile(aSourceURL, StreamMode::READ);
+ vcl::filter::PDFDocument aDocument;
+
+ // Without the accompanying fix in place, this test would have failed, because Tokenize() didn't
+ // stop at the end of the first xref.
+ CPPUNIT_ASSERT(aDocument.Read(aFile));
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/font.cxx b/vcl/qa/cppunit/font.cxx
new file mode 100644
index 000000000..e99bf12a5
--- /dev/null
+++ b/vcl/qa/cppunit/font.cxx
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <vcl/font.hxx>
+
+class VclFontTest : public test::BootstrapFixture
+{
+public:
+ VclFontTest() : BootstrapFixture(true, false) {}
+
+ void testName();
+ void testWeight();
+ void testWidthType();
+ void testPitch();
+ void testItalic();
+ void testAlignment();
+ void testQuality();
+ void testSymbolFlagAndCharSet();
+
+ CPPUNIT_TEST_SUITE(VclFontTest);
+ CPPUNIT_TEST(testName);
+ CPPUNIT_TEST(testWeight);
+ CPPUNIT_TEST(testWidthType);
+ CPPUNIT_TEST(testPitch);
+ CPPUNIT_TEST(testItalic);
+ CPPUNIT_TEST(testAlignment);
+ CPPUNIT_TEST(testQuality);
+ CPPUNIT_TEST(testSymbolFlagAndCharSet);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclFontTest::testName()
+{
+ vcl::Font aFont;
+
+ CPPUNIT_ASSERT_MESSAGE( "Family name should be empty", aFont.GetFamilyName().isEmpty());
+ CPPUNIT_ASSERT_MESSAGE( "Style name should be empty", aFont.GetStyleName().isEmpty());
+ aFont.SetFamilyName("Test family name");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Family name should not be empty", OUString("Test family name"), aFont.GetFamilyName());
+ aFont.SetStyleName("Test style name");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Style name should not be empty", OUString("Test style name"), aFont.GetStyleName());
+}
+
+void VclFontTest::testWeight()
+{
+ vcl::Font aFont;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Weight should be WEIGHT_DONTKNOW", FontWeight::WEIGHT_DONTKNOW, aFont.GetWeight());
+
+ aFont.SetWeight(FontWeight::WEIGHT_BLACK);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Weight should be WEIGHT_BLACK", FontWeight::WEIGHT_BLACK, aFont.GetWeight());
+}
+
+void VclFontTest::testWidthType()
+{
+ vcl::Font aFont;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Font width should be WIDTH_DONTKNOW", FontWidth::WIDTH_DONTKNOW, aFont.GetWidthType());
+
+ aFont.SetWidthType(FontWidth::WIDTH_EXPANDED);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Font width should be EXPANDED", FontWidth::WIDTH_EXPANDED, aFont.GetWidthType());
+}
+
+void VclFontTest::testItalic()
+{
+ vcl::Font aFont;
+
+ // shouldn't this be set to ITALIC_DONTKNOW? currently it defaults to ITALIC_NONE
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Italic should be ITALIC_NONE", FontItalic::ITALIC_NONE, aFont.GetItalic());
+
+ aFont.SetItalic(FontItalic::ITALIC_NORMAL);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Italic should be EXPANDED", FontItalic::ITALIC_NORMAL, aFont.GetItalic());
+}
+
+
+void VclFontTest::testAlignment()
+{
+ vcl::Font aFont;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Text alignment should be ALIGN_TOP", TextAlign::ALIGN_TOP, aFont.GetAlignment());
+
+ aFont.SetAlignment(TextAlign::ALIGN_BASELINE);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Text alignment should be ALIGN_BASELINE", TextAlign::ALIGN_BASELINE, aFont.GetAlignment());
+}
+
+
+void VclFontTest::testPitch()
+{
+ vcl::Font aFont;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Pitch should be PITCH_DONTKNOW", FontPitch::PITCH_DONTKNOW, aFont.GetPitch());
+
+ aFont.SetPitch(FontPitch::PITCH_FIXED);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Pitch should be PITCH_FIXED", FontPitch::PITCH_FIXED, aFont.GetPitch());
+}
+
+void VclFontTest::testQuality()
+{
+ vcl::Font aFont;
+
+ CPPUNIT_ASSERT_EQUAL( int(0), aFont.GetQuality() );
+
+ aFont.SetQuality( 100 );
+ CPPUNIT_ASSERT_EQUAL( int(100), aFont.GetQuality() );
+
+ aFont.IncreaseQualityBy( 50 );
+ CPPUNIT_ASSERT_EQUAL( int(150), aFont.GetQuality() );
+
+ aFont.DecreaseQualityBy( 100 );
+ CPPUNIT_ASSERT_EQUAL( int(50), aFont.GetQuality() );
+}
+
+
+void VclFontTest::testSymbolFlagAndCharSet()
+{
+ // default constructor should set scalable flag to false
+ vcl::Font aFont;
+
+ CPPUNIT_ASSERT_MESSAGE( "Should not be seen as a symbol font after default constructor called", !aFont.IsSymbolFont() );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Character set should be RTL_TEXTENCODING_DONTKNOW after default constructor called",
+ RTL_TEXTENCODING_DONTKNOW, aFont.GetCharSet() );
+
+ aFont.SetSymbolFlag(true);
+
+ CPPUNIT_ASSERT_MESSAGE( "Test 1: Symbol font flag should be on", aFont.IsSymbolFont() );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Test 1: Character set should be RTL_TEXTENCODING_SYMBOL",
+ RTL_TEXTENCODING_SYMBOL, aFont.GetCharSet() );
+
+ aFont.SetSymbolFlag(false);
+
+ CPPUNIT_ASSERT_MESSAGE( "Test 2: Symbol font flag should be off", !aFont.IsSymbolFont() );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Test 2: Character set should be RTL_TEXTENCODING_DONTKNOW",
+ RTL_TEXTENCODING_DONTKNOW, aFont.GetCharSet() );
+
+ aFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
+
+ CPPUNIT_ASSERT_MESSAGE( "Test 3: Symbol font flag should be on", aFont.IsSymbolFont() );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Test 3: Character set should be RTL_TEXTENCODING_SYMBOL",
+ RTL_TEXTENCODING_SYMBOL, aFont.GetCharSet() );
+
+ aFont.SetCharSet( RTL_TEXTENCODING_UNICODE );
+
+ CPPUNIT_ASSERT_MESSAGE( "Test 4: Symbol font flag should be off", !aFont.IsSymbolFont() );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Test 4: Character set should be RTL_TEXTENCODING_UNICODE",
+ RTL_TEXTENCODING_UNICODE, aFont.GetCharSet() );
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclFontTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/fontcharmap.cxx b/vcl/qa/cppunit/fontcharmap.cxx
new file mode 100644
index 000000000..26a2fe9a0
--- /dev/null
+++ b/vcl/qa/cppunit/fontcharmap.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/fontcharmap.hxx>
+
+class VclFontCharMapTest : public test::BootstrapFixture
+{
+public:
+ VclFontCharMapTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testDefaultFontCharMap();
+
+ CPPUNIT_TEST_SUITE(VclFontCharMapTest);
+ CPPUNIT_TEST(testDefaultFontCharMap);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclFontCharMapTest::testDefaultFontCharMap()
+{
+ FontCharMapRef xfcmap(new FontCharMap()); // gets default map
+
+ CPPUNIT_ASSERT(xfcmap->IsDefaultMap());
+
+ sal_uInt32 nStartBMPPlane = xfcmap->GetFirstChar();
+ sal_uInt32 nStartSupBMPPlane = xfcmap->GetNextChar(0xD800);
+ sal_uInt32 nEndBMPPlane = xfcmap->GetLastChar();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(0x0020), nStartBMPPlane);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(0xE000), nStartSupBMPPlane);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(0xFFF0 - 1), nEndBMPPlane);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclFontCharMapTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/fontmetric.cxx b/vcl/qa/cppunit/fontmetric.cxx
new file mode 100644
index 000000000..8ee42f170
--- /dev/null
+++ b/vcl/qa/cppunit/fontmetric.cxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <vcl/metric.hxx>
+
+class VclFontMetricTest : public test::BootstrapFixture
+{
+public:
+ VclFontMetricTest() : BootstrapFixture(true, false) {}
+
+ void testFullstopCenteredFlag();
+ void testSpacings();
+ void testSlant();
+ void testBulletOffset();
+ void testEqualityOperator();
+
+ CPPUNIT_TEST_SUITE(VclFontMetricTest);
+ CPPUNIT_TEST(testFullstopCenteredFlag);
+ CPPUNIT_TEST(testSpacings);
+ CPPUNIT_TEST(testSlant);
+ CPPUNIT_TEST(testBulletOffset);
+ CPPUNIT_TEST(testEqualityOperator);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclFontMetricTest::testFullstopCenteredFlag()
+{
+ // default constructor should set scalable flag to false
+ FontMetric aFontMetric;
+
+ CPPUNIT_ASSERT_MESSAGE( "Fullstop centered flag should be false after default constructor called", !aFontMetric.IsFullstopCentered() );
+
+ aFontMetric.SetFullstopCenteredFlag(true);
+
+ CPPUNIT_ASSERT_MESSAGE( "Fullstop centered flag should be true", aFontMetric.IsFullstopCentered() );
+}
+
+void VclFontMetricTest::testSpacings()
+{
+ // default constructor should set scalable flag to false
+ FontMetric aFontMetric;
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), aFontMetric.GetAscent());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), aFontMetric.GetDescent());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), aFontMetric.GetExternalLeading());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), aFontMetric.GetInternalLeading());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), aFontMetric.GetLineHeight());
+
+
+ aFontMetric.SetAscent( 100 );
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aFontMetric.GetAscent());
+
+ aFontMetric.SetDescent( 100 );
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aFontMetric.GetDescent());
+
+ aFontMetric.SetExternalLeading( 100 );
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aFontMetric.GetExternalLeading());
+
+ aFontMetric.SetInternalLeading( 100 );
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aFontMetric.GetInternalLeading());
+
+ aFontMetric.SetLineHeight( 100 );
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aFontMetric.GetLineHeight());
+}
+
+void VclFontMetricTest::testSlant()
+{
+ // default constructor should set scalable flag to false
+ FontMetric aFontMetric;
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), aFontMetric.GetSlant());
+
+ aFontMetric.SetSlant( 45 );
+ CPPUNIT_ASSERT_EQUAL(tools::Long(45), aFontMetric.GetSlant());
+}
+
+void VclFontMetricTest::testBulletOffset()
+{
+ // default constructor should set scalable flag to false
+ FontMetric aFontMetric;
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0), aFontMetric.GetBulletOffset());
+
+ aFontMetric.SetBulletOffset( 45 );
+ CPPUNIT_ASSERT_EQUAL(tools::Long(45), aFontMetric.GetBulletOffset());
+}
+
+void VclFontMetricTest::testEqualityOperator()
+{
+ // default constructor should set scalable flag to false
+ FontMetric aLhs, aRhs;
+
+ aLhs.SetFullstopCenteredFlag(true);
+ aRhs.SetFullstopCenteredFlag(true);
+ CPPUNIT_ASSERT_MESSAGE( "Fullstop centered flag set same, aLhs == aRhs failed", aLhs.operator ==(aRhs) );
+ CPPUNIT_ASSERT_MESSAGE( "Fullstop centered flag set same, aLhs != aRhs succeeded", !aLhs.operator !=(aRhs) );
+
+ aLhs.SetExternalLeading(10);
+ aRhs.SetExternalLeading(10);
+ CPPUNIT_ASSERT_MESSAGE( "External leading set same, aLHS == aRhs failed", aLhs.operator ==(aRhs) );
+ CPPUNIT_ASSERT_MESSAGE( "External leading set same, aLHS != aRhs succeeded", !aLhs.operator !=(aRhs) );
+
+ aLhs.SetInternalLeading(10);
+ aRhs.SetInternalLeading(10);
+ CPPUNIT_ASSERT_MESSAGE( "Internal leading set same, aLHS == aRhs failed", aLhs.operator ==(aRhs) );
+ CPPUNIT_ASSERT_MESSAGE( "Internal leading set same, aLHS != aRhs succeeded", !aLhs.operator !=(aRhs) );
+
+ aLhs.SetAscent( 100 );
+ aRhs.SetAscent( 100 );
+ CPPUNIT_ASSERT_MESSAGE( "Ascent set same, aLHS == aRhs failed", aLhs.operator ==(aRhs) );
+ CPPUNIT_ASSERT_MESSAGE( "Ascent set same, aLHS != aRhs succeeded", !aLhs.operator !=(aRhs) );
+
+ aLhs.SetDescent( 100 );
+ aRhs.SetDescent( 100 );
+ CPPUNIT_ASSERT_MESSAGE( "Descent set same, aLHS == aRhs failed", aLhs.operator ==(aRhs));
+ CPPUNIT_ASSERT_MESSAGE( "Descent set same, aLHS != aRhs succeeded", !aLhs.operator !=(aRhs) );
+
+ aLhs.SetSlant( 100 );
+ aRhs.SetSlant( 100 );
+ CPPUNIT_ASSERT_MESSAGE( "Slant set same, aLHS == aRhs failed", aLhs.operator ==(aRhs));
+ CPPUNIT_ASSERT_MESSAGE( "Slant set same, aLHS != aRhs succeeded", !aLhs.operator !=(aRhs) );
+}
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclFontMetricTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/fontmocks.hxx b/vcl/qa/cppunit/fontmocks.hxx
new file mode 100644
index 000000000..7367acab6
--- /dev/null
+++ b/vcl/qa/cppunit/fontmocks.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <font/FontSelectPattern.hxx>
+#include <font/PhysicalFontFace.hxx>
+#include <font/PhysicalFontFaceCollection.hxx>
+#include <fontattributes.hxx>
+#include <fontinstance.hxx>
+
+class TestFontInstance : public LogicalFontInstance
+{
+public:
+ TestFontInstance(vcl::font::PhysicalFontFace const& rFontFace,
+ vcl::font::FontSelectPattern const& rFontSelectPattern)
+ : LogicalFontInstance(rFontFace, rFontSelectPattern)
+ {
+ }
+
+ bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const override
+ {
+ return true;
+ }
+
+protected:
+ bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const override { return true; }
+};
+
+class TestFontFace : public vcl::font::PhysicalFontFace
+{
+public:
+ TestFontFace(sal_uIntPtr nId)
+ : vcl::font::PhysicalFontFace(FontAttributes())
+ , mnFontId(nId)
+ {
+ }
+
+ TestFontFace(FontAttributes const& rFontAttributes, sal_uIntPtr nId)
+ : vcl::font::PhysicalFontFace(rFontAttributes)
+ , mnFontId(nId)
+ {
+ }
+
+ rtl::Reference<LogicalFontInstance>
+ CreateFontInstance(vcl::font::FontSelectPattern const& rFontSelectPattern) const override
+ {
+ return new TestFontInstance(*this, rFontSelectPattern);
+ }
+
+ sal_IntPtr GetFontId() const override { return mnFontId; }
+ FontCharMapRef GetFontCharMap() const override { return FontCharMap::GetDefaultMap(false); }
+ bool GetFontCapabilities(vcl::FontCapabilities&) const override { return true; }
+
+private:
+ sal_IntPtr mnFontId;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/qa/cppunit/gen/data/tdf121120.png b/vcl/qa/cppunit/gen/data/tdf121120.png
new file mode 100644
index 000000000..8e48fba38
--- /dev/null
+++ b/vcl/qa/cppunit/gen/data/tdf121120.png
Binary files differ
diff --git a/vcl/qa/cppunit/gen/gen.cxx b/vcl/qa/cppunit/gen/gen.cxx
new file mode 100644
index 000000000..e313ff5d8
--- /dev/null
+++ b/vcl/qa/cppunit/gen/gen.cxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <com/sun/star/frame/Desktop.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/sfxbasemodel.hxx>
+#include <test/unoapi_test.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/virdev.hxx>
+
+using namespace com::sun::star;
+
+/// This test uses the gen backend (i.e. intentionally not the svp one, which is the default.)
+class GenTest : public UnoApiTest
+{
+public:
+ GenTest()
+ : UnoApiTest("/vcl/qa/cppunit/gen/data/")
+ {
+ }
+
+ virtual void setUp() override
+ {
+ UnoApiTest::setUp();
+ mxDesktop.set(
+ frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())));
+ SfxApplication::GetOrCreate();
+ };
+
+ virtual void tearDown() override
+ {
+ if (mxComponent.is())
+ {
+ closeDocument(mxComponent);
+ mxComponent->dispose();
+ }
+ UnoApiTest::tearDown();
+ };
+
+ Bitmap load(const char* pName)
+ {
+ OUString aFileURL;
+ createFileURL(OUString::createFromAscii(pName), aFileURL);
+ mxComponent = loadFromDesktop(aFileURL, "com.sun.star.drawing.DrawingDocument");
+ SfxBaseModel* pModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pModel);
+ SfxObjectShell* pShell = pModel->GetObjectShell();
+ std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
+ BitmapEx aResultBitmap;
+ CPPUNIT_ASSERT(xMetaFile->CreateThumbnail(aResultBitmap));
+ return aResultBitmap.GetBitmap();
+ }
+
+ uno::Reference<lang::XComponent> mxComponent;
+};
+
+CPPUNIT_TEST_FIXTURE(GenTest, testTdf121120)
+{
+ Bitmap aBitmap = load("tdf121120.png");
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ const Size& rSize = aBitmap.GetSizePixel();
+ Color aColor(pAccess->GetPixel(rSize.getHeight() / 2, rSize.getWidth() / 2));
+ // Without the accompanying fix in place, this test would have failed with 'Expected: 255;
+ // Actual : 1'. I.e. center of the preview (which has the background color) was ~black, not
+ // white.
+ CPPUNIT_ASSERT_EQUAL(0xff, int(aColor.GetRed()));
+ CPPUNIT_ASSERT_EQUAL(0xff, int(aColor.GetBlue()));
+ CPPUNIT_ASSERT_EQUAL(0xff, int(aColor.GetGreen()));
+}
+
+/// Test that drawing a line preview to a bitmap is not lost.
+CPPUNIT_TEST_FIXTURE(GenTest, testTdf107966)
+{
+ // Set up the virtual device: white background.
+ ScopedVclPtr<VirtualDevice> pVirtualDevice(VclPtr<VirtualDevice>::Create());
+ pVirtualDevice->SetLineColor();
+ MapMode aMapMode;
+ aMapMode.SetMapUnit(MapUnit::MapTwip);
+ pVirtualDevice->SetMapMode(aMapMode);
+ pVirtualDevice->SetOutputSizePixel(Size(90, 15));
+ pVirtualDevice->SetFillColor(Color(255, 255, 255));
+ pVirtualDevice->DrawRect(tools::Rectangle(Point(), Size(1350, 225)));
+ pVirtualDevice->SetFillColor(Color(0, 0, 0));
+ AntialiasingFlags nOldAA = pVirtualDevice->GetAntialiasing();
+ pVirtualDevice->SetAntialiasing(nOldAA & ~AntialiasingFlags::Enable);
+
+ // Paint a black polygon on it.
+ basegfx::B2DPolygon aPolygon;
+ aPolygon.append(basegfx::B2DPoint(0, 15));
+ aPolygon.append(basegfx::B2DPoint(1350, 15));
+ aPolygon.append(basegfx::B2DPoint(1350, 0));
+ aPolygon.append(basegfx::B2DPoint(0, 0));
+ pVirtualDevice->DrawPolygon(aPolygon);
+
+ // Make sure that the polygon is visible.
+ Bitmap aBitmap = pVirtualDevice->GetBitmap(Point(), Size(1350, 15));
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ Color aPixel(pAccess->GetPixel(0, 0));
+ // Without the accompanying fix in place, this test would have failed with 'Expected: 000000;
+ // Actual: ffffff', i.e. the top left pixel was white, not black.
+ CPPUNIT_ASSERT_EQUAL(OUString("000000"), aPixel.AsRGBHexString());
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/gradient.cxx b/vcl/qa/cppunit/gradient.cxx
new file mode 100644
index 000000000..474c619be
--- /dev/null
+++ b/vcl/qa/cppunit/gradient.cxx
@@ -0,0 +1,256 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <test/outputdevice.hxx>
+
+#include <sal/log.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/vector/b2enums.hxx>
+
+#include <vcl/gradient.hxx>
+#include <vcl/lineinfo.hxx>
+#include <vcl/print.hxx>
+#include <vcl/rendercontext/RasterOp.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/window.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/metaact.hxx>
+
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <bufferdevice.hxx>
+#include <window.h>
+
+class VclGradientTest : public test::BootstrapFixture
+{
+public:
+ VclGradientTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testAddGradientActions_rect_linear();
+ void testAddGradientActions_rect_axial();
+ void testAddGradientActions_rect_complex();
+
+ CPPUNIT_TEST_SUITE(VclGradientTest);
+ CPPUNIT_TEST(testAddGradientActions_rect_linear);
+ CPPUNIT_TEST(testAddGradientActions_rect_axial);
+ CPPUNIT_TEST(testAddGradientActions_rect_complex);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+static size_t TestLinearStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
+{
+ nIndex++;
+ MetaAction* pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (start)", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action (start)", MetaActionType::POLYGON,
+ pAction->GetType());
+
+ for (size_t i = 0; i < nTimes - 1; i++)
+ {
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+ }
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (end)", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action (end)", MetaActionType::POLYGON,
+ pAction->GetType());
+
+ return nIndex;
+}
+
+void VclGradientTest::testAddGradientActions_rect_linear()
+{
+ GDIMetaFile aMtf;
+ tools::Rectangle aRect(Point(10, 10), Size(40, 40));
+ Gradient aGradient(GradientStyle::Linear, COL_RED, COL_WHITE);
+ aGradient.SetBorder(100);
+
+ aGradient.AddGradientActions(aRect, aMtf);
+
+ size_t nIndex = 0;
+
+ MetaAction* pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
+ MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
+ pAction->GetType());
+
+ TestLinearStripes(aMtf, 3, nIndex);
+}
+
+static size_t TestAxialStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
+{
+ nIndex++;
+ MetaAction* pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+
+ for (size_t i = 0; i < nTimes - 1; i++)
+ {
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+ }
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+
+ return nIndex;
+}
+
+void VclGradientTest::testAddGradientActions_rect_axial()
+{
+ GDIMetaFile aMtf;
+ tools::Rectangle aRect(Point(10, 10), Size(40, 40));
+ Gradient aGradient(GradientStyle::Axial, COL_RED, COL_WHITE);
+ aGradient.SetBorder(100);
+
+ aGradient.AddGradientActions(aRect, aMtf);
+
+ size_t nIndex = 0;
+
+ MetaAction* pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
+ MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
+ pAction->GetType());
+
+ TestAxialStripes(aMtf, 3, nIndex);
+}
+
+static size_t TestComplexStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
+{
+ nIndex++;
+ MetaAction* pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ for (size_t i = 1; i < nTimes; i++)
+ {
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYPOLYGON,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+ }
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+
+ return nIndex;
+}
+
+void VclGradientTest::testAddGradientActions_rect_complex()
+{
+ GDIMetaFile aMtf;
+ tools::Rectangle aRect(Point(10, 10), Size(40, 40));
+ Gradient aGradient(GradientStyle::Square, COL_RED, COL_WHITE);
+ aGradient.SetBorder(10);
+
+ aGradient.AddGradientActions(aRect, aMtf);
+
+ size_t nIndex = 0;
+
+ MetaAction* pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
+ MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
+ pAction->GetType());
+
+ TestComplexStripes(aMtf, 40, nIndex);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclGradientTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/data/README b/vcl/qa/cppunit/graphicfilter/data/README
new file mode 100644
index 000000000..2cc9fb3cb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/README
@@ -0,0 +1,7 @@
+Files with the string 'CVE' in their name are encrypted to avoid
+problems with virus checkers on source code download.; use:
+
+mdecrypt --bare -a arcfour -o hex -k 435645 -s 3 foo.doc # to unencrypt
+mcrypt --bare -a arcfour -o hex -k 435645 -s 3 foo.doc # to create new tests
+
+to get access to the plain files for manual testing.
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2004-0691-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2004-0691-1.bmp
new file mode 100644
index 000000000..d77db5782
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2004-0691-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2006-0006-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2006-0006-1.bmp
new file mode 100644
index 000000000..4cfbdfff8
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2006-0006-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-2244-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-2244-1.bmp
new file mode 100644
index 000000000..289cf8c0e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-2244-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-3741-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-3741-1.bmp
new file mode 100644
index 000000000..84ac054db
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-3741-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-3741-2.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-3741-2.bmp
new file mode 100644
index 000000000..a6aed5983
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2007-3741-2.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2008-1097-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2008-1097-1.bmp
new file mode 100644
index 000000000..76aaecf97
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2008-1097-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2008-5870-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2008-5870-1.bmp
new file mode 100644
index 000000000..d223dde28
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2008-5870-1.bmp
@@ -0,0 +1 @@
+ .GxK؝'se2~.G1-#1Y!ʢ/DV \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2016-10504-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2016-10504-1.bmp
new file mode 100644
index 000000000..b733b2484
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/CVE-2016-10504-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/EDB-24743-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/EDB-24743-1.bmp
new file mode 100644
index 000000000..2b58d1035
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/EDB-24743-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/EDB-24743-4.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/EDB-24743-4.bmp
new file mode 100644
index 000000000..cfe7e40f6
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/EDB-24743-4.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/afl-sample-bad-rle-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/afl-sample-bad-rle-1.bmp
new file mode 100644
index 000000000..1ca6e0008
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/afl-sample-bad-rle-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/nodict-compress.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/nodict-compress.bmp
new file mode 100644
index 000000000..a75d6ebae
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/nodict-compress.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/bmp/indeterminate/.gitignore
new file mode 100644
index 000000000..583b009c7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.wmf-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2014-1947-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2014-1947-1.bmp
new file mode 100644
index 000000000..3815a1c13
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2014-1947-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/EDB-22680-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/EDB-22680-1.bmp
new file mode 100644
index 000000000..88b11ad57
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/EDB-22680-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/crash-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/crash-1.bmp
new file mode 100644
index 000000000..84b6c35c8
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/crash-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/dxf/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/fail/CVE-2010-1681-1.dxf b/vcl/qa/cppunit/graphicfilter/data/dxf/fail/CVE-2010-1681-1.dxf
new file mode 100644
index 000000000..b4629d9dc
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/fail/CVE-2010-1681-1.dxf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/fail/hang-1.dxf b/vcl/qa/cppunit/graphicfilter/data/dxf/fail/hang-1.dxf
new file mode 100644
index 000000000..d97edbb29
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/fail/hang-1.dxf
@@ -0,0 +1 @@
+99 \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/dxf/indeterminate/.gitignore
new file mode 100644
index 000000000..98457bc10
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.dxf-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/pass/bigangle-1.dxf b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/bigangle-1.dxf
new file mode 100644
index 000000000..3c4741447
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/bigangle-1.dxf
@@ -0,0 +1,143 @@
+99
+170141183460469231731687303715884105718
+ 2
+BL0C
+ 0
+SECTION
+ 2
+ENTITIES
+ 0111 N9.0
+0
+ARC
+111 N9
+ 1
+I
+ 39
+9
+130
+
+ 51
+1758770265ded1a13ecce6855794837535bf766a7fRC
+111 N9.0007
+ 39
+9
+130
+10
+ 2
+BL0C
+ 0
+SECTION
+ 2
+ENTITIES
+ 0111 N9.0
+0
+ARC
+111 N9
+ 1
+I
+ 39
+9
+130
+
+ 51
+9705
+0
+ARC
+111 39
+9
+130
+
+ 51
+183460469231731687303715884105718
+ 2
+BL0C
+ 0
+SECTION
+ 2
+ENTITIES
+ 0111 N9.0
+0
+ARC
+111 N9
+ 1
+I
+ 39
+9
+130
+
+ 51
+1758770265ded1a13ecce6855794837535bf766a7fRC
+111 N9.0007
+ 39
+9
+130
+10
+ 2
+BL0C
+ 0
+SECTION
+ 2
+ENTITIES
+ 0111 N9.0
+0
+ARC
+111 N9
+ 1
+I
+ 39
+9
+130
+
+ 51
+9705
+0
+ARC
+111 39
+9
+130
+
+ 51
+197
+0
+ARC
+111 N9.00dL07
+ 39
+9
+130
+
+ 56
+15
+ 8
+
+0
+EOF
+111 N9.0
+ 56*
+15
+ 8
+
+0
+EO?
+111 197
+0
+ARC
+111 N9.00dL07
+ 39
+9
+130
+
+ 56
+15
+ 8
+
+0
+EOF
+111 N9.0
+ 56*
+15
+ 8
+
+0
+EO?
+111 N9.000
+3 N 2S 79 799
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/pass/loop-1.dxf b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/loop-1.dxf
new file mode 100644
index 000000000..e3277e69b
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/loop-1.dxf
@@ -0,0 +1,17320 @@
+ 0
+SECTION
+ 2
+HEADER
+ 9
+$ACADVER
+ 1
+AC1015
+ 9
+$ACADMAINTVER
+ 70
+ 6
+ 9
+$DWGCODEPAGE
+ 3
+ANSI_1252
+ 9
+$INSBASE
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$EXTMIN
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$EXTMAX
+ 10
+297.0
+ 20
+420.0
+ 30
+0.0
+ 9
+$LIMMIN
+ 10
+0.0
+ 20
+0.0
+ 9
+$LIMMAX
+ 10
+297.0
+ 20
+420.0
+ 9
+$ORTHOMODE
+ 70
+ 0
+ 9
+$REGENMODE
+ 70
+ 1
+ 9
+$FILLODE
+ 70
+ 1
+ 9
+$QTEXTMODE
+ 70
+ 0
+ 9
+$MIRRTEXT
+ 70
+ 1
+ 9
+$LTSCALE
+ 40
+1.0
+ 9
+$ATTMODE
+ 70
+ 1
+ 9
+$TEXTSIZE
+ 40
+3.5
+ 9
+$TRACEWID
+ 40
+1.0
+ 9
+$TEXTSTYLE
+ 7
+Standard
+ 9
+$CLAYER
+ 8
+0
+ 9
+$CELTYPE
+ 6
+ByLayer
+ 9
+$CECOLOR
+ 62
+ 256
+ 9
+$CELTSCALE
+ 40
+1.0
+ 9
+$DISPSILH
+ 70
+ 0
+ 9
+$DIMSCALE
+ 40
+1.0
+ 9
+$DIMASZ
+ 40
+3.0
+ 9
+$DIMEXO
+ 40
+1.0
+ 9
+$DIMDLI
+ 40
+3.75
+ 9
+$DIMRND
+ 40
+0.0
+ 9
+$DIMDLE
+ 40
+0.0
+ 9
+$DIMEXE
+ 40
+1.0
+ 9
+$DIMTP
+ 40
+0.0
+ 9
+$DIMTM
+ 40
+0.0
+ 9
+$DIMTXT
+ 40
+3.5
+ 9
+$DIMCEN
+ 40
+2.5
+ 9
+$DIMTSZ
+ 40
+0.0
+ 9
+$DIMTOL
+ 70
+ 0
+ 9
+$DIMLIM
+ 70
+ 0
+ 9
+$DIMTIH
+ 70
+ 1
+ 9
+$DIMTOH
+ 70
+ 1
+ 9
+$DIMSE1
+ 70
+ 0
+ 9
+$DIMSE2
+ 70
+ 0
+ 9
+$DIMTAD
+ 70
+ 1
+ 9
+$DIMZIN
+ 70
+ 0
+ 9
+$DIMBLK
+ 1
+
+ 9
+$DIMASO
+ 70
+ 1
+ 9
+$DIMSHO
+ 70
+ 1
+ 9
+$DIMPOST
+ 1
+
+ 9
+$DIMAPOST
+ 1
+
+ 9
+$DIMALT
+ 70
+ 0
+ 9
+$DIMALTD
+ 70
+ 3
+ 9
+$DIMALTF
+ 40
+0.0393700787
+ 9
+$DIMLFAC
+ 40
+100.0
+ 9
+$DIMTOFL
+ 70
+ 1
+ 9
+$DIMTVP
+ 40
+0.0
+ 9
+$DIMTIX
+ 70
+ 0
+ 9
+$DIMSOXD
+ 70
+ 0
+ 9
+$DIMSAH
+ 70
+ 0
+ 9
+$DIMBLK1
+ 1
+
+ 9
+$DIMBLK2
+ 1
+
+ 9
+$DIMSTYLE
+ 2
+ISO-25
+ 9
+$DIMCLRD
+ 70
+ 0
+ 9
+$DIMCLRE
+ 70
+ 0
+ 9
+$DIMCLRT
+ 70
+ 0
+ 9
+$DIMTFAC
+ 40
+1.0
+ 9
+$DIMGAP
+ 40
+1.524
+ 9
+$DIMJUST
+ 70
+ 0
+ 9
+$DIMSD1
+ 70
+ 0
+ 9
+$DIMSD2
+ 70
+ 0
+ 9
+$DIMTOLJ
+ 70
+ 0
+ 9
+$DIMTZIN
+ 70
+ 0
+ 9
+$DIMALTZ
+ 70
+ 0
+ 9
+$DIMALTTZ
+ 70
+ 0
+ 9
+$DIMUPT
+ 70
+ 0
+ 9
+$DIMDEC
+ 70
+ 3
+ 9
+$DIMTDEC
+ 70
+ 3
+ 9
+$DIMALTU
+ 70
+ 2
+ 9
+$DIMALTTD
+ 70
+ 3
+ 9
+$DIMTXSTY
+ 7
+Standard
+ 9
+$DIMAUNIT
+ 70
+ 0
+ 9
+$DIMADEC
+ 70
+ 2
+ 9
+$DIMALTRND
+ 40
+0.0
+ 9
+$DIMAZIN
+ 70
+ 0
+ 9
+$DIMDSEP
+ 70
+ 44
+ 9
+$DIMATFIT
+ 70
+ 3
+ 9
+$DIMFRAC
+ 70
+ 0
+ 9
+$DIMLDRBLK
+ 1
+
+ 9
+$DIMLUNIT
+ 70
+ 2
+ 9
+$DIMLWD
+ 70
+ -2
+ 9
+$DIMLWE
+ 70
+ -2
+ 9
+$DIMTMOVE
+ 70
+ 0
+ 9
+$LUNITS
+ 70
+ 2
+ 9
+$LUPREC
+ 70
+ 2
+ 9
+$SKETCHINC
+ 40
+1.0
+ 9
+$FILLETRAD
+ 40
+10.0
+ 9
+$AUNITS
+ 70
+ 0
+ 9
+$AUPREC
+ 70
+ 2
+ 9
+$MENU
+ 1
+.
+ 9
+$ELEVATION
+ 40
+0.0
+ 9
+$PELEVATION
+ 40
+0.0
+ 9
+$THICKNESS
+ 40
+0.0
+ 9
+$LIMCHECK
+ 70
+ 0
+ 9
+$CHAMFERA
+ 40
+10.0
+ 9
+$CHAMFERB
+ 40
+10.0
+ 9
+$CHAMFERC
+ 40
+20.0
+ 9
+$CHAMFERD
+ 40
+0.0
+ 9
+$SKPOLY
+ 70
+ 0
+ 9
+$TDCREATE
+ 40
+2456962.662635255
+ 9
+$TDUCREATE
+ 40
+2456962.620968588
+ 9
+$TDUPDATE
+ 40
+2456962.662636401
+ 9
+$TDUUPDATE
+ 40
+2456962.620969734
+ 9
+$TDINDWG
+ 40
+0.0000000116
+ 9
+$TDUSRTIMER
+ 40
+0.0000000116
+ 9
+$USRTIMER
+ 70
+ 1
+ 9
+$ANGBASE
+ 50
+0.0
+ 9
+$ANGDIR
+ 70
+ 0
+ 9
+$PDMODE
+ 70
+ 0
+ 9
+$PDSIZE
+ 40
+-1.0
+ 9
+$PLINEWID
+ 40
+0.0
+ 9
+$SPLFRAME
+ 70
+ 0
+ 9
+$SPLINETYPE
+ 70
+ 6
+ 9
+$SPLINESEGS
+ 70
+ 8
+ 9
+$HANDSEED
+ 5
+5C0
+ 9
+$SURFTAB1
+ 70
+ 6
+ 9
+$SURFTAB2
+ 70
+ 6
+ 9
+$SURFTYPE
+ 70
+ 6
+ 9
+$SURFU
+ 70
+ 6
+ 9
+$SURFV
+ 70
+ 6
+ 9
+$UCSBASE
+ 2
+
+ 9
+$UCSNAME
+ 2
+
+ 9
+$UCSORG
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$UCSXDIR
+ 10
+1.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$UCSYDIR
+ 10
+0.0
+ 20
+1.0
+ 30
+0.0
+ 9
+$UCSORTHOREF
+ 2
+
+ 9
+$UCSORTHOVIEW
+ 70
+ 0
+ 9
+$UCSORGTOP
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$UCSORGBOTTOM
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$UCSORGLEFT
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$UCSORGRIGHT
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$UCSORGFRONT
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$UCSORGBACK
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PUCSBASE
+ 2
+
+ 9
+$PUCSNAME
+ 2
+
+ 9
+$PUCSORG
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PUCSXDIR
+ 10
+1.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PUCSYDIR
+ 10
+0.0
+ 20
+1.0
+ 30
+0.0
+ 9
+$PUCSORTHOREF
+ 2
+
+ 9
+$PUCSORTHOVIEW
+ 70
+ 0
+ 9
+$PUCSORGTOP
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PUCSORGBOTTOM
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PUCSORGLEFT
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PUCSORGRIGHT
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PUCSORGFRONT
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PUCSORGBACK
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$USERI1
+ 70
+ 0
+ 9
+$USERI2
+ 70
+ 0
+ 9
+$USERI3
+ 70
+ 0
+ 9
+$USERI4
+ 70
+ 0
+ 9
+$USERI5
+ 70
+ 0
+ 9
+$USERR1
+ 40
+0.0
+ 9
+$USERR2
+ 40
+0.0
+ 9
+$USERR3
+ 40
+0.0
+ 9
+$USERR4
+ 40
+0.0
+ 9
+$USERR5
+ 40
+0.0
+ 9
+$WORLDVIEW
+ 70
+ 1
+ 9
+$SHADEDGE
+ 70
+ 3
+ 9
+$SHADEDIF
+ 70
+ 70
+ 9
+$TILEMODE
+ 70
+ 1
+ 9
+$MAXACTVP
+ 70
+ 64
+ 9
+$PINSBASE
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$PLIMCHECK
+ 70
+ 0
+ 9
+$PEXTMIN
+ 10
+1.0000000000E+20
+ 20
+1.0000000000E+20
+ 30
+1.0000000000E+20
+ 9
+$PEXTMAX
+ 10
+-1.0000000000E+20
+ 20
+-1.0000000000E+20
+ 30
+-1.0000000000E+20
+ 9
+$PLIMMIN
+ 10
+0.0
+ 20
+0.0
+ 9
+$PLIMMAX
+ 10
+420.0
+ 20
+297.0
+ 9
+$UNITMODE
+ 70
+ 0
+ 9
+$VISRETAIN
+ 70
+ 1
+ 9
+$PLINEGEN
+ 70
+ 0
+ 9
+$PSLTSCALE
+ 70
+ 1
+ 9
+$TREEDEPTH
+ 70
+ 3020
+ 9
+$CMLSTYLE
+ 2
+Standard
+ 9
+$CMLJUST
+ 70
+ 0
+ 9
+$CMLSCALE
+ 40
+20.0
+ 9
+$PROXYGRAPHICS
+ 70
+ 1
+ 9
+$MEASUREMENT
+ 70
+ 1
+ 9
+$CELWEIGHT
+370
+ -1
+ 9
+$ENDCAPS
+280
+ 0
+ 9
+$JOINSTYLE
+280
+ 0
+ 9
+$LWDISPLAY
+290
+ 1
+ 9
+$INSUNITS
+ 70
+ 4
+ 9
+$HYPERLINKBASE
+ 1
+
+ 9
+$STYLESHEET
+ 1
+
+ 9
+$XEDIT
+290
+ 1
+ 9
+$CEPSNTYPE
+380
+ 0
+ 9
+$PSTYLEMODE
+290
+ 1
+ 9
+$FINGERPRINTGUID
+ 2
+{12852F08-F252-4439-8DDF-34F6DEA5435B}
+ 9
+$VERSIONGUID
+ 2
+{FAEB1C32-E019-11D5-929B-00C0DF256EC4}
+ 9
+$EXTNAMES
+290
+ 1
+ 9
+$PSVPSCALE
+ 40
+0.0
+ 9
+$OLESTARTUP
+290
+ 0
+ 0
+ENDSEC
+ 0
+SECTION
+ 2
+CLASSES
+ 0
+CLASS
+ 1
+ACDBDICTIONARYWDFLT
+ 2
+AcDbDictionaryWithDefault
+ 3
+ObjectDBX Classes
+ 90
+ 0
+280
+ 0
+281
+ 0
+ 0
+CLASS
+ 1
+VISUALSTYLE
+ 2
+AcDbVisualStyle
+ 3
+ObjectDBX Classes
+ 90
+ 4095
+280
+ 0
+281
+ 0
+ 0
+CLASS
+ 1
+MATERIAL
+ 2
+AcDbMaterial
+ 3
+ObjectDBX Classes
+ 90
+ 1153
+280
+ 0
+281
+ 0
+ 0
+CLASS
+ 1
+ACDBPLACEHOLDER
+ 2
+AcDbPlaceHolder
+ 3
+ObjectDBX Classes
+ 90
+ 0
+280
+ 0
+281
+ 0
+ 0
+CLASS
+ 1
+LAYOUT
+ 2
+AcDbLayout
+ 3
+ObjectDBX Classes
+ 90
+ 0
+280
+ 0
+281
+ 0
+ 0
+ENDSEC
+ 0
+SECTION
+ 2
+TABLES
+ 0
+TABLE
+ 2
+VPORT
+ 5
+8
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 1
+ 0
+VPORT
+ 5
+29
+330
+8
+100
+AcDbSymbolTableRecord
+100
+AcDbViewportTableRecord
+ 2
+*Active
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 11
+1.0
+ 21
+1.0
+ 12
+148.5
+ 22
+210.0
+ 13
+0.0
+ 23
+0.0
+ 14
+10.0
+ 24
+10.0
+ 15
+10.0
+ 25
+10.0
+ 16
+0.0
+ 26
+0.0
+ 36
+1.0
+ 17
+0.0
+ 27
+0.0
+ 37
+0.0
+ 40
+420.0
+ 41
+0.7071428571
+ 42
+50.0
+ 43
+0.0
+ 44
+0.0
+ 50
+0.0
+ 51
+0.0
+ 71
+ 0
+ 72
+ 2000
+ 73
+ 1
+ 74
+ 3
+ 75
+ 0
+ 76
+ 0
+ 77
+ 0
+ 78
+ 0
+281
+ 0
+ 65
+ 1
+110
+0.0
+120
+0.0
+130
+0.0
+111
+1.0
+121
+0.0
+131
+0.0
+112
+0.0
+122
+1.0
+132
+0.0
+ 79
+ 0
+146
+0.0
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+LTYPE
+ 5
+5
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 6
+ 0
+LTYPE
+ 5
+14
+330
+5
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+ 2
+ByBlock
+ 70
+ 0
+ 3
+
+ 72
+ 65
+ 73
+ 0
+ 40
+0.0
+ 0
+LTYPE
+ 5
+15
+330
+5
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+ 2
+ByLayer
+ 70
+ 0
+ 3
+
+ 72
+ 65
+ 73
+ 0
+ 40
+0.0
+ 0
+LTYPE
+ 5
+16
+330
+5
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+ 2
+Continuous
+ 70
+ 0
+ 3
+Solid line
+ 72
+ 65
+ 73
+ 0
+ 40
+0.0
+ 0
+LTYPE
+ 5
+3F
+330
+5
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+ 2
+HIDDEN
+ 70
+ 0
+ 3
+Hidden __ __ __ __ __ __ __ __ __ __ __ __ __ __
+ 72
+ 65
+ 73
+ 2
+ 40
+1.905
+ 49
+1.27
+ 74
+ 0
+ 49
+-0.635
+ 74
+ 0
+ 0
+LTYPE
+ 5
+40
+330
+5
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+ 2
+PHANTOM
+ 70
+ 0
+ 3
+Phantom ______ __ __ ______ __ __ ______
+ 72
+ 65
+ 73
+ 6
+ 40
+12.7
+ 49
+6.35
+ 74
+ 0
+ 49
+-1.27
+ 74
+ 0
+ 49
+1.27
+ 74
+ 0
+ 49
+-1.27
+ 74
+ 0
+ 49
+1.27
+ 74
+ 0
+ 49
+-1.27
+ 74
+ 0
+ 0
+LTYPE
+ 5
+41
+330
+5
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+ 2
+CENTER
+ 70
+ 0
+ 3
+Center ____ _ ____ _ ____ _ ____ _ ____ _ ____
+ 72
+ 65
+ 73
+ 4
+ 40
+10.16
+ 49
+6.35
+ 74
+ 0
+ 49
+-1.27
+ 74
+ 0
+ 49
+1.27
+ 74
+ 0
+ 49
+-1.27
+ 74
+ 0
+ 0
+LTYPE
+ 5
+42
+330
+5
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+ 2
+CENTERX2
+ 70
+ 0
+ 3
+Center (2x) ________ __ ________ __ _____
+ 72
+ 65
+ 73
+ 4
+ 40
+20.32
+ 49
+12.7
+ 74
+ 0
+ 49
+-2.54
+ 74
+ 0
+ 49
+2.54
+ 74
+ 0
+ 49
+-2.54
+ 74
+ 0
+ 0
+LTYPE
+ 5
+43
+330
+5
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+ 2
+DOT2
+ 70
+ 0
+ 3
+Dot (.5x) ........................................
+ 72
+ 65
+ 73
+ 2
+ 40
+0.635
+ 49
+0.0
+ 74
+ 0
+ 49
+-0.635
+ 74
+ 0
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+LAYER
+ 5
+2
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 8
+ 0
+LAYER
+ 5
+10
+330
+2
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+ 2
+0
+ 70
+ 0
+ 62
+ 7
+ 6
+Continuous
+370
+ -3
+390
+F
+ 0
+LAYER
+ 5
+44
+330
+2
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+ 2
+TEKENLIJN
+ 70
+ 0
+ 62
+ 7
+ 6
+Continuous
+370
+ -3
+390
+F
+ 0
+LAYER
+ 5
+45
+330
+2
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+ 2
+HARTLIJN
+ 70
+ 0
+ 62
+ 7
+ 6
+CENTER
+370
+ -3
+390
+F
+ 0
+LAYER
+ 5
+46
+330
+2
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+ 2
+STIPPELIJN
+ 70
+ 0
+ 62
+ 7
+ 6
+HIDDEN
+370
+ 15
+390
+F
+ 0
+LAYER
+ 5
+47
+330
+2
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+ 2
+DIKKE_MAATLIJN
+ 70
+ 0
+ 62
+ 7
+ 6
+Continuous
+370
+ 158
+390
+F
+ 0
+LAYER
+ 5
+48
+330
+2
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+ 2
+STUKLIJST
+ 70
+ 0
+ 62
+ 7
+ 6
+Continuous
+370
+ 15
+390
+F
+ 0
+LAYER
+ 5
+49
+330
+2
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+ 2
+MAATLIJN
+ 70
+ 0
+ 62
+ 7
+ 6
+Continuous
+370
+ -3
+390
+F
+ 0
+LAYER
+ 5
+4A
+330
+2
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+ 2
+TEKST
+ 70
+ 0
+ 62
+ 7
+ 6
+Continuous
+370
+ 15
+390
+F
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+STYLE
+ 5
+3
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 3
+ 0
+STYLE
+ 5
+11
+330
+3
+100
+AcDbSymbolTableRecord
+100
+AcDbTextStyleTableRecord
+ 2
+Standard
+ 70
+ 0
+ 40
+0.0
+ 41
+1.0
+ 50
+0.0
+ 71
+ 0
+ 42
+3.5
+ 3
+txt
+ 4
+
+ 0
+STYLE
+ 5
+54
+330
+3
+100
+AcDbSymbolTableRecord
+100
+AcDbTextStyleTableRecord
+ 2
+SLDTEXTSTYLE0
+ 70
+ 0
+ 40
+0.0
+ 41
+0.75
+ 50
+0.0
+ 71
+ 0
+ 42
+0.2
+ 3
+TXT
+ 4
+
+ 0
+STYLE
+ 5
+56A
+330
+3
+100
+AcDbSymbolTableRecord
+100
+AcDbTextStyleTableRecord
+ 2
+SLDTEXTSTYLE1
+ 70
+ 0
+ 40
+0.0
+ 41
+0.7
+ 50
+0.0
+ 71
+ 0
+ 42
+0.2
+ 3
+TXT
+ 4
+
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+VIEW
+ 5
+6
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 0
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+UCS
+ 5
+7
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 0
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+APPID
+ 5
+9
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 1
+ 0
+APPID
+ 5
+12
+330
+9
+100
+AcDbSymbolTableRecord
+100
+AcDbRegAppTableRecord
+ 2
+ACAD
+ 70
+ 0
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+DIMSTYLE
+ 5
+A
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 4
+100
+AcDbDimStyleTable
+ 0
+DIMSTYLE
+105
+27
+330
+A
+100
+AcDbSymbolTableRecord
+100
+AcDbDimStyleTableRecord
+ 2
+ISO-25
+ 70
+ 0
+ 41
+2.5
+ 42
+0.625
+ 43
+3.75
+ 44
+1.25
+ 73
+ 0
+ 74
+ 0
+ 77
+ 1
+ 78
+ 8
+140
+2.5
+141
+2.5
+143
+0.0393700787
+147
+0.625
+171
+ 3
+172
+ 1
+178
+ 0
+271
+ 2
+272
+ 2
+274
+ 3
+278
+ 44
+283
+ 0
+284
+ 8
+340
+11
+ 0
+DIMSTYLE
+105
+501
+102
+{ACAD_REACTORS
+330
+500
+102
+}
+330
+A
+100
+AcDbSymbolTableRecord
+100
+AcDbDimStyleTableRecord
+ 2
+SLDDIMSTYLE0
+ 70
+ 0
+ 41
+3.0
+ 44
+0.0
+ 45
+0.000000001
+ 73
+ 0
+ 74
+ 0
+ 77
+ 1
+ 78
+ 12
+ 79
+ 3
+140
+3.5
+144
+2.5
+147
+0.875
+172
+ 1
+173
+ 1
+178
+ 0
+271
+ 3
+272
+ 3
+276
+ 2
+284
+ 12
+289
+ 0
+340
+54
+ 0
+DIMSTYLE
+105
+50E
+102
+{ACAD_REACTORS
+330
+50D
+330
+51A
+330
+526
+330
+56C
+330
+578
+330
+584
+102
+}
+330
+A
+100
+AcDbSymbolTableRecord
+100
+AcDbDimStyleTableRecord
+ 2
+SLDDIMSTYLE1
+ 70
+ 0
+ 41
+3.0
+ 44
+0.0
+ 45
+0.000000001
+ 73
+ 0
+ 74
+ 0
+ 77
+ 1
+ 78
+ 12
+ 79
+ 3
+140
+3.5
+144
+2.5
+147
+0.875
+172
+ 1
+173
+ 1
+178
+ 0
+271
+ 0
+272
+ 0
+276
+ 2
+284
+ 12
+289
+ 0
+340
+54
+ 0
+DIMSTYLE
+105
+533
+102
+{ACAD_REACTORS
+330
+532
+330
+53C
+330
+545
+330
+54E
+330
+557
+330
+561
+102
+}
+330
+A
+100
+AcDbSymbolTableRecord
+100
+AcDbDimStyleTableRecord
+ 2
+SLDDIMSTYLE2
+ 70
+ 0
+ 41
+3.0
+ 44
+0.0
+ 45
+0.000000001
+ 73
+ 0
+ 74
+ 0
+ 77
+ 1
+ 78
+ 12
+ 79
+ 3
+140
+3.5
+144
+2.5
+147
+0.875
+173
+ 1
+178
+ 0
+271
+ 3
+272
+ 3
+276
+ 2
+284
+ 12
+340
+54
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+BLOCK_RECORD
+ 5
+1
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 15
+ 0
+BLOCK_RECORD
+ 5
+1F
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+*Model_Space
+340
+22
+ 0
+BLOCK_RECORD
+ 5
+1B
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+*Paper_Space
+340
+1E
+ 0
+BLOCK_RECORD
+ 5
+23
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+*Paper_Space0
+340
+26
+ 0
+BLOCK_RECORD
+ 5
+56
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+SW_BROKEN_VIEW_0
+340
+0
+102
+{BLKREFS
+331
+59
+102
+}
+ 0
+BLOCK_RECORD
+ 5
+502
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+50F
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_1
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+51B
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_2
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+527
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_3
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+534
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_4
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+53D
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_5
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+546
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_6
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+54F
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_7
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+558
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_8
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+562
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_9
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+56D
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_10
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+579
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_11
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+585
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_12
+340
+0
+ 0
+ENDTAB
+ 0
+ENDSEC
+ 0
+SECTION
+ 2
+BLOCKS
+ 0
+BLOCK
+ 5
+20
+330
+1F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+*Model_Space
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+*Model_Space
+ 1
+
+ 0
+ENDBLK
+ 5
+21
+330
+1F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+1C
+330
+1B
+100
+AcDbEntity
+ 67
+ 1
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+*Paper_Space
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+*Paper_Space
+ 1
+
+ 0
+ENDBLK
+ 5
+1D
+330
+1B
+100
+AcDbEntity
+ 67
+ 1
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+24
+330
+23
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+*Paper_Space0
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+*Paper_Space0
+ 1
+
+ 0
+ENDBLK
+ 5
+25
+330
+23
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+57
+330
+56
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+SW_BROKEN_VIEW_0
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+SW_BROKEN_VIEW_0
+ 1
+
+ 0
+ENDBLK
+ 5
+58
+330
+56
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+503
+330
+502
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D
+ 1
+
+ 0
+SOLID
+ 5
+505
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+194.9299255838
+ 21
+25.7821787182
+ 31
+0.0
+ 12
+195.9299255838
+ 22
+25.7821787182
+ 32
+0.0
+ 13
+195.9299255838
+ 23
+25.7821787182
+ 33
+0.0
+ 0
+SOLID
+ 5
+506
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.9299255838
+ 21
+44.9821787182
+ 31
+0.0
+ 12
+194.9299255838
+ 22
+44.9821787182
+ 32
+0.0
+ 13
+194.9299255838
+ 23
+44.9821787182
+ 33
+0.0
+ 0
+LINE
+ 5
+507
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+143.0299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+196.4299255838
+ 21
+28.7821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+508
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+196.4299255838
+ 21
+41.9821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+509
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+22.7821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+50A
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+41.9821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+50B
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+47.9821787182
+ 31
+0.0
+ 0
+MTEXT
+ 5
+50C
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+190.9181886692
+ 20
+31.991019801
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+33
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+504
+330
+502
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+510
+330
+50F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_1
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_1
+ 1
+
+ 0
+SOLID
+ 5
+512
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+280.0124004364
+ 30
+0.0
+ 11
+170.9299255838
+ 21
+277.0124004364
+ 31
+0.0
+ 12
+171.9299255838
+ 22
+277.0124004364
+ 32
+0.0
+ 13
+171.9299255838
+ 23
+277.0124004364
+ 33
+0.0
+ 0
+SOLID
+ 5
+513
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+287.499722104
+ 30
+0.0
+ 11
+171.9299255838
+ 21
+290.499722104
+ 31
+0.0
+ 12
+170.9299255838
+ 22
+290.499722104
+ 32
+0.0
+ 13
+170.9299255838
+ 23
+290.499722104
+ 33
+0.0
+ 0
+LINE
+ 5
+514
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+150.4168593775
+ 20
+280.0124004364
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+280.0124004364
+ 31
+0.0
+ 0
+LINE
+ 5
+515
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+516
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+280.0124004364
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+267.6770872868
+ 31
+0.0
+ 0
+LINE
+ 5
+517
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+280.0124004364
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+518
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+287.499722104
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+293.499722104
+ 31
+0.0
+ 0
+MTEXT
+ 5
+519
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+166.9181886692
+ 20
+267.6770872868
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+19
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+511
+330
+50F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+51C
+330
+51B
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_2
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_2
+ 1
+
+ 0
+SOLID
+ 5
+51E
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+202.8200717467
+ 30
+0.0
+ 11
+170.9299255838
+ 21
+199.8200717467
+ 31
+0.0
+ 12
+171.9299255838
+ 22
+199.8200717467
+ 32
+0.0
+ 13
+171.9299255838
+ 23
+199.8200717467
+ 33
+0.0
+ 0
+SOLID
+ 5
+51F
+330
+51B
+370
+ 0
+100
+AcDbCircle
+ 10
+149.1879091276
+ 20
+124.2049907824
+ 30
+0.0
+ 40
+0.0800276369171186
+100
+AcDbArc
+ 50
+31.2357600789
+ 51
+89.9882535152
+ 0
+LINE
+ 5
+3A8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2563360204
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+149.2563360204
+ 21
+124.2464899752
+ 31
+0.0
+ 0
+LINE
+ 5
+3A9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2162960043
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+134.2162960043
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3AA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2162960043
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3AB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.4299252202
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+133.4299252202
+ 21
+124.2555737231
+ 31
+0.0
+ 0
+LWPOLYLINE
+ 5
+3AC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbPolyline
+ 90
+ 4
+ 70
+ 128
+ 43
+0.0
+ 10
+149.2569536736
+ 20
+124.2454528544
+ 10
+149.2656842639
+ 20
+124.2305516932
+ 10
+149.2736712863
+ 20
+124.2169141505
+ 10
+149.2808976044
+ 20
+124.204575989
+ 0
+LINE
+ 5
+3AD
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.3099258115
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+149.3099258115
+ 21
+124.1757392619
+ 31
+0.0
+ 0
+LINE
+ 5
+3AE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2563360204
+ 20
+124.2464899752
+ 30
+0.0
+ 11
+149.2569536736
+ 21
+124.2454528544
+ 31
+0.0
+ 0
+LINE
+ 5
+3AF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2299253514
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+134.2299253514
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3B0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2299253514
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+134.2162960043
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3B1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.5099256804
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+148.5099256804
+ 21
+123.090755913
+ 31
+0.0
+ 0
+LINE
+ 5
+3B2 5
+4FF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+133.4299255838
+ 20
+660.3011936068
+ 30
+0.0
+ 0
+DIMENSION
+ 5
+500
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+34.5771309945
+ 31
+0.0
+ 70
+ 160
+ 1
+33
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE0
+100
+AcDbAlignedDimension
+ 13
+142.0299255838
+ 23
+28.7821787182
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+41.9821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+50D
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_1
+ 10
+171.4299255838
+ 20
+287.499722104
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+271.6850735678
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+280.0124004364
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+287.499722104
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+51A
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_2
+ 10
+171.4299255838
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+194.8678981433
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+202.8200717467
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+210.3073934143
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+526
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_3
+ 10
+171.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+113.1236101725
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+126.2783621669
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+133.7256838344
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+532
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_4
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+84.1586135498
+ 31
+0.0
+ 70
+ 160
+ 1
+675,902
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+148.0299255838
+ 23
+133.7256838344
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+41.9821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+53C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_5
+ 10
+195.3191971725
+ 20
+133.7649839595
+ 30
+0.0
+ 11
+195.2817915125
+ 21
+178.7746730971
+ 31
+0.0
+ 70
+ 160
+ 1
+524,500
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+210.3073934143
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+133.7256838344
+ 34
+0.0
+ 50
+-89.9523838979
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+545
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_6
+ 10
+195.2555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+246.0726158741
+ 31
+0.0
+ 70
+ 160
+ 1
+524,400
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+287.499722104
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+210.3073934143
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+54E
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_7
+ 10
+195.2555696261
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+357.7845521004
+ 31
+0.0
+ 70
+ 160
+ 1
+545,698
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+287.499722104
+ 33
+0.0
+ 14
+145.8378589248
+ 24
+397.2202084954
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+557
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_8
+ 10
+219.4299255838
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+219.4299255838
+ 21
+226.31135989
+ 31
+0.0
+ 70
+ 160
+ 1
+Kozijnmaat =
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+142.0299255838
+ 23
+28.7821787182
+ 33
+0.0
+ 14
+145.8378589248
+ 24
+397.2202084954
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+561
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_9
+ 10
+99.2299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+99.2299255838
+ 21
+214.5361780403
+ 31
+0.0
+ 70
+ 160
+ 1
+DMH =
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+133.4299255838
+ 23
+383.8202084954
+ 33
+0.0
+ 14
+142.0299255838
+ 24
+28.7821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+56C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_10
+ 10
+117.2299255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+157.3719824392
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+147.8850158005
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+148.4450158005
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+578
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_11
+ 10
+117.2299255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+236.5334651005
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+224.4267253803
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+224.9867253803
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+584
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_12
+ 10
+117.2299255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+311.8110919194
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+301.61905407
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+302.17905407
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+LINE
+ 5
+590
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+103.4
+ 51
+89.9999492362
+ 0
+ARC
+ 5
+3D7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.5163691973
+ 20
+133.4850123101
+ 30
+0.0
+ 40
+0.1200011213146664
+100
+AcDbArc
+ 50
+138.497247328
+ 51
+269.9999068087
+ 0
+ARC
+ 5
+3D8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+136.355993356
+ 20
+132.6849348127
+ 30
+0.0
+ 40
+0.0800841035922697
+100
+AcDbArc
+ 50
+90.0150168159
+ 51
+113.8359930711
+ 0
+ARC
+ 5
+3D9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+135.0299508788
+ 20
+135.6849288285
+ 30
+0.0
+ 40
+3.199908694378492
+100
+AcDbArc
+ 50
+269.9995452672
+ 51
+293.8464037785
+ 0
+LINE
+ 5
+3DA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+135.0299254825
+ 20
+132.4850201342
+ 30
+0.0
+ 11
+134.2499256899
+ 21
+132.4850201342
+ 31
+0.0
+ 0
+ARC
+ 5
+3DB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.2499379652
+ 20
+132.3650080634
+ 30
+0.0
+ 40
+0.1200120715024033
+100
+AcDbArc
+ 50
+90.0058604254
+ 51
+179.9980525768
+ 0
+LINE
+ 5
+3DC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1299258938
+ 20
+132.3650121424
+ 30
+0.0
+ 11
+134.1299258938
+ 21
+132.2075128291
+ 31
+0.0
+ 0
+ARC
+ 5
+3DD
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.2499411967
+ 20
+132.2075174672
+ 30
+0.0
+ 40
+0.1200153029850342
+100
+AcDbArc
+ 50
+180.0022142502
+ 51
+218.9973251432
+ 0
+LINE
+ 5
+3DE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1566682627
+ 20
+132.1319937442
+ 30
+0.0
+ 11
+134.4031833877
+ 21
+131.8275689814
+ 31
+0.0
+ 0
+ARC
+ 5
+3DF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.3099104538
+ 20
+131.7520452584
+ 30
+0.0
+ 40
+0.1200153029849757
+100
+AcDbArc
+ 50
+0.0022142501
+ 51
+38.9973251432
+ 0
+LINE
+ 5
+3E0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.4299257567
+ 20
+131.7520498965
+ 30
+0.0
+ 11
+134.4299257567
+ 21
+127.9414653514
+ 31
+0.0
+ 0
+ARC
+ 5
+3E1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.3099104538
+ 20
+127.9414699895
+ 30
+0.0
+ 40
+0.1200153029849757
+100
+AcDbArc
+ 50
+321.0026748568
+ 51
+359.9977857499
+ 0
+LINE
+ 5
+3E2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.4031833877
+ 20
+127.8659462664
+ 30
+0.0
+ 11
+134.05666806
+ 21
+127.4380445216
+ 31
+0.0
+ 0
+ARC
+ 5
+3E3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.149940994
+ 20
+127.3625207985
+ 30
+0.0
+ 40
+0.120015302984857
+100
+AcDbArc
+ 50
+141.0026748568
+ 51
+179.9977857499
+ 0
+LINE
+ 5
+3E4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.0299256911
+ 20
+127.3625254367
+ 30
+0.0
+ 11
+134.0299256911
+ 21
+126.1250138018
+ 31
+0.0
+ 0
+ARC
+ 5
+3E5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.1499186836
+ 20
+126.1250107233
+ 30
+0.0
+ 40
+0.1199929925412997
+100
+AcDbArc
+ 50
+179.9985300323
+ 51
+270.0032486934
+ 0
+LINE
+ 5
+3E6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1499254873
+ 20
+126.005017731
+ 30
+0.0
+ 11
+136.2299256792
+ 21
+126.005017731
+ 31
+0.0
+ 0
+ARC
+ 5
+3E7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+136.229912767
+ 20
+125.8850050222
+ 30
+0.0
+ 40
+0.1200127094438369
+100
+AcDbArc
+ 50
+0.0079431648
+ 51
+89.9938355609
+ 0
+LINE
+ 5
+3E8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+136.3499254753
+ 20
+125.8850216601
+ 30
+0.0
+ 11
+136.3499254753
+ 21
+125.2050161097
+ 31
+0.0
+ 0
+ARC
+ 5
+3E9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+136.4699184679
+ 20
+125.2050130312
+ 30
+0.0
+ 40
+0.1199929925783876
+100
+AcDbArc
+ 50
+179.9985300396
+ 51
+270.0034265556
+ 0
+LINE
+ 5
+3EA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+136.469925644
+ 20
+125.0850200389
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+125.0850200389
+ 31
+0.0
+ 0
+ARC
+ 5
+3EB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.7099328893
+ 20
+125.2050130312
+ 30
+0.0
+ 40
+0.119992992617387
+100
+AcDbArc
+ 50
+269.9963955831
+ 51
+0.0014699527
+ 0
+LINE
+ 5
+3EC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.8299258818
+ 20
+125.2050161097
+ 30
+0.0
+ 11
+148.8299258818
+ 21
+125.9183764193
+ 31
+0.0
+ 0
+ARC
+ 5
+3ED
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.709927865
+ 20
+125.91837716
+ 30
+0.0
+ 40
+0.1199980168837526
+100
+AcDbArc
+ 50
+359.9996463459
+ 51
+53.9732887541
+ 0
+LINE
+ 5
+3EE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7805061807
+ 20
+126.0154247019
+ 30
+0.0
+ 11
+146.6793448498
+ 21
+127.5435447428
+ 31
+0.0
+ 0
+ARC
+ 5
+3EF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.749919111
+ 20
+127.6405897595
+ 30
+0.0
+ 40
+0.1199935898327405
+100
+AcDbArc
+ 50
+179.9984405241
+ 51
+233.9741452813
+ 0
+LINE
+ 5
+3F0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.6299255212
+ 20
+127.6405930255
+ 30
+0.0
+ 11
+146.6299255212
+ 21
+133.3159088824
+ 31
+0.0
+ 0
+ARC
+ 5
+3F1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.5099232936
+ 20
+133.315903341
+ 30
+0.0
+ 40
+0.120002227728508
+100
+AcDbArc
+ 50
+0.0026457597
+ 51
+20.999682824
+ 0
+LINE
+ 5
+3F2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.6219552626
+ 20
+133.3589076731
+ 30
+0.0
+ 11
+146.3471007367
+ 21
+134.0749263499
+ 31
+0.0
+ 0
+ARC
+ 5
+3F3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.2350683839
+ 20
+134.0319208293
+ 30
+0.0
+ 40
+0.1200030119081427
+100
+AcDbArc
+ 50
+21.0001469018
+ 51
+134.9966517297
+ 0
+LINE
+ 5
+3F4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.1502183994
+ 20
+134.1167807315
+ 30
+0.0
+ 11
+144.8336009701
+ 21
+132.8001618121
+ 31
+0.0
+ 0
+ARC
+ 5
+3F5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+144.748758296
+ 20
+132.8850047843
+ 30
+0.0
+ 40
+0.1199858712428317
+100
+AcDbArc
+ 50
+269.995164801
+ 51
+314.9998993415
+ 0
+LINE
+ 5
+3F6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+144.7487481703
+ 20
+132.7650189135
+ 30
+0.0
+ 11
+136.3559723665
+ 21
+132.7650189135
+ 31
+0.0
+ 0
+ARC
+ 5
+3F7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+133.3499200157
+ 20
+124.3450103265
+ 30
+0.0
+ 40
+0.1199960615305855
+100
+AcDbArc
+ 50
+127.9778213362
+ 51
+315.5786816839
+ 0
+ARC
+ 5
+3F8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+133.492770837
+ 20
+124.204971188
+ 30
+0.0
+ 40
+0.0800472312450756
+100
+AcDbArc
+ 50
+90.0117105688
+ 51
+135.5556160835
+ 0
+LINE
+ 5
+3F9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.4927544763
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+ARC
+ 5
+3FA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.1499294027
+ 20
+124.3650139485
+ 30
+0.0
+ 40
+0.0799955310302896
+100
+AcDbArc
+ 50
+269.9971956253
+ 51
+15.9984086718
+ 0
+LINE
+ 5
+3FB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2268266549
+ 20
+124.3870615695
+ 30
+0.0
+ 11
+134.0812475254
+ 21
+124.8947620127
+ 31
+0.0
+ 0
+ARC
+ 5
+3FC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.465753153
+ 20
+125.0050135586
+ 30
+0.0
+ 40
+0.3999999762120172
+100
+AcDbArc
+ 50
+90.0000765526
+ 51
+195.9994948625
+ 0
+LINE
+ 5
+3FD
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.4657526185
+ 20
+125.4050135348
+ 30
+0.0
+ 11
+134.8818720152
+ 21
+125.4050135348
+ 31
+0.0
+ 0
+ARC
+ 5
+3FE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.8818895266
+ 20
+125.0050340998
+ 30
+0.0
+ 40
+0.3999794353998879
+100
+AcDbArc
+ 50
+15.9988052851
+ 51
+90.0025084456
+ 0
+LINE
+ 5
+3FF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+135.2663767358
+ 20
+125.1152753565
+ 30
+0.0
+ 11
+135.3382822891
+ 21
+124.864506695
+ 31
+0.0
+ 0
+ARC
+ 5
+400
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+136.1072824299
+ 20
+125.085006887
+ 30
+0.0
+ 40
+0.7999884694317702
+100
+AcDbArc
+ 50
+195.9995146278
+ 51
+270.000666096
+ 0
+LINE
+ 5
+401
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+136.1072917303
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+144.2699256187
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+ARC
+ 5
+402
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+144.2699168791
+ 20
+124.2050096278
+ 30
+0.0
+ 40
+0.0800087902519152
+100
+AcDbArc
+ 50
+0.0053247404
+ 51
+89.9937414529
+ 0
+LINE
+ 5
+403
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+144.349925669
+ 20
+124.2050170634
+ 30
+0.0
+ 11
+144.349925669
+ 21
+123.9650130007
+ 31
+0.0
+ 0
+ARC
+ 5
+404
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+144.4299341409
+ 20
+123.9650201183
+ 30
+0.0
+ 40
+0.0800084721904046
+100
+AcDbArc
+ 50
+180.0050970011
+ 51
+269.9938357899
+ 0
+LINE
+ 5
+405
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+144.4299255331
+ 20
+123.8850116465
+ 30
+0.0
+ 11
+144.669925498
+ 21
+123.8850116465
+ 31
+0.0
+ 0
+ARC
+ 5
+406
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+144.6699166267
+ 20
+123.9650207543
+ 30
+0.0
+ 40
+0.0800091083155471
+100
+AcDbArc
+ 50
+270.0063528841
+ 51
+359.9944475208
+ 0
+LINE
+ 5
+407
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+144.7499257346
+ 20
+123.9650130007
+ 30
+0.0
+ 11
+144.7499257346
+ 21
+124.2050170634
+ 31
+0.0
+ 0
+ARC
+ 5
+408
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+144.8299342065
+ 20
+124.2050099459
+ 30
+0.0
+ 40
+0.0800084721903386
+100
+AcDbArc
+ 50
+90.00616421
+ 51
+179.9949029989
+ 0
+LINE
+ 5
+409
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+144.8299255987
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+147.7288805713
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+ARC
+ 5
+40A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.7288779357
+ 20
+123.8850159947
+ 30
+0.0
+ 40
+0.4000024229248144
+100
+AcDbArc
+ 50
+345.0003781315
+ 51
+89.9996224743
+ 0
+LINE
+ 5
+40B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.1152512898
+ 20
+123.7814902995
+ 30
+0.0
+ 11
+147.6108663549
+ 21
+121.8991040919
+ 31
+0.0
+ 0
+ARC
+ 5
+40C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.1754788065
+ 20
+122.0157535212
+ 30
+0.0
+ 40
+0.4507431714908194
+100
+AcDbArc
+ 50
+188.9989377763
+ 51
+345.0015117857
+ 0
+LINE
+ 5
+40D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.7302837243
+ 20
+121.9452500079
+ 30
+0.0
+ 11
+146.7030935754
+ 21
+122.1169233058
+ 31
+0.0
+ 0
+ARC
+ 5
+40E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.5055559119
+ 20
+122.0856369716
+ 30
+0.0
+ 40
+0.1999999080912635
+100
+AcDbArc
+ 50
+8.9998420876
+ 51
+161.9998367828
+ 0
+LINE
+ 5
+40F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.3153448721
+ 20
+122.1474408839
+ 30
+0.0
+ 11
+145.8463118245
+ 21
+120.7038998339
+ 31
+0.0
+ 0
+ARC
+ 5
+410
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircleTrace
+ 10
+195.2555696261
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+194.7555696261
+ 21
+394.2202084954
+ 31
+0.0
+ 12
+195.7555696261
+ 22
+394.2202084954
+ 32
+0.0
+ 13
+195.7555696261
+ 23
+394.2202084954
+ 33
+0.0
+ 0
+LINE
+ 5
+554
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+555
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+146.8378589248
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+LINE
+ 5
+556
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.2555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+ENDBLK
+ 5
+551
+330
+54F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+559
+330
+558
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_8
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_8
+ 1
+
+ 0
+SOLID
+ 5
+55B
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+219.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+219.9299255838
+ 21
+31.7821787182
+ 31
+0.0
+ 12
+218.9299255838
+ 22
+31.7821787182
+ 32
+0.0
+ 13
+218.9299255838
+ 23
+31.7821787182
+ 33
+0.0
+ 0
+SOLID
+ 5
+55C
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+219.4299255838
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+218.9299255838
+ 21
+394.2202084954
+ 31
+0.0
+ 12
+219.9299255838
+ 22
+394.2202084954
+ 32
+0.0
+ 13
+219.9299255838
+ 23
+394.2202084954
+ 33
+0.0
+ 0
+LINE
+ 5
+55D
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+143.0299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+220.4299255838
+ 21
+28.7821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+55E
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+146.8378589248
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+220.4299255838
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+LINE
+ 5
+55F
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+219.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+219.4299255838
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+MTEXT
+ 5
+560
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+214.9181886692
+ 20
+211.8228183688
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+Kozijnmaat =
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+55A
+330
+558
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+563
+330
+562
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_9
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_9
+ 1
+
+ 0
+SOLID
+ 5
+565
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+99.2299255838
+ 20
+383.8202084954
+ 30
+0.0
+ 11
+98.7299255838
+ 21
+380.8202084954
+ 31
+0.0
+ 12
+99.7299255838
+ 22
+380.8202084954
+ 32
+0.0
+ 13
+99.7299255838
+ 23
+380.8202084954
+ 33
+0.0
+ 0
+SOLID
+ 5
+566
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+99.2299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+99.7299255838
+ 21
+31.7821787182
+ 31
+0.0
+ 12
+98.7299255838
+ 22
+31.7821787182
+ 32
+0.0
+ 13
+98.7299255838
+ 23
+31.7821787182
+ 33
+0.0
+ 0
+LINE
+ 5
+567
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.4299255838
+ 20
+383.8202084954
+ 30
+0.0
+ 11
+98.2299255838
+ 21
+383.8202084954
+ 31
+0.0
+ 0
+LINE
+ 5
+568
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+141.0299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+98.2299255838
+ 21
+28.7821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+569
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+99.2299255838
+ 20
+383.8202084954
+ 30
+0.0
+ 11
+99.2299255838
+ 21
+28.7821787182
+ 31
+0.0
+ 0
+MTEXT
+ 5
+56B
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+94.7181886692
+ 20
+207.001456174
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+DMH =
+ 7
+SLDTEXTSTYLE1
+ 11
+-7.044195017643634E-15
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+564
+330
+562
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+56E
+330
+56D
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_10
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_10
+ 1
+
+ 0
+SOLID
+ 5
+570
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+147.8850158005
+ 30
+0.0
+ 11
+116.7299255838
+ 21
+144.8850158005
+ 31
+0.0
+ 12
+117.7299255838
+ 22
+144.8850158005
+ 32
+0.0
+ 13
+117.7299255838
+ 23
+144.8850158005
+ 33
+0.0
+ 0
+SOLID
+ 5
+571
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+117.7299255838
+ 21
+151.4450158005
+ 31
+0.0
+ 12
+116.7299255838
+ 22
+151.4450158005
+ 32
+0.0
+ 13
+116.7299255838
+ 23
+151.4450158005
+ 33
+0.0
+ 0
+LINE
+ 5
+572
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+147.8850158005
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+147.8850158005
+ 31
+0.0
+ 0
+LINE
+ 5
+573
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+148.4450158005
+ 31
+0.0
+ 0
+LINE
+ 5
+574
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+147.8850158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+141.8850158005
+ 31
+0.0
+ 0
+LINE
+ 5
+575
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+147.8850158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+148.4450158005
+ 31
+0.0
+ 0
+LINE
+ 5
+576
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+160.0869130071
+ 31
+0.0
+ 0
+MTEXT
+ 5
+577
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+112.7181886692
+ 20
+154.6570518713
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+1
+ 7
+SLDTEXTSTYLE0
+ 11
+-7.044195017643634E-15
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+56F
+330
+56D
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+57A
+330
+579
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_11
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_11
+ 1
+
+ 0
+SOLID
+ 5
+57C
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+224.4267253803
+ 30
+0.0
+ 11
+116.7299255838
+ 21
+221.4267253803
+ 31
+0.0
+ 12
+117.7299255838
+ 22
+221.4267253803
+ 32
+0.0
+ 13
+117.7299255838
+ 23
+221.4267253803
+ 33
+0.0
+ 0
+SOLID
+ 5
+57D
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+117.7299255838
+ 21
+227.9867253803
+ 31
+0.0
+ 12
+116.7299255838
+ 22
+227.9867253803
+ 32
+0.0
+ 13
+116.7299255838
+ 23
+227.9867253803
+ 33
+0.0
+ 0
+LINE
+ 5
+57E
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+224.4267253803
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+224.4267253803
+ 31
+0.0
+ 0
+LINE
+ 5
+57F
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+224.9867253803
+ 31
+0.0
+ 0
+LINE
+ 5
+580
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+224.4267253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+218.4267253803
+ 31
+0.0
+ 0
+LINE
+ 5
+581
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+224.4267253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+224.9867253803
+ 31
+0.0
+ 0
+LINE
+ 5
+582
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+239.2483956684
+ 31
+0.0
+ 0
+MTEXT
+ 5
+583
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+112.7181886692
+ 20
+233.8185345326
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+1
+ 7
+SLDTEXTSTYLE0
+ 11
+-7.044195017643634E-15
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+57B
+330
+579
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+586
+330
+585
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_12
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_12
+ 1
+
+ 0
+SOLID
+ 5
+588
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+301.61905407
+ 30
+0.0
+ 11
+116.7299255838
+ 21
+298.61905407
+ 31
+0.0
+ 12
+117.7299255838
+ 22
+298.61905407
+ 32
+0.0
+ 13
+117.7299255838
+ 23
+298.61905407
+ 33
+0.0
+ 0
+SOLID
+ 5
+589
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+117.7299255838
+ 21
+305.17905407
+ 31
+0.0
+ 12
+116.7299255838
+ 22
+305.17905407
+ 32
+0.0
+ 13
+116.7299255838
+ 23
+305.17905407
+ 33
+0.0
+ 0
+LINE
+ 5
+58A
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+301.61905407
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+301.61905407
+ 31
+0.0
+ 0
+LINE
+ 5
+58B
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+302.17905407
+ 31
+0.0
+ 0
+LINE
+ 5
+58C
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+301.61905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+295.61905407
+ 31
+0.0
+ 0
+LINE
+ 5
+58D
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+301.61905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+302.17905407
+ 31
+0.0
+ 0
+LINE
+ 5
+58E
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+314.5260224873
+ 31
+0.0
+ 0
+MTEXT
+ 5
+58F
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+112.7181886692
+ 20
+309.0961613515
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+1
+ 7
+SLDTEXTSTYLE0
+ 11
+-7.044195017643634E-15
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+587
+330
+585
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+ENDSEC
+ 0
+SECTION
+ 2
+ENTITIES
+ 0
+LINE
+ 5
+4B
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+123.9140543182
+ 20
+383.8493547742
+ 30
+0.0
+ 11
+160.598524565
+ 21
+383.8493547742
+ 31
+0.0
+ 0
+LINE
+ 5
+4C
+330
+1F
+100
+AcDbEntity
+ 8
+STUKLIJST
+100
+AcDbLine
+ 10
+10.3087825773
+ 20
+9.2198227322
+ 30
+0.0
+ 11
+10.3087825773
+ 21
+409.2698227322
+ 31
+0.0
+ 0
+LINE
+ 5
+4D
+330
+1F
+100
+AcDbEntity
+ 8
+STUKLIJST
+100
+AcDbLine
+ 10
+10.3087825773
+ 20
+9.2198227322
+ 30
+0.0
+ 11
+287.198438446
+ 21
+9.2198227322
+ 31
+0.0
+ 0
+LINE
+ 5
+4E
+330
+1F
+100
+AcDbEntity
+ 8
+STUKLIJST
+100
+AcDbLine
+ 10
+287.198438446
+ 20
+409.2698227322
+ 30
+0.0
+ 11
+287.198438446
+ 21
+9.2198227322
+ 31
+0.0
+ 0
+LINE
+ 5
+4F
+330
+1F
+100
+AcDbEntity
+ 8
+STUKLIJST
+100
+AcDbLine
+ 10
+287.198438446
+ 20
+409.2698227322
+ 30
+0.0
+ 11
+10.3087825773
+ 21
+409.2698227322
+ 31
+0.0
+ 0
+LINE
+ 5
+50
+330
+1F
+100
+AcDbEntity
+ 8
+MAATLIJN
+100
+AcDbLine
+ 10
+4.3087825773
+ 20
+3.2198227322
+ 30
+0.0
+ 11
+4.3087825773
+ 21
+415.2698227322
+ 31
+0.0
+ 0
+LINE
+ 5
+51
+330
+1F
+100
+AcDbEntity
+ 8
+MAATLIJN
+100
+AcDbLine
+ 10
+4.3087825773
+ 20
+415.2698227322
+ 30
+0.0
+ 11
+293.4090035115
+ 21
+415.2698227322
+ 31
+0.0
+ 0
+LINE
+ 5
+52
+330
+1F
+100
+AcDbEntity
+ 8
+MAATLIJN
+100
+AcDbLine
+ 10
+293.4090035115
+ 20
+415.2698227322
+ 30
+0.0
+ 11
+293.4090035115
+ 21
+3.2198227322
+ 31
+0.0
+ 0
+LINE
+ 5
+53
+330
+1F
+100
+AcDbEntity
+ 8
+MAATLIJN
+100
+AcDbLine
+ 10
+293.4090035115
+ 20
+3.2198227322
+ 30
+0.0
+ 11
+4.3087825773
+ 21
+3.2198227322
+ 31
+0.0
+ 0
+MTEXT
+ 5
+55
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+211.9617900851
+ 20
+18.9651870984
+ 30
+0.0
+ 40
+4.2333333333
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+Alum. deurblad - 4 secties
+ 7
+SLDTEXTSTYLE0
+ 73
+ 1
+ 44
+1.0
+ 0
+INSERT
+ 5
+59
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+100
+AcDbBlockReference
+ 2
+SW_BROKEN_VIEW_0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 0
+LINE
+ 5
+5A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.9420049658
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+148.9420049658
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1445668807
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+149.1445668807
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.0406432023
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+149.0406432023
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.0406432023
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+148.9420049658
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.9137577285
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.9137577285
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.797846066
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.797846066
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+60
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.6992078294
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.6992078294
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+61
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.797846066
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+133.6992078294
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+62
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.5952848961
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.5952848961
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+ARC
+ 5
+63
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.1879324767
+ 20
+359.1402151319
+ 30
+0.0
+ 40
+0.0799861772139263
+100
+AcDbArc
+ 50
+31.2190407028
+ 51
+90.0049728915
+ 0
+LINE
+ 5
+64
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2563360204
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+149.2563360204
+ 21
+359.1816728664
+ 31
+0.0
+ 0
+LINE
+ 5
+65
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2162960043
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+134.2162960043
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+66
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2162960043
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+67
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.4299252202
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.4299252202
+ 21
+359.1907804561
+ 31
+0.0
+ 0
+ARC
+ 5
+68
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+127.793914781
+ 20
+346.5773729462
+ 30
+0.0
+ 40
+24.8898367051569
+100
+AcDbArc
+ 50
+30.3127339119
+ 51
+30.4217624082
+ 0
+LINE
+ 5
+69
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.3099258115
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+149.3099258115
+ 21
+359.1109102321
+ 31
+0.0
+ 0
+LINE
+ 5
+6A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2563360204
+ 20
+359.1816728664
+ 30
+0.0
+ 11
+149.2569536736
+ 21
+359.1806238247
+ 31
+0.0
+ 0
+LINE
+ 5
+6B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2299253514
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+134.2299253514
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+6C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2299253514
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+134.2162960043
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+6D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.5099256804
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+148.5099256804
+ 21
+358.0259626461
+ 31
+0.0
+ 0
+LINE
+ 5
+6E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.6299254169
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+134.6299254169
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+6F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.6299254169
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+134.2299253514
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+70
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0299256762
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+143.0299256762
+ 21
+353.6202257229
+ 31
+0.0
+ 0
+LINE
+ 5
+71
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0299256762
+ 20
+353.6202257229
+ 30
+0.0
+ 11
+147.3280240615
+ 21
+353.6202257229
+ 31
+0.0
+ 0
+LINE
+ 5
+72
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+147.3280240615
+ 20
+353.6202257229
+ 30
+0.0
+ 11
+147.5545917471
+ 21
+354.4657533718
+ 31
+0.0
+ 0
+LINE
+ 5
+73
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+141.5499255826
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+141.3099255843
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+74
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+138.9099255969
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+134.6299254169
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+ARC
+ 5
+75
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.1595398236
+ 20
+361.9409267861
+ 30
+0.0
+ 40
+0.3992677940247622
+100
+AcDbArc
+ 50
+89.9681903289
+ 51
+114.7477262168
+ 0
+LINE
+ 5
+76
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+137.1597614904
+ 20
+362.3401945186
+ 30
+0.0
+ 11
+139.7899255922
+ 21
+362.3401945186
+ 31
+0.0
+ 0
+ARC
+ 5
+77
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+139.7899227961
+ 20
+361.9401917488
+ 30
+0.0
+ 40
+0.4000027697985571
+100
+AcDbArc
+ 50
+0.0045494665
+ 51
+89.9995994903
+ 0
+LINE
+ 5
+78
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+140.1899255646
+ 20
+361.9402235103
+ 30
+0.0
+ 11
+140.1899255646
+ 21
+360.4202097011
+ 31
+0.0
+ 0
+ARC
+ 5
+79
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+140.5899283325
+ 20
+360.4201937773
+ 30
+0.0
+ 40
+0.4000027681863966
+100
+AcDbArc
+ 50
+179.9977190938
+ 51
+269.999606256
+ 0
+LINE
+ 5
+7A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+140.5899255836
+ 20
+360.0201910091
+ 30
+0.0
+ 11
+142.2699255703
+ 21
+360.0201910091
+ 31
+0.0
+ 0
+ARC
+ 5
+7B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+142.2699229338
+ 20
+360.4201936183
+ 30
+0.0
+ 40
+0.4000026092087915
+100
+AcDbArc
+ 50
+270.0003776416
+ 51
+0.0023036787
+ 0
+LINE
+ 5
+7C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+142.6699255427
+ 20
+360.4202097011
+ 30
+0.0
+ 11
+142.6699255427
+ 21
+361.9402235103
+ 31
+0.0
+ 0
+ARC
+ 5
+7D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.0699283112
+ 20
+361.9401917488
+ 30
+0.0
+ 40
+0.4000027697974622
+100
+AcDbArc
+ 50
+90.0003871694
+ 51
+179.9954505335
+ 0
+LINE
+ 5
+7E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0699256082
+ 20
+362.3401945186
+ 30
+0.0
+ 11
+148.5899255445
+ 21
+362.3401945186
+ 31
+0.0
+ 0
+ARC
+ 5
+7F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5899336175
+ 20
+362.4601862448
+ 30
+0.0
+ 40
+0.1199917263967713
+100
+AcDbArc
+ 50
+269.9961451292
+ 51
+0.0134590356
+ 0
+LINE
+ 5
+80
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+362.4602144314
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+366.669732864
+ 31
+0.0
+ 0
+ARC
+ 5
+81
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+366.669705415
+ 30
+0.0
+ 40
+0.2001077687858761
+100
+AcDbArc
+ 50
+0.0078593224
+ 51
+46.1736252111
+ 0
+ARC
+ 5
+82
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.229892261
+ 20
+367.4202030254
+ 30
+0.0
+ 40
+0.8399663770856335
+100
+AcDbArc
+ 50
+133.8120979057
+ 51
+226.1879020943
+ 0
+ARC
+ 5
+83
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+368.1707006358
+ 30
+0.0
+ 40
+0.200107768785933
+100
+AcDbArc
+ 50
+313.8263747889
+ 51
+359.9921406775
+ 0
+LINE
+ 5
+84
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+368.1706731868
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+370.3305070949
+ 31
+0.0
+ 0
+ARC
+ 5
+85
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5900202217
+ 20
+370.3305234822
+ 30
+0.0
+ 40
+0.1199051200450481
+100
+AcDbArc
+ 50
+359.9921694514
+ 51
+45.0183972297
+ 0
+LINE
+ 5
+86
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.6747787168
+ 20
+370.4153364254
+ 30
+0.0
+ 11
+148.5050731172
+ 21
+370.58504277
+ 31
+0.0
+ 0
+ARC
+ 5
+87
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5900489089
+ 20
+370.6699467703
+ 30
+0.0
+ 40
+0.1201231635795685
+100
+AcDbArc
+ 50
+180.0128717119
+ 51
+224.9757867508
+ 0
+LINE
+ 5
+88
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.4699257483
+ 20
+370.6699197841
+ 30
+0.0
+ 11
+148.4699257483
+ 21
+371.770507629
+ 31
+0.0
+ 0
+ARC
+ 5
+89
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5898274113
+ 20
+371.7705247037
+ 30
+0.0
+ 40
+0.1199016642176248
+100
+AcDbArc
+ 50
+134.9804150373
+ 51
+180.0081592821
+ 0
+LINE
+ 5
+8A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.5050731172
+ 20
+371.8553369594
+ 30
+0.0
+ 11
+148.6747787168
+ 21
+372.025043304
+ 31
+0.0
+ 0
+ARC
+ 5
+8B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5897987133
+ 20
+372.1099479939
+ 30
+0.0
+ 40
+0.1201266304909027
+100
+AcDbArc
+ 50
+315.0254004562
+ 51
+359.9867997393
+ 0
+LINE
+ 5
+8C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+372.1099203182
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+374.2697542263
+ 31
+0.0
+ 0
+ARC
+ 5
+8D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5100322735
+ 20
+374.2697706431
+ 30
+0.0
+ 40
+0.1998930677679371
+100
+AcDbArc
+ 50
+359.9952944114
+ 51
+46.1998513567
+ 0
+ARC
+ 5
+8E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.229948176
+ 20
+375.0202005459
+ 30
+0.0
+ 40
+0.840022291756649
+100
+AcDbArc
+ 50
+133.8137242063
+ 51
+226.1862757937
+ 0
+ARC
+ 5
+8F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5100322233
+ 20
+375.7706304833
+ 30
+0.0
+ 40
+0.1998931275890775
+100
+AcDbArc
+ 50
+313.8001521475
+ 51
+0.018363319
+ 0
+LINE
+ 5
+90
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+375.7706945491
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+392.9185693813
+ 31
+0.0
+ 0
+ARC
+ 5
+91
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.3098818552
+ 20
+392.9185180141
+ 30
+0.0
+ 40
+0.4000434887682899
+100
+AcDbArc
+ 50
+0.0073570038
+ 51
+106.4508778333
+ 0
+ARC
+ 5
+92
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.6299231955
+ 20
+395.2202061714
+ 30
+0.0
+ 40
+1.999979879929223
+100
+AcDbArc
+ 50
+230.0551007785
+ 51
+286.4594915024
+ 0
+ARC
+ 5
+93
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.0888728608
+ 20
+393.3797645665
+ 30
+0.0
+ 40
+0.4004495854783311
+100
+AcDbArc
+ 50
+50.0825069136
+ 51
+89.9794164413
+ 0
+LINE
+ 5
+94
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.0890167227
+ 20
+393.7802141262
+ 30
+0.0
+ 11
+136.7708344778
+ 21
+393.7802141262
+ 31
+0.0
+ 0
+ARC
+ 5
+95
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+136.7709783396
+ 20
+393.3797645665
+ 30
+0.0
+ 40
+0.4004495854783879
+100
+AcDbArc
+ 50
+90.0205835587
+ 51
+129.9174930864
+ 0
+ARC
+ 5
+96
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+135.2299278051
+ 20
+395.220206584
+ 30
+0.0
+ 40
+1.999980324488907
+100
+AcDbArc
+ 50
+253.5405071009
+ 51
+309.9448960222
+ 0
+ARC
+ 5
+97
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.5499689727
+ 20
+392.9185180141
+ 30
+0.0
+ 40
+0.4000434887683444
+100
+AcDbArc
+ 50
+73.5491221667
+ 51
+179.9926429962
+ 0
+LINE
+ 5
+98
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1499254873
+ 20
+392.9185693813
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+361.3064115596
+ 31
+0.0
+ 0
+ARC
+ 5
+99
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.3499114332
+ 20
+361.3063661517
+ 30
+0.0
+ 40
+0.1999859510592641
+100
+AcDbArc
+ 50
+179.9869906558
+ 51
+294.7406415951
+ 0
+LINE
+ 5
+9A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.4336078336
+ 20
+361.1247366024
+ 30
+0.0
+ 11
+136.9923968633
+ 21
+362.3035257412
+ 31
+0.0
+ 0
+ARC
+ 5
+9B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+135.2299441549
+ 20
+395.2202094278
+ 30
+0.0
+ 40
+1.999982807792111
+100
+AcDbArc
+ 50
+346.3277484711
+ 51
+21.510375133
+ 0
+ARC
+ 5
+9C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.3676151968
+ 20
+394.7002149549
+ 30
+0.0
+ 40
+0.2000244053689593
+100
+AcDbArc
+ 50
+166.3324477609
+ 51
+269.9922055192
+ 0
+LINE
+ 5
+9D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+145.4922632148
+ 20
+394.5001905513
+ 30
+0.0
+ 11
+137.3675879856
+ 21
+394.5001905513
+ 31
+0.0
+ 0
+ARC
+ 5
+9E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.4922360036
+ 20
+394.7002149549
+ 30
+0.0
+ 40
+0.2000244053689451
+100
+AcDbArc
+ 50
+270.0077944808
+ 51
+13.6675522392
+ 0
+ARC
+ 5
+9F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.6299070455
+ 20
+395.2202094278
+ 30
+0.0
+ 40
+1.999982807792221
+100
+AcDbArc
+ 50
+158.489624867
+ 51
+193.6722515289
+ 0
+ARC
+ 5
+A0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.3970883777
+ 20
+396.1002000547
+ 30
+0.0
+ 40
+0.3999885893651534
+100
+AcDbArc
+ 50
+338.4905744645
+ 51
+90.0012269037
+ 0
+LINE
+ 5
+A1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.9099256714
+ 20
+396.500188644
+ 30
+0.0
+ 11
+145.3970798125
+ 21
+396.500188644
+ 31
+0.0
+ 0
+ARC
+ 5
+A2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.9099748178
+ 20
+396.5802378337
+ 30
+0.0
+ 40
+0.0800492048011358
+100
+AcDbArc
+ 50
+180.0257061046
+ 51
+269.9648231328
+ 0
+LINE
+ 5
+A3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.8299256211
+ 20
+397.1401994777
+ 30
+0.0
+ 11
+143.8299256211
+ 21
+396.5802019191
+ 31
+0.0
+ 0
+ARC
+ 5
+A4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.9098934092
+ 20
+397.1402449584
+ 30
+0.0
+ 40
+0.0799678010352043
+100
+AcDbArc
+ 50
+89.9768845512
+ 51
+180.0325862115
+ 0
+LINE
+ 5
+A5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+145.8378587683
+ 20
+397.2202127529
+ 30
+0.0
+ 11
+143.9099256714
+ 21
+397.2202127529
+ 31
+0.0
+ 0
+ARC
+ 5
+A6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.8378250788
+ 20
+396.8201414766
+ 30
+0.0
+ 40
+0.4000712776531297
+100
+AcDbArc
+ 50
+35.0061485493
+ 51
+89.9951751956
+ 0
+LINE
+ 5
+A7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.7657630166
+ 20
+396.1923902584
+ 30
+0.0
+ 11
+146.1655196567
+ 21
+397.0496481014
+ 31
+0.0
+ 0
+ARC
+ 5
+A8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.667516349
+ 20
+396.1235761057
+ 30
+0.0
+ 40
+0.1199491362526079
+100
+AcDbArc
+ 50
+316.8039486115
+ 51
+35.0082542764
+ 0
+ARC
+ 5
+A9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.6299254989
+ 20
+395.2202090721
+ 30
+0.0
+ 40
+1.200014262087242
+100
+AcDbArc
+ 50
+136.8133643338
+ 51
+43.1866356662
+ 0
+ARC
+ 5
+AA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5923363035
+ 20
+396.1235762241
+ 30
+0.0
+ 40
+0.1199504236850838
+100
+AcDbArc
+ 50
+144.9922455228
+ 51
+223.1955515893
+ 0
+LINE
+ 5
+AB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1713189354
+ 20
+397.1596067501
+ 30
+0.0
+ 11
+148.4940879812
+ 21
+396.1923902584
+ 31
+0.0
+ 0
+ARC
+ 5
+AC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.2877619365
+ 20
+397.0780497932
+ 30
+0.0
+ 40
+0.1421636723032836
+100
+AcDbArc
+ 50
+0.0071750237
+ 51
+144.9925091982
+ 0
+LINE
+ 5
+AD
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.4299256077
+ 20
+375.5001848293
+ 30
+0.0
+ 11
+149.4299256077
+ 21
+397.078067596
+ 31
+0.0
+ 0
+ARC
+ 5
+AE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484881
+ 20
+375.500185302
+ 30
+0.0
+ 40
+0.3999771195635114
+100
+AcDbArc
+ 50
+292.617691446
+ 51
+359.9999322798
+ 0
+ARC
+ 5
+AF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.2299252955
+ 20
+375.0202005459
+ 30
+0.0
+ 40
+0.1199998892853004
+100
+AcDbArc
+ 50
+112.6196870788
+ 51
+247.3803129212
+ 0
+ARC
+ 5
+B0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484881
+ 20
+374.5402157897
+ 30
+0.0
+ 40
+0.3999771195634261
+100
+AcDbArc
+ 50
+0.0000677202
+ 51
+67.382308554
+ 0
+LINE
+ 5
+B1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.4299256077
+ 20
+371.973878677
+ 30
+0.0
+ 11
+149.4299256077
+ 21
+374.5402162624
+ 31
+0.0
+ 0
+ARC
+ 5
+B2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.3098934127
+ 20
+371.9739249372
+ 30
+0.0
+ 40
+0.1200322038601951
+100
+AcDbArc
+ 50
+284.0483064245
+ 51
+359.9779182862
+ 0
+LINE
+ 5
+B3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2808216085
+ 20
+371.8429391933
+ 30
+0.0
+ 11
+149.3390300145
+ 21
+371.8574827266
+ 31
+0.0
+ 0
+ARC
+ 5
+B4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.309957026
+ 20
+371.7264971484
+ 30
+0.0
+ 40
+0.1200317557485873
+100
+AcDbArc
+ 50
+104.0477772241
+ 51
+180.000758526
+ 0
+LINE
+ 5
+B5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1899252703
+ 20
+370.7138841701
+ 30
+0.0
+ 11
+149.1899252703
+ 21
+371.7264955593
+ 31
+0.0
+ 0
+ARC
+ 5
+B6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.3099570381
+ 20
+370.7139302833
+ 30
+0.0
+ 40
+0.120031776642215
+ 0
+ARC
+ 5
+46F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.3098818552
+ 20
+46.4038720687
+ 30
+0.0
+ 40
+0.4000434887682782
+100
+AcDbArc
+ 50
+253.5491221667
+ 51
+359.9926429962
+ 0
+LINE
+ 5
+470
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+63.5516955336
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+46.4038207015
+ 31
+0.0
+ 0
+ARC
+ 5
+471
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+63.5516680847
+ 30
+0.0
+ 40
+0.2001077687861043
+100
+AcDbArc
+ 50
+0.0078593225
+ 51
+46.1736252111
+ 0
+ARC
+ 5
+472
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.229948176
+ 20
+64.3021895369
+ 30
+0.0
+ 40
+0.8400222917564932
+100
+AcDbArc
+ 50
+133.8137242063
+ 51
+226.1862757937
+ 0
+ARC
+ 5
+473
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5100322735
+ 20
+65.0526194397
+ 30
+0.0
+ 40
+0.1998930677682871
+100
+AcDbArc
+ 50
+313.8001486433
+ 51
+0.0047055886
+ 0
+LINE
+ 5
+474
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+67.2124697646
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+65.0526358565
+ 31
+0.0
+ 0
+ARC
+ 5
+475
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5897987133
+ 20
+67.2124420889
+ 30
+0.0
+ 40
+0.1201266304911527
+100
+AcDbArc
+ 50
+0.0132002608
+ 51
+44.9745995438
+ 0
+LINE
+ 5
+476
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.5050731172
+ 20
+67.4670531234
+ 30
+0.0
+ 11
+148.6747787168
+ 21
+67.2973467788
+ 31
+0.0
+ 0
+ARC
+ 5
+477
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5898274113
+ 20
+67.5518653791
+ 30
+0.0
+ 40
+0.1199016642178358
+100
+AcDbArc
+ 50
+179.9918407179
+ 51
+225.0195849627
+ 0
+LINE
+ 5
+478
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.4699257483
+ 20
+68.6524702987
+ 30
+0.0
+ 11
+148.4699257483
+ 21
+67.5518824538
+ 31
+0.0
+ 0
+ARC
+ 5
+479
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5900489089
+ 20
+68.6524433125
+ 30
+0.0
+ 40
+0.1201231635794379
+100
+AcDbArc
+ 50
+135.0242132492
+ 51
+179.9871282881
+ 0
+LINE
+ 5
+47A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.6747787168
+ 20
+68.9070536574
+ 30
+0.0
+ 11
+148.5050731172
+ 21
+68.7373473128
+ 31
+0.0
+ 0
+ARC
+ 5
+47B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5900202217
+ 20
+68.9918666006
+ 30
+0.0
+ 40
+0.1199051200450481
+100
+AcDbArc
+ 50
+314.9816027702
+ 51
+0.0078305486
+ 0
+LINE
+ 5
+47C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+71.151716896
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+68.9918829879
+ 31
+0.0
+ 0
+ARC
+ 5
+47D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+71.151689447
+ 30
+0.0
+ 40
+0.200107768785911
+100
+AcDbArc
+ 50
+0.0078593225
+ 51
+46.1736252111
+ 0
+ARC
+ 5
+47E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.229892261
+ 20
+71.9021870574
+ 30
+0.0
+ 40
+0.8399663770856326
+100
+AcDbArc
+ 50
+133.8120979057
+ 51
+226.1879020943
+ 0
+ARC
+ 5
+47F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+72.6526846678
+ 30
+0.0
+ 40
+0.200107768785933
+100
+AcDbArc
+ 50
+313.8263747889
+ 51
+359.9921406776
+ 0
+LINE
+ 5
+480
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+76.8621756514
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+72.6526572188
+ 31
+0.0
+ 0
+ARC
+ 5
+481
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5899336175
+ 20
+76.862203838
+ 30
+0.0
+ 40
+0.1199917263968139
+100
+AcDbArc
+ 50
+359.9865409644
+ 51
+90.0038548708
+ 0
+LINE
+ 5
+482
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0699256082
+ 20
+76.9821955642
+ 30
+0.0
+ 11
+148.5899255445
+ 21
+76.9821955642
+ 31
+0.0
+ 0
+ARC
+ 5
+483
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.0699283112
+ 20
+77.382198334
+ 30
+0.0
+ 40
+0.4000027697974338
+100
+AcDbArc
+ 50
+180.0045494665
+ 51
+269.9996128306
+ 0
+LINE
+ 5
+484
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+142.6699255427
+ 20
+78.9021803817
+ 30
+0.0
+ 11
+142.6699255427
+ 21
+77.3821665725
+ 31
+0.0
+ 0
+ARC
+ 5
+485
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+142.2699229338
+ 20
+78.9021964645
+ 30
+0.0
+ 40
+0.4000026092089052
+100
+AcDbArc
+ 50
+359.9976963213
+ 51
+89.9996223584
+ 0
+LINE
+ 5
+486
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+140.5899255836
+ 20
+79.3021990737
+ 30
+0.0
+ 11
+142.2699255703
+ 21
+79.3021990737
+ 31
+0.0
+ 0
+ARC
+ 5
+487
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+140.5899283325
+ 20
+78.9021963055
+ 30
+0.0
+ 40
+0.4000027681864251
+100
+AcDbArc
+ 50
+90.000393744
+ 51
+180.0022809062
+ 0
+LINE
+ 5
+488
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+140.1899255646
+ 20
+77.3821665725
+ 30
+0.0
+ 11
+140.1899255646
+ 21
+78.9021803817
+ 31
+0.0
+ 0
+ARC
+ 5
+489
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+139.7899227961
+ 20
+77.382198334
+ 30
+0.0
+ 40
+0.400002769798557
+100
+AcDbArc
+ 50
+270.0004005097
+ 51
+359.9954505335
+ 0
+LINE
+ 5
+48A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+137.1597614904
+ 20
+76.9821955642
+ 30
+0.0
+ 11
+139.7899255922
+ 21
+76.9821955642
+ 31
+0.0
+ 0
+ARC
+ 5
+48B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.1595398236
+ 20
+77.3814632967
+ 30
+0.0
+ 40
+0.3992677940260214
+100
+AcDbArc
+ 50
+245.2522737832
+ 51
+270.0318096711
+ 0
+LINE
+ 5
+48C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.4336078336
+ 20
+78.1976534804
+ 30
+0.0
+ 11
+136.9923968633
+ 21
+77.0188643416
+ 31
+0.0
+ 0
+ARC
+ 5
+48D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.3499584368
+ 20
+78.0159505357
+ 30
+0.0
+ 40
+0.2000329515294041
+100
+AcDbArc
+ 50
+65.2803842384
+ 51
+179.9919835107
+ 0
+LINE
+ 5
+48E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+137.4627713879
+ 20
+42.8222014388
+ 30
+0.0
+ 11
+138.949925529
+ 21
+42.8222014388
+ 31
+0.0
+ 0
+ARC
+ 5
+48F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+138.9498760641
+ 20
+42.7421519306
+ 30
+0.0
+ 40
+0.0800495234356318
+100
+AcDbArc
+ 50
+0.0259339259
+ 51
+89.9645953115
+ 0
+LINE
+ 5
+490
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+139.0299255793
+ 20
+42.7421881637
+ 30
+0.0
+ 11
+139.0299255793
+ 21
+42.1821906051
+ 31
+0.0
+ 0
+ARC
+ 5
+491
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+138.9499574737
+ 20
+42.182145442
+ 30
+0.0
+ 40
+0.0799681184311334
+100
+AcDbArc
+ 50
+269.9771121806
+ 51
+0.032358582
+ 0
+LINE
+ 5
+492
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+138.949925529
+ 20
+42.1021773299
+ 30
+0.0
+ 11
+137.0219920596
+ 21
+42.1021773299
+ 31
+0.0
+ 0
+ARC
+ 5
+493
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.0220261217
+ 20
+42.5022486063
+ 30
+0.0
+ 40
+0.400071277792755
+100
+AcDbArc
+ 50
+215.0061485542
+ 51
+269.9951218307
+ 0
+LINE
+ 5
+494
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+136.6943315437
+ 20
+42.2727419814
+ 30
+0.0
+ 11
+136.0940881839
+ 21
+43.1299998244
+ 31
+0.0
+ 0
+ARC
+ 5
+495
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+136.1923348514
+ 20
+43.1988139771
+ 30
+0.0
+ 40
+0.1199491362525765
+100
+AcDbArc
+ 50
+136.8039486115
+ 51
+215.0082542764
+ 0
+ARC
+ 5
+496
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+135.2299255153
+ 20
+44.1021809094
+ 30
+0.0
+ 40
+1.20001432860059
+100
+AcDbArc
+ 50
+316.8133739453
+ 51
+223.1866260547
+ 0
+ARC
+ 5
+497
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.2675178339
+ 20
+43.1988140955
+ 30
+0.0
+ 40
+0.1199478488608696
+100
+AcDbArc
+ 50
+324.9912459259
+ 51
+43.1965511861
+ 0
+LINE
+ 5
+498
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.3657628467
+ 20
+43.1299998244
+ 30
+0.0
+ 11
+133.6885318925
+ 21
+42.1627833327
+ 31
+0.0
+ 0
+ARC
+ 5
+499
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+133.5720888914
+ 20
+42.2443402896
+ 30
+0.0
+ 40
+0.1421636723032335
+100
+AcDbArc
+ 50
+180.0071750236
+ 51
+324.9925091983
+ 0
+LINE
+ 5
+49A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.4299252202
+ 20
+42.2443224868
+ 30
+0.0
+ 11
+133.4299252202
+ 21
+79.6323134383
+ 31
+0.0
+ 0
+ARC
+ 5
+49B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+133.0298319476
+ 20
+79.6322623339
+ 30
+0.0
+ 40
+0.4000932758665615
+100
+AcDbArc
+ 50
+0.0073184602
+ 51
+52.0135000174
+ 0
+ARC
+ 5
+49C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+133.3499255703
+ 20
+80.0421799816
+ 30
+0.0
+ 40
+0.1199955680613621
+100
+AcDbArc
+ 50
+44.424867041
+ 51
+232.0186299389
+ 0
+ARC
+ 5
+49D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+133.4927816435
+ 20
+80.1822896055
+ 30
+0.0
+ 40
+0.080100836150903
+100
+AcDbArc
+ 50
+224.4724320243
+ 51
+269.9805674286
+ 0
+LINE
+ 5
+49E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.4927544763
+ 20
+80.102188774
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+80.102188774
+ 31
+0.0
+ 0
+ARC
+ 5
+49F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.1499294027
+ 20
+80.0221932431
+ 30
+0.0
+ 40
+0.0799955310303124
+100
+AcDbArc
+ 50
+344.0015913282
+ 51
+90.0028043747
+ 0
+LINE
+ 5
+4A0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2268266549
+ 20
+80.0001456221
+ 30
+0.0
+ 11
+134.042500781
+ 21
+79.3573214492
+ 31
+0.0
+ 0
+ARC
+ 5
+4A1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.2347360924
+ 20
+79.3021720325
+ 30
+0.0
+ 40
+0.1999896824440735
+100
+AcDbArc
+ 50
+163.9926116413
+ 51
+245.2696135787
+ 0
+LINE
+ 5
+4A2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1510706415
+ 20
+79.1205241164
+ 30
+0.0
+ 11
+137.1502664705
+ 21
+77.7388884505
+ 31
+0.0
+ 0
+ARC
+ 5
+4A3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.317737162
+ 20
+78.1024627412
+ 30
+0.0
+ 40
+0.4002907660301162
+100
+AcDbArc
+ 50
+245.2681140451
+ 51
+269.98476511
+ 0
+LINE
+ 5
+4A4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+137.3176307251
+ 20
+77.7021719893
+ 30
+0.0
+ 11
+139.1499255618
+ 21
+77.7021719893
+ 31
+0.0
+ 0
+ARC
+ 5
+4A5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+139.1499227005
+ 20
+78.1021749165
+ 30
+0.0
+ 40
+0.4000029271641257
+100
+AcDbArc
+ 50
+270.0004098464
+ 51
+0.0022581337
+ 0
+LINE
+ 5
+4A6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+139.5499256273
+ 20
+78.1021906814
+ 30
+0.0
+ 11
+139.5499256273
+ 21
+78.9021803817
+ 31
+0.0
+ 0
+ARC
+ 5
+4A7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+139.1499227005
+ 20
+78.9021961465
+ 30
+0.0
+ 40
+0.4000029271641541
+100
+AcDbArc
+ 50
+359.9977418663
+ 51
+89.9995901536
+ 0
+LINE
+ 5
+4A8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+139.1499255618
+ 20
+79.3021990737
+ 30
+0.0
+ 11
+138.9099255969
+ 21
+79.3021990737
+ 31
+0.0
+ 0
+ARC
+ 5
+4A9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+138.9099203808
+ 20
+79.7021939238
+ 30
+0.0
+ 40
+0.3999948501927155
+100
+AcDbArc
+ 50
+89.9992528415
+ 51
+270.0007471585
+ 0
+LINE
+ 5
+4AA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+138.9099255969
+ 20
+80.102188774
+ 30
+0.0
+ 11
+141.3099255843
+ 21
+80.102188774
+ 31
+0.0
+ 0
+ARC
+ 5
+4AB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+141.4299255835
+ 20
+80.1021688621
+ 30
+0.0
+ 40
+0.1200000008033507
+100
+AcDbArc
+ 50
+179.9904927603
+ 51
+0.0095072397
+ 0
+LINE
+ 5
+4AC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+141.5499255826
+ 20
+80.102188774
+ 30
+0.0
+ 11
+144.2299255004
+ 21
+80.102188774
+ 31
+0.0
+ 0
+ARC
+ 5
+4AD
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+144.2299329932
+ 20
+80.2221814513
+ 30
+0.0
+ 40
+0.1199926775530223
+100
+AcDbArc
+ 50
+269.9964221996
+ 51
+359.9902360528
+ 0
+LINE
+ 5
+4AE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+144.349925669
+ 20
+80.222161003
+ 30
+0.0
+ 11
+144.349925669
+ 21
+80.3821875533
+ 31
+0.0
+ 0
+ARC
+ 5
+4AF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+144.4699183448
+ 20
+80.382167105
+ 30
+0.0
+ 40
+0.1199926775144228
+100
+AcDbArc
+ 50
+89.9966000615
+ 51
+179.9902360605
+ 0
+LINE
+ 5
+4B0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 99255659
+ 21
+158.8450193141
+ 31
+0.0
+ 0
+ARC
+ 5
+366
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+144.629912391
+ 20
+158.7250059711
+ 30
+0.0
+ 40
+0.1200133437027802
+100
+AcDbArc
+ 50
+0.0025547204
+ 51
+89.9937101469
+ 0
+LINE
+ 5
+367
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+144.7499257346
+ 20
+158.7250113223
+ 30
+0.0
+ 11
+144.7499257346
+ 21
+158.445012543
+ 31
+0.0
+ 0
+ARC
+ 5
+368
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.9499198813
+ 20
+158.445016775
+ 30
+0.0
+ 40
+0.8000058532867297
+100
+AcDbArc
+ 50
+270.0004098155
+ 51
+359.9996969061
+ 0
+LINE
+ 5
+369
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.9499256035
+ 20
+157.6450109217
+ 30
+0.0
+ 11
+143.7099256386
+ 21
+157.6450109217
+ 31
+0.0
+ 0
+ARC
+ 5
+36A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.7099078321
+ 20
+157.2450286629
+ 30
+0.0
+ 40
+0.3999822592042693
+100
+AcDbArc
+ 50
+89.9974492852
+ 51
+180.0018036581
+ 0
+LINE
+ 5
+36B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.3099255731
+ 20
+157.2450160716
+ 30
+0.0
+ 11
+143.3099255731
+ 21
+156.4450144503
+ 31
+0.0
+ 0
+ARC
+ 5
+36C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.7099281818
+ 20
+156.4450222089
+ 30
+0.0
+ 40
+0.4000026087843038
+100
+AcDbArc
+ 50
+180.0011113328
+ 51
+269.9996357238
+ 0
+LINE
+ 5
+36D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.7099256386
+ 20
+156.0450196002
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+156.0450196002
+ 31
+0.0
+ 0
+ARC
+ 5
+36E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.7099328893
+ 20
+156.1650125925
+ 30
+0.0
+ 40
+0.1199929926174386
+100
+AcDbArc
+ 50
+269.9963955831
+ 51
+0.0014699526
+ 0
+LINE
+ 5
+36F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.8299258818
+ 20
+156.165015671
+ 30
+0.0
+ 11
+148.8299258818
+ 21
+157.5693249438
+ 31
+0.0
+ 0
+ARC
+ 5
+370
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.7098943691
+ 20
+157.569311977
+ 30
+0.0
+ 40
+0.1200315134707315
+100
+AcDbArc
+ 50
+0.0061895736
+ 51
+64.4733233418
+ 0
+LINE
+ 5
+371
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.761619704
+ 20
+157.6776265834
+ 30
+0.0
+ 11
+148.4608449807
+ 21
+157.8211903308
+ 31
+0.0
+ 0
+ARC
+ 5
+372
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5125576602
+ 20
+157.9295010743
+ 30
+0.0
+ 40
+0.1200225744513657
+100
+AcDbArc
+ 50
+195.0053952559
+ 51
+244.4779803301
+ 0
+LINE
+ 5
+373
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.3966276815
+ 20
+157.8984260295
+ 30
+0.0
+ 11
+147.6108663549
+ 21
+160.8309268687
+ 31
+0.0
+ 0
+ARC
+ 5
+374
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.1754788065
+ 20
+160.7142774394
+ 30
+0.0
+ 40
+0.4507431714908047
+100
+AcDbArc
+ 50
+14.9984882143
+ 51
+171.0010622237
+ 0
+LINE
+ 5
+375
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.7302837243
+ 20
+160.7847809527
+ 30
+0.0
+ 11
+146.7030935754
+ 21
+160.6131076548
+ 31
+0.0
+ 0
+ARC
+ 5
+376
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.5055559119
+ 20
+160.644393989
+ 30
+0.0
+ 40
+0.1999999080912547
+100
+AcDbArc
+ 50
+198.0001632172
+ 51
+351.0001579124
+ 0
+LINE
+ 5
+377
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.3153448721
+ 20
+160.5825900767
+ 30
+0.0
+ 11
+145.8463118245
+ 21
+162.0261311267
+ 31
+0.0
+ 0
+ARC
+ 5
+378
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.1506496208
+ 20
+162.1250192095
+ 30
+0.0
+ 40
+0.3200005424109761
+100
+AcDbArc
+ 50
+23.0000921291
+ 51
+198.0004663253
+ 0
+LINE
+ 5
+379
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.4452114721
+ 20
+162.2500538562
+ 30
+0.0
+ 11
+146.5646275153
+ 21
+161.9687199328
+ 31
+0.0
+ 0
+ARC
+ 5
+37A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.9328278996
+ 20
+162.1250205588
+ 30
+0.0
+ 40
+0.4000017608535774
+100
+AcDbArc
+ 50
+203.0011649826
+ 51
+14.9999803862
+ 0
+LINE
+ 5
+37B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+147.3191999664
+ 20
+162.2285485003
+ 30
+0.0
+ 11
+147.1380212178
+ 21
+162.9047155116
+ 31
+0.0
+ 0
+ARC
+ 5
+37C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.2539203196
+ 20
+162.9357712365
+ 30
+0.0
+ 40
+0.1199877487818145
+100
+AcDbArc
+ 50
+127.997310757
+ 51
+195.0003017269
+ 0
+LINE
+ 5
+37D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+147.1800529232
+ 20
+163.03032634
+ 30
+0.0
+ 11
+147.4331305196
+ 21
+163.2280587886
+ 31
+0.0
+ 0
+ARC
+ 5
+37E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.482384254
+ 20
+163.1650243775
+ 30
+0.0
+ 40
+0.0799954206548413
+100
+AcDbArc
+ 50
+14.9903109854
+ 51
+128.0033046167
+ 0
+LINE
+ 5
+37F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+147.5596573969
+ 20
+163.1857156489
+ 30
+0.0
+ 11
+148.8140375187
+ 21
+158.5043072436
+ 31
+0.0
+ 0
+ARC
+ 5
+380
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.8913172899
+ 20
+158.5250198997
+ 30
+0.0
+ 40
+0.0800073569232727
+100
+AcDbArc
+ 50
+195.0038763407
+ 51
+269.9961833848
+ 0
+LINE
+ 5
+381
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1546171179
+ 20
+157.4790596697
+ 30
+0.0
+ 11
+137.2058146467
+ 21
+156.0562610362
+ 31
+0.0
+ 0
+LINE
+ 5
+382
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7197578718
+ 20
+138.1291627619
+ 30
+0.0
+ 11
+148.1495865454
+ 21
+138.0822777484
+ 31
+0.0
+ 0
+ARC
+ 5
+383
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.7099336428
+ 20
+138.2487521509
+ 30
+0.0
+ 40
+0.1199922390625343
+100
+AcDbArc
+ 50
+274.6962840302
+ 51
+0.000654307
+ 0
+LINE
+ 5
+384
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.8299258818
+ 20
+155.2850126956
+ 30
+0.0
+ 11
+148.8299258818
+ 21
+138.2487535212
+ 31
+0.0
+ 0
+ARC
+ 5
+385
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.7099125383
+ 20
+155.2850073444
+ 30
+0.0
+ 40
+0.1200133436339415
+100
+AcDbArc
+ 50
+0.0025547068
+ 51
+89.9938880295
+ 0
+LINE
+ 5
+386
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0699256082
+ 20
+155.4050206874
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+155.4050206874
+ 31
+0.0
+ 0
+ARC
+ 5
+387
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.0699079607
+ 20
+155.8050031051
+ 30
+0.0
+ 40
+0.3999824181675279
+100
+AcDbArc
+ 50
+179.9982191144
+ 51
+270.0025279423
+ 0
+LINE
+ 5
+388
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+142.6699255427
+ 20
+157.2450160716
+ 30
+0.0
+ 11
+142.6699255427
+ 21
+155.8050155375
+ 31
+0.0
+ 0
+ARC
+ 5
+389
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+142.2699432837
+ 20
+157.2450286629
+ 30
+0.0
+ 40
+0.3999822591972353
+100
+AcDbArc
+ 50
+359.9981963414
+ 51
+90.002537375
+ 0
+LINE
+ 5
+38A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+141.7499255688
+ 20
+157.6450109217
+ 30
+0.0
+ 11
+142.2699255703
+ 21
+157.6450109217
+ 31
+0.0
+ 0
+ARC
+ 5
+38B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+141.6299255748
+ 20
+157.645014845
+ 30
+0.0
+ 40
+0.1199999941223236
+100
+AcDbArc
+ 50
+180.001873219
+ 51
+359.998126781
+ 0
+LINE
+ 5
+38C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+141.3499255833
+ 20
+157.6450109217
+ 30
+0.0
+ 11
+141.5099255807
+ 21
+157.6450109217
+ 31
+0.0
+ 0
+ARC
+ 5
+38D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+141.2299255842
+ 20
+157.6450148501
+ 30
+0.0
+ 40
+0.1199999992156321
+100
+AcDbArc
+ 50
+180.0018756508
+ 51
+359.9981243492
+ 0
+LINE
+ 5
+38E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+140.5899255836
+ 20
+157.6450109217
+ 30
+0.0
+ 11
+141.109925585
+ 21
+157.6450109217
+ 31
+0.0
+ 0
+ARC
+ 5
+38F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+140.5899079826
+ 20
+157.245028504
+ 30
+0.0
+ 40
+0.3999824181641026
+100
+AcDbArc
+ 50
+89.9974787276
+ 51
+180.0017808858
+ 0
+LINE
+ 5
+390
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+140.1899255646
+ 20
+155.8050155375
+ 30
+0.0
+ 11
+140.1899255646
+ 21
+157.2450160716
+ 31
+0.0
+ 0
+ARC
+ 5
+391
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+139.7899431466
+ 20
+155.8050031051
+ 30
+0.0
+ 40
+0.3999824181605363
+100
+AcDbArc
+ 50
+269.9974853975
+ 51
+0.001780886
+ 0
+LINE
+ 5
+392
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2699252834
+ 20
+155.4050206874
+ 30
+0.0
+ 11
+139.7899255922
+ 21
+155.4050206874
+ 31
+0.0
+ 0
+ARC
+ 5
+393
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.2699388309
+ 20
+155.2850073443
+ 30
+0.0
+ 40
+0.1200133437736084
+100
+AcDbArc
+ 50
+90.0064677366
+ 51
+179.9974452656
+ 0
+LINE
+ 5
+394
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1499254873
+ 20
+154.7275066111
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+155.2850126956
+ 31
+0.0
+ 0
+ARC
+ 5
+395
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.2699407901
+ 20
+154.7275112492
+ 30
+0.0
+ 40
+0.1200153029849757
+100
+AcDbArc
+ 50
+180.0022142501
+ 51
+218.9973251432
+ 0
+LINE
+ 5
+396
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.4031833877
+ 20
+154.3722629283
+ 30
+0.0
+ 11
+134.1766678562
+ 21
+154.6519875262
+ 31
+0.0
+ 0
+ARC
+ 5
+397
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.3099758432
+ 20
+154.2967623625
+ 30
+0.0
+ 40
+0.1199499136121352
+100
+AcDbArc
+ 50
+359.99684824
+ 51
+39.0083836716
+ 0
+LINE
+ 5
+398
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.4299257567
+ 20
+150.296747658
+ 30
+0.0
+ 11
+134.4299257567
+ 21
+154.2967557643
+ 31
+0.0
+ 0
+ARC
+ 5
+399
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.3099104538
+ 20
+150.2967522961
+ 30
+0.0
+ 40
+0.12001530298499
+100
+AcDbArc
+ 50
+321.0026748568
+ 51
+359.9977857498
+ 0
+LINE
+ 5
+39A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1766678562
+ 20
+149.9415039752
+ 30
+0.0
+ 11
+134.4031833877
+ 21
+150.2212285731
+ 31
+0.0
+ 0
+ARC
+ 5
+39B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.2698754103
+ 20
+149.8660034041
+ 30
+0.0
+ 40
+0.1199499244803327
+100
+AcDbArc
+ 50
+140.9916172207
+ 51
+180.0088433859
+ 0
+LINE
+ 5
+39C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.1499254873
+ 20
+149.1650104258
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+149.8659848902
+ 31
+0.0
+ 0
+ARC
+ 5
+39D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+134.2699184798
+ 20
+149.1650073473
+ 30
+0.0
+ 40
+0.1199929925413281
+100
+AcDbArc
+ 50
+179.9985300323
+ 51
+270.0032486934
+ 0
+LINE
+ 5
+39E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.9420049658
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+148.9420049658
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+39F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1445668807
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+149.1445668807
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3A0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.0406432023
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+149.0406432023
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3A1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.0406432023
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+148.9420049658
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3A2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.9137577285
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+133.9137577285
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3A3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.797846066
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+133.797846066
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3A4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.6992078294
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+133.6992078294
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3A5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.797846066
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+133.6992078294
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3A6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.5952848961
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+133.5952848961
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+ARC
+ 5
+3A7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.1879091276
+ 20
+124.2049907824
+ 30
+0.0
+ 40
+0.0800276369171186
+100
+AcDbArc
+ 50
+31.2357600789
+ 51
+89.9882535152
+ 0
+LINE
+ 5
+3A8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2563360204
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+149.2563360204
+ 21
+124.2464899752
+ 31
+0.0
+ 0
+LINE
+ 5
+3A9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2162960043
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+134.2162960043
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3AA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2162960043
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3AB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.4299252202
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+133.4299252202
+ 21
+124.2555737231
+ 31
+0.0
+ 0
+LWPOLYLINE
+ 5
+3AC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbPolyline
+ 90
+ 4
+ 70
+ 128
+ 43
+0.0
+ 10
+149.2569536736
+ 20
+124.2454528544
+ 10
+149.2656842639
+ 20
+124.2305516932
+ 10
+149.2736712863
+ 20
+124.2169141505
+ 10
+149.2808976044
+ 20
+124.204575989
+ 0
+LINE
+ 5
+3AD
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.3099258115
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+149.3099258115
+ 21
+124.1757392619
+ 31
+0.0
+ 0
+LINE
+ 5
+3AE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2563360204
+ 20
+124.2464899752
+ 30
+0.0
+ 11
+149.2569536736
+ 21
+124.2454528544
+ 31
+0.0
+ 0
+LINE
+ 5
+3AF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2299253514
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+134.2299253514
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3B0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2299253514
+ 20
+124.2850184176
+ 30
+0.0
+ 11
+134.2162960043
+ 21
+124.2850184176
+ 31
+0.0
+ 0
+LINE
+ 5
+3B1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.5099256804
+ 20
+105.7777046893
+ 30
+0.0
+ 11
+148.5099256804
+ 21
+123.090755913
+ 31
+0.0
+ 0
+LINE
+ 5
+3B2 5
+4FF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+133.4299255838
+ 20
+660.3011936068
+ 30
+0.0
+ 0
+DIMENSION
+ 5
+500
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+34.5771309945
+ 31
+0.0
+ 70
+ 160
+ 1
+33
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE0
+100
+AcDbAlignedDimension
+ 13
+142.0299255838
+ 23
+28.7821787182
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+41.9821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+50D
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_1
+ 10
+171.4299255838
+ 20
+287.499722104
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+271.6850735678
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+280.0124004364
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+287.499722104
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+51A
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_2
+ 10
+171.4299255838
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+194.8678981433
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+202.8200717467
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+210.3073934143
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+526
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_3
+ 10
+171.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+113.1236101725
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+126.2783621669
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+133.7256838344
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+532
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_4
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+84.1586135498
+ 31
+0.0
+ 70
+ 160
+ 1
+675,902
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+148.0299255838
+ 23
+133.7256838344
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+41.9821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+53C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_5
+ 10
+195.3191971725
+ 20
+133.7649839595
+ 30
+0.0
+ 11
+195.2817915125
+ 21
+178.7746730971
+ 31
+0.0
+ 70
+ 160
+ 1
+524,500
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+210.3073934143
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+133.7256838344
+ 34
+0.0
+ 50
+-89.9523838979
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+545
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_6
+ 10
+195.2555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+246.0726158741
+ 31
+0.0
+ 70
+ 160
+ 1
+524,400
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+287.499722104
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+210.3073934143
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+54E
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_7
+ 10
+195.2555696261
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+357.7845521004
+ 31
+0.0
+ 70
+ 160
+ 1
+545,698
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+287.499722104
+ 33
+0.0
+ 14
+145.8378589248
+ 24
+397.2202084954
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+557
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_8
+ 10
+219.4299255838
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+219.4299255838
+ 21
+226.31135989
+ 31
+0.0
+ 70
+ 160
+ 1
+Kozijnmaat =
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+142.0299255838
+ 23
+28.7821787182
+ 33
+0.0
+ 14
+145.8378589248
+ 24
+397.2202084954
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+561
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_9
+ 10
+99.2299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+99.2299255838
+ 21
+214.5361780403
+ 31
+0.0
+ 70
+ 160
+ 1
+DMH =
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+133.4299255838
+ 23
+383.8202084954
+ 33
+0.0
+ 14
+142.0299255838
+ 24
+28.7821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+56C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_10
+ 10
+117.2299255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+157.3719824392
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+147.8850158005
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+148.4450158005
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+578
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_11
+ 10
+117.2299255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+236.5334651005
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+224.4267253803
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+224.9867253803
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+584
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_12
+ 10
+117.2299255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+311.8110919194
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+301.61905407
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+302.17905407
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+LINE
+ 5
+590
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+591
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+592
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+593
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+101.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+594
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+101.7777066237
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+595
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+596
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+597
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+107.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+598
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+107.7777066237
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+599
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59A
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59B
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59D
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59E
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59F
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 31
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+177.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A0
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+177.2366515846
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A1
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A2
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A3
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+183.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A4
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+183.2366515846
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A5
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A6
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A7
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A8
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5A9
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AA
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AB
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+254.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AC
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+254.4750445598
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AD
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AE
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+260.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B0
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+260.4750445598
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B1
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B2
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B3
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B4
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B5
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B6
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B7
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+332.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B8
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+332.7369117996
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B9
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BA
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BB
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+338.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BC
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+338.7369117996
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BD
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BE
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+ENDSEC
+ 0
+SECTION
+ 2
+OBJECTS
+ 0
+DICTIONARY
+ 5
+C
+330
+0
+100
+AcDbDictionary
+281
+ 1
+ 3
+ACAD_GROUP
+350
+D
+ 3
+ACAD_LAYOUT
+350
+1A
+ 3
+ACAD_MLINESTYLE
+350
+17
+ 3
+ACAD_PLOTSETTINGS
+350
+19
+ 3
+ACAD_PLOTSTYLENAME
+350
+E
+ 0
+DICTIONARY
+ 5
+D
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 0
+DICTIONARY
+ 5
+1A
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 3
+Layout1
+350
+1E
+ 3
+Layout2
+350
+26
+ 3
+Model
+350
+22
+ 0
+DICTIONARY
+ 5
+17
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 3
+Standard
+350
+18
+ 0
+DICTIONARY
+ 5
+19
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 0
+ACDBDICTIONARYWDFLT
+ 5
+E
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 3
+Normal
+350
+F
+100
+AcDbDictionaryWithDefault
+340
+F
+ 0
+LAYOUT
+ 5
+1E
+102
+{ACAD_REACTORS
+330
+1A
+102
+}
+330
+1A
+100
+AcDbPlotSettings
+ 1
+
+ 2
+none_device
+ 4
+
+ 6
+
+ 40
+0.0
+ 41
+0.0
+ 42
+0.0
+ 43
+0.0
+ 44
+0.0
+ 45
+0.0
+ 46
+0.0
+ 47
+0.0
+ 48
+0.0
+ 49
+0.0
+140
+0.0
+141
+0.0
+142
+1.0
+143
+1.0
+ 70
+ 688
+ 72
+ 0
+ 73
+ 0
+ 74
+ 5
+ 7
+
+ 75
+ 16
+147
+1.0
+148
+0.0
+149
+0.0
+100
+AcDbLayout
+ 1
+Layout1
+ 70
+ 1
+ 71
+ 1
+ 10
+0.0
+ 20
+0.0
+ 11
+420.0
+ 21
+297.0
+ 12
+0.0
+ 22
+0.0
+ 32
+0.0
+ 14
+1.0000000000E+20
+ 24
+1.0000000000E+20
+ 34
+1.0000000000E+20
+ 15
+-1.0000000000E+20
+ 25
+-1.0000000000E+20
+ 35
+-1.0000000000E+20
+146
+0.0
+ 13
+0.0
+ 23
+0.0
+ 33
+0.0
+ 16
+1.0
+ 26
+0.0
+ 36
+0.0
+ 17
+0.0
+ 27
+1.0
+ 37
+0.0
+ 76
+ 0
+330
+1B
+ 0
+LAYOUT
+ 5
+26
+102
+{ACAD_REACTORS
+330
+1A
+102
+}
+330
+1A
+100
+AcDbPlotSettings
+ 1
+
+ 2
+none_device
+ 4
+
+ 6
+
+ 40
+0.0
+ 41
+0.0
+ 42
+0.0
+ 43
+0.0
+ 44
+0.0
+ 45
+0.0
+ 46
+0.0
+ 47
+0.0
+ 48
+0.0
+ 49
+0.0
+140
+0.0
+141
+0.0
+142
+1.0
+143
+1.0
+ 70
+ 688
+ 72
+ 0
+ 73
+ 0
+ 74
+ 5
+ 7
+
+ 75
+ 16
+147
+1.0
+148
+0.0
+149
+0.0
+100
+AcDbLayout
+ 1
+Layout2
+ 70
+ 1
+ 71
+ 2
+ 10
+0.0
+ 20
+0.0
+ 11
+0.0
+ 21
+0.0
+ 12
+0.0
+ 22
+0.0
+ 32
+0.0
+ 14
+0.0
+ 24
+0.0
+ 34
+0.0
+ 15
+0.0
+ 25
+0.0
+ 35
+0.0
+146
+0.0
+ 13
+0.0
+ 23
+0.0
+ 33
+0.0
+ 16
+1.0
+ 26
+0.0
+ 36
+0.0
+ 17
+0.0
+ 27
+1.0
+ 37
+0.0
+ 76
+ 0
+330
+23
+ 0
+LAYOUT
+ 5
+22
+102
+{ACAD_REACTORS
+330
+1A
+102
+}
+330
+1A
+100
+AcDbPlotSettings
+ 1
+
+ 2
+none_device
+ 4
+
+ 6
+
+ 40
+0.0
+ 41
+0.0
+ 42
+0.0
+ 43
+0.0
+ 44
+0.0
+ 45
+0.0
+ 46
+0.0
+ 47
+0.0
+ 48
+0.0
+ 49
+0.0
+140
+0.0
+141
+0.0
+142
+1.0
+143
+1.0
+ 70
+ 1712
+ 72
+ 0
+ 73
+ 0
+ 74
+ 0
+ 7
+
+ 75
+ 0
+147
+1.0
+148
+0.0
+149
+0.0
+100
+AcDbLayout
+ 1
+Model
+ 70
+ 1
+ 71
+ 0
+ 10
+0.0
+ 20
+0.0
+ 11
+297.0
+ 21
+420.0
+ 12
+0.0
+ 22
+0.0
+ 32
+0.0
+ 14
+0.0
+ 24
+0.0
+ 34
+0.0
+ 15
+297.0
+ 25
+420.0
+ 35
+0.0
+146
+0.0
+ 13
+0.0
+ 23
+0.0
+ 33
+0.0
+ 16
+1.0
+ 26
+0.0
+ 36
+0.0
+ 17
+0.0
+ 27
+1.0
+ 37
+0.0
+ 76
+ 0
+330
+1F
+331
+29
+ 0
+MLINESTYLE
+ 5
+18
+102
+{ACAD_REACTORS
+330
+17
+102
+}
+330
+17
+100
+AcDbMlineStyle
+ 2
+Standard
+ 70
+ 0
+ 3
+
+ 62
+ 256
+ 51
+90.0
+ 52
+90.0
+ 71
+ 2
+ 49
+0.5
+ 62
+ 256
+ 6
+BYLAYER
+ 49
+-0.5
+ 62
+ 256
+ 6
+BYLAYER
+ 0
+ACDBPLACEHOLDER
+ 5
+F
+102
+{ACAD_REACTORS
+330
+E
+102
+}
+330
+E
+ 0
+ENDSEC
+ 0
+EOF
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/pass/loop-2.dxf b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/loop-2.dxf
new file mode 100644
index 000000000..961dd35a1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/loop-2.dxf
@@ -0,0 +1,13974 @@
+ 0
+SECTION*
+ 2
+HEADER
+ 9
+$ACADVER
+ 1
+AC1015
+ 9
+$ACADMAINTVER
+ 70
+ 6
+ 9
+$DWGCODEPAGE
+ 3
+ANSI_1252
+ 9
+$INSBASE
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$EXTMIN
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 9
+$EXTMAX
+ 10
+297.0
+ 20
+420.0
+ 30
+0.0
+ 9
+$LIMMIN
+ 10
+0.0
+ 20
+0.0
+ 9
+$LIMMAX
+ 10
+297.0
+ 20
+420.0
+ 9
+$ORTHOMODE
+ 70
+ 0
+ 9
+$REGENMODE
+ 70
+ 1
+ 9
+$FILLODE
+ 70
+ 1
+ 9
+$QTEXTMODE
+ 70
+ 0
+ 9
+$MIRRTEXT
+ 70
+ 1
+ 0
+DIMSTYLE
+105
+501
+102
+{ACAD_REACTORS
+330
+500
+102
+}
+330
+A
+100
+AcDbSymbolTableRecord
+100
+AcDbDimStyleTableRecord
+ 2
+SLDDIMSTYLE0
+ 70
+ 0
+ 41
+3.0
+ 44
+0.0
+ 45
+0.000000001
+ 73
+ 0
+ 74
+ 0
+ 77
+ 1
+ 78
+ 12
+ 79
+ 3
+140
+3.5
+144
+2.5
+147
+0.875
+172
+ 1
+173
+ 1
+178
+ 0
+271
+ 3
+272
+ 3
+276
+ 2
+284
+ 12
+289
+ 0
+340
+54
+ 0
+DIMSTYLE
+105
+50E
+102
+{ACAD_REACTORS
+330
+50D
+330
+51A
+330
+526
+330
+56C
+330
+578
+330
+584
+102
+}
+330
+A
+100
+AcDbSymbolTableRecord
+100
+AcDbDimStyleTableRecord
+ 2
+SLDDIMSTYLE1
+ 70
+ 0
+ 41
+3.0
+ 44
+0.0
+ 45
+0.000000001
+ 73
+ 0
+ 74
+ 0
+ 77
+ 1
+ 78
+ 12
+ 79
+ 3
+140
+3.5
+144
+2.5
+147
+0.875
+172
+ 1
+173
+ 1
+178
+ 0
+271
+ 0
+272
+ 0
+276
+ 2
+284
+ 12
+289
+ 0
+340
+54
+ 0
+DIMSTYLE
+105
+533
+102
+{ACAD_REACTORS
+330
+532
+330
+53C
+330
+545
+330
+54E
+330
+557
+330
+561
+102
+}
+330
+A
+100
+AcDbSymbolTableRecord
+100
+AcDbDimStyleTableRecord
+ 2
+SLDDIMSTYLE2
+ 70
+ 0
+ 41
+3.0
+ 44
+0.0
+ 45
+0.000000001
+ 73
+ 0
+ 74
+ 0
+ 77
+ 1
+ 78
+ 12
+ 79
+ 3
+140
+3.5
+144
+2.5
+147
+0.875
+173
+ 1
+178
+ 0
+271
+ 3
+272
+ 3
+276
+ 2
+284
+ 12
+340
+54
+ 0
+ENDTAB
+ 0
+TABLE
+ 2
+BLOCK_RECORD
+ 5
+1
+330
+0
+100
+AcDbSymbolTable
+ 70
+ 15
+ 0
+BLOCK_RECORD
+ 5
+1F
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+*Model_Space
+340
+22
+ 0
+BLOCK_RECORD
+ 5
+1B
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+*Paper_Space
+340
+1E
+ 0
+BLOCK_RECORD
+ 5
+23
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+*Paper_Space0
+340
+26
+ 0
+BLOCK_RECORD
+ 5
+56
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+SW_BROKEN_VIEW_0
+340
+0
+102
+{BLKREFS
+331
+59
+102
+}
+ 0
+BLOCK_RECORD
+ 5
+502
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+50F
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_1
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+51B
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_2
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+527
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_3
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+534
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_4
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+53D
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_5
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+546
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_6
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+54F
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_7
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+558
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_8
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+562
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_9
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+56D
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_10
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+579
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_11
+340
+0
+ 0
+BLOCK_RECORD
+ 5
+585
+330
+1
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+ 2
+_D_12
+340
+0
+ 0
+ENDTAB
+ 0
+ENDSEC
+ 0
+SECTION
+ 2
+BLOCKS
+ 0
+BLOCK
+ 5
+20
+330
+1F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+*Model_Space
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+*Model_Space
+ 1
+
+ 0
+ENDBLK
+ 5
+21
+330
+1F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+1C
+330
+1B
+100
+AcDbEntity
+ 67
+ 1
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+*Paper_Space
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+*Paper_Space
+ 1
+
+ 0
+ENDBLK
+ 5
+1D
+330
+1B
+100
+AcDbEntity
+ 67
+ 1
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+24
+330
+23
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+*Paper_Space0
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+*Paper_Space0
+ 1
+
+ 0
+ENDBL
+ 5
+25
+330
+23
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+57
+330
+56
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+SW_BROKEN_VIEW_0
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+SW_BROKEN_VIEW_0
+ 1
+
+ 0
+ENDBLK
+ 5
+58
+330
+56
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+503
+330
+502
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D
+ 1
+
+ 0
+SOLID
+ 5
+505
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+194.9299255838
+ 21
+25.7821787182
+ 31
+0.0
+ 12
+195.9299255838
+ 22
+25.7821787182
+ 32
+0.0
+ 13
+195.9299255838
+ 23
+25.7821787182
+ 33
+0.0
+ 0
+SOLID
+ 5
+506
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.9299255838
+ 21
+44.9821787182
+ 31
+0.0
+ 12
+194.9299255838
+ 22
+44.9821787182
+ 32
+0.0
+ 13
+194.9299255838
+ 23
+44.9821787182
+ 33
+0.0
+ 0
+LINE
+ 5
+507
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+143.0299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+196.4299255838
+ 21
+28.7821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+508
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+196.4299255838
+ 21
+41.9821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+509
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+22.7821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+50A
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+41.9821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+50B
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+47.9821787182
+ 31
+0.0
+ 0
+MTEXT
+ 5
+50C
+330
+502
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+190.9181886692
+ 20
+31.991019801
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+33
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+504
+330
+502
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+510
+330
+50F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_1
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_1
+ 1
+
+ 0
+SOLID
+ 5
+512
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+280.0124004364
+ 30
+0.0
+ 11
+170.9299255838
+ 21
+277.0124004364
+ 31
+0.0
+ 12
+171.9299255838
+ 22
+277.0124004364
+ 32
+0.0
+ 13
+171.9299255838
+ 23
+277.0124004364
+ 33
+0.0
+ 0
+SOLID
+ 5
+513
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+287.499722104
+ 30
+0.0
+ 11
+171.9299255838
+ 21
+290.499722104
+ 31
+0.0
+ 12
+170.9299255838
+ 22
+290.499722104
+ 32
+0.0
+ 13
+170.9299255838
+ 23
+290.499722104
+ 33
+0.0
+ 0
+LINE
+ 5
+514
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+150.4168593775
+ 20
+280.0124004364
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+280.0124004364
+ 31
+0.0
+ 0
+LINE
+ 5
+515
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+516
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+280.0124004364
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+267.6770872868
+ 31
+0.0
+ 0
+LINE
+ 5
+517
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+280.0124004364
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+518
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+287.499722104
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+293.499722104
+ 31
+0.0
+ 0
+MTEXT
+ 5
+519
+330
+50F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+166.9181886692
+ 20
+267.6770872868
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+19
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+511
+330
+50F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+51C
+330
+51B
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_2
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_2
+ 1
+
+ 0
+SOLID
+ 5
+51E
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+202.8200717467
+ 30
+0.0
+ 11
+170.9299255838
+ 21
+199.8200717467
+ 31
+0.0
+ 12
+1715696261
+ 21
+284.499722104
+ 31
+0.0
+ 12
+195.7555696261
+ 22
+284.499722104
+ 32
+0.0
+ 13
+195.7555696261
+ 23
+284.499722104
+ 33
+0.0
+ 0
+SOLID
+ 5
+54A
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+195.7555696261
+ 21
+213.3073934143
+ 31
+0.0
+ 12
+194.7555696261
+ 22
+213.3073934143
+ 32
+0.0
+ 13
+194.7555696261
+ 23
+213.3073934143
+ 33
+0.0
+ 0
+LINE
+ 5
+54B
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+54C
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+210.3073934143
+ 31
+0.0
+ 0
+LINE
+ 5
+54D
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.2555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+210.3073934143
+ 31
+0.0
+ 0
+ENDBLK
+ 5
+548
+330
+546
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+550
+330
+54F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_7
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_7
+ 1
+
+ 0
+SOLID
+ 5
+552
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+195.7555696261
+ 21
+290.499722104
+ 31
+0.0
+ 12
+194.7555696261
+ 22
+290.499722104
+ 32
+0.0
+ 13
+194.7555696261
+ 23
+290.499722104
+ 33
+0.0
+ 0
+SOLID
+ 5
+553
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555696261
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+194.7555696261
+ 21
+394.2202084954
+ 31
+0.0
+ 12
+195.7555696261
+ 22
+394.2202084954
+ 32
+0.0
+ 13
+195.7555696261
+ 23
+394.2202084954
+ 33
+0.0
+ 0
+LINE
+ 5
+554
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+555
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+146.8378589248
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+LINE
+ 5
+556
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.2555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+ENDBLK
+ 5
+551
+330
+54F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+559
+330
+558
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_8
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_8
+ 1
+
+ 0
+SOLID
+ 5
+55B
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+219.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+219.9299255838
+ 21
+31.7821787182
+ 31
+0.0
+ 12
+218.9299255838
+ 22
+31.7821787182
+ 32
+0.0
+ 13
+218.9299255838
+ 23
+31.7821787182
+ 33
+0.0
+ 0
+SOLID
+ 5
+55C
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+219.4299255838
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+218.9299255838
+ 21
+394.2202084954
+ 31
+0.0
+ 12
+219.9299255838
+ 22
+394.2202084954
+ 32
+0.0
+ 13
+219.9299255838
+ 23
+394.2202084954
+ 33
+0.0
+ 0
+LINE
+ 5
+5527
+ 20
+360.4202097011
+ 30
+0.0
+ 11
+142.6699255427
+ 21
+361.9402235103
+ 31
+0.0
+ 0
+ARC
+ 5
+7D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.0699283112
+ 20
+361.9401917488
+ 30
+0.0
+ 40
+0.4000027697974622
+100
+AcDbArc
+ 50
+90.0003871694
+ 51
+179.9954505335
+ 0
+LINE
+ 5
+7E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0699256082
+ 20
+362.3401945186
+ 30
+0.0
+ 11
+148.5899255445
+ 21
+362.3401945186
+ 31
+0.0
+ 0
+ARC
+ 5
+7F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5899336175
+ 20
+362.4601862448
+ 30
+0.0
+ 40
+0.1199917263967713
+100
+AcDbArc
+ 50
+269.9961451292
+ 51
+0.0134590356
+ 0
+LINE
+ 5
+80
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+362.4602144314
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+366.669732864
+ 31
+0.0
+ 0
+ARC
+ 5
+81
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+366.669705415
+ 30
+0.0
+ 40
+0.2001077687858761
+100
+AcDbArc
+ 50
+0.0078593224
+ 51
+46.1736252111
+ 0
+ARC
+ 5
+82
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.229892261
+ 20
+367.4202030254
+ 30
+0.0
+ 40
+0.8399663770856335
+100
+AcDbArc
+ 50
+133.8120979057
+ 51
+226.1879020943
+ 0
+ARC
+ 5
+83
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+368.1707006358
+ 30
+0.0
+ 40
+0.200107768785933
+100
+AcDbArc
+ 50
+313.8263747889
+ 51
+359.9921406775
+ 0
+LINE
+ 5
+84
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+368.1706731868
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+370.3305070949
+ 31
+0.0
+ 0
+ARC
+ 5
+85
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5900202217
+ 20
+370.3305234822
+ 30
+0.0
+ 40
+0.1199051200450481
+100
+AcDbArc
+ 50
+359.9921694514
+ 51
+45.0183972297
+ 0
+LINE
+ 5
+86
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.6747787168
+ 20
+370.4153364254
+ 30
+0.0
+ 11
+148.5050731172
+ 21
+370.58504277
+ 31
+0.0
+ 0
+ARC
+ 5
+87
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5900489089
+ 20
+370.6699467703
+ 30
+0.0
+ 40
+0.1201231635795685
+100
+AcDbArc
+ 50
+180.0128717119
+ 51
+224.9757867508
+ 0
+LINE
+ 5
+88
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.4699257483
+ 20
+370.669919ontinuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484826
+ 20
+72.3821479784
+ 30
+0.0
+ 40
+0.399977127854635
+100
+AcDbArc
+ 50
+292.6176918057
+ 51
+0.0067619015
+ 0
+ARC
+ 5
+4D2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.2299252955
+ 20
+71.9021632155
+ 30
+0.0
+ 40
+0.1199998892853113
+100
+AcDbArc
+ 50
+112.6196870788
+ 51
+247.3803129212
+ 0
+ARC
+ 5
+4D3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484881
+ 20
+71.4221784593
+ 30
+0.0
+ 40
+0.3999771195634846
+100
+AcDbArc
+ 50
+0.0000677203
+ 51
+67.382308554
+ 0
+LINE
+ 5
+4D4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.4299256077
+ 20
+71.4221789321
+ 30
+0.0
+ 11
+149.4299256077
+ 21
+68.8558890304
+ 31
+0.0
+ 0
+ARC
+ 5
+4D5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.3098934248
+ 20
+68.8558875882
+ 30
+0.0
+ 40
+0.1200321828299822
+100
+AcDbArc
+ 50
+284.0483029705
+ 51
+0.0006883757
+ 0
+LINE
+ 5
+4D6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.3390300145
+ 20
+68.7394453963
+ 30
+0.0
+ 11
+149.2808216085
+ 21
+68.724901863
+ 31
+0.0
+ 0
+ARC
+ 5
+4D7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.3099570381
+ 20
+68.6084597995
+ 30
+0.0
+ 40
+0.1200317766406951
+100
+AcDbArc
+ 50
+104.0477806555
+ 51
+179.9779884139
+ 0
+LINE
+ 5
+4D8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1899252703
+ 20
+68.6085059127
+ 30
+0.0
+ 11
+149.1899252703
+ 21
+67.5958945235
+ 31
+0.0
+ 0
+ARC
+ 5
+4D9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.309957026
+ 20
+67.5958929344
+ 30
+0.0
+ 40
+0.1200317557485991
+100
+AcDbArc
+ 50
+179.999241474
+ 51
+255.952222776
+ 0
+LINE
+ 5
+4DA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2808216085
+ 20
+67.4794508895
+ 30
+0.0
+ 11
+149.3390300145
+ 21
+67.4649073562
+ 31
+0.0
+ 0
+ARC
+ 5
+4DB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.3098934248
+ 20
+67.3484651642
+ 30
+0.0
+ 40
+0.1200321828298969
+100
+AcDbArc
+ 50
+359.9993116244
+ 51
+75.9516970296
+ 0
+LINE
+ 5
+4DC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.4299256077
+ 20
+67.3484637221
+ 30
+0.0
+ 11
+149.4299256077
+ 21
+64.7821738204
+ 31
+0.0
+ 0
+ARC
+ 5
+4DD
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484881
+ 20
+64.7821742931
+ 30
+0.0
+ 40
+0.3999771195634605
+100
+AcDbArc
+ 50
+292.617691446
+ 51
+359.9999322797
+ 0
+ARC
+ 5
+4DE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.2299252955
+ 20
+64.3021895369
+ 30
+0.0
+ 40
+0.1199998892853769
+100
+AcDbArc
+ 50
+112.6196870788
+ 51
+247.3803129212
+ 0
+ARC
+ 5
+4DF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484826
+ 20
+63.8222047741
+ 30
+0.0
+ 40
+0.3999771278546918
+100
+AcDbArc
+ 50
+359.9932380985
+ 51
+67.3823081943
+ 0
+LINE
+ 5
+4E0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.4299256077
+ 20
+63.8221575698
+ 30
+0.0
+ 11
+149.4299256077
+ 21
+42.2443224868
+ 31
+0.0
+ 0
+ARC
+ 5
+4E1
+330
+1F
+100
+AcDbEnt
+ 21
+254.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AC
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+254.4750445598
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AD
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AE
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+260.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B0
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+260.4750445598
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+258.4750.9299255838
+ 22
+199.8200717467
+ 32
+0.0
+ 13
+171.9299255838
+ 23
+199.8200717467
+ 33
+0.0
+ 0
+SOLID
+ 5
+51F
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+171.9299255838
+ 21
+213.3073934143
+ 31
+0.0
+ 12
+170.9299255838
+ 22
+213.3073934143
+ 32
+0.0
+ 13
+170.9299255838
+ 23
+213.3073934143
+ 33
+0.0
+ 0
+LINE
+ 5
+520
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+150.4168593775
+ 20
+202.8200717467
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+202.8200717467
+ 31
+0.0
+ 0
+LINE
+ 5
+521
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+210.3073934143
+ 31
+0.0
+ 0
+LINE
+ 5
+522
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+202.8200717467
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+190.8599118622
+ 31
+0.0
+ 0
+LINE
+ 5
+523
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+202.8200717467
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+210.3073934143
+ 31
+0.0
+ 0
+LINE
+ 5
+524
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+216.3073934143
+ 31
+0.0
+ 0
+MTEXT
+ 5
+525
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+166.9181886692
+ 20
+190.8599118622
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+19
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+51D
+330
+51B
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+528
+330
+527
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_3
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_3
+ 1
+
+ 0
+SOLID
+ 5
+52A
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+126.2783621669
+ 30
+0.0
+ 11
+170.9299255838
+ 21
+123.2783621669
+ 31
+0.0
+ 12
+171.9299255838
+ 22
+123.2783621669
+ 32
+0.0
+ 13
+171.9299255838
+ 23
+123.2783621669
+ 33
+0.0
+ 0
+SOLID
+ 5
+52B
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+171.9299255838
+ 21
+136.7256838344
+ 31
+0.0
+ 12
+170.9299255838
+ 22
+136.7256838344
+ 32
+0.0
+ 13
+170.9299255838
+ 23
+136.7256838344
+ 33
+0.0
+ 0
+LINE
+ 5
+52C
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+150.4168593775
+ 20
+126.2783621669
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+126.2783621669
+ 31
+0.0
+ 0
+LINE
+ 5
+52D
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+133.7256838344
+ 31
+0.0
+ 0
+LINE
+ 5
+52E
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+126.2783621669
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+109.1156238914
+ 31
+0.0
+ 0
+LINE
+ 5
+52F
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+126.2783621669
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+133.7256838344
+ 31
+0.0
+ 0
+LINE
+ 5
+530
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+139.7256838344
+ 31
+0.0
+ 0
+MTEXT
+ 5
+531
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+166.9181886692
+ 20
+109.1156238914
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+19
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+529
+330
+527
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+535
+330
+534
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_4
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_4
+ 1
+
+ 0
+SOLID
+ 5
+537
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+194.9299255838
+ 21
+130.7256838344
+ 31
+0.0
+ 12
+195.9299255838
+ 22
+130.7256838344
+ 32
+0.0
+ 13
+195.9299255838
+ 23
+130.7256838344
+ 33
+0.0
+ 0
+SOLID
+ 5
+538
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.9299255838
+ 21
+44.9821787182
+ 31
+0.0
+ 12
+194.9299255838
+ 22
+44.9821787182
+ 32
+0.0
+ 13
+194.9299255838
+ 23
+44.9821787182
+ 33
+0.0
+ 0
+LINE
+ 5
+539
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+196.4299255838
+ 21
+133.7256838344
+ 31
+0.0
+ 0
+LINE
+ 5
+53A
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+196.4299255838
+ 21
+41.9821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+53B
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+41.9821787182
+ 31
+0.0
+ 0
+ENDBLK
+ 5
+536
+330
+534
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+53E
+330
+53D
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_5
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_5
+ 1
+
+ 0
+SOLID
+ 5
+540
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555532575
+ 20
+210.3467855475
+ 30
+0.0
+ 11
+194.7580466032
+ 21
+207.3463710546
+ 31
+0.0
+ 12
+195.7580462578
+ 22
+207.3472021123
+ 32
+0.0
+ 13
+195.7580462578
+ 23
+207.3472021123
+ 33
+0.0
+ 0
+SOLID
+ 5
+541
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.3191971725
+ 20
+133.7649839595
+ 30
+0.0
+ 11
+195.8167038268
+ 21
+136.7653984523
+ 31
+0.0
+ 12
+194.8167041722
+ 22
+136.7645673947
+ 32
+0.0
+ 13
+194.8167041722
+ 23
+136.7645673947
+ 33
+0.0
+ 0
+LINE
+ 5
+542
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555692807
+ 20
+210.3082244719
+ 30
+0.0
+ 11
+196.2555529122
+ 21
+210.3476166051
+ 31
+0.0
+ 0
+LINE
+ 5
+543
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.029925238ity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.2877619365
+ 20
+42.2443402896
+ 30
+0.0
+ 40
+0.1421636723032661
+100
+AcDbArc
+ 50
+215.0074908018
+ 51
+359.9928249763
+ 0
+LINE
+ 5
+4E2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1713189354
+ 20
+42.1627833327
+ 30
+0.0
+ 11
+148.4940879812
+ 21
+43.1299998244
+ 31
+0.0
+ 0
+ARC
+ 5
+4E3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5923363035
+ 20
+43.1988138586
+ 30
+0.0
+ 40
+0.1199504236850504
+100
+AcDbArc
+ 50
+136.8044484108
+ 51
+215.0077544772
+ 0
+ARC
+ 5
+4E4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.6299254989
+ 20
+44.1021810107
+ 30
+0.0
+ 40
+1.200014262087228
+100
+AcDbArc
+ 50
+316.8133643338
+ 51
+223.1866356662
+ 0
+ARC
+ 5
+4E5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.667516349
+ 20
+43.1988139771
+ 30
+0.0
+ 40
+0.1199491362526016
+100
+AcDbArc
+ 50
+324.9917457236
+ 51
+43.1960513885
+ 0
+LINE
+ 5
+4E6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.7657630166
+ 20
+43.1299998244
+ 30
+0.0
+ 11
+146.1655196567
+ 21
+42.2727419814
+ 31
+0.0
+ 0
+ARC
+ 5
+4E7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.8378250788
+ 20
+42.5022486061
+ 30
+0.0
+ 40
+0.4000712776530942
+100
+AcDbArc
+ 50
+270.0048248044
+ 51
+324.9938514507
+ 0
+LINE
+ 5
+4E8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+145.8378587683
+ 20
+42.1021773299
+ 30
+0.0
+ 11
+143.9099256714
+ 21
+42.1021773299
+ 31
+0.0
+ 0
+ARC
+ 5
+4E9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.9098934092
+ 20
+42.1821451244
+ 30
+0.0
+ 40
+0.0799678010352872
+100
+AcDbArc
+ 50
+179.9674137886
+ 51
+270.0231154488
+ 0
+LINE
+ 5
+4EA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.8299256211
+ 20
+42.1821906051
+ 30
+0.0
+ 11
+143.8299256211
+ 21
+42.7421881637
+ 31
+0.0
+ 0
+ARC
+ 5
+4EB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.9099748178
+ 20
+42.7421522491
+ 30
+0.0
+ 40
+0.080049204801129
+100
+AcDbArc
+ 50
+90.0351768672
+ 51
+179.9742938954
+ 0
+LINE
+ 5
+4EC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.9099256714
+ 20
+42.8222014388
+ 30
+0.0
+ 11
+145.3970798125
+ 21
+42.8222014388
+ 31
+0.0
+ 0
+ARC
+ 5
+4ED
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.3970883777
+ 20
+43.2221900281
+ 30
+0.0
+ 40
+0.3999885893651605
+100
+AcDbArc
+ 50
+269.9987730963
+ 51
+21.5094255355
+ 0
+ARC
+ 5
+4EE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.6299070455
+ 20
+44.102180655
+ 30
+0.0
+ 40
+1.999982807792672
+100
+AcDbArc
+ 50
+166.3277484711
+ 51
+201.510375133
+ 0
+ARC
+ 5
+4EF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.4922360036
+ 20
+44.6221751279
+ 30
+0.0
+ 40
+0.2000244053689678
+100
+AcDbArc
+ 50
+346.3324477609
+ 51
+89.9922055192
+ 0
+LINE
+ 5
+4F0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+145.4922632148
+ 20
+44.8221995315
+ 30
+0.0
+ 11
+137.3675879856
+ 21
+44.8221995315
+ 31
+0.0
+ 0
+ARC
+ 5
+4F1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.3676151968
+ 20
+44.6221751279
+ 30
+0.0
+ 40
+0.2000244053689526
+100
+AcDbArc
+ 50
+90.0077944808
+ 51
+193.6675522391
+ 0
+ARC
+ 5
+4F2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+135.2299441549
+ 20
+44.102180655
+ 30
+0.0
+ 40
+1.999982807792147
+100
+AcDbArc
+ 50
+338.489624867
+ 51
+13.672251529
+ 0
+ARC
+ 5
+4F3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.4627628227
+ 20
+43.2221900281
+ 30
+0.0
+ 40
+0.399988589365143
+100
+AcDbArc
+ 50
+158.4905744645
+ 51
+270.0012269037
+ 0
+LINE
+ 5
+4F4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 8
+370
+ 0
+100
+AcDbLine
+ 10
+148.8260940482
+ 20
+80.1358534774
+ 30
+0.0
+ 11
+148.8260940482
+ 21
+103.7777020415
+ 31
+0.0
+ 0
+LINE
+ 5
+4F5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 8
+370
+ 0
+100
+AcDbLine
+ 10
+133.4835157563
+ 20
+80.1027132949
+ 30
+0.0
+ 11
+133.4835157563
+ 21
+103.7777020415
+ 31
+0.0
+ 0
+LINE
+ 5
+4F6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 8
+370
+ 0
+100
+AcDbLine
+ 10
+148.5235550275
+ 20
+81.2455489119
+ 30
+0.0
+ 11
+148.5235550275
+ 21
+103.7777020415
+ 31
+0.0
+ 0
+LINE
+ 5
+4F7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 8
+370
+ 0
+100
+AcDbLine
+ 10
+148.1099256148
+ 20
+82.7892615279
+ 30
+0.0
+ 11
+148.1099256148
+ 21
+103.7777020415
+ 31
+0.0
+ 0
+POINT
+ 5
+4F8
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+142.0299255838
+ 20
+-247.6988063932
+ 30
+0.0
+ 0
+POINT
+ 5
+4F9
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+149.4168593775
+ 20
+447.9345399732
+ 30
+0.0
+ 0
+POINT
+ 5
+4FA
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+149.4168593775
+ 20
+238.1745399732
+ 30
+0.0
+ 0
+POINT
+ 5
+4FB
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+147.8555696261
+ 20
+245.6618616408
+ 30
+0.0
+ 0
+POINT
+ 5
+4FC
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+147.8555696261
+ 20
+455.4218616408
+ 30
+0.0
+ 0
+POINT
+ 5
+4FD
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+148.0299255838
+ 20
+35.8618616408
+ 30
+0.0
+ 0
+POINT
+ 5
+4FE
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+149.4168593775
+ 20
+28.4145399732
+ 30
+0.0
+ 0
+POINT
+ 5
+4FF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+133.4299255838
+ 20
+660.3011936068
+ 30
+0.0
+ 0
+DIMENSION
+ 5
+500
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+34.5771309945
+ 31
+0.0
+ 70
+ 160
+ 1
+33
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE0
+100
+AcDbAlignedDimension
+ 13
+142.0299255838
+ 23
+28.7821787182
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+41.9821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+50D
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_1
+ 10
+171.4299255838
+ 20
+287.499722104
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+271.6850735678
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+280.0124004364
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+287.499722104
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+51A
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_2
+ 10
+171.4299255838
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+194.8678981433
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+202.8200717467
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+210.3073934143
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+526
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_3
+ 10
+171.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+113.1236101725
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+126.2783621669
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+133.7256838344
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+532
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_4
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+84.1586135498
+ 31
+0.0
+ 70
+ 160
+ 1
+675,902
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+148.0299255838
+ 23
+133.7256838344
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+41.9821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+53C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_5
+ 10
+195.3191971725
+ 20
+133.7649839595
+ 30
+0.0
+ 11
+195.2817915125
+ 21
+178.7746730971
+ 31
+0.0
+ 70
+ 160
+ 1
+524,500
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+210.3073934143
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+133.7256838344
+ 34
+0.0
+ 50
+-89.9523838979
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+545
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_6
+ 10
+195.2555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+246.0726158741
+ 31
+0.0
+ 70
+ 160
+ 1
+524,400
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+287.499722104
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+210.3073934143
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+54E
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_7
+ 10
+195.2555696261
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+357.7845521004
+ 31
+0.0
+ 70
+ 160
+ 1
+545,698
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+287.499722104
+ 33
+0.0
+ 14
+145.8378589248
+ 24
+397.2202084954
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+557
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_8
+ 10
+219.4299255838
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+219.4299255838
+ 21
+226.31135989
+ 31
+0.0
+ 70
+ 160
+ 1
+Kozijnmaat =
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+142.0299255838
+ 23
+28.7821787182
+ 33
+0.0
+ 14
+145.8378589248
+ 24
+397.2202084954
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+561
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_9
+ 10
+99.2299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+99.2299255838
+ 21
+214.5361780403
+ 31
+0.0
+ 70
+ 160
+ 1
+DMH =
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+133.4299255838
+ 23
+383.8202084954
+ 33
+0.0
+ 14
+142.0299255838
+ 24
+28.7821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+56C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_10
+ 10
+117.2299255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+157.3719824392
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+147.8850158005
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+148.4450158005
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+578
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_11
+ 10
+117.2299255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+236.5334651005
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+224.4267253803
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+224.9867253803
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+584
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_12
+ 10
+117.2299255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+311.8110919194
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+301.61905407
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+302.17905407
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+LINE
+ 5
+590
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+591
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+592
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+593
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+101.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+594
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+101.7777066237
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+595
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+596
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+597
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+107.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+598
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+107.7777066237
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+599
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59A
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59B
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59D
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59E
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59F
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+177.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A0
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+177.2366515846
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A1
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A2
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A3
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+183.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A4
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+183.2366515846
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A5
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A6
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A7
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A8
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5A9
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AA
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AB
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+254.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AC
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+254.4750445598
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AD
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AE
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+260.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B0
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+260.4750445598
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+258.4750.9299255838
+ 22
+199.8200717467
+ 32
+0.0
+ 13
+171.9299255838
+ 23
+199.8200717467
+ 33
+0.0
+ 0
+SOLID
+ 5
+51F
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+171.9299255838
+ 21
+213.3073934143
+ 31
+0.0
+ 12
+170.9299255838
+ 22
+213.3073934143
+ 32
+0.0
+ 13
+170.9299255838
+ 23
+213.3073934143
+ 33
+0.0
+ 0
+LINE
+ 5
+520
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+150.4168593775
+ 20
+202.8200717467
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+202.8200717467
+ 31
+0.0
+ 0
+LINE
+ 5
+521
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+210.3073934143
+ 31
+0.0
+ 0
+LINE
+ 5
+522
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+202.8200717467
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+190.8599118622
+ 31
+0.0
+ 0
+LINE
+ 5
+523
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+202.8200717467
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+210.3073934143
+ 31
+0.0
+ 0
+LINE
+ 5
+524
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+216.3073934143
+ 31
+0.0
+ 0
+MTEXT
+ 5
+525
+330
+51B
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+166.9181886692
+ 20
+190.8599118622
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+19
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+51D
+330
+51B
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+528
+330
+527
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_3
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_3
+ 1
+
+ 0
+SOLID
+ 5
+52A
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+126.2783621669
+ 30
+0.0
+ 11
+170.9299255838
+ 21
+123.2783621669
+ 31
+0.0
+ 12
+171.9299255838
+ 22
+123.2783621669
+ 32
+0.0
+ 13
+171.9299255838
+ 23
+123.2783621669
+ 33
+0.0
+ 0
+SOLID
+ 5
+52B
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+171.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+171.9299255838
+ 21
+136.7256838344
+ 31
+0.0
+ 12
+170.9299255838
+ 22
+136.7256838344
+ 32
+0.0
+ 13
+170.9299255838
+ 23
+136.7256838344
+ 33
+0.0
+ 0
+LINE
+ 5
+52C
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+150.4168593775
+ 20
+126.2783621669
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+126.2783621669
+ 31
+0.0
+ 0
+LINE
+ 5
+52D
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+172.4299255838
+ 21
+133.7256838344
+ 31
+0.0
+ 0
+LINE
+ 5
+52E
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+126.2783621669
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+109.1156238914
+ 31
+0.0
+ 0
+LINE
+ 5
+52F
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+126.2783621669
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+133.7256838344
+ 31
+0.0
+ 0
+LINE
+ 5
+530
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+171.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+139.7256838344
+ 31
+0.0
+ 0
+MTEXT
+ 5
+531
+330
+527
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+166.9181886692
+ 20
+109.1156238914
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+19
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+529
+330
+527
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+535
+330
+534
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_4
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_4
+ 1
+
+ 0
+SOLID
+ 5
+537
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+194.9299255838
+ 21
+130.7256838344
+ 31
+0.0
+ 12
+195.9299255838
+ 22
+130.7256838344
+ 32
+0.0
+ 13
+195.9299255838
+ 23
+130.7256838344
+ 33
+0.0
+ 0
+SOLID
+ 5
+538
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.9299255838
+ 21
+44.9821787182
+ 31
+0.0
+ 12
+194.9299255838
+ 22
+44.9821787182
+ 32
+0.0
+ 13
+194.9299255838
+ 23
+44.9821787182
+ 33
+0.0
+ 0
+LINE
+ 5
+539
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+196.4299255838
+ 21
+133.7256838344
+ 31
+0.0
+ 0
+LINE
+ 5
+53A
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+196.4299255838
+ 21
+41.9821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+53B
+330
+534
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+41.9821787182
+ 31
+0.0
+ 0
+ENDBLK
+ 5
+536
+330
+534
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+53E
+330
+53D
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_5
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_5
+ 1
+
+ 0
+SOLID
+ 5
+540
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555532575
+ 20
+210.3467855475
+ 30
+0.0
+ 11
+194.7580466032
+ 21
+207.3463710546
+ 31
+0.0
+ 12
+195.7580462578
+ 22
+207.3472021123
+ 32
+0.0
+ 13
+195.7580462578
+ 23
+207.3472021123
+ 33
+0.0
+ 0
+SOLID
+ 5
+541
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.3191971725
+ 20
+133.7649839595
+ 30
+0.0
+ 11
+195.8167038268
+ 21
+136.7653984523
+ 31
+0.0
+ 12
+194.8167041722
+ 22
+136.7645673947
+ 32
+0.0
+ 13
+194.8167041722
+ 23
+136.7645673947
+ 33
+0.0
+ 0
+LINE
+ 5
+542
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555692807
+ 20
+210.3082244719
+ 30
+0.0
+ 11
+196.2555529122
+ 21
+210.3476166051
+ 31
+0.0
+ 0
+LINE
+ 5
+543
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+149.0299252385
+ 20
+133.7265148921
+ 30
+0.0
+ 11
+196.3191968272
+ 21
+133.7658150172
+ 31
+0.0
+ 0
+LINE
+ 5
+544
+330
+53D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.2555532575
+ 20
+210.3467855475
+ 30
+0.0
+ 11
+195.3191971725
+ 21
+133.7649839595
+ 31
+0.0
+ 0
+ENDBLK
+ 5
+53F
+330
+53D
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+547
+330
+546
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_6
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_6
+ 1
+
+ 0
+SOLID
+ 5
+549
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+194.7555696261
+ 21
+284.499722104
+ 31
+0.0
+ 12
+195.7555696261
+ 22
+284.499722104
+ 32
+0.0
+ 13
+195.7555696261
+ 23
+284.499722104
+ 33
+0.0
+ 0
+SOLID
+ 5
+54A
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+195.7555696261
+ 21
+213.3073934143
+ 31
+0.0
+ 12
+194.7555696261
+ 22
+213.3073934143
+ 32
+0.0
+ 13
+194.7555696261
+ 23
+213.3073934143
+ 33
+0.0
+ 0
+LINE
+ 5
+54B
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+54C
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+210.3073934143
+ 31
+0.0
+ 0
+LINE
+ 5
+54D
+330
+546
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.2555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+210.3073934143
+ 31
+0.0
+ 0
+ENDBLK
+ 5
+548
+330
+546
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+550
+330
+54F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_7
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_7
+ 1
+
+ 0
+SOLID
+ 5
+552
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+195.7555696261
+ 21
+290.499722104
+ 31
+0.0
+ 12
+194.7555696261
+ 22
+290.499722104
+ 32
+0.0
+ 13
+194.7555696261
+ 23
+290.499722104
+ 33
+0.0
+ 0
+SOLID
+ 5
+553
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+195.2555696261
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+194.7555696261
+ 21
+394.2202084954
+ 31
+0.0
+ 12
+195.7555696261
+ 22
+394.2202084954
+ 32
+0.0
+ 13
+195.7555696261
+ 23
+394.2202084954
+ 33
+0.0
+ 0
+LINE
+ 5
+554
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+148.8555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+287.499722104
+ 31
+0.0
+ 0
+LINE
+ 5
+555
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+146.8378589248
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+196.2555696261
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+LINE
+ 5
+556
+330
+54F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+195.2555696261
+ 20
+287.499722104
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+ENDBLK
+ 5
+551
+330
+54F
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+559
+330
+558
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_8
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_8
+ 1
+
+ 0
+SOLID
+ 5
+55B
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+219.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+219.9299255838
+ 21
+31.7821787182
+ 31
+0.0
+ 12
+218.9299255838
+ 22
+31.7821787182
+ 32
+0.0
+ 13
+218.9299255838
+ 23
+31.7821787182
+ 33
+0.0
+ 0
+SOLID
+ 5
+55C
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+219.4299255838
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+218.9299255838
+ 21
+394.2202084954
+ 31
+0.0
+ 12
+219.9299255838
+ 22
+394.2202084954
+ 32
+0.0
+ 13
+219.9299255838
+ 23
+394.2202084954
+ 33
+0.0
+ 0
+LINE
+ 5
+55D
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+143.0299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+220.4299255838
+ 21
+28.7821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+55E
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+146.8378589248
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+220.4299255838
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+LINE
+ 5
+55F
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+219.4299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+219.4299255838
+ 21
+397.2202084954
+ 31
+0.0
+ 0
+MTEXT
+ 5
+560
+330
+558
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+214.9181886692
+ 20
+211.8228183688
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+Kozijnmaat =
+ 7
+SLDTEXTSTYLE0
+ 11
+6.123233995736766E-17
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+55A
+330
+558
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+563
+330
+562
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_9
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_9
+ 1
+
+ 0
+SOLID
+ 5
+565
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+99.2299255838
+ 20
+383.8202084954
+ 30
+0.0
+ 11
+98.7299255838
+ 21
+380.8202084954
+ 31
+0.0
+ 12
+99.7299255838
+ 22
+380.8202084954
+ 32
+0.0
+ 13
+99.7299255838
+ 23
+380.8202084954
+ 33
+0.0
+ 0
+SOLID
+ 5
+566
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+99.2299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+99.7299255838
+ 21
+31.7821787182
+ 31
+0.0
+ 12
+98.7299255838
+ 22
+31.7821787182
+ 32
+0.0
+ 13
+98.7299255838
+ 23
+31.7821787182
+ 33
+0.0
+ 0
+LINE
+ 5
+567
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.4299255838
+ 20
+383.8202084954
+ 30
+0.0
+ 11
+98.2299255838
+ 21
+383.8202084954
+ 31
+0.0
+ 0
+LINE
+ 5
+568
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+141.0299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+98.2299255838
+ 21
+28.7821787182
+ 31
+0.0
+ 0
+LINE
+ 5
+569
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+99.2299255838
+ 20
+383.8202084954
+ 30
+0.0
+ 11
+99.2299255838
+ 21
+28.7821787182
+ 31
+0.0
+ 0
+MTEXT
+ 5
+56B
+330
+562
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+94.7181886692
+ 20
+207.001456174
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+DMH =
+ 7
+SLDTEXTSTYLE1
+ 11
+-7.044195017643634E-15
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+564
+330
+562
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+56E
+330
+56D
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_10
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_10
+ 1
+
+ 0
+SOLID
+ 5
+570
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+147.8850158005
+ 30
+0.0
+ 11
+116.7299255838
+ 21
+144.8850158005
+ 31
+0.0
+ 12
+117.7299255838
+ 22
+144.8850158005
+ 32
+0.0
+ 13
+117.7299255838
+ 23
+144.8850158005
+ 33
+0.0
+ 0
+SOLID
+ 5
+571
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+117.7299255838
+ 21
+151.4450158005
+ 31
+0.0
+ 12
+116.7299255838
+ 22
+151.4450158005
+ 32
+0.0
+ 13
+116.7299255838
+ 23
+151.4450158005
+ 33
+0.0
+ 0
+LINE
+ 5
+572
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+147.8850158005
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+147.8850158005
+ 31
+0.0
+ 0
+LINE
+ 5
+573
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+148.4450158005
+ 31
+0.0
+ 0
+LINE
+ 5
+574
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+147.8850158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+141.8850158005
+ 31
+0.0
+ 0
+LINE
+ 5
+575
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+147.8850158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+148.4450158005
+ 31
+0.0
+ 0
+LINE
+ 5
+576
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+160.0869130071
+ 31
+0.0
+ 0
+MTEXT
+ 5
+577
+330
+56D
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+112.7181886692
+ 20
+154.6570518713
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+1
+ 7
+SLDTEXTSTYLE0
+ 11
+-7.044195017643634E-15
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+56F
+330
+56D
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+57A
+330
+579
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_11
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_11
+ 1
+
+ 0
+SOLID
+ 5
+57C
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+224.4267253803
+ 30
+0.0
+ 11
+116.7299255838
+ 21
+221.4267253803
+ 31
+0.0
+ 12
+117.7299255838
+ 22
+221.4267253803
+ 32
+0.0
+ 13
+117.7299255838
+ 23
+221.4267253803
+ 33
+0.0
+ 0
+SOLID
+ 5
+57D
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+117.7299255838
+ 21
+227.9867253803
+ 31
+0.0
+ 12
+116.7299255838
+ 22
+227.9867253803
+ 32
+0.0
+ 13
+116.7299255838
+ 23
+227.9867253803
+ 33
+0.0
+ 0
+LINE
+ 5
+57E
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+224.4267253803
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+224.4267253803
+ 31
+0.0
+ 0
+LINE
+ 5
+57F
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+224.9867253803
+ 31
+0.0
+ 0
+LINE
+ 5
+580
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+224.4267253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+218.4267253803
+ 31
+0.0
+ 0
+LINE
+ 5
+581
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+224.4267253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+224.9867253803
+ 31
+0.0
+ 0
+LINE
+ 5
+582
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+239.2483956684
+ 31
+0.0
+ 0
+MTEXT
+ 5
+583
+330
+579
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+112.7181886692
+ 20
+233.8185345326
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+1
+ 7
+SLDTEXTSTYLE0
+ 11
+-7.044195017643634E-15
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+57B
+330
+579
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+BLOCK
+ 5
+586
+330
+585
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockBegin
+ 2
+_D_12
+ 70
+ 0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 3
+_D_12
+ 1
+
+ 0
+SOLID
+ 5
+588
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+301.61905407
+ 30
+0.0
+ 11
+116.7299255838
+ 21
+298.61905407
+ 31
+0.0
+ 12
+117.7299255838
+ 22
+298.61905407
+ 32
+0.0
+ 13
+117.7299255838
+ 23
+298.61905407
+ 33
+0.0
+ 0
+SOLID
+ 5
+589
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbTrace
+ 10
+117.2299255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+117.7299255838
+ 21
+305.17905407
+ 31
+0.0
+ 12
+116.7299255838
+ 22
+305.17905407
+ 32
+0.0
+ 13
+116.7299255838
+ 23
+305.17905407
+ 33
+0.0
+ 0
+LINE
+ 5
+58A
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+301.61905407
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+301.61905407
+ 31
+0.0
+ 0
+LINE
+ 5
+58B
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+132.5499255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+116.2299255838
+ 21
+302.17905407
+ 31
+0.0
+ 0
+LINE
+ 5
+58C
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+301.61905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+295.61905407
+ 31
+0.0
+ 0
+LINE
+ 5
+58D
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+301.61905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+302.17905407
+ 31
+0.0
+ 0
+LINE
+ 5
+58E
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+117.2299255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+314.5260224873
+ 31
+0.0
+ 0
+MTEXT
+ 5
+58F
+330
+585
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+112.7181886692
+ 20
+309.0961613515
+ 30
+0.04
+ 40
+3.5
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+1
+ 7
+SLDTEXTSTYLE0
+ 11
+-7.044195017643634E-15
+ 21
+1.0
+ 31
+0.0
+ 73
+ 1
+ 44
+1.0
+ 0
+ENDBLK
+ 5
+587
+330
+585
+100
+AcDbEntity
+ 8
+0
+100
+AcDbBlockEnd
+ 0
+ENDSEC
+ 0
+SECTION
+ 2
+ENTITIES
+ 0
+LINE
+ 5
+4B
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbLine
+ 10
+123.9140543182
+ 20
+383.8493547742
+ 30
+0.0
+ 11
+160.598524565
+ 21
+383.8493547742
+ 31
+0.0
+ 0
+LINE
+ 5
+4C
+330
+1F
+100
+AcDbEntity
+ 8
+STUKLIJST
+100
+AcDbLine
+ 10
+10.3087825773
+ 20
+9.2198227322
+ 30
+0.0
+ 11
+10.3087825773
+ 21
+409.2698227322
+ 31
+0.0
+ 0
+LINE
+ 5
+4D
+330
+1F
+100
+AcDbEntity
+ 8
+STUKLIJST
+100
+AcDbLine
+ 10
+10.3087825773
+ 20
+9.2198227322
+ 30
+0.0
+ 11
+287.198438446
+ 21
+9.2198227322
+ 31
+0.0
+ 0
+LINE
+ 5
+4E
+330
+1F
+100
+AcDbEntity
+ 8
+STUKLIJST
+100
+AcDbLine
+ 10
+287.198438446
+ 20
+409.2698227322
+ 30
+0.0
+ 11
+287.198438446
+ 21
+9.2198227322
+ 31
+0.0
+ 0
+LINE
+ 5
+4F
+330
+1F
+100
+AcDbEntity
+ 8
+STUKLIJST
+100
+AcDbLine
+ 10
+287.198438446
+ 20
+409.2698227322
+ 30
+0.0
+ 11
+10.3087825773
+ 21
+409.2698227322
+ 31
+0.0
+ 0
+LINE
+ 5
+50
+330
+1F
+100
+AcDbEntity
+ 8
+MAATLIJN
+100
+AcDbLine
+ 10
+4.3087825773
+ 20
+3.2198227322
+ 30
+0.0
+ 11
+4.3087825773
+ 21
+415.2698227322
+ 31
+0.0
+ 0
+LINE
+ 5
+51
+330
+1F
+100
+AcDbEntity
+ 8
+MAATLIJN
+100
+AcDbLine
+ 10
+4.3087825773
+ 20
+415.2698227322
+ 30
+0.0
+ 11
+293.4090035115
+ 21
+415.2698227322
+ 31
+0.0
+ 0
+LINE
+ 5
+52
+330
+1F
+100
+AcDbEntity
+ 8
+MAATLIJN
+100
+AcDbLine
+ 10
+293.4090035115
+ 20
+415.2698227322
+ 30
+0.0
+ 11
+293.4090035115
+ 21
+3.2198227322
+ 31
+0.0
+ 0
+LINE
+ 5
+53
+330
+1F
+100
+AcDbEntity
+ 8
+MAATLIJN
+100
+AcDbLine
+ 10
+293.4090035115
+ 20
+3.2198227322
+ 30
+0.0
+ 11
+4.3087825773
+ 21
+3.2198227322
+ 31
+0.0
+ 0
+MTEXT
+ 5
+55
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbMText
+ 10
+211.9617900851
+ 20
+18.9651870984
+ 30
+0.0
+ 40
+4.2333333333
+ 41
+0.0
+ 71
+ 1
+ 72
+ 1
+ 1
+Alum. deurblad - 4 secties
+ 7
+SLDTEXTSTYLE0
+ 73
+ 1
+ 44
+1.0
+ 0
+INSERT
+ 5
+59
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+100
+AcDbBlockReference
+ 2
+SW_BROKEN_VIEW_0
+ 10
+0.0
+ 20
+0.0
+ 30
+0.0
+ 0
+LINE
+ 5
+5A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.9420049658
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+148.9420049658
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1445668807
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+149.1445668807
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.0406432023
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+149.0406432023
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.0406432023
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+148.9420049658
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.9137577285
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.9137577285
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+5F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.797846066
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.797846066
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+60
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.6992078294
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.6992078294
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+61
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.797846066
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+133.6992078294
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+62
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.5952848961
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.5952848961
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+ARC
+ 5
+63
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.1879324767
+ 20
+359.1402151319
+ 30
+0.0
+ 40
+0.0799861772139263
+100
+AcDbArc
+ 50
+31.2190407028
+ 51
+90.0049728915
+ 0
+LINE
+ 5
+64
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2563360204
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+149.2563360204
+ 21
+359.1816728664
+ 31
+0.0
+ 0
+LINE
+ 5
+65
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2162960043
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+134.2162960043
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+66
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2162960043
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+134.1499254873
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+67
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+133.4299252202
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+133.4299252202
+ 21
+359.1907804561
+ 31
+0.0
+ 0
+ARC
+ 5
+68
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+127.793914781
+ 20
+346.5773729462
+ 30
+0.0
+ 40
+24.8898367051569
+100
+AcDbArc
+ 50
+30.3127339119
+ 51
+30.4217624082
+ 0
+LINE
+ 5
+69
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.3099258115
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+149.3099258115
+ 21
+359.1109102321
+ 31
+0.0
+ 0
+LINE
+ 5
+6A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2563360204
+ 20
+359.1816728664
+ 30
+0.0
+ 11
+149.2569536736
+ 21
+359.1806238247
+ 31
+0.0
+ 0
+LINE
+ 5
+6B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2299253514
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+134.2299253514
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+6C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.2299253514
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+134.2162960043
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+6D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.5099256804
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+148.5099256804
+ 21
+358.0259626461
+ 31
+0.0
+ 0
+LINE
+ 5
+6E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.6299254169
+ 20
+336.7369001461
+ 30
+0.0
+ 11
+134.6299254169
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+6F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+134.6299254169
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+134.2299253514
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+70
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0299256762
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+143.0299256762
+ 21
+353.6202257229
+ 31
+0.0
+ 0
+LINE
+ 5
+71
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0299256762
+ 20
+353.6202257229
+ 30
+0.0
+ 11
+147.3280240615
+ 21
+353.6202257229
+ 31
+0.0
+ 0
+LINE
+ 5
+72
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+147.3280240615
+ 20
+353.6202257229
+ 30
+0.0
+ 11
+147.5545917471
+ 21
+354.4657533718
+ 31
+0.0
+ 0
+LINE
+ 5
+73
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+141.5499255826
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+141.3099255843
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+LINE
+ 5
+74
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+138.9099255969
+ 20
+359.2202013088
+ 30
+0.0
+ 11
+134.6299254169
+ 21
+359.2202013088
+ 31
+0.0
+ 0
+ARC
+ 5
+75
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.1595398236
+ 20
+361.9409267861
+ 30
+0.0
+ 40
+0.3992677940247622
+100
+AcDbArc
+ 50
+89.9681903289
+ 51
+114.7477262168
+ 0
+LINE
+ 5
+76
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+137.1597614904
+ 20
+362.3401945186
+ 30
+0.0
+ 11
+139.7899255922
+ 21
+362.3401945186
+ 31
+0.0
+ 0
+ARC
+ 5
+77
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+139.7899227961
+ 20
+361.9401917488
+ 30
+0.0
+ 40
+0.4000027697985571
+100
+AcDbArc
+ 50
+0.0045494665
+ 51
+89.9995994903
+ 0
+LINE
+ 5
+78
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+140.1899255646
+ 20
+361.9402235103
+ 30
+0.0
+ 11
+140.1899255646
+ 21
+360.4202097011
+ 31
+0.0
+ 0
+ARC
+ 5
+79
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+140.5899283325
+ 20
+360.4201937773
+ 30
+0.0
+ 40
+0.4000027681863966
+100
+AcDbArc
+ 50
+179.9977190938
+ 51
+269.999606256
+ 0
+LINE
+ 5
+7A
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+140.5899255836
+ 20
+360.0201910091
+ 30
+0.0
+ 11
+142.2699255703
+ 21
+360.0201910091
+ 31
+0.0
+ 0
+ARC
+ 5
+7B
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+142.2699229338
+ 20
+360.4201936183
+ 30
+0.0
+ 40
+0.4000026092087915
+100
+AcDbArc
+ 50
+270.0003776416
+ 51
+0.0023036787
+ 0
+LINE
+ 5
+7C
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+142.6699255427
+ 20
+360.4202097011
+ 30
+0.0
+ 11
+142.6699255427
+ 21
+361.9402235103
+ 31
+0.0
+ 0
+ARC
+ 5
+7D
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.0699283112
+ 20
+361.9401917488
+ 30
+0.0
+ 40
+0.4000027697974622
+100
+AcDbArc
+ 50
+90.0003871694
+ 51
+179.9954505335
+ 0
+LINE
+ 5
+7E
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.0699256082
+ 20
+362.3401945186
+ 30
+0.0
+ 11
+148.5899255445
+ 21
+362.3401945186
+ 31
+0.0
+ 0
+ARC
+ 5
+7F
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5899336175
+ 20
+362.4601862448
+ 30
+0.0
+ 40
+0.1199917263967713
+100
+AcDbArc
+ 50
+269.9961451292
+ 51
+0.0134590356
+ 0
+LINE
+ 5
+80
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+362.4602144314
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+366.669732864
+ 31
+0.0
+ 0
+ARC
+ 5
+81
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+366.669705415
+ 30
+0.0
+ 40
+0.2001077687858761
+100
+AcDbArc
+ 50
+0.0078593224
+ 51
+46.1736252111
+ 0
+ARC
+ 5
+82
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.229892261
+ 20
+367.4202030254
+ 30
+0.0
+ 40
+0.8399663770856335
+100
+AcDbArc
+ 50
+133.8120979057
+ 51
+226.1879020943
+ 0
+ARC
+ 5
+83
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5098175737
+ 20
+368.1707006358
+ 30
+0.0
+ 40
+0.200107768785933
+100
+AcDbArc
+ 50
+313.8263747889
+ 51
+359.9921406775
+ 0
+LINE
+ 5
+84
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.7099253406
+ 20
+368.1706731868
+ 30
+0.0
+ 11
+148.7099253406
+ 21
+370.3305070949
+ 31
+0.0
+ 0
+ARC
+ 5
+85
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5900202217
+ 20
+370.3305234822
+ 30
+0.0
+ 40
+0.1199051200450481
+100
+AcDbArc
+ 50
+359.9921694514
+ 51
+45.0183972297
+ 0
+LINE
+ 5
+86
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.6747787168
+ 20
+370.4153364254
+ 30
+0.0
+ 11
+148.5050731172
+ 21
+370.58504277
+ 31
+0.0
+ 0
+ARC
+ 5
+87
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5900489089
+ 20
+370.6699467703
+ 30
+0.0
+ 40
+0.1201231635795685
+100
+AcDbArc
+ 50
+180.0128717119
+ 51
+224.9757867508
+ 0
+LINE
+ 5
+88
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+148.4699257483
+ 20
+370.669919ontinuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484826
+ 20
+72.3821479784
+ 30
+0.0
+ 40
+0.399977127854635
+100
+AcDbArc
+ 50
+292.6176918057
+ 51
+0.0067619015
+ 0
+ARC
+ 5
+4D2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.2299252955
+ 20
+71.9021632155
+ 30
+0.0
+ 40
+0.1199998892853113
+100
+AcDbArc
+ 50
+112.6196870788
+ 51
+247.3803129212
+ 0
+ARC
+ 5
+4D3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484881
+ 20
+71.4221784593
+ 30
+0.0
+ 40
+0.3999771195634846
+100
+AcDbArc
+ 50
+0.0000677203
+ 51
+67.382308554
+ 0
+LINE
+ 5
+4D4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.4299256077
+ 20
+71.4221789321
+ 30
+0.0
+ 11
+149.4299256077
+ 21
+68.8558890304
+ 31
+0.0
+ 0
+ARC
+ 5
+4D5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.3098934248
+ 20
+68.8558875882
+ 30
+0.0
+ 40
+0.1200321828299822
+100
+AcDbArc
+ 50
+284.0483029705
+ 51
+0.0006883757
+ 0
+LINE
+ 5
+4D6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.3390300145
+ 20
+68.7394453963
+ 30
+0.0
+ 11
+149.2808216085
+ 21
+68.724901863
+ 31
+0.0
+ 0
+ARC
+ 5
+4D7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.3099570381
+ 20
+68.6084597995
+ 30
+0.0
+ 40
+0.1200317766406951
+100
+AcDbArc
+ 50
+104.0477806555
+ 51
+179.9779884139
+ 0
+LINE
+ 5
+4D8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1899252703
+ 20
+68.6085059127
+ 30
+0.0
+ 11
+149.1899252703
+ 21
+67.5958945235
+ 31
+0.0
+ 0
+ARC
+ 5
+4D9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.309957026
+ 20
+67.5958929344
+ 30
+0.0
+ 40
+0.1200317557485991
+100
+AcDbArc
+ 50
+179.999241474
+ 51
+255.952222776
+ 0
+LINE
+ 5
+4DA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.2808216085
+ 20
+67.4794508895
+ 30
+0.0
+ 11
+149.3390300145
+ 21
+67.4649073562
+ 31
+0.0
+ 0
+ARC
+ 5
+4DB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.3098934248
+ 20
+67.3484651642
+ 30
+0.0
+ 40
+0.1200321828298969
+100
+AcDbArc
+ 50
+359.9993116244
+ 51
+75.9516970296
+ 0
+LINE
+ 5
+4DC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.4299256077
+ 20
+67.3484637221
+ 30
+0.0
+ 11
+149.4299256077
+ 21
+64.7821738204
+ 31
+0.0
+ 0
+ARC
+ 5
+4DD
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484881
+ 20
+64.7821742931
+ 30
+0.0
+ 40
+0.3999771195634605
+100
+AcDbArc
+ 50
+292.617691446
+ 51
+359.9999322797
+ 0
+ARC
+ 5
+4DE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.2299252955
+ 20
+64.3021895369
+ 30
+0.0
+ 40
+0.1199998892853769
+100
+AcDbArc
+ 50
+112.6196870788
+ 51
+247.3803129212
+ 0
+ARC
+ 5
+4DF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.0299484826
+ 20
+63.8222047741
+ 30
+0.0
+ 40
+0.3999771278546918
+100
+AcDbArc
+ 50
+359.9932380985
+ 51
+67.3823081943
+ 0
+LINE
+ 5
+4E0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.4299256077
+ 20
+63.8221575698
+ 30
+0.0
+ 11
+149.4299256077
+ 21
+42.2443224868
+ 31
+0.0
+ 0
+ARC
+ 5
+4E1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+149.2877619365
+ 20
+42.2443402896
+ 30
+0.0
+ 40
+0.1421636723032661
+100
+AcDbArc
+ 50
+215.0074908018
+ 51
+359.9928249763
+ 0
+LINE
+ 5
+4E2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+149.1713189354
+ 20
+42.1627833327
+ 30
+0.0
+ 11
+148.4940879812
+ 21
+43.1299998244
+ 31
+0.0
+ 0
+ARC
+ 5
+4E3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+148.5923363035
+ 20
+43.1988138586
+ 30
+0.0
+ 40
+0.1199504236850504
+100
+AcDbArc
+ 50
+136.8044484108
+ 51
+215.0077544772
+ 0
+ARC
+ 5
+4E4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.6299254989
+ 20
+44.1021810107
+ 30
+0.0
+ 40
+1.200014262087228
+100
+AcDbArc
+ 50
+316.8133643338
+ 51
+223.1866356662
+ 0
+ARC
+ 5
+4E5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+146.667516349
+ 20
+43.1988139771
+ 30
+0.0
+ 40
+0.1199491362526016
+100
+AcDbArc
+ 50
+324.9917457236
+ 51
+43.1960513885
+ 0
+LINE
+ 5
+4E6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+146.7657630166
+ 20
+43.1299998244
+ 30
+0.0
+ 11
+146.1655196567
+ 21
+42.2727419814
+ 31
+0.0
+ 0
+ARC
+ 5
+4E7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.8378250788
+ 20
+42.5022486061
+ 30
+0.0
+ 40
+0.4000712776530942
+100
+AcDbArc
+ 50
+270.0048248044
+ 51
+324.9938514507
+ 0
+LINE
+ 5
+4E8
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+145.8378587683
+ 20
+42.1021773299
+ 30
+0.0
+ 11
+143.9099256714
+ 21
+42.1021773299
+ 31
+0.0
+ 0
+ARC
+ 5
+4E9
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.9098934092
+ 20
+42.1821451244
+ 30
+0.0
+ 40
+0.0799678010352872
+100
+AcDbArc
+ 50
+179.9674137886
+ 51
+270.0231154488
+ 0
+LINE
+ 5
+4EA
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.8299256211
+ 20
+42.1821906051
+ 30
+0.0
+ 11
+143.8299256211
+ 21
+42.7421881637
+ 31
+0.0
+ 0
+ARC
+ 5
+4EB
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+143.9099748178
+ 20
+42.7421522491
+ 30
+0.0
+ 40
+0.080049204801129
+100
+AcDbArc
+ 50
+90.0351768672
+ 51
+179.9742938954
+ 0
+LINE
+ 5
+4EC
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+143.9099256714
+ 20
+42.8222014388
+ 30
+0.0
+ 11
+145.3970798125
+ 21
+42.8222014388
+ 31
+0.0
+ 0
+ARC
+ 5
+4ED
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.3970883777
+ 20
+43.2221900281
+ 30
+0.0
+ 40
+0.3999885893651605
+100
+AcDbArc
+ 50
+269.9987730963
+ 51
+21.5094255355
+ 0
+ARC
+ 5
+4EE
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+147.6299070455
+ 20
+44.102180655
+ 30
+0.0
+ 40
+1.999982807792672
+100
+AcDbArc
+ 50
+166.3277484711
+ 51
+201.510375133
+ 0
+ARC
+ 5
+4EF
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+145.4922360036
+ 20
+44.6221751279
+ 30
+0.0
+ 40
+0.2000244053689678
+100
+AcDbArc
+ 50
+346.3324477609
+ 51
+89.9922055192
+ 0
+LINE
+ 5
+4F0
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbLine
+ 10
+145.4922632148
+ 20
+44.8221995315
+ 30
+0.0
+ 11
+137.3675879856
+ 21
+44.8221995315
+ 31
+0.0
+ 0
+ARC
+ 5
+4F1
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.3676151968
+ 20
+44.6221751279
+ 30
+0.0
+ 40
+0.2000244053689526
+100
+AcDbArc
+ 50
+90.0077944808
+ 51
+193.6675522391
+ 0
+ARC
+ 5
+4F2
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+135.2299441549
+ 20
+44.102180655
+ 30
+0.0
+ 40
+1.999982807792147
+100
+AcDbArc
+ 50
+338.489624867
+ 51
+13.672251529
+ 0
+ARC
+ 5
+4F3
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 7
+370
+ 0
+100
+AcDbCircle
+ 10
+137.4627628227
+ 20
+43.2221900281
+ 30
+0.0
+ 40
+0.399988589365143
+100
+AcDbArc
+ 50
+158.4905744645
+ 51
+270.0012269037
+ 0
+LINE
+ 5
+4F4
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 8
+370
+ 0
+100
+AcDbLine
+ 10
+148.8260940482
+ 20
+80.1358534774
+ 30
+0.0
+ 11
+148.8260940482
+ 21
+103.7777020415
+ 31
+0.0
+ 0
+LINE
+ 5
+4F5
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 8
+370
+ 0
+100
+AcDbLine
+ 10
+133.4835157563
+ 20
+80.1027132949
+ 30
+0.0
+ 11
+133.4835157563
+ 21
+103.7777020415
+ 31
+0.0
+ 0
+LINE
+ 5
+4F6
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 8
+370
+ 0
+100
+AcDbLine
+ 10
+148.5235550275
+ 20
+81.2455489119
+ 30
+0.0
+ 11
+148.5235550275
+ 21
+103.7777020415
+ 31
+0.0
+ 0
+LINE
+ 5
+4F7
+330
+1F
+100
+AcDbEntity
+ 8
+0
+ 6
+Continuous
+ 62
+ 8
+370
+ 0
+100
+AcDbLine
+ 10
+148.1099256148
+ 20
+82.7892615279
+ 30
+0.0
+ 11
+148.1099256148
+ 21
+103.7777020415
+ 31
+0.0
+ 0
+POINT
+ 5
+4F8
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+142.0299255838
+ 20
+-247.6988063932
+ 30
+0.0
+ 0
+POINT
+ 5
+4F9
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+149.4168593775
+ 20
+447.9345399732
+ 30
+0.0
+ 0
+POINT
+ 5
+4FA
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+149.4168593775
+ 20
+238.1745399732
+ 30
+0.0
+ 0
+POINT
+ 5
+4FB
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+147.8555696261
+ 20
+245.6618616408
+ 30
+0.0
+ 0
+POINT
+ 5
+4FC
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+147.8555696261
+ 20
+455.4218616408
+ 30
+0.0
+ 0
+POINT
+ 5
+4FD
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+148.0299255838
+ 20
+35.8618616408
+ 30
+0.0
+ 0
+POINT
+ 5
+4FE
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+149.4168593775
+ 20
+28.4145399732
+ 30
+0.0
+ 0
+POINT
+ 5
+4FF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbPoint
+ 10
+133.4299255838
+ 20
+660.3011936068
+ 30
+0.0
+ 0
+DIMENSION
+ 5
+500
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+34.5771309945
+ 31
+0.0
+ 70
+ 160
+ 1
+33
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE0
+100
+AcDbAlignedDimension
+ 13
+142.0299255838
+ 23
+28.7821787182
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+41.9821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+50D
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_1
+ 10
+171.4299255838
+ 20
+287.499722104
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+271.6850735678
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+280.0124004364
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+287.499722104
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+51A
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_2
+ 10
+171.4299255838
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+194.8678981433
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+202.8200717467
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+210.3073934143
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+526
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_3
+ 10
+171.4299255838
+ 20
+133.7256838344
+ 30
+0.0
+ 11
+171.4299255838
+ 21
+113.1236101725
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+149.4168593775
+ 23
+126.2783621669
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+133.7256838344
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+532
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_4
+ 10
+195.4299255838
+ 20
+41.9821787182
+ 30
+0.0
+ 11
+195.4299255838
+ 21
+84.1586135498
+ 31
+0.0
+ 70
+ 160
+ 1
+675,902
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+148.0299255838
+ 23
+133.7256838344
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+41.9821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+53C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_5
+ 10
+195.3191971725
+ 20
+133.7649839595
+ 30
+0.0
+ 11
+195.2817915125
+ 21
+178.7746730971
+ 31
+0.0
+ 70
+ 160
+ 1
+524,500
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+210.3073934143
+ 33
+0.0
+ 14
+148.0299255838
+ 24
+133.7256838344
+ 34
+0.0
+ 50
+-89.9523838979
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+545
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_6
+ 10
+195.2555696261
+ 20
+210.3073934143
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+246.0726158741
+ 31
+0.0
+ 70
+ 160
+ 1
+524,400
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+287.499722104
+ 33
+0.0
+ 14
+147.8555696261
+ 24
+210.3073934143
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+54E
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_7
+ 10
+195.2555696261
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+195.2555696261
+ 21
+357.7845521004
+ 31
+0.0
+ 70
+ 160
+ 1
+545,698
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+147.8555696261
+ 23
+287.499722104
+ 33
+0.0
+ 14
+145.8378589248
+ 24
+397.2202084954
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+557
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_8
+ 10
+219.4299255838
+ 20
+397.2202084954
+ 30
+0.0
+ 11
+219.4299255838
+ 21
+226.31135989
+ 31
+0.0
+ 70
+ 160
+ 1
+Kozijnmaat =
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+142.0299255838
+ 23
+28.7821787182
+ 33
+0.0
+ 14
+145.8378589248
+ 24
+397.2202084954
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+561
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_9
+ 10
+99.2299255838
+ 20
+28.7821787182
+ 30
+0.0
+ 11
+99.2299255838
+ 21
+214.5361780403
+ 31
+0.0
+ 70
+ 160
+ 1
+DMH =
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE2
+100
+AcDbAlignedDimension
+ 13
+133.4299255838
+ 23
+383.8202084954
+ 33
+0.0
+ 14
+142.0299255838
+ 24
+28.7821787182
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+56C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_10
+ 10
+117.2299255838
+ 20
+148.4450158005
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+157.3719824392
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+147.8850158005
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+148.4450158005
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+578
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_11
+ 10
+117.2299255838
+ 20
+224.9867253803
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+236.5334651005
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+224.4267253803
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+224.9867253803
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+DIMENSION
+ 5
+584
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+100
+AcDbDimension
+ 2
+_D_12
+ 10
+117.2299255838
+ 20
+302.17905407
+ 30
+0.0
+ 11
+117.2299255838
+ 21
+311.8110919194
+ 31
+0.0
+ 70
+ 160
+ 1
+<>
+ 71
+ 2
+ 42
+-1.0
+ 3
+SLDDIMSTYLE1
+100
+AcDbAlignedDimension
+ 13
+133.5499255838
+ 23
+301.61905407
+ 33
+0.0
+ 14
+133.5499255838
+ 24
+302.17905407
+ 34
+0.0
+ 50
+90.0
+100
+AcDbRotatedDimension
+ 0
+LINE
+ 5
+590
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+591
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+592
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+593
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+101.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+594
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+101.7777066237
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+595
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+596
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+597
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+107.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+598
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+107.7777066237
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+599
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+103.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59A
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+103.7777066237
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59B
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+105.7777066237
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+105.7777066237
+ 31
+0.0
+ 0
+LINE
+ 5
+59C
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59D
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59E
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+59F
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+177.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A0
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+177.2366515846
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A1
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A2
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A3
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+183.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A4
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+183.2366515846
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A5
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+179.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A6
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+179.2366515846
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A7
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+181.2366515846
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+181.2366515846
+ 31
+0.0
+ 0
+LINE
+ 5
+5A8
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5A9
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AA
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AB
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+254.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AC
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+254.4750445598
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AD
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AE
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5AF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+260.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B0
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+260.4750445598
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B1
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+256.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B2
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+256.4750445598
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B3
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+258.4750445598
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+258.4750445598
+ 31
+0.0
+ 0
+LINE
+ 5
+5B4
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B5
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B6
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B7
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+332.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B8
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+332.7369117996
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5B9
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BA
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+152.4849255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+142.3699255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BB
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+142.3699255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+143.3699255838
+ 21
+338.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BC
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+143.3699255838
+ 20
+338.7369117996
+ 30
+0.0
+ 11
+141.3699255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BD
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+141.3699255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+139.3699255838
+ 21
+334.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BE
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+139.3699255838
+ 20
+334.7369117996
+ 30
+0.0
+ 11
+140.3699255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+LINE
+ 5
+5BF
+330
+1F
+100
+AcDbEntity
+ 8
+HARTLIJN
+ 62
+ 7
+100
+AcDbLine
+ 10
+140.3699255838
+ 20
+336.7369117996
+ 30
+0.0
+ 11
+130.2549255838
+ 21
+336.7369117996
+ 31
+0.0
+ 0
+ENDSEC
+ 0
+SECTION
+ 2
+OBJECTS
+ 0
+DICTIONARY
+ 5
+C
+330
+0
+100
+AcDbDictionary
+281
+ 1
+ 3
+ACAD_GROUP
+350
+D
+ 3
+ACAD_LAYOUT
+350
+1A
+ 3
+ACAD_MLINESTYLE
+350
+17
+ 3
+ACAD_PLOTSETTINGS
+350
+19
+ 3
+ACAD_PLOTSTYLENAME
+350
+E
+ 0
+DICTIONARY
+ 5
+D
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 0
+DICTIONARY
+ 5
+1A
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 3
+Layout1
+350
+1E
+ 3
+Layout2
+350
+26
+ 3
+Model
+350
+22
+ 0
+DICTIONARY
+ 5
+17
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 3
+Standard
+350
+18
+ 0
+DICTIONARY
+ 5
+19
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 0
+ACDBDICTIONARYWDFLT
+ 5
+E
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+330
+C
+100
+AcDbDictionary
+281
+ 1
+ 3
+Normal
+350
+F
+100
+AcDbDictionaryWithDefault
+340
+F
+ 0
+LAYOUT
+ 5
+1E
+102
+{ACAD_REACTORS
+330
+1A
+102
+}
+330
+1A
+100
+AcDbPlotSettings
+ 1
+
+ 2
+none_device
+ 4
+
+ 6
+
+ 40
+0.0
+ 41
+0.0
+ 42
+0.0
+ 43
+0.0
+ 44
+0.0
+ 45
+0.0
+ 46
+0.0
+ 47
+0.0
+ 48
+0.0
+ 49
+0.0
+140
+0.0
+141
+0.0
+142
+1.0
+143
+1.0
+ 70
+ 688
+ 72
+ 0
+ 73
+ 0
+ 74
+ 5
+ 7
+
+ 75
+ 16
+147
+1.0
+148
+0.0
+149
+0.0
+100
+AcDbLayout
+ 1
+Layout1
+ 70
+ 1
+ 71
+ 1
+ 10
+0.0
+ 20
+0.0
+ 11
+420.0
+ 21
+297.0
+ 12
+0.0
+ 22
+0.0
+ 32
+0.0
+ 14
+1.0000000000E+20
+ 24
+1.0000000000E+20
+ 34
+1.0000000000E+20
+ 15
+-1.0000000000E+20
+ 25
+-1.0000000000E+20
+ 35
+-1.0000000000E+20
+146
+0.0
+ 13
+0.0
+ 23
+0.0
+ 33
+0.0
+ 16
+1.0
+ 26
+0.0
+ 36
+0.0
+ 17
+0.0
+ 27
+1.0
+ 37
+0.0
+ 76
+ 0
+330
+1B
+ 0
+LAYOUT
+ 5
+26
+102
+{ACAD_REACTORS
+330
+1A
+102
+}
+330
+1A
+100
+AcDbPlotSettings
+ 1
+
+ 2
+none_device
+ 4
+
+ 6
+
+ 40
+0.0
+ 41
+0.0
+ 42
+0.0
+ 43
+0.0
+ 44
+0.0
+ 45
+0.0
+ 46
+0.0
+ 47
+0.0
+ 48
+0.0
+ 49
+0.0
+140
+0.0
+141
+0.0
+142
+1.0
+143
+1.0
+ 70
+ 688
+ 72
+ 0
+ 73
+ 0
+ 74
+ 5
+ 7
+
+ 75
+ 16
+147
+1.0
+148
+0.0
+149
+0.0
+100
+AcDbLayout
+ 1
+Layout2
+ 70
+ 1
+ 71
+ 2
+ 10
+0.0
+ 20
+0.0
+ 11
+0.0
+ 21
+0.0
+ 12
+0.0
+ 22
+0.0
+ 32
+0.0
+ 14
+0.0
+ 24
+0.0
+ 34
+0.0
+ 15
+0.0
+ 25
+0.0
+ 35
+0.0
+146
+0.0
+ 13
+0.0
+ 23
+0.0
+ 33
+0.0
+ 16
+1.0
+ 26
+0.0
+ 36
+0.0
+ 17
+0.0
+ 27
+1.0
+ 37
+0.0
+ 76
+ 0
+330
+23
+ 0
+LAYOUT
+ 5
+22
+102
+{ACAD_REACTORS
+330
+1A
+102
+}
+330
+1A
+100
+AcDbPlotSettings
+ 1
+
+ 2
+none_device
+ 4
+
+ 6
+
+ 40
+0.0
+ 41
+0.0
+ 42
+0.0
+ 43
+0.0
+ 44
+0.0
+ 45
+0.0
+ 46
+0.0
+ 47
+0.0
+ 48
+0.0
+ 49
+0.0
+140
+0.0
+141
+0.0
+142
+1.0
+143
+1.0
+ 70
+ 1712
+ 72
+ 0
+ 73
+ 0
+ 74
+ 0
+ 7
+
+ 75
+ 0
+147
+1.0
+148
+0.0
+149
+0.0
+100
+AcDbLayout
+ 1
+Model
+ 70
+ 1
+ 71
+ 0
+ 10
+0.0
+ 20
+0.0
+ 11
+297.0
+ 21
+420.0
+ 12
+0.0
+ 22
+0.0
+ 32
+0.0
+ 14
+0.0
+ 24
+0.0
+ 34
+0.0
+ 15
+297.0
+ 25
+420.0
+ 35
+0.0
+146
+0.0
+ 13
+0.0
+ 23
+0.0
+ 33
+0.0
+ 16
+1.0
+ 26
+0.0
+ 36
+0.0
+ 17
+0.0
+ 27
+1.0
+ 37
+0.0
+ 76
+ 0
+330
+1F
+331
+29
+ 0
+MLINESTYLE
+ 5
+18
+102
+{ACAD_REACTORS
+330
+17
+102
+}
+330
+17
+100
+AcDbMlineStyle
+ 2
+Standard
+ 70
+ 0
+ 3
+
+ 62
+ 256
+ 51
+90.0
+ 52
+90.0
+ 71
+ 2
+ 49
+0.5
+ 62
+ 256
+ 6
+BYLAYER
+ 49
+-0.5
+ 62
+ 256
+ 6
+BYLAYER
+ 0
+ACDBPLACEHOLDER
+ 5
+F
+102
+{ACAD_REACTORS
+330
+E
+102
+}
+330
+E
+ 0
+ENDSEC
+ 0
+EOF
diff --git a/vcl/qa/cppunit/graphicfilter/data/dxf/pass/pyramid.dxf b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/pyramid.dxf
new file mode 100644
index 000000000..65cd5f838
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/dxf/pass/pyramid.dxf
@@ -0,0 +1,25008 @@
+0
+SECTION
+2
+HEADER
+9
+$ACADVER
+1
+AC1014
+9
+$ACADMAINTVER
+70
+8
+9
+$DWGCODEPAGE
+3
+ANSI_1252
+9
+$INSBASE
+10
+0.0
+20
+0.0
+30
+0.0
+9
+$EXTMIN
+10
+1.000000E+20
+20
+1.000000E+20
+30
+1.000000E+20
+9
+$EXTMAX
+10
+-1.000000E+20
+20
+-1.000000E+20
+30
+-1.000000E+20
+9
+$LIMMIN
+10
+0.0
+20
+0.0
+9
+$LIMMAX
+10
+12.0
+20
+9.0
+9
+$ORTHOMODE
+70
+0
+9
+$REGENMODE
+70
+1
+9
+$FILLMODE
+70
+1
+9
+$QTEXTMODE
+70
+0
+9
+$MIRRTEXT
+70
+1
+9
+$DRAGMODE
+70
+2
+9
+$LTSCALE
+40
+1.0
+9
+$OSMODE
+70
+0
+9
+$ATTMODE
+70
+1
+9
+$TEXTSIZE
+40
+0.2
+9
+$TRACEWID
+40
+0.05
+9
+$TEXTSTYLE
+7
+STANDARD
+9
+$CLAYER
+8
+0
+9
+$CELTYPE
+6
+BYLAYER
+9
+$CECOLOR
+62
+256
+9
+$CELTSCALE
+40
+1.0
+9
+$DELOBJ
+70
+1
+9
+$DISPSILH
+70
+0
+9
+$DIMSCALE
+40
+1.0
+9
+$DIMASZ
+40
+0.18
+9
+$DIMEXO
+40
+0.0625
+9
+$DIMDLI
+40
+0.38
+9
+$DIMRND
+40
+0.0
+9
+$DIMDLE
+40
+0.0
+9
+$DIMEXE
+40
+0.18
+9
+$DIMTP
+40
+0.0
+9
+$DIMTM
+40
+0.0
+9
+$DIMTXT
+40
+0.18
+9
+$DIMCEN
+40
+0.09
+9
+$DIMTSZ
+40
+0.0
+9
+$DIMTOL
+70
+0
+9
+$DIMLIM
+70
+0
+9
+$DIMTIH
+70
+1
+9
+$DIMTOH
+70
+1
+9
+$DIMSE1
+70
+0
+9
+$DIMSE2
+70
+0
+9
+$DIMTAD
+70
+0
+9
+$DIMZIN
+70
+0
+9
+$DIMBLK
+1
+
+9
+$DIMASO
+70
+1
+9
+$DIMSHO
+70
+1
+9
+$DIMPOST
+1
+
+9
+$DIMAPOST
+1
+
+9
+$DIMALT
+70
+0
+9
+$DIMALTD
+70
+2
+9
+$DIMALTF
+40
+25.4
+9
+$DIMLFAC
+40
+1.0
+9
+$DIMTOFL
+70
+0
+9
+$DIMTVP
+40
+0.0
+9
+$DIMTIX
+70
+0
+9
+$DIMSOXD
+70
+0
+9
+$DIMSAH
+70
+0
+9
+$DIMBLK1
+1
+
+9
+$DIMBLK2
+1
+
+9
+$DIMSTYLE
+2
+STANDARD
+9
+$DIMCLRD
+70
+0
+9
+$DIMCLRE
+70
+0
+9
+$DIMCLRT
+70
+0
+9
+$DIMTFAC
+40
+1.0
+9
+$DIMGAP
+40
+0.09
+9
+$DIMJUST
+70
+0
+9
+$DIMSD1
+70
+0
+9
+$DIMSD2
+70
+0
+9
+$DIMTOLJ
+70
+1
+9
+$DIMTZIN
+70
+0
+9
+$DIMALTZ
+70
+0
+9
+$DIMALTTZ
+70
+0
+9
+$DIMFIT
+70
+3
+9
+$DIMUPT
+70
+0
+9
+$DIMUNIT
+70
+2
+9
+$DIMDEC
+70
+4
+9
+$DIMTDEC
+70
+4
+9
+$DIMALTU
+70
+2
+9
+$DIMALTTD
+70
+2
+9
+$DIMTXSTY
+7
+STANDARD
+9
+$DIMAUNIT
+70
+0
+9
+$LUNITS
+70
+2
+9
+$LUPREC
+70
+4
+9
+$SKETCHINC
+40
+0.1
+9
+$FILLETRAD
+40
+0.5
+9
+$AUNITS
+70
+0
+9
+$AUPREC
+70
+0
+9
+$MENU
+1
+.
+9
+$ELEVATION
+40
+0.0
+9
+$PELEVATION
+40
+0.0
+9
+$THICKNESS
+40
+0.0
+9
+$LIMCHECK
+70
+0
+9
+$BLIPMODE
+70
+0
+9
+$CHAMFERA
+40
+0.5
+9
+$CHAMFERB
+40
+0.5
+9
+$CHAMFERC
+40
+1.0
+9
+$CHAMFERD
+40
+0.0
+9
+$SKPOLY
+70
+1
+9
+$TDCREATE
+40
+2451008.519973958
+9
+$TDUPDATE
+40
+2451008.523538426
+9
+$TDINDWG
+40
+0.0024055556
+9
+$TDUSRTIMER
+40
+0.0024055556
+9
+$USRTIMER
+70
+1
+9
+$ANGBASE
+50
+0.0
+9
+$ANGDIR
+70
+0
+9
+$PDMODE
+70
+0
+9
+$PDSIZE
+40
+0.0
+9
+$PLINEWID
+40
+0.0
+9
+$COORDS
+70
+1
+9
+$SPLFRAME
+70
+0
+9
+$SPLINETYPE
+70
+6
+9
+$SPLINESEGS
+70
+8
+9
+$ATTDIA
+70
+0
+9
+$ATTREQ
+70
+1
+9
+$HANDLING
+70
+1
+9
+$HANDSEED
+5
+5B
+9
+$SURFTAB1
+70
+6
+9
+$SURFTAB2
+70
+6
+9
+$SURFTYPE
+70
+6
+9
+$SURFU
+70
+6
+9
+$SURFV
+70
+6
+9
+$UCSNAME
+2
+
+9
+$UCSORG
+10
+0.0
+20
+0.0
+30
+0.0
+9
+$UCSXDIR
+10
+1.0
+20
+0.0
+30
+0.0
+9
+$UCSYDIR
+10
+0.0
+20
+1.0
+30
+0.0
+9
+$PUCSNAME
+2
+
+9
+$PUCSORG
+10
+0.0
+20
+0.0
+30
+0.0
+9
+$PUCSXDIR
+10
+1.0
+20
+0.0
+30
+0.0
+9
+$PUCSYDIR
+10
+0.0
+20
+1.0
+30
+0.0
+9
+$USERI1
+70
+0
+9
+$USERI2
+70
+0
+9
+$USERI3
+70
+0
+9
+$USERI4
+70
+0
+9
+$USERI5
+70
+0
+9
+$USERR1
+40
+0.0
+9
+$USERR2
+40
+0.0
+9
+$USERR3
+40
+0.0
+9
+$USERR4
+40
+0.0
+9
+$USERR5
+40
+0.0
+9
+$WORLDVIEW
+70
+1
+9
+$SHADEDGE
+70
+3
+9
+$SHADEDIF
+70
+70
+9
+$TILEMODE
+70
+1
+9
+$MAXACTVP
+70
+48
+9
+$PINSBASE
+10
+0.0
+20
+0.0
+30
+0.0
+9
+$PLIMCHECK
+70
+0
+9
+$PEXTMIN
+10
+1.000000E+20
+20
+1.000000E+20
+30
+1.000000E+20
+9
+$PEXTMAX
+10
+-1.000000E+20
+20
+-1.000000E+20
+30
+-1.000000E+20
+9
+$PLIMMIN
+10
+0.0
+20
+0.0
+9
+$PLIMMAX
+10
+12.0
+20
+9.0
+9
+$UNITMODE
+70
+0
+9
+$VISRETAIN
+70
+1
+9
+$PLINEGEN
+70
+0
+9
+$PSLTSCALE
+70
+1
+9
+$TREEDEPTH
+70
+3020
+9
+$PICKSTYLE
+70
+1
+9
+$CMLSTYLE
+2
+STANDARD
+9
+$CMLJUST
+70
+0
+9
+$CMLSCALE
+40
+1.0
+9
+$PROXYGRAPHICS
+70
+1
+9
+$MEASUREMENT
+70
+0
+0
+ENDSEC
+0
+SECTION
+2
+CLASSES
+0
+ENDSEC
+0
+SECTION
+2
+TABLES
+0
+TABLE
+2
+VPORT
+5
+8
+100
+AcDbSymbolTable
+70
+3
+0
+VPORT
+5
+5A
+100
+AcDbSymbolTableRecord
+100
+AcDbViewportTableRecord
+2
+*ACTIVE
+70
+0
+10
+0.0
+20
+0.0
+11
+1.0
+21
+1.0
+12
+7.623626
+22
+4.5
+13
+0.0
+23
+0.0
+14
+0.5
+24
+0.5
+15
+0.5
+25
+0.5
+16
+0.0
+26
+0.0
+36
+1.0
+17
+0.0
+27
+0.0
+37
+0.0
+40
+9.0
+41
+1.694139
+42
+50.0
+43
+0.0
+44
+0.0
+50
+0.0
+51
+0.0
+71
+0
+72
+100
+73
+1
+74
+1
+75
+0
+76
+0
+77
+0
+78
+0
+0
+ENDTAB
+0
+TABLE
+2
+LTYPE
+5
+5
+100
+AcDbSymbolTable
+70
+1
+0
+LTYPE
+5
+13
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+2
+BYBLOCK
+70
+0
+3
+
+72
+65
+73
+0
+40
+0.0
+0
+LTYPE
+5
+14
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+2
+BYLAYER
+70
+0
+3
+
+72
+65
+73
+0
+40
+0.0
+0
+LTYPE
+5
+15
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+2
+CONTINUOUS
+70
+0
+3
+Solid line
+72
+65
+73
+0
+40
+0.0
+0
+ENDTAB
+0
+TABLE
+2
+LAYER
+5
+2
+100
+AcDbSymbolTable
+70
+10
+0
+LAYER
+5
+F
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+0
+70
+0
+62
+7
+6
+CONTINUOUS
+0
+LAYER
+5
+4C
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+FRAMES
+70
+0
+62
+2
+6
+CONTINUOUS
+0
+LAYER
+5
+4D
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+JOINTS
+70
+0
+62
+2
+6
+CONTINUOUS
+0
+LAYER
+5
+4E
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+SHELLS
+70
+0
+62
+1
+6
+CONTINUOUS
+0
+LAYER
+5
+4F
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+GRIDS
+70
+0
+62
+8
+6
+CONTINUOUS
+0
+LAYER
+5
+50
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+PLANES
+70
+0
+62
+5
+6
+CONTINUOUS
+0
+LAYER
+5
+51
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+ASOLIDS
+70
+0
+62
+6
+6
+CONTINUOUS
+0
+LAYER
+5
+52
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+SOLIDS
+70
+0
+62
+7
+6
+CONTINUOUS
+0
+LAYER
+5
+53
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+TEXT
+70
+0
+62
+94
+6
+CONTINUOUS
+0
+LAYER
+5
+58
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+NLLINKS
+70
+0
+62
+3
+6
+CONTINUOUS
+0
+ENDTAB
+0
+TABLE
+2
+STYLE
+5
+3
+100
+AcDbSymbolTable
+70
+1
+0
+STYLE
+5
+10
+100
+AcDbSymbolTableRecord
+100
+AcDbTextStyleTableRecord
+2
+STANDARD
+70
+0
+40
+0.0
+41
+1.0
+50
+0.0
+71
+0
+42
+0.2
+3
+txt
+4
+
+0
+ENDTAB
+0
+TABLE
+2
+VIEW
+5
+6
+100
+AcDbSymbolTable
+70
+0
+0
+ENDTAB
+0
+TABLE
+2
+UCS
+5
+7
+100
+AcDbSymbolTable
+70
+0
+0
+ENDTAB
+0
+TABLE
+2
+APPID
+5
+9
+100
+AcDbSymbolTable
+70
+1
+0
+APPID
+5
+11
+100
+AcDbSymbolTableRecord
+100
+AcDbRegAppTableRecord
+2
+ACAD
+70
+0
+0
+ENDTAB
+0
+TABLE
+2
+DIMSTYLE
+5
+A
+100
+AcDbSymbolTable
+70
+1
+0
+DIMSTYLE
+105
+1D
+100
+AcDbSymbolTableRecord
+100
+AcDbDimStyleTableRecord
+2
+STANDARD
+70
+0
+3
+
+4
+
+5
+
+6
+
+7
+
+40
+1.0
+41
+0.18
+42
+0.0625
+43
+0.38
+44
+0.18
+45
+0.0
+46
+0.0
+47
+0.0
+48
+0.0
+140
+0.18
+141
+0.09
+142
+0.0
+143
+25.4
+144
+1.0
+145
+0.0
+146
+1.0
+147
+0.09
+71
+0
+72
+0
+73
+1
+74
+1
+75
+0
+76
+0
+77
+0
+78
+0
+170
+0
+171
+2
+172
+0
+173
+0
+174
+0
+175
+0
+176
+0
+177
+0
+178
+0
+270
+2
+271
+4
+272
+4
+273
+2
+274
+2
+340
+10
+275
+0
+280
+0
+281
+0
+282
+0
+283
+1
+284
+0
+285
+0
+286
+0
+287
+3
+288
+0
+0
+ENDTAB
+0
+TABLE
+2
+BLOCK_RECORD
+5
+1
+100
+AcDbSymbolTable
+70
+0
+0
+BLOCK_RECORD
+5
+19
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+2
+*MODEL_SPACE
+0
+BLOCK_RECORD
+5
+16
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+2
+*PAPER_SPACE
+0
+ENDTAB
+0
+ENDSEC
+0
+SECTION
+2
+BLOCKS
+0
+BLOCK
+5
+1A
+100
+AcDbEntity
+8
+0
+100
+AcDbBlockBegin
+2
+*MODEL_SPACE
+70
+0
+10
+0.0
+20
+0.0
+30
+0.0
+3
+*MODEL_SPACE
+1
+
+0
+ENDBLK
+5
+1B
+100
+AcDbEntity
+8
+0
+100
+AcDbBlockEnd
+0
+BLOCK
+5
+17
+100
+AcDbEntity
+67
+1
+8
+0
+100
+AcDbBlockBegin
+2
+*PAPER_SPACE
+70
+0
+10
+0.0
+20
+0.0
+30
+0.0
+3
+*PAPER_SPACE
+1
+
+0
+ENDBLK
+5
+18
+100
+AcDbEntity
+67
+1
+8
+0
+100
+AcDbBlockEnd
+0
+ENDSEC
+0
+SECTION
+2
+ENTITIES
+0
+POLYLINE
+5
+B1
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B2
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B3
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B4
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B5
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B6
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B7
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B8
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B9
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B10
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B11
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B12
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B13
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B14
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B15
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B16
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B17
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B18
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B19
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-684
+30
+240
+70
+64
+0
+SEQEND
+5
+B20
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B21
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B22
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B23
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B24
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B25
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B26
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B27
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B28
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B29
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B30
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B31
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B32
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B33
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B34
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B35
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B36
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B37
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B38
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B39
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-648
+30
+480
+70
+64
+0
+SEQEND
+5
+B40
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B41
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B42
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B43
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B44
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B45
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B46
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B47
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B48
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B49
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B50
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B51
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B52
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B53
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B54
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B55
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B56
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B57
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B58
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B59
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-612
+30
+720
+70
+64
+0
+SEQEND
+5
+B60
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B61
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B62
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B63
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B64
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B65
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B66
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B67
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B68
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B69
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B70
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B71
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B72
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B73
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B74
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B75
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B76
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B77
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B78
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B79
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-576
+30
+960
+70
+64
+0
+SEQEND
+5
+B80
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B81
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B82
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B83
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B84
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B85
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B86
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B87
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B88
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B89
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B90
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B91
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B92
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B93
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B94
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B95
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B96
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B97
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B98
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B99
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+SEQEND
+5
+B100
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B101
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B102
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B103
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B104
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B105
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B106
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B107
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B108
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B109
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B110
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B111
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B112
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B113
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B114
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B115
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B116
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B117
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B118
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B119
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+SEQEND
+5
+B120
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B121
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B122
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B123
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B124
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B125
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B126
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B127
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B128
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B129
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B130
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B131
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B132
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B133
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B134
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B135
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B136
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B137
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B138
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B139
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+SEQEND
+5
+B140
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B141
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B142
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B143
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B144
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B145
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B146
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B147
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B148
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B149
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B150
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B151
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B152
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B153
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B154
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B155
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B156
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B157
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B158
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B159
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-432
+30
+960
+70
+64
+0
+SEQEND
+5
+B160
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B161
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B162
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B163
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B164
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B165
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B166
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B167
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B168
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B169
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B170
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B171
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B172
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B173
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B174
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B175
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B176
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B177
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B178
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B179
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+SEQEND
+5
+B180
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B181
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B182
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B183
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B184
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B185
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B186
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B187
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B188
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B189
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B190
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B191
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B192
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B193
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B194
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B195
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B196
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B197
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B198
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B199
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+SEQEND
+5
+B200
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B201
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B202
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B203
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B204
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B205
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B206
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B207
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B208
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B209
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B210
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B211
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B212
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B213
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B214
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B215
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B216
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B217
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B218
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B219
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+SEQEND
+5
+B220
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B221
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B222
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B223
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B224
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B225
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B226
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B227
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B228
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B229
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B230
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B231
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B232
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B233
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B234
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B235
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B236
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B237
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B238
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B239
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-288
+30
+960
+70
+64
+0
+SEQEND
+5
+B240
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B241
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B242
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B243
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B244
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B245
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B246
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B247
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B248
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B249
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B250
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B251
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B252
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B253
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B254
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B255
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B256
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B257
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B258
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B259
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+SEQEND
+5
+B260
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B261
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B262
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B263
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B264
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B265
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B266
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B267
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B268
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B269
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B270
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B271
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B272
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B273
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B274
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B275
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B276
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B277
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B278
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B279
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+SEQEND
+5
+B280
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B281
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B282
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B283
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B284
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B285
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B286
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B287
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B288
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B289
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B290
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B291
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B292
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B293
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B294
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B295
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B296
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B297
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B298
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B299
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+SEQEND
+5
+B300
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B301
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B302
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B303
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B304
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B305
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B306
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B307
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B308
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B309
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B310
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B311
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B312
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B313
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B314
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B315
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B316
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B317
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B318
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B319
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+-144
+30
+960
+70
+64
+0
+SEQEND
+5
+B320
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B321
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B322
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B323
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B324
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B325
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B326
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B327
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B328
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B329
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+720
+30
+0
+70
+64
+0
+VERTEX
+5
+B330
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-480
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B331
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B332
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+720
+30
+0
+70
+64
+0
+VERTEX
+5
+B333
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B334
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B335
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B336
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B337
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B338
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B339
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+SEQEND
+5
+B340
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B341
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B342
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B343
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B344
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B345
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B346
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B347
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B348
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B349
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B350
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-444
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B351
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B352
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B353
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B354
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B355
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B356
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B357
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B358
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B359
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+SEQEND
+5
+B360
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B361
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B362
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B363
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B364
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B365
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B366
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B367
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B368
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B369
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B370
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-408
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B371
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B372
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B373
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B374
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B375
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B376
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B377
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B378
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B379
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+SEQEND
+5
+B380
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B381
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B382
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B383
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B384
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B385
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B386
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B387
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B388
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B389
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B390
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-372
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B391
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B392
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B393
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B394
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B395
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B396
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B397
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B398
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B399
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-336
+20
+0
+30
+960
+70
+64
+0
+SEQEND
+5
+B400
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B401
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B402
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B403
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B404
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B405
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B406
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B407
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B408
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B409
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B410
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B411
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B412
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B413
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B414
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B415
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B416
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B417
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B418
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B419
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+SEQEND
+5
+B420
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B421
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B422
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B423
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B424
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B425
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B426
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B427
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B428
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B429
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B430
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B431
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B432
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B433
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B434
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B435
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B436
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B437
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B438
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B439
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+SEQEND
+5
+B440
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B441
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B442
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B443
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B444
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B445
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B446
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B447
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B448
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B449
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B450
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B451
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B452
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B453
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B454
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B455
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B456
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B457
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B458
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B459
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+SEQEND
+5
+B460
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B461
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B462
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B463
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B464
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B465
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B466
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B467
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B468
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B469
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B470
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B471
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B472
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B473
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B474
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B475
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B476
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B477
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B478
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B479
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-576
+30
+960
+70
+64
+0
+SEQEND
+5
+B480
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B481
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B482
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B483
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B484
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B485
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B486
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B487
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B488
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B489
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B490
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B491
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B492
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B493
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B494
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B495
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B496
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B497
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B498
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B499
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+SEQEND
+5
+B500
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B501
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B502
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B503
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B504
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B505
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B506
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B507
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B508
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B509
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B510
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B511
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B512
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B513
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B514
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B515
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B516
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B517
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B518
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B519
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+SEQEND
+5
+B520
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B521
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B522
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B523
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B524
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B525
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B526
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B527
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B528
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B529
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B530
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B531
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B532
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B533
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B534
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B535
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B536
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B537
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B538
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B539
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+SEQEND
+5
+B540
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B541
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B542
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B543
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B544
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B545
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B546
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B547
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B548
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B549
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B550
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B551
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B552
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B553
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B554
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B555
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B556
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B557
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B558
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B559
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-432
+30
+960
+70
+64
+0
+SEQEND
+5
+B560
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B561
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B562
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B563
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B564
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B565
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B566
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B567
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B568
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B569
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B570
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B571
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B572
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B573
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B574
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B575
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B576
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B577
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B578
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B579
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+SEQEND
+5
+B580
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B581
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B582
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B583
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B584
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B585
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B586
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B587
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B588
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B589
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B590
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B591
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B592
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B593
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B594
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B595
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B596
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B597
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B598
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B599
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+SEQEND
+5
+B600
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B601
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B602
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B603
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B604
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B605
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B606
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B607
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B608
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B609
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B610
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B611
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B612
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B613
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B614
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B615
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B616
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B617
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B618
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B619
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+SEQEND
+5
+B620
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B621
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B622
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B623
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B624
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B625
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B626
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B627
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B628
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B629
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B630
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B631
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B632
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B633
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B634
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B635
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B636
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B637
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B638
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B639
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-288
+30
+960
+70
+64
+0
+SEQEND
+5
+B640
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B641
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B642
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B643
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B644
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B645
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B646
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B647
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B648
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B649
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B650
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B651
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B652
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B653
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B654
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B655
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B656
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B657
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B658
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B659
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+SEQEND
+5
+B660
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B661
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B662
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B663
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B664
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B665
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B666
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B667
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B668
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B669
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B670
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B671
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B672
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B673
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B674
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B675
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B676
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B677
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B678
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B679
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+SEQEND
+5
+B680
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B681
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B682
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B683
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B684
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B685
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B686
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B687
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B688
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B689
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B690
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B691
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B692
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B693
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B694
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B695
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B696
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B697
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B698
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B699
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+SEQEND
+5
+B700
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B701
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B702
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B703
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B704
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B705
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B706
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B707
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B708
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B709
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B710
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B711
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B712
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B713
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B714
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B715
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B716
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B717
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B718
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B719
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+-144
+30
+960
+70
+64
+0
+SEQEND
+5
+B720
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B721
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B722
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B723
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B724
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B725
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B726
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B727
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B728
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B729
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+720
+30
+0
+70
+64
+0
+VERTEX
+5
+B730
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B731
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B732
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+720
+30
+0
+70
+64
+0
+VERTEX
+5
+B733
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B734
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B735
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B736
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B737
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B738
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B739
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+SEQEND
+5
+B740
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B741
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B742
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B743
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B744
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B745
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B746
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B747
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B748
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B749
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B750
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-144
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B751
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B752
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B753
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B754
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B755
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B756
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B757
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B758
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B759
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+SEQEND
+5
+B760
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B761
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B762
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B763
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B764
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B765
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B766
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B767
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B768
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B769
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B770
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-128
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B771
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B772
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B773
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B774
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B775
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B776
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B777
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B778
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B779
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+SEQEND
+5
+B780
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B781
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B782
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B783
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B784
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B785
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B786
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B787
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B788
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B789
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B790
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-112
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B791
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B792
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B793
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B794
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B795
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B796
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B797
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B798
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B799
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+-96
+20
+0
+30
+960
+70
+64
+0
+SEQEND
+5
+B800
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B801
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B802
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B803
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B804
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B805
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B806
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B807
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B808
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B809
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B810
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B811
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B812
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B813
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-720
+30
+0
+70
+64
+0
+VERTEX
+5
+B814
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B815
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B816
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B817
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B818
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B819
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+SEQEND
+5
+B820
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B821
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B822
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B823
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B824
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B825
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B826
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B827
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B828
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B829
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B830
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B831
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B832
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B833
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-684
+30
+240
+70
+64
+0
+VERTEX
+5
+B834
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B835
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B836
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B837
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B838
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B839
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+SEQEND
+5
+B840
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B841
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B842
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B843
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B844
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B845
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B846
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B847
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B848
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B849
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B850
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B851
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B852
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B853
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-648
+30
+480
+70
+64
+0
+VERTEX
+5
+B854
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B855
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B856
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B857
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B858
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B859
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+SEQEND
+5
+B860
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B861
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B862
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B863
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B864
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B865
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B866
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B867
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B868
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B869
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B870
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B871
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B872
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B873
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-612
+30
+720
+70
+64
+0
+VERTEX
+5
+B874
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B875
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B876
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-576
+30
+960
+70
+64
+0
+VERTEX
+5
+B877
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B878
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B879
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-576
+30
+960
+70
+64
+0
+SEQEND
+5
+B880
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B881
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B882
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B883
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B884
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B885
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B886
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B887
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B888
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B889
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B890
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B891
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B892
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B893
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-432
+30
+0
+70
+64
+0
+VERTEX
+5
+B894
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B895
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B896
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B897
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B898
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B899
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+SEQEND
+5
+B900
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B901
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B902
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B903
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B904
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B905
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B906
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B907
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B908
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B909
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B910
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B911
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B912
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B913
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-432
+30
+240
+70
+64
+0
+VERTEX
+5
+B914
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B915
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B916
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B917
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B918
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B919
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+SEQEND
+5
+B920
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B921
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B922
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B923
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B924
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B925
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B926
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B927
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B928
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B929
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B930
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B931
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B932
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B933
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-432
+30
+480
+70
+64
+0
+VERTEX
+5
+B934
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B935
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B936
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B937
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B938
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B939
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+SEQEND
+5
+B940
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B941
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B942
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B943
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B944
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B945
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B946
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B947
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B948
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B949
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B950
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B951
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B952
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B953
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-432
+30
+720
+70
+64
+0
+VERTEX
+5
+B954
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B955
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B956
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-432
+30
+960
+70
+64
+0
+VERTEX
+5
+B957
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B958
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B959
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-432
+30
+960
+70
+64
+0
+SEQEND
+5
+B960
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B961
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B962
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B963
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B964
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B965
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B966
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B967
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B968
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B969
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B970
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B971
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B972
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B973
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+-144
+30
+0
+70
+64
+0
+VERTEX
+5
+B974
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B975
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B976
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B977
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B978
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B979
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+SEQEND
+5
+B980
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B981
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B982
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B983
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B984
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B985
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B986
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B987
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B988
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B989
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B990
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B991
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B992
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B993
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+-180
+30
+240
+70
+64
+0
+VERTEX
+5
+B994
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B995
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B996
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B997
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B998
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B999
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+SEQEND
+5
+B1000
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1001
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1002
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1003
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1004
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1005
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1006
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1007
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1008
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1009
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1010
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1011
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1012
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1013
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+-216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1014
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1015
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1016
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1017
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1018
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1019
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+SEQEND
+5
+B1020
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1021
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1022
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B1023
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1024
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1025
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B1026
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1027
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1028
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1029
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1030
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1031
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1032
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1033
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-252
+30
+720
+70
+64
+0
+VERTEX
+5
+B1034
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1035
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1036
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-288
+30
+960
+70
+64
+0
+VERTEX
+5
+B1037
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1038
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1039
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-288
+30
+960
+70
+64
+0
+SEQEND
+5
+B1040
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1041
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1042
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1043
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B1044
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B1045
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1046
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B1047
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B1048
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1049
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B1050
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B1051
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1052
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B1053
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+144
+30
+0
+70
+64
+0
+VERTEX
+5
+B1054
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1055
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1056
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1057
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1058
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1059
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+SEQEND
+5
+B1060
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1061
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1062
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1063
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1064
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1065
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1066
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1067
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1068
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1069
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1070
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1071
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1072
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1073
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+72
+30
+240
+70
+64
+0
+VERTEX
+5
+B1074
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1075
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1076
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1077
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1078
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1079
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+SEQEND
+5
+B1080
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1081
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1082
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1083
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1084
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1085
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1086
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1087
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1088
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1089
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1090
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1091
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1092
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1093
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+0
+30
+480
+70
+64
+0
+VERTEX
+5
+B1094
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1095
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1096
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1097
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1098
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1099
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+SEQEND
+5
+B1100
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1101
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1102
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1103
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1104
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1105
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1106
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1107
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1108
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1109
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1110
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1111
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1112
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1113
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+-72
+30
+720
+70
+64
+0
+VERTEX
+5
+B1114
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1115
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1116
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+-144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1117
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1118
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1119
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+-144
+30
+960
+70
+64
+0
+SEQEND
+5
+B1120
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1121
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1122
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1123
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B1124
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B1125
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1126
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B1127
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B1128
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B1129
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+720
+30
+0
+70
+64
+0
+VERTEX
+5
+B1130
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+160
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B1131
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B1132
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+720
+30
+0
+70
+64
+0
+VERTEX
+5
+B1133
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+480
+20
+432
+30
+0
+70
+64
+0
+VERTEX
+5
+B1134
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B1135
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B1136
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1137
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B1138
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B1139
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+SEQEND
+5
+B1140
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1141
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1142
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1143
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1144
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1145
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1146
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1147
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1148
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B1149
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B1150
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+156
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1151
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B1152
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+576
+30
+240
+70
+64
+0
+VERTEX
+5
+B1153
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+456
+20
+324
+30
+240
+70
+64
+0
+VERTEX
+5
+B1154
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B1155
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B1156
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1157
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B1158
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B1159
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+SEQEND
+5
+B1160
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1161
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1162
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1163
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1164
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1165
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1166
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1167
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1168
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B1169
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B1170
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+152
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1171
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B1172
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+432
+30
+480
+70
+64
+0
+VERTEX
+5
+B1173
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+432
+20
+216
+30
+480
+70
+64
+0
+VERTEX
+5
+B1174
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B1175
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B1176
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1177
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B1178
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B1179
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+SEQEND
+5
+B1180
+100
+AcDbEntity
+8
+SOLIDS
+0
+POLYLINE
+5
+B1181
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbPolygonMesh
+66
+1
+10
+0
+20
+0
+30
+0
+70
+16
+71
+6
+72
+3
+0
+VERTEX
+5
+B1182
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1183
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1184
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1185
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1186
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1187
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1188
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1189
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B1190
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+148
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1191
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1192
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+288
+30
+720
+70
+64
+0
+VERTEX
+5
+B1193
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+408
+20
+108
+30
+720
+70
+64
+0
+VERTEX
+5
+B1194
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1195
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1196
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+384
+20
+0
+30
+960
+70
+64
+0
+VERTEX
+5
+B1197
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1198
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+144
+30
+960
+70
+64
+0
+VERTEX
+5
+B1199
+100
+AcDbEntity
+8
+SOLIDS
+100
+AcDbVertex
+100
+AcDbPolygonMeshVertex
+10
+144
+20
+0
+30
+960
+70
+64
+0
+SEQEND
+5
+B1200
+100
+AcDbEntity
+8
+SOLIDS
+0
+ENDSEC
+0
+SECTION
+2
+OBJECTS
+0
+DICTIONARY
+5
+C
+100
+AcDbDictionary
+3
+ACAD_GROUP
+350
+D
+3
+ACAD_MLINESTYLE
+350
+E
+0
+DICTIONARY
+5
+D
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+100
+AcDbDictionary
+0
+DICTIONARY
+5
+E
+102
+{ACAD_REACTORS
+330
+C
+102
+}
+100
+AcDbDictionary
+3
+STANDARD
+350
+1C
+0
+MLINESTYLE
+5
+1C
+102
+{ACAD_REACTORS
+330
+E
+102
+}
+100
+AcDbMlineStyle
+2
+STANDARD
+70
+0
+3
+
+62
+0
+51
+90.0
+52
+90.0
+71
+2
+49
+0.5
+62
+256
+6
+BYLAYER
+49
+-0.5
+62
+256
+6
+BYLAYER
+0
+ENDSEC
+0
+EOF
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/emf/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2004-0209-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2004-0209-1.emf
new file mode 100644
index 000000000..a511da43a
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2004-0209-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2008-1083-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2008-1083-1.emf
new file mode 100644
index 000000000..dd57d9102
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2008-1083-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2009-1217-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2009-1217-1.emf
new file mode 100644
index 000000000..8fa6e9377
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2009-1217-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/crash-2.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/crash-2.emf
new file mode 100644
index 000000000..6adabec8b
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/crash-2.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/crash-3.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/crash-3.emf
new file mode 100644
index 000000000..92da5f05a
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/crash-3.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/fdo71307-2.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/fdo71307-2.emf
new file mode 100644
index 000000000..b89db21c2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/fdo71307-2.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/hang-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/hang-1.emf
new file mode 100644
index 000000000..634fccdc0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/hang-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/hang-2.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/hang-2.emf
new file mode 100644
index 000000000..e3baf3bfa
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/hang-2.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/slow-moveclip-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/slow-moveclip-1.emf
new file mode 100644
index 000000000..ef4c6a009
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/slow-moveclip-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/emf/indeterminate/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/emf/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-1087-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-1087-1.emf
new file mode 100644
index 000000000..c71739a50
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-1087-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-2245-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-2245-1.emf
new file mode 100644
index 000000000..746e85e84
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-2245-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0168-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0168-1.emf
new file mode 100644
index 000000000..fbd546cb0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0168-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0168-2.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0168-2.emf
new file mode 100644
index 000000000..40f24b41d
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0168-2.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-1.emf
new file mode 100644
index 000000000..dcc2a66f7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-2.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-2.emf
new file mode 100644
index 000000000..b82444a97
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-2.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-3.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-3.emf
new file mode 100644
index 000000000..8e67ce5ae
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0169-3.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0170-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0170-1.emf
new file mode 100644
index 000000000..b17ce7061
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-0170-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3301-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3301-1.emf
new file mode 100644
index 000000000..0991bba4f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3301-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3303-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3303-1.emf
new file mode 100644
index 000000000..78d030daa
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3303-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3304-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3304-1.emf
new file mode 100644
index 000000000..fadbb7516
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2016-3304-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/crash-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/crash-1.emf
new file mode 100644
index 000000000..bbc0285db
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/crash-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/crash-2.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/crash-2.emf
new file mode 100644
index 000000000..a52213238
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/crash-2.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/fdo38580-3.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/fdo38580-3.emf
new file mode 100644
index 000000000..0af6c749b
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/fdo38580-3.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/eps/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/eps/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/eps/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/eps/fail/CVE-2009-4195-1.eps b/vcl/qa/cppunit/graphicfilter/data/eps/fail/CVE-2009-4195-1.eps
new file mode 100644
index 000000000..5ae189f15
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/eps/fail/CVE-2009-4195-1.eps
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/eps/fail/short-1.eps b/vcl/qa/cppunit/graphicfilter/data/eps/fail/short-1.eps
new file mode 100644
index 000000000..4b38b782f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/eps/fail/short-1.eps
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/eps/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/eps/indeterminate/.gitignore
new file mode 100644
index 000000000..b2a2eb047
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/eps/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.eps-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/eps/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/eps/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/eps/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/eps/pass/CVE-2013-4979-1.eps b/vcl/qa/cppunit/graphicfilter/data/eps/pass/CVE-2013-4979-1.eps
new file mode 100644
index 000000000..ae6c6aad7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/eps/pass/CVE-2013-4979-1.eps
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/eps/pass/fdo13433-4.eps b/vcl/qa/cppunit/graphicfilter/data/eps/pass/fdo13433-4.eps
new file mode 100644
index 000000000..6ca427f86
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/eps/pass/fdo13433-4.eps
@@ -0,0 +1,667 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Title: /home/amg/newtest05.eps
+%%Creator: matplotlib version 0.98.0, http://matplotlib.sourceforge.net/
+%%CreationDate: Sat Jul 19 09:49:37 2008
+%%Orientation: portrait
+%%BoundingBox: 13 175 598 616
+%%EndComments
+%%BeginProlog
+/mpldict 7 dict def
+mpldict begin
+/m { moveto } bind def
+/l { lineto } bind def
+/r { rlineto } bind def
+/c { curveto } bind def
+/cl { closepath } bind def
+/box {
+m
+1 index 0 r
+0 exch r
+neg 0 r
+cl
+} bind def
+/clipbox {
+box
+clip
+newpath
+} bind def
+end
+%%EndProlog
+mpldict begin
+13.5 175.5 translate
+585 441 0 0 clipbox
+1.000 setlinewidth
+0 setlinejoin
+2 setlinecap
+[] 0 setdash
+1.000 setgray
+gsave
+0 0 m
+585 0 l
+585 441 l
+0 441 l
+0 0 l
+gsave
+fill
+grestore
+stroke
+grestore
+0.000 setgray
+gsave
+73.125 44.1 m
+526.5 44.1 l
+526.5 396.9 l
+73.125 396.9 l
+73.125 44.1 l
+gsave
+1.000 setgray
+fill
+grestore
+stroke
+grestore
+0.500 setlinewidth
+0 setlinecap
+gsave
+453.4 352.8 73.12 44.1 clipbox
+/o {
+gsave
+newpath
+translate
+0 -3 m
+0.795609 -3 1.55874 -2.6839 2.12132 -2.12132 c
+2.6839 -1.55874 3 -0.795609 3 0 c
+3 0.795609 2.6839 1.55874 2.12132 2.12132 c
+1.55874 2.6839 0.795609 3 0 3 c
+-0.795609 3 -1.55874 2.6839 -2.12132 2.12132 c
+-2.6839 1.55874 -3 0.795609 -3 0 c
+-3 -0.795609 -2.6839 -1.55874 -2.12132 -2.12132 c
+-1.55874 -2.6839 -0.795609 -3 0 -3 c
+cl
+gsave
+1.000 0.000 0.000 setrgbcolor
+fill
+grestore
+stroke
+grestore
+} bind def
+73.1 92.5 o
+77.7 206 o
+82.2 204 o
+86.7 293 o
+91.3 189 o
+95.8 276 o
+100 250 o
+105 226 o
+109 240 o
+114 329 o
+118 250 o
+123 226 o
+128 99 o
+132 195 o
+137 241 o
+141 168 o
+146 166 o
+150 301 o
+155 294 o
+159 223 o
+164 220 o
+168 184 o
+173 205 o
+177 242 o
+182 320 o
+186 239 o
+191 306 o
+196 272 o
+200 96.1 o
+205 293 o
+209 265 o
+214 233 o
+218 231 o
+223 138 o
+227 204 o
+232 278 o
+236 271 o
+241 165 o
+245 199 o
+250 239 o
+254 234 o
+259 306 o
+264 304 o
+268 246 o
+273 172 o
+277 180 o
+282 246 o
+286 146 o
+291 97.8 o
+295 241 o
+300 141 o
+304 242 o
+309 177 o
+313 189 o
+318 142 o
+322 216 o
+327 273 o
+332 261 o
+336 173 o
+341 223 o
+345 282 o
+350 285 o
+354 90.1 o
+359 241 o
+363 344 o
+368 187 o
+372 172 o
+377 224 o
+381 300 o
+386 237 o
+390 107 o
+395 249 o
+400 263 o
+404 146 o
+409 162 o
+413 228 o
+418 252 o
+422 166 o
+427 255 o
+431 92.7 o
+436 277 o
+440 204 o
+445 226 o
+449 356 o
+454 277 o
+458 247 o
+463 244 o
+468 272 o
+472 286 o
+477 259 o
+481 332 o
+486 138 o
+490 212 o
+495 203 o
+499 163 o
+504 374 o
+508 371 o
+513 223 o
+517 126 o
+522 205 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 4 l
+stroke
+grestore
+} bind def
+73.1 44.1 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 -4 l
+stroke
+grestore
+} bind def
+73.1 397 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+70.389000 31.664000 translate
+0.000000 rotate
+0.000000 0.000000 m /zero glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 4 l
+stroke
+grestore
+} bind def
+164 44.1 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 -4 l
+stroke
+grestore
+} bind def
+164 397 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+158.328000 31.436000 translate
+0.000000 rotate
+0.000000 0.000000 m /two glyphshow
+5.472000 0.000000 m /zero glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 4 l
+stroke
+grestore
+} bind def
+254 44.1 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 -4 l
+stroke
+grestore
+} bind def
+254 397 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+249.003000 31.436000 translate
+0.000000 rotate
+0.000000 0.000000 m /four glyphshow
+5.472000 0.000000 m /zero glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 4 l
+stroke
+grestore
+} bind def
+345 44.1 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 -4 l
+stroke
+grestore
+} bind def
+345 397 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+339.678000 31.664000 translate
+0.000000 rotate
+0.000000 0.000000 m /six glyphshow
+5.472000 0.000000 m /zero glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 4 l
+stroke
+grestore
+} bind def
+436 44.1 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 -4 l
+stroke
+grestore
+} bind def
+436 397 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+430.353000 31.664000 translate
+0.000000 rotate
+0.000000 0.000000 m /eight glyphshow
+5.472000 0.000000 m /zero glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 4 l
+stroke
+grestore
+} bind def
+526 44.1 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+0 -4 l
+stroke
+grestore
+} bind def
+526 397 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+518.292000 31.436000 translate
+0.000000 rotate
+0.000000 0.000000 m /one glyphshow
+5.472000 0.000000 m /zero glyphshow
+10.944000 0.000000 m /zero glyphshow
+grestore
+ 1.000 setlinewidth
+gsave
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+296.531 17.82 moveto
+0.0 rotate
+(X)
+0.000 0.000 0.000 setrgbcolor
+show
+grestore
+stroke
+grestore
+0.500 setlinewidth
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+4 0 l
+stroke
+grestore
+} bind def
+73.1 44.1 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+-4 0 l
+stroke
+grestore
+} bind def
+526 44.1 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+57.905000 39.882000 translate
+0.000000 rotate
+0.000000 0.000000 m /minus glyphshow
+5.748000 0.000000 m /three glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+4 0 l
+stroke
+grestore
+} bind def
+73.1 103 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+-4 0 l
+stroke
+grestore
+} bind def
+526 103 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+57.905000 98.682000 translate
+0.000000 rotate
+0.000000 0.000000 m /minus glyphshow
+5.748000 0.000000 m /two glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+4 0 l
+stroke
+grestore
+} bind def
+73.1 162 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+-4 0 l
+stroke
+grestore
+} bind def
+526 162 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+57.905000 157.482000 translate
+0.000000 rotate
+0.000000 0.000000 m /minus glyphshow
+5.748000 0.000000 m /one glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+4 0 l
+stroke
+grestore
+} bind def
+73.1 221 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+-4 0 l
+stroke
+grestore
+} bind def
+526 221 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+63.653000 216.282000 translate
+0.000000 rotate
+0.000000 0.000000 m /zero glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+4 0 l
+stroke
+grestore
+} bind def
+73.1 279 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+-4 0 l
+stroke
+grestore
+} bind def
+526 279 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+63.653000 275.082000 translate
+0.000000 rotate
+0.000000 0.000000 m /one glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+4 0 l
+stroke
+grestore
+} bind def
+73.1 338 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+-4 0 l
+stroke
+grestore
+} bind def
+526 338 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+63.653000 333.882000 translate
+0.000000 rotate
+0.000000 0.000000 m /two glyphshow
+grestore
+ gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+4 0 l
+stroke
+grestore
+} bind def
+73.1 397 o
+grestore
+gsave
+/o {
+gsave
+newpath
+translate
+0 0 m
+-4 0 l
+stroke
+grestore
+} bind def
+526 397 o
+grestore
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+63.653000 392.682000 translate
+0.000000 rotate
+0.000000 0.000000 m /three glyphshow
+grestore
+ 1.000 setlinewidth
+gsave
+gsave
+/Helvetica-Narrow findfont
+12.0 scalefont
+setfont
+52.905 217.218 moveto
+90.0 rotate
+(Y)
+0.000 0.000 0.000 setrgbcolor
+show
+grestore
+stroke
+grestore
+2 setlinecap
+gsave
+73.125 44.1 m
+526.5 44.1 l
+526.5 396.9 l
+73.125 396.9 l
+73.125 44.1 l
+stroke
+grestore
+0 setlinecap
+gsave
+gsave
+/Helvetica-Narrow findfont
+14.0 scalefont
+setfont
+277.798 404.798 moveto
+0.0 rotate
+(Test plot)
+0.000 0.000 0.000 setrgbcolor
+show
+grestore
+stroke
+grestore
+
+end
+showpage
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/gif/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2007-3958-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2007-3958-1.gif
new file mode 100644
index 000000000..7e84566e9
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2007-3958-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2008-5937-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2008-5937-1.gif
new file mode 100644
index 000000000..cbefd0162
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2008-5937-1.gif
@@ -0,0 +1 @@
+&Vus؝ [e21oX \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/EBD-36334-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/fail/EBD-36334-1.gif
new file mode 100644
index 000000000..a8f51b6ef
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/EBD-36334-1.gif
@@ -0,0 +1,2 @@
+&X=؝;ekbΐ~6*^1.Ą#᛾fLtwO zjAFHT
+eԠ?AUaȻL*Vqd&`6~[Ӆj`oD9.>4 \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/EBD-36335-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/fail/EBD-36335-1.gif
new file mode 100644
index 000000000..8f0f4fdb7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/EBD-36335-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/EDB-23279-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/fail/EDB-23279-1.gif
new file mode 100644
index 000000000..d81d3b084
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/EDB-23279-1.gif
@@ -0,0 +1 @@
+&H1؝'[ek2ΐ~m1L-ha[^.!7/&VOʻBB^u2k]YnEG)q \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/too-small-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/fail/too-small-1.gif
new file mode 100644
index 000000000..26b35e63b
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/too-small-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/gif/indeterminate/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/gif/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2007-6715-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2007-6715-1.gif
new file mode 100644
index 000000000..63426f9d8
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2007-6715-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2008-3013-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2008-3013-1.gif
new file mode 100644
index 000000000..e92a316e4
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2008-3013-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2011-2131-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2011-2131-1.gif
new file mode 100644
index 000000000..190c7b079
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2011-2131-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2012-0282-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2012-0282-1.gif
new file mode 100644
index 000000000..cf4f30c21
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2012-0282-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/EDB-19333-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/EDB-19333-1.gif
new file mode 100644
index 000000000..53d2ca01e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/EDB-19333-1.gif
@@ -0,0 +1 @@
+&t};'[ek2ΐ~m1L-ha[^.!7/&VOʻBB^u2k]YnyG)ʿjkB:d#|u\#L@E \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/afl-sample-short-read-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/afl-sample-short-read-1.gif
new file mode 100644
index 000000000..7cb2a03d5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/afl-sample-short-read-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/afl-sample-short-read-2.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/afl-sample-short-read-2.gif
new file mode 100644
index 000000000..cddbdc357
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/afl-sample-short-read-2.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/crash-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/crash-1.gif
new file mode 100644
index 000000000..860f9e1d8
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/crash-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/crash-2.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/crash-2.gif
new file mode 100644
index 000000000..b7265f807
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/crash-2.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/sf_3e0068c9b19bb548826bed0599f65745-15940-minimized.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/sf_3e0068c9b19bb548826bed0599f65745-15940-minimized.gif
new file mode 100644
index 000000000..47f5d4341
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/sf_3e0068c9b19bb548826bed0599f65745-15940-minimized.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-1.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-1.jpg
new file mode 100644
index 000000000..c03c8529c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-2.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-2.jpg
new file mode 100644
index 000000000..1a24da322
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-2.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-3.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-3.jpg
new file mode 100644
index 000000000..794ff52e4
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-3.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-4.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-4.jpg
new file mode 100644
index 000000000..8911646fa
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-4.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-5.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-5.jpg
new file mode 100644
index 000000000..c5373df43
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-1097-5.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-5314-1.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-5314-1.jpg
new file mode 100644
index 000000000..33bbe9b5f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-5314-1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/crash-1.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/crash-1.jpg
new file mode 100644
index 000000000..e783bd33e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/crash-1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/jpg/indeterminate/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-1.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-1.jpg
new file mode 100644
index 000000000..3d9481aca
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-2.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-2.jpg
new file mode 100644
index 000000000..5eb27ffb5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-2.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-3.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-3.jpg
new file mode 100644
index 000000000..4917f207f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-3.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-4.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-4.jpg
new file mode 100644
index 000000000..9d26db005
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-4.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-5.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-5.jpg
new file mode 100644
index 000000000..bc668d3e3
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-5.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2017-9614-1.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2017-9614-1.jpg
new file mode 100644
index 000000000..675881f36
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2017-9614-1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/EDB-24743-2.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/EDB-24743-2.jpg
new file mode 100644
index 000000000..01e7fe16f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/EDB-24743-2.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/EDB-24743-3.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/EDB-24743-3.jpg
new file mode 100644
index 000000000..4753ed8db
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/EDB-24743-3.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/fatalerror-1.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/fatalerror-1.jpg
new file mode 100644
index 000000000..c6ee53505
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/fatalerror-1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/met/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/fail/afl-divide-zero-1.met b/vcl/qa/cppunit/graphicfilter/data/met/fail/afl-divide-zero-1.met
new file mode 100644
index 000000000..62ccf48f6
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/fail/afl-divide-zero-1.met
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/fail/afl-msan-1.met b/vcl/qa/cppunit/graphicfilter/data/met/fail/afl-msan-1.met
new file mode 100644
index 000000000..18877582a
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/fail/afl-msan-1.met
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/fail/crash-1.met b/vcl/qa/cppunit/graphicfilter/data/met/fail/crash-1.met
new file mode 100644
index 000000000..c46b4a9f1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/fail/crash-1.met
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-1.met b/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-1.met
new file mode 100644
index 000000000..c1a095d3f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-1.met
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-2.met b/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-2.met
new file mode 100644
index 000000000..e807d584e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-2.met
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-3.met b/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-3.met
new file mode 100644
index 000000000..84b432e63
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/fail/hang-3.met
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/met/indeterminate/.gitignore
new file mode 100644
index 000000000..8276f4291
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.met-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/met/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/met/pass/sample.met b/vcl/qa/cppunit/graphicfilter/data/met/pass/sample.met
new file mode 100644
index 000000000..7635e841f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/met/pass/sample.met
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pbm/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pbm/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pbm/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/pbm/fail/crash-1.pbm b/vcl/qa/cppunit/graphicfilter/data/pbm/fail/crash-1.pbm
new file mode 100644
index 000000000..9ddcddfe6
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pbm/fail/crash-1.pbm
@@ -0,0 +1,6 @@
+P3
+30000000000000000000000000000000 1
+255
+103 79 59
+ 95 7P 55
+ 87 67 51
diff --git a/vcl/qa/cppunit/graphicfilter/data/pbm/fail/hang-1.pbm b/vcl/qa/cppunit/graphicfilter/data/pbm/fail/hang-1.pbm
new file mode 100644
index 000000000..21742d204
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pbm/fail/hang-1.pbm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pbm/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pbm/indeterminate/.gitignore
new file mode 100644
index 000000000..e9c5b1765
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pbm/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.ppm-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/pbm/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pbm/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pbm/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/pbm/pass/rhbz160429-1.pbm b/vcl/qa/cppunit/graphicfilter/data/pbm/pass/rhbz160429-1.pbm
new file mode 100644
index 000000000..d6e3fc634
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pbm/pass/rhbz160429-1.pbm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcd/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pcd/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcd/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcd/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pcd/indeterminate/.gitignore
new file mode 100644
index 000000000..23ad7d155
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcd/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.pcd-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcd/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pcd/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcd/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcd/pass/blank-square.pcd b/vcl/qa/cppunit/graphicfilter/data/pcd/pass/blank-square.pcd
new file mode 100644
index 000000000..a626b5f23
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcd/pass/blank-square.pcd
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-1.pcx b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-1.pcx
new file mode 100644
index 000000000..915f38aec
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-1.pcx
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-2.pcx b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-2.pcx
new file mode 100644
index 000000000..9c8a751a4
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-2.pcx
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-3.pcx b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-3.pcx
new file mode 100644
index 000000000..41175653a
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2007-3741-3.pcx
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2008-1097-1.pcx b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2008-1097-1.pcx
new file mode 100644
index 000000000..c55c64ed9
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/CVE-2008-1097-1.pcx
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/fail/hang-1.pcx b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/hang-1.pcx
new file mode 100644
index 000000000..73798ea56
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/fail/hang-1.pcx
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pcx/indeterminate/.gitignore
new file mode 100644
index 000000000..f73b09798
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.pcx-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pcx/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/pcx/pass/rhbz469075-1.pcx b/vcl/qa/cppunit/graphicfilter/data/pcx/pass/rhbz469075-1.pcx
new file mode 100644
index 000000000..d928c0890
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pcx/pass/rhbz469075-1.pcx
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/clipping-problem.pct b/vcl/qa/cppunit/graphicfilter/data/pict/clipping-problem.pct
new file mode 100644
index 000000000..37fe66c80
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/clipping-problem.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pict/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2008-1097-1.pct b/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2008-1097-1.pct
new file mode 100644
index 000000000..73943c9d7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2008-1097-1.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2012-0277-1.pct b/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2012-0277-1.pct
new file mode 100644
index 000000000..5683a55b5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2012-0277-1.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2013-2577-1.pct b/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2013-2577-1.pct
new file mode 100644
index 000000000..1e1f6d5b5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/fail/CVE-2013-2577-1.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/fail/EDB-19332-1.pct b/vcl/qa/cppunit/graphicfilter/data/pict/fail/EDB-19332-1.pct
new file mode 100644
index 000000000..5f8740305
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/fail/EDB-19332-1.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/fail/exception-1.pct b/vcl/qa/cppunit/graphicfilter/data/pict/fail/exception-1.pct
new file mode 100644
index 000000000..f9cd85a4a
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/fail/exception-1.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/fail/hang-1.pct b/vcl/qa/cppunit/graphicfilter/data/pict/fail/hang-1.pct
new file mode 100644
index 000000000..735ce0aca
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/fail/hang-1.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pict/indeterminate/.gitignore
new file mode 100644
index 000000000..1bdee7737
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/indeterminate/.gitignore
@@ -0,0 +1,2 @@
+*.pict-*
+*.pct-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/pict/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/pass/ooo25876-2.pct b/vcl/qa/cppunit/graphicfilter/data/pict/pass/ooo25876-2.pct
new file mode 100644
index 000000000..9807e36f7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/pass/ooo25876-2.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/pict/pass/tdf92789.pct b/vcl/qa/cppunit/graphicfilter/data/pict/pass/tdf92789.pct
new file mode 100644
index 000000000..2d6f0d884
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/pict/pass/tdf92789.pct
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/png/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2004-0597-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2004-0597-1.png
new file mode 100644
index 000000000..fa90a296f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2004-0597-1.png
@@ -0,0 +1,3 @@
+#Mb}o72~X.^TwB!f1s tga2bAHb"8|eGfS$N0nI֪
+0"JGzܢ(s?d)"GEF9~}r TΝp?*ck$E"X8=2T_3v# $Hh4JKi݊J&7r=u69KjWh{$ dV[Жy\%%ǾH me+ }gXI2>*ī& )̸6pUTjODh1-<WURK591M?
+~*Nru;khX{֍Ԥ' ӏwF[KRfyO%0ihx׃wz4dT.@Xm4ipZ^yЯ`_Y? tuw4\kdJ~mg`<2ln* kh*nw7!YIßP+hK*Ԟ`? \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2005-0633-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2005-0633-1.png
new file mode 100644
index 000000000..d0644d139
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2005-0633-1.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2006-7210-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2006-7210-1.png
new file mode 100644
index 000000000..9b30cc38c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2006-7210-1.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2007-2365-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2007-2365-1.png
new file mode 100644
index 000000000..b9ff67bb8
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2007-2365-1.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2009-1511-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2009-1511-1.png
new file mode 100644
index 000000000..592fda10a
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2009-1511-1.png
@@ -0,0 +1 @@
+#Mb}o72͐~\._舄{'p|&F/ \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0951-2.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0951-2.png
new file mode 100644
index 000000000..38899f733
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0951-2.png
@@ -0,0 +1 @@
+#Mb}o72ΰ~X.^@Ji#+p%Hh/٦0!0 {å[B]2ӌ*[@Κ}{` RtԴ|}3N=aDITgI!ҨC]ˍ ErGOX9 ̓^;0/A )O"vgӍj1{b*[o:ٖw*^_ˉ i8dq?]0}ȴ $}|6Es0x%mL-m:  \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-1.png
new file mode 100644
index 000000000..7848d5ad5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-1.png
@@ -0,0 +1 @@
+#Mb}o72Δ~X._l!#+p%Hh/G%L69lR?nCGxP&؝Ȝs0- C 99$8n;GFԾc \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-2.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-2.png
new file mode 100644
index 000000000..5494ca00e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-2.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/EDB-34720-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/EDB-34720-1.png
new file mode 100644
index 000000000..3165f2c5e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/EDB-34720-1.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/ofz32026.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/ofz32026.png
new file mode 100644
index 000000000..290671ecb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/ofz32026.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/png/indeterminate/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/png/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/CVE-2016-0951-1.png b/vcl/qa/cppunit/graphicfilter/data/png/pass/CVE-2016-0951-1.png
new file mode 100644
index 000000000..b5e6220dc
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/pass/CVE-2016-0951-1.png
@@ -0,0 +1 @@
+#Mb}o72Ε~X._#+pHh/G%L69lR?Y֏)RȍAl7*[.{H Z# \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-IDAT.png b/vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-IDAT.png
new file mode 100644
index 000000000..b116a92ec
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-IDAT.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-Z_NEED_DICT.png b/vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-Z_NEED_DICT.png
new file mode 100644
index 000000000..db8e7a834
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-Z_NEED_DICT.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/black.png b/vcl/qa/cppunit/graphicfilter/data/png/pass/black.png
new file mode 100644
index 000000000..cbba93bed
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/pass/black.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/invalid-chunk.png b/vcl/qa/cppunit/graphicfilter/data/png/pass/invalid-chunk.png
new file mode 100644
index 000000000..1c45c7689
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/pass/invalid-chunk.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/ppm/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/ppm/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ppm/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/ppm/fail/CVE-2008-1097-1.ppm b/vcl/qa/cppunit/graphicfilter/data/ppm/fail/CVE-2008-1097-1.ppm
new file mode 100644
index 000000000..457289577
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ppm/fail/CVE-2008-1097-1.ppm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/ppm/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/ppm/indeterminate/.gitignore
new file mode 100644
index 000000000..e9c5b1765
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ppm/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.ppm-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/ppm/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/ppm/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ppm/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/ppm/pass/fdo19811-2.ppm b/vcl/qa/cppunit/graphicfilter/data/ppm/pass/fdo19811-2.ppm
new file mode 100644
index 000000000..828b97256
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ppm/pass/fdo19811-2.ppm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/psd/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/psd/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/psd/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/psd/fail/CVE-2007-3741-1.psd b/vcl/qa/cppunit/graphicfilter/data/psd/fail/CVE-2007-3741-1.psd
new file mode 100644
index 000000000..59b690063
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/psd/fail/CVE-2007-3741-1.psd
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/psd/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/psd/indeterminate/.gitignore
new file mode 100644
index 000000000..49b8ba044
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/psd/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.psd-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/psd/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/psd/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/psd/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/psd/pass/blank-square.psd b/vcl/qa/cppunit/graphicfilter/data/psd/pass/blank-square.psd
new file mode 100644
index 000000000..fc811da00
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/psd/pass/blank-square.psd
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/psd/pass/hang-1.psd b/vcl/qa/cppunit/graphicfilter/data/psd/pass/hang-1.psd
new file mode 100644
index 000000000..8f557dd80
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/psd/pass/hang-1.psd
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/psd/pass/rhbz899670-1.psd b/vcl/qa/cppunit/graphicfilter/data/psd/pass/rhbz899670-1.psd
new file mode 100644
index 000000000..ce8de8493
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/psd/pass/rhbz899670-1.psd
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/psd/tdf142629.psd b/vcl/qa/cppunit/graphicfilter/data/psd/tdf142629.psd
new file mode 100644
index 000000000..097536bcc
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/psd/tdf142629.psd
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/ras/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/ras/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ras/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/ras/fail/CVE-2007-2356-1.ras b/vcl/qa/cppunit/graphicfilter/data/ras/fail/CVE-2007-2356-1.ras
new file mode 100644
index 000000000..c00c27016
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ras/fail/CVE-2007-2356-1.ras
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/ras/fail/CVE-2008-1097-1.ras b/vcl/qa/cppunit/graphicfilter/data/ras/fail/CVE-2008-1097-1.ras
new file mode 100644
index 000000000..effd654ac
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ras/fail/CVE-2008-1097-1.ras
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/ras/fail/crash-1.ras b/vcl/qa/cppunit/graphicfilter/data/ras/fail/crash-1.ras
new file mode 100644
index 000000000..d1abbaefc
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ras/fail/crash-1.ras
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/ras/fail/hang-1.ras b/vcl/qa/cppunit/graphicfilter/data/ras/fail/hang-1.ras
new file mode 100644
index 000000000..44dec6760
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ras/fail/hang-1.ras
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/ras/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/ras/indeterminate/.gitignore
new file mode 100644
index 000000000..60147ad08
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ras/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.ras-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/ras/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/ras/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ras/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/ras/pass/marbles.ras b/vcl/qa/cppunit/graphicfilter/data/ras/pass/marbles.ras
new file mode 100644
index 000000000..9b3fb0d85
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/ras/pass/marbles.ras
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/svm/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-1.svm b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-1.svm
new file mode 100644
index 000000000..2fce465f7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-1.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-2.svm b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-2.svm
new file mode 100644
index 000000000..1b3cd1416
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-2.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-3.svm b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-3.svm
new file mode 100644
index 000000000..b4afeb09f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-3.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-4.svm b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-4.svm
new file mode 100644
index 000000000..c2f14d4a0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-4.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-5.svm b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-5.svm
new file mode 100644
index 000000000..835e7f668
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-5.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-6.svm b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-6.svm
new file mode 100644
index 000000000..8d6d94e12
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/fail/mapmode-6.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/fail/ofz7165-1.svm b/vcl/qa/cppunit/graphicfilter/data/svm/fail/ofz7165-1.svm
new file mode 100644
index 000000000..ad722ea13
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/fail/ofz7165-1.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/svm/indeterminate/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/svm/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/pass/leak-1.svm b/vcl/qa/cppunit/graphicfilter/data/svm/pass/leak-1.svm
new file mode 100644
index 000000000..14dbea080
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/pass/leak-1.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz-timeout-1.svm b/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz-timeout-1.svm
new file mode 100644
index 000000000..5b61891be
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz-timeout-1.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz32885-1.svm b/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz32885-1.svm
new file mode 100644
index 000000000..b4d5126b9
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz32885-1.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz45269-1.svm b/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz45269-1.svm
new file mode 100644
index 000000000..4dceee3a9
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz45269-1.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz45583-1.svm b/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz45583-1.svm
new file mode 100644
index 000000000..d730a1bcc
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/svm/pass/ofz45583-1.svm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tga/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/tga/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tga/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/tga/fail/CVE-2012-3755-1.tga b/vcl/qa/cppunit/graphicfilter/data/tga/fail/CVE-2012-3755-1.tga
new file mode 100644
index 000000000..963e5d3ae
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tga/fail/CVE-2012-3755-1.tga
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tga/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/tga/indeterminate/.gitignore
new file mode 100644
index 000000000..38bf024a9
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tga/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.tga-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/tga/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/tga/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tga/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/tga/pass/fdo14924-5.tga b/vcl/qa/cppunit/graphicfilter/data/tga/pass/fdo14924-5.tga
new file mode 100644
index 000000000..c3b38f313
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tga/pass/fdo14924-5.tga
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tga/pass/fdo14924-6.tga b/vcl/qa/cppunit/graphicfilter/data/tga/pass/fdo14924-6.tga
new file mode 100644
index 000000000..92b720053
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tga/pass/fdo14924-6.tga
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/blue16.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/blue16.tif
new file mode 100644
index 000000000..284594d34
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/blue16.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/blue8.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/blue8.tif
new file mode 100644
index 000000000..29d17dcb3
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/blue8.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/BID-51132-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/BID-51132-1.tiff
new file mode 100644
index 000000000..929ac15f1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/BID-51132-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2006-3459-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2006-3459-1.tiff
new file mode 100644
index 000000000..323fb1761
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2006-3459-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2007-2217-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2007-2217-1.tiff
new file mode 100644
index 000000000..e078b73d0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2007-2217-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2009-2285-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2009-2285-1.tiff
new file mode 100644
index 000000000..896de2b7b
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2009-2285-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2010-2482-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2010-2482-1.tiff
new file mode 100644
index 000000000..59e3c7ed6
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2010-2482-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2013-3906-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2013-3906-1.tiff
new file mode 100644
index 000000000..a7704996c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2013-3906-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2013-5575-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2013-5575-1.tiff
new file mode 100644
index 000000000..ae3cee16c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2013-5575-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-10688-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-10688-1.tiff
new file mode 100644
index 000000000..a41eb50b9
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-10688-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-9147-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-9147-1.tiff
new file mode 100644
index 000000000..d59119e4f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-9147-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-9936-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-9936-1.tiff
new file mode 100644
index 000000000..372a33b6f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/CVE-2017-9936-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/EBD-22681-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/EBD-22681-1.tiff
new file mode 100644
index 000000000..614051dd7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/EBD-22681-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/EDB-24743-5.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/EDB-24743-5.tiff
new file mode 100644
index 000000000..5f5feed59
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/EDB-24743-5.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-1.tiff
new file mode 100644
index 000000000..9e9d192f9
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-2.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-2.tiff
new file mode 100644
index 000000000..8aaede4a7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-2.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-3.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-3.tiff
new file mode 100644
index 000000000..712e780a9
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-3.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-4.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-4.tiff
new file mode 100644
index 000000000..7c5402e76
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-4.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-5.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-5.tiff
new file mode 100644
index 000000000..97433c354
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-5.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-6.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-6.tiff
new file mode 100644
index 000000000..2b2846df0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-6.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-7.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-7.tiff
new file mode 100644
index 000000000..0ca75a0a7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-crash-7.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-1.tiff
new file mode 100644
index 000000000..5b5b72d4a
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-10.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-10.tiff
new file mode 100644
index 000000000..ad722fc5c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-10.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-2.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-2.tiff
new file mode 100644
index 000000000..9924b3898
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-2.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-3.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-3.tiff
new file mode 100644
index 000000000..8de41b59f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-3.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-4.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-4.tiff
new file mode 100644
index 000000000..e51e39192
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-4.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-5.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-5.tiff
new file mode 100644
index 000000000..1123dacee
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-5.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-6.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-6.tiff
new file mode 100644
index 000000000..fc65d92d2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-6.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-7.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-7.tiff
new file mode 100644
index 000000000..cbac07326
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-7.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-8.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-8.tiff
new file mode 100644
index 000000000..2ee04554d
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-8.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-9.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-9.tiff
new file mode 100644
index 000000000..719f5931c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/RC4-hang-9.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/fail/ofz47589.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/ofz47589.tiff
new file mode 100644
index 000000000..936afbd99
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/fail/ofz47589.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/green16.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/green16.tif
new file mode 100644
index 000000000..28ae344d8
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/green16.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/green8.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/green8.tif
new file mode 100644
index 000000000..945ddc7a0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/green8.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/tiff/indeterminate/.gitignore
new file mode 100644
index 000000000..9c056f096
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/indeterminate/.gitignore
@@ -0,0 +1,2 @@
+*.tiff-*
+*.tif-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2005-1544-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2005-1544-1.tiff
new file mode 100644
index 000000000..a985d63d7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2005-1544-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2006-2656-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2006-2656-1.tiff
new file mode 100644
index 000000000..c61878e9b
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2006-2656-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-0276-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-0276-1.tiff
new file mode 100644
index 000000000..ea6dd77bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-0276-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-0276-2.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-0276-2.tiff
new file mode 100644
index 000000000..a66476b7d
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-0276-2.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-2027-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-2027-1.tiff
new file mode 100644
index 000000000..ea6dd77bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/CVE-2012-2027-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/pass/multi-page-1.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/multi-page-1.tiff
new file mode 100644
index 000000000..8eb7c8078
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/multi-page-1.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/pass/tdf149417.tiff b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/tdf149417.tiff
new file mode 100644
index 000000000..07c0d8972
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/pass/tdf149417.tiff
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/red16.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/red16.tif
new file mode 100644
index 000000000..9ec1e8d3f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/red16.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/red8.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/red8.tif
new file mode 100644
index 000000000..be41707af
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/red8.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/tdf115863.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf115863.tif
new file mode 100644
index 000000000..b5e2dd9e4
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf115863.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/tdf126460.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf126460.tif
new file mode 100644
index 000000000..ffdf6a1d5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf126460.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/tdf138818.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf138818.tif
new file mode 100644
index 000000000..bb3e51011
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf138818.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/tdf149418.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf149418.tif
new file mode 100644
index 000000000..dd451e001
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf149418.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/tdf74331.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf74331.tif
new file mode 100644
index 000000000..702b8218c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf74331.tif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossless.webp b/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossless.webp
new file mode 100644
index 000000000..abb67cc5f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossless.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossy.webp b/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossy.webp
new file mode 100644
index 000000000..c587b1bb2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossy.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/webp/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/webp/indeterminate/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossless.webp b/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossless.webp
new file mode 100644
index 000000000..b22ebc3b2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossless.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossy.webp b/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossy.webp
new file mode 100644
index 000000000..c118febb0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossy.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/webp/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2123-1.wmf-0.009-676 b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2123-1.wmf-0.009-676
new file mode 100644
index 000000000..49d3ddf28
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2123-1.wmf-0.009-676
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2124-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2124-1.wmf
new file mode 100644
index 000000000..ac546ce5b
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2124-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-4560-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-4560-1.wmf
new file mode 100644
index 000000000..aab34004e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-4560-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-1.wmf
new file mode 100644
index 000000000..b68b7403c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-1.wmf
@@ -0,0 +1 @@
+HU۬.DZ|d[e2ː~Sb&[1-kg"uZJj<we⊏ \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-2.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-2.wmf
new file mode 100644
index 000000000..370abe0e2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-2.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2007-1238-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2007-1238-1.wmf
new file mode 100644
index 000000000..10da32742
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2007-1238-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2007-1245-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2007-1245-1.wmf
new file mode 100644
index 000000000..10da32742
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2007-1245-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-1.wmf
new file mode 100644
index 000000000..87319c2d4
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-2.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-2.wmf
new file mode 100644
index 000000000..ff20cad78
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-2.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-3.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-3.wmf
new file mode 100644
index 000000000..20a70fa67
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-3.wmf
@@ -0,0 +1,5 @@
+HUҬBGx}ؘؤ`{3ΐ~._1,ʄ"f[Ch!64/LV@Hs0=3k]iuC)NF)#ɰ-hKDz8
+~ " ޤт!>iHh׮cCߝ?jaC ε
+#Bqoba6T_ljW+ o'PeS%^̈%'_VKpJ62AF<+qIjbn} {g"!k[3A+t}s
+->m=~HZ(ޔ f[c 36_Gߎ\V@BzyGd2n)|3 ÏczD2_&pNx9YXD`Fh4+C^b?o
+@փq \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-4.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-4.wmf
new file mode 100644
index 000000000..045f1f45e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/RC4-hang-4.wmf
@@ -0,0 +1,3 @@
+6.GxG;>e2ΐ 8Y-1-#ᛞv5."2/f_LBΌ건i]Yowټ(KP
+)W`1a%#Xmi-
+Hn<n~  ˕Z!> |xHf}Hx;cCa?jlGCLO9VƵ$#Bq]ak .wx} c461JpHѫ!'f7VWpJp2AFvG<7j \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/bitcount-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/bitcount-1.wmf
new file mode 100644
index 000000000..2ec88066f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/bitcount-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/exttextout-2.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/exttextout-2.wmf
new file mode 100644
index 000000000..02c72ad88
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/exttextout-2.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/facename-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/facename-1.wmf
new file mode 100644
index 000000000..29c534fdc
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/facename-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz35149-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz35149-1.wmf
new file mode 100644
index 000000000..f91e3a9fb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz35149-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz35150-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz35150-1.wmf
new file mode 100644
index 000000000..2d1561981
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz35150-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz5942-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz5942-1.wmf
new file mode 100644
index 000000000..f9a72867c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/ofz5942-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/seek-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/seek-1.wmf
new file mode 100644
index 000000000..e2fac1523
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/seek-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/wmf/indeterminate/.gitignore
new file mode 100644
index 000000000..583b009c7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.wmf-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2005-2123-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2005-2123-1.wmf
new file mode 100644
index 000000000..e70664e64
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2005-2123-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2006-4071-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2006-4071-1.wmf
new file mode 100644
index 000000000..cdb09c6b2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2006-4071-1.wmf
@@ -0,0 +1 @@
+HU۬.DZI2wɐ~._1-#f1.!0/ٸTDHN \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1090-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1090-1.wmf
new file mode 100644
index 000000000..7864da572
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1090-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2015-0848-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2015-0848-1.wmf
new file mode 100644
index 000000000..1512a2256
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2015-0848-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/exttextout-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/exttextout-1.wmf
new file mode 100644
index 000000000..365a247a7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/exttextout-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/noheader.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/noheader.wmf
new file mode 100644
index 000000000..bfd7e20de
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/noheader.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/xbm/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/xbm/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xbm/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/xbm/fail/crash-1.xbm b/vcl/qa/cppunit/graphicfilter/data/xbm/fail/crash-1.xbm
new file mode 100644
index 000000000..9d2a43470
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xbm/fail/crash-1.xbm
@@ -0,0 +1,12 @@
+#define?te_width 31
+#define te_height = {
+ 0x0e, 0x20, 0x02, 0x38, 0x11, 0x70, 0x07, 0x 0x44,
+ 0x11, 1x2e, 0x3a, 0x44, 0x8e, 0x24, 0x92, 0x38, 0xdf, 0x25, 0xd2,0x7d,
+ 0x91, 0x24 0x92, 0x44, 0x95: 0x24, 0x92, 0x54, 0xf5, 0x7f, 0xff, 0x57,
+ 0x95, 0x24, 0x92, 0x54, 0x95, 0x 4,54, 0x95, 0x24, 0x92, 0x54,
+ 0x95, 0x24,x54, 0x95, 0x24, 0x92, 0x54, 0x95, 0x24, 0x92, 0x54,
+ 0x95, 0x24, 0x92, 0x54, 0x95, 0x24, 0x92,0x54, 0x95, 0x24, 0x92, 0x54,
+ 0x95, 0x24, 0x92, 0x54, 0x95, 0x24, 0x92, 0x54, 0xf5, 0x7f, 0xff, 0x57,
+ 0x95,0x24, 0x92, 0x54, 0x95, 0x24, 0x92, 0x54, 0, 0x54, 0xf5, 0xd= {
+ 25, 0xd2, 0x7d,
+0x00, 0x7c }; \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/xbm/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/xbm/indeterminate/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xbm/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/xbm/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/xbm/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xbm/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/xbm/pass/grafix4.xbm b/vcl/qa/cppunit/graphicfilter/data/xbm/pass/grafix4.xbm
new file mode 100644
index 000000000..aad9f0305
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xbm/pass/grafix4.xbm
@@ -0,0 +1,2011 @@
+#define Grafix1_width 485
+#define Grafix1_height 395
+static char Grafix1_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00,
+ 0x07, 0x00, 0x1c, 0xfc, 0x80, 0x81, 0x03, 0x30, 0x70, 0x00, 0x00, 0x00,
+ 0xe0, 0x00, 0x0c, 0xdc, 0x00, 0x70, 0x00, 0x37, 0x07, 0x00, 0x38, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x06, 0x00, 0x18, 0xd6, 0x80, 0xc1, 0x02, 0x30, 0x58, 0x00, 0x00,
+ 0x00, 0xb0, 0x00, 0x0c, 0xd6, 0x00, 0x60, 0x80, 0x35, 0x06, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x01,
+ 0x00, 0x00, 0x06, 0x00, 0x18, 0xc2, 0x00, 0x40, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x60, 0x80, 0x00, 0x06, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80,
+ 0x01, 0x00, 0x00, 0x06, 0x00, 0x18, 0xc3, 0x00, 0x60, 0x00, 0x00, 0x0c,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x03, 0x00, 0x60, 0xc0, 0x00, 0x06,
+ 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x58,
+ 0xf0, 0xe1, 0x63, 0xc1, 0x87, 0x0f, 0x9f, 0xcf, 0xcc, 0xf1, 0xe1, 0x3b,
+ 0x3e, 0xe0, 0x01, 0x0e, 0x7f, 0xf8, 0x8e, 0xef, 0xe0, 0x63, 0xe6, 0x3b,
+ 0xe6, 0xe0, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x64, 0x98, 0x99, 0x91, 0x61, 0x66, 0x86, 0x19, 0xc3, 0x9e, 0x61, 0x98,
+ 0x31, 0x0c, 0x30, 0x03, 0x8c, 0x19, 0x66, 0x0c, 0xc3, 0x98, 0x61, 0xcf,
+ 0x30, 0x46, 0x98, 0xb1, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x4c, 0x8c, 0x19, 0x31, 0x31, 0x66, 0xc4, 0x18, 0xc3, 0x99, 0x61,
+ 0x18, 0x31, 0x0c, 0x18, 0x00, 0xd8, 0x18, 0x46, 0x0c, 0xc3, 0x18, 0xe1,
+ 0xcc, 0x30, 0x26, 0x18, 0x71, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x1c, 0x8c, 0x19, 0x71, 0x30, 0x66, 0xc4, 0x18, 0xc3, 0x98,
+ 0x61, 0x18, 0x31, 0x0c, 0x18, 0x00, 0x70, 0x18, 0x46, 0x0c, 0xc3, 0x18,
+ 0x61, 0xcc, 0x30, 0x16, 0x18, 0x31, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x38, 0x8c, 0x99, 0xe1, 0x30, 0x66, 0xc6, 0x18, 0xc3,
+ 0x98, 0x61, 0x98, 0x31, 0x0c, 0x18, 0x00, 0x70, 0x18, 0x66, 0x0c, 0xc3,
+ 0x98, 0x61, 0xcc, 0x30, 0x1e, 0x98, 0x31, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x70, 0x8c, 0xf1, 0xc0, 0x31, 0xc6, 0xc3, 0x18,
+ 0xc3, 0x98, 0x61, 0xf0, 0x30, 0x0c, 0x18, 0x00, 0x70, 0x18, 0x3c, 0x0c,
+ 0xc3, 0xf0, 0x60, 0xcc, 0x30, 0x36, 0xf0, 0x30, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x64, 0x8c, 0x11, 0x90, 0x31, 0x46, 0xc0,
+ 0x18, 0xc3, 0x98, 0x61, 0x10, 0x30, 0x0c, 0x18, 0x00, 0xd8, 0x18, 0x04,
+ 0x0c, 0xc3, 0x10, 0x60, 0xcc, 0x30, 0x66, 0x10, 0x30, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x4c, 0x98, 0xf1, 0x31, 0x61, 0xc6,
+ 0x87, 0x19, 0xc3, 0x98, 0x61, 0xf0, 0x31, 0x0c, 0x30, 0x03, 0x8c, 0x19,
+ 0x7c, 0x0c, 0xc3, 0xf0, 0x61, 0xcc, 0x30, 0xc6, 0xf0, 0x31, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x34, 0xf0, 0xf3, 0xd7, 0xc0,
+ 0xcf, 0x1f, 0xbf, 0xe7, 0xb9, 0xf1, 0xf0, 0x37, 0x1e, 0xe0, 0x01, 0x86,
+ 0x3f, 0xfc, 0x8d, 0xc7, 0xf0, 0xf7, 0xfc, 0x31, 0xc7, 0xf1, 0x7f, 0x0e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x06,
+ 0x00, 0x20, 0x18, 0x00, 0x00, 0x80, 0x01, 0x08, 0x36, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x82, 0x0d, 0xc0, 0x08, 0x06, 0x00, 0x30, 0x00, 0x08, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18,
+ 0x04, 0x00, 0x60, 0x10, 0x00, 0x00, 0x80, 0x01, 0x18, 0x34, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0d, 0xc0, 0x18, 0x04, 0x00, 0x30, 0x00, 0x18,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x38, 0x02, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xe0, 0x00, 0x38, 0x1e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x8e, 0x07, 0x70, 0x38, 0x02, 0x00, 0x1c, 0x00,
+ 0x38, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0xf0, 0x01, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x60, 0x00, 0xf0, 0x0d,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x03, 0x30, 0xf0, 0x01, 0x00, 0x0c,
+ 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xff, 0x7f, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0x55, 0x55, 0x55, 0x55, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xbc, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7c, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xab, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x80, 0x7f, 0x44, 0x44, 0x44, 0xc4, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x55, 0x7f, 0x77, 0x77, 0x77, 0x77, 0x77, 0xf7,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0xfe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0xf1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xfa, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x47, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xab, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xdf, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xfd, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x45, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x0f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe3, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xfa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x91, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0xdc,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x45,
+ 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+ 0xa2, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x71, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x8b, 0xd8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x7d, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x22, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xae,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x89, 0xe8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xea, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x44, 0x74, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0xc4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x22, 0x7a, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x11, 0x17, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x89, 0x88, 0xab, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x44, 0xc4, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x22, 0x62, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x57, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x11, 0x19,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x88,
+ 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xba,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44,
+ 0xc4, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+ 0x22, 0x62, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0xff, 0xff, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0xf7, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0xff, 0x11, 0x11, 0x1d, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x88, 0x88, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xea, 0x89, 0x88, 0x88, 0xe8, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x44, 0x44, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0x44, 0x46, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0xa2, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x23, 0x22, 0x22, 0x22, 0x22, 0xae, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xba, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x11, 0xd1, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x79, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x88, 0xe8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0x8f, 0x88, 0x88, 0x88, 0x88, 0x88, 0xd8, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x44, 0x54, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0xe4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x22, 0xae, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xae,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x11, 0x13, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x17, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x50, 0x0d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xc8, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x89, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0x7d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x75, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x44, 0x74, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x74, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa0, 0xea, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x22, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
+ 0x17, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x17, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x55,
+ 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88,
+ 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x89, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdc, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x74, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x80, 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x26, 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2e,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x13, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x80, 0xaa, 0xaa, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x89, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xea, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xb8,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x44, 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x64, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x64, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x55, 0x55, 0x75, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xe2, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x3f, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x62, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0xf7, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x35, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xaa, 0xaa, 0xaa, 0x0e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x8b, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xc8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x46, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x54, 0x55, 0x55,
+ 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xa8,
+ 0xaa, 0xaa, 0xaa, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xa8, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x8e, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xab, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x5c,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x50, 0x55, 0x55, 0x55, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x23, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x76, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0x00, 0x00, 0x00,
+ 0x00, 0x98, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
+ 0x00, 0x00, 0x6c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x74,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x54, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01,
+ 0x00, 0x00, 0x00, 0xbc, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x2a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x16, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x17, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x1d, 0x00, 0x00, 0x80, 0xdf, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x6a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x44, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x1d, 0x00, 0xd7, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x9d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xd8, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 0x60, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x54, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0xe0, 0xba, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x26, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xe2,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x10,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5f,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x89, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0xdf, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0e, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xb1, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0xb2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x60, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0xd1, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa8, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x3a, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xba, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x00, 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x5c, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x50, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x03, 0x80, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x62, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x80, 0x19, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x13,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x00, 0xc0, 0xa8, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xbc, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x40, 0xc4, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x4f, 0x44, 0x44,
+ 0x44, 0xc4, 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x03, 0x00, 0x20, 0x22, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x62, 0x37, 0x22,
+ 0x22, 0x22, 0x22, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0d, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x30, 0x11,
+ 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x51,
+ 0x11, 0x11, 0x11, 0x11, 0xd1, 0x17, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x80, 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x90,
+ 0x88, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x9a, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xae,
+ 0xea, 0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x1a, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x50, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4,
+ 0x45, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x47, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x05, 0x00,
+ 0x00, 0x28, 0x22, 0x72, 0x77, 0x77, 0x77, 0x77, 0x77, 0x2f, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x62, 0x77, 0xf7, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x7a, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x15, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x18, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x31, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x13,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0xaa, 0xaa, 0xea,
+ 0x00, 0x00, 0x00, 0x88, 0x88, 0xc8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x8e,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0xb8, 0xaa, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x4c, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x74, 0x44, 0x44, 0x44, 0x44, 0x44, 0x14, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xaa,
+ 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x26, 0x22, 0x22, 0xab, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0x23, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xa2, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xba, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x11, 0x11, 0x13, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x3d, 0x11, 0x11, 0x11, 0x11, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x54, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x8a, 0x88, 0x88, 0xdc, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0x89, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xc8, 0xdd, 0xdd, 0xdd, 0xdd, 0x7d, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x46, 0x44, 0x44, 0x4c,
+ 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x47, 0x44, 0x44, 0x44, 0x24,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0xa8, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x23, 0x22, 0x22,
+ 0xba, 0xaa, 0xaa, 0xaa, 0x6a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xb2, 0xaa, 0xaa, 0xaa, 0x23,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xae, 0xaa, 0xaa, 0xaa,
+ 0xea, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11, 0x11,
+ 0x11, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x89,
+ 0x88, 0x88, 0xe8, 0xdd, 0xdd, 0xdd, 0xdd, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdc, 0xdd, 0xdd,
+ 0xdd, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xe8, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x03,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, 0x44,
+ 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4,
+ 0x45, 0x44, 0x44, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x22, 0x22, 0x22, 0xe2, 0xaa, 0xaa, 0xaa, 0x2a, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xab,
+ 0xaa, 0xaa, 0xaa, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x06, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91,
+ 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0xbd, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xc8, 0xdd, 0xdd, 0xdd, 0xdd, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xd8, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x05, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x64,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x64, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x54, 0x44, 0x44, 0x44, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x22, 0x22, 0x22, 0x22, 0xab, 0xaa, 0xaa,
+ 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xb2, 0xaa, 0xaa, 0xaa, 0xaa, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x11, 0x11, 0x11, 0x11, 0x13, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x88, 0x88, 0x88, 0x88, 0xaa,
+ 0xaa, 0xaa, 0x9a, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xc8, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x22, 0x22, 0x22,
+ 0x22, 0x76, 0x77, 0x77, 0x2f, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x76, 0x77, 0x77, 0x77, 0x77, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0x77, 0x77,
+ 0x77, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x11, 0x11,
+ 0x11, 0x11, 0x19, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11,
+ 0x11, 0x11, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xa8, 0xaa, 0xaa, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xea, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xab, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x44, 0x44, 0x44, 0x44, 0x54, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x45, 0x44, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x22, 0x22, 0x22, 0x22, 0x72, 0x77, 0x77, 0x2f, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x62, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x77, 0x77, 0x77, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x35, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x14, 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x19, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x8c, 0x88, 0x88, 0x88, 0x88, 0xa8, 0xaa, 0xaa, 0x8a, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xa8,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64, 0x44, 0x44, 0x4c,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x64, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x26, 0x22, 0x22, 0x22, 0x22, 0x62, 0x77, 0x77,
+ 0x2f, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x76, 0x77, 0x77, 0x77, 0x77, 0x37, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x77, 0x77, 0x77, 0x5f, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x11, 0x11, 0x11, 0x11, 0x51, 0x11,
+ 0x11, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x11, 0x11, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x88, 0x88, 0x88, 0x88, 0xc8,
+ 0xaa, 0xaa, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, 0xba,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x44, 0x44, 0x44, 0x44,
+ 0xc4, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x54, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, 0x44, 0x44,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0xa2, 0xaa, 0xaa, 0x2a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0xe2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa,
+ 0xaa, 0xba, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13,
+ 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xd8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0x9d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xde, 0xdd, 0xdd, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x54, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x46, 0x44, 0x44, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0x2a, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xae, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x11, 0x19, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x13, 0x11, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdc, 0xdd, 0x8d, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0x7d, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x4c,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa,
+ 0x2a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x51, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xd8, 0xdd, 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xe8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x8d, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0x7d,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0d, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x64, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x54, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xa2, 0xaa, 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x26, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xab, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xc8, 0xaa, 0x9a, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x8e, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x54, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0xc4, 0x44, 0x44, 0x44, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x77, 0x37, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0xe2, 0x77, 0x77, 0x77, 0x77, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x15, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0x9a, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xc8, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xc8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x1a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x54,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x7a,
+ 0x37, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x72, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0xf7, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x62, 0x77, 0x77, 0x77, 0x77, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x35, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x31, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xa8, 0xea, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x64, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64, 0x44, 0x44, 0x44,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x62, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x72, 0x77, 0x77,
+ 0x77, 0x77, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x35, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x91, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xab, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xa8,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x6a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x54, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x4c, 0x44, 0x44, 0x44, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xae, 0x23, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0xe2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x2a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x6a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xe8, 0x8b,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xe8, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xde, 0xdd, 0xdd, 0xdd, 0x5d, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x54, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x46, 0x44, 0x44, 0x44, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0xa2, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0xab, 0xaa, 0xaa, 0xaa, 0xba, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x8e, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdc,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x89, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0x5d,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xe2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0xd9, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x11, 0x11,
+ 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xd8, 0x8b, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xbd, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xe8, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xd5, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x54, 0x4c, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64,
+ 0x44, 0x44, 0x44, 0x44, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0x3a, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0xb2, 0xaa, 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x51,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xe8,
+ 0xaa, 0x89, 0x88, 0x88, 0x88, 0x88, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x46, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0xe2, 0x77, 0x3f, 0x22, 0x22, 0x22, 0x22, 0x76, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x27, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x76, 0x77, 0x77, 0x77, 0x77, 0x57, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x91, 0x11, 0xf1, 0x11, 0x11, 0x11, 0x11, 0x15, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x11, 0x11, 0x11, 0x11, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xab, 0xaa, 0x8f, 0x88, 0x88, 0x88, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x5c, 0x44, 0x44, 0x44, 0x45,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x77, 0x77, 0x77, 0x22, 0x22, 0xa2,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x23, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x11, 0x91, 0x11, 0x11,
+ 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xac, 0xaa, 0xaa, 0x8e,
+ 0x88, 0xc8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xa8, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44,
+ 0x74, 0x44, 0x64, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x54, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x7a, 0x77,
+ 0x77, 0xf7, 0x27, 0x62, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0xf7,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x7a,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0xd5, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x39, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x51, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x19, 0x11, 0x11, 0x11, 0x11, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0xa8, 0xaa, 0xaa, 0xaa, 0xea, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xea, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x64, 0x44, 0x44, 0x44, 0x44, 0x4f, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x64, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xe2, 0xaa, 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x2a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x11, 0xf5, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xc8, 0xdd, 0xdd, 0xdd, 0xdd, 0x8d, 0xdf, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x9d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0xc8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x7d, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x46, 0x7c,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x54, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x74, 0x44, 0x44, 0x44, 0x44, 0x44, 0x24,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x27, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0xab, 0xaa, 0xaa, 0xaa, 0x23,
+ 0xa2, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xba, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x14, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91,
+ 0x11, 0x11, 0x3d, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8d,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdf, 0xdd, 0xdd,
+ 0xdd, 0x88, 0x88, 0xc8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x8d, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdf, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x54, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x5e, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa8, 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xae,
+ 0xaa, 0xaa, 0x6a, 0x22, 0x22, 0x22, 0xe2, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xe2, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x2a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x38, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x19, 0x11, 0x11, 0x51, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11,
+ 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x57, 0xbd, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xd8, 0xdd, 0xdd, 0xbd, 0x88, 0x88, 0x88, 0x88, 0xf8, 0xdd, 0xdd,
+ 0xdd, 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdc,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x35, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x00, 0x70, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x54, 0x44, 0x44, 0x64, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x47,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0xaa, 0x6a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0xa2, 0xaa, 0xaa, 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0xfa, 0xaa, 0xaa, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0xe2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x60, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x1f, 0x11, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xea, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xe8, 0xaa, 0xaa, 0x8a, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xe8, 0xab, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x1a, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x40, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x7e, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0xc4, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0xd5, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xe2, 0x77, 0x77, 0x27, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xe2, 0x3f, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x7a, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x15,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0xf3, 0x1f, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0xd1, 0x17, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xaa, 0xaa,
+ 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xab, 0xaa,
+ 0x8e, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xfa, 0x8f,
+ 0x88, 0x88, 0x88, 0x88, 0xbe, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x1a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45,
+ 0x44, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, 0x44,
+ 0xfc, 0xff, 0x7f, 0xe4, 0xff, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x55, 0xd5, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x77, 0x77, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x76,
+ 0x77, 0x77, 0x77, 0xf7, 0x7f, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x0d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xb0, 0xaa, 0xaa, 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0xac, 0xaa, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x06, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x49, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x4c, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x55, 0x55, 0x31, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x7a, 0xf7, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x57, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xaa, 0xaa, 0xa2, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xa8, 0xea, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x42, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xaa, 0xaa, 0x42, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xe2, 0x6a, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xab, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x84,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x31, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x51,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x55,
+ 0x85, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xc8, 0xbd,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0x7d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x08, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4,
+ 0x64, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
+ 0xaa, 0xaa, 0x0a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0xa2, 0x3a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xab,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xba, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x08, 0x14, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x50, 0x55, 0x55, 0x0d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x4e, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xb0, 0xaa, 0xaa, 0x0a, 0x20, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x26, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x20, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x55, 0x55, 0x15, 0xc0, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8c, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x80, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa, 0x1a, 0x00,
+ 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x2a, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x00, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa,
+ 0x1a, 0x00, 0x8c, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x9a,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x20, 0x00, 0x58, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x65, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+ 0x55, 0x55, 0x35, 0x00, 0x20, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x37, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x03, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x20, 0x00, 0x40, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x31, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xa0, 0xaa, 0xaa, 0x2a, 0x00, 0x80, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0xea, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xea, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x45, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x60, 0x55, 0x55, 0x35, 0x00, 0x00, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x62, 0xf7, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xa2, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x14, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x51, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xa8, 0xaa, 0x89, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64, 0x44, 0x45, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x00,
+ 0x00, 0x20, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x72, 0x77, 0x23, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0xc0, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xaa, 0xaa,
+ 0x6a, 0x00, 0x00, 0x80, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0xb8, 0xaa,
+ 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x14, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x2c, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0xaa, 0xaa, 0x26, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x15, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0xa0, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0xdc, 0xdd, 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x46, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xc0, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x80, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0x2a, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xea, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x55, 0x55, 0xd5, 0x00, 0x00, 0x00,
+ 0x00, 0x8c, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0x8d, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x35, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x4c, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x4c, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0xaa, 0xaa, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x22, 0x22, 0x22, 0xe2, 0xaa, 0xaa, 0x2a, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x1a, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x60, 0x11, 0x11, 0x11, 0x31, 0x11, 0x11, 0x19,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, 0x55,
+ 0x55, 0x01, 0x00, 0x00, 0x00, 0x80, 0x89, 0x88, 0x88, 0xf8, 0xdd, 0xdd,
+ 0x8d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x5d, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x44, 0x44, 0x54, 0x44,
+ 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x34, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x22, 0x22, 0xaa,
+ 0xaa, 0xaa, 0x2a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xa2, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xae, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11,
+ 0x19, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x91,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x88,
+ 0x88, 0xac, 0xaa, 0xaa, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x45, 0x44, 0x46, 0x44, 0x44, 0x4c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x64,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x26, 0x22, 0x77, 0x77, 0x77, 0x2f, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x91, 0x11, 0x11, 0x11, 0x19, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xaa, 0xaa, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0xc8, 0xaa, 0xaa, 0xaa, 0x8e, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x75, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x05,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x77, 0x77, 0x77, 0x27, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x11, 0x11, 0x11, 0x15,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
+ 0xaa, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0xaa, 0xaa, 0xaa,
+ 0x8e, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xab, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x47, 0x44,
+ 0x44, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x56, 0x55, 0x55, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, 0x7d,
+ 0x77, 0x77, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x35, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x30, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0xaa, 0xea, 0xab, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x4e, 0xc4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x46, 0x44, 0x44, 0x44, 0x44, 0x44, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xac, 0xaa, 0xaa, 0xfa, 0x6a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x13, 0x11, 0x11, 0x11, 0x11, 0x71, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 0xbd, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xde, 0xdd, 0xdd, 0xdd, 0xdd, 0x5f, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x45, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xe4, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0xaa, 0xaa, 0xaa,
+ 0x06, 0x00, 0x00, 0x00, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, 0x01, 0x3e, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xae, 0xaa, 0xaa, 0xaa, 0xbe,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x60, 0x00, 0xe0,
+ 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x11, 0x11, 0xf1,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x55,
+ 0x55, 0x55, 0x35, 0x00, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 0x1f, 0x00,
+ 0x00, 0xfc, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdc, 0xdd, 0xdd,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x01,
+ 0x00, 0x00, 0x80, 0x4f, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4c, 0x44,
+ 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0xc0, 0xab, 0xaa, 0xaa, 0xaa, 0x6a,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0xaa,
+ 0xea, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x99, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x58, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x88, 0x88, 0x88,
+ 0x88, 0x7f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+ 0xff, 0x7f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xb0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xab, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x55, 0x55, 0x55,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xaa, 0xaa,
+ 0xaa, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0xaa, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x56, 0x55, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x75, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x1d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xb0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0xc0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x55, 0x55, 0x55, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xaa, 0xaa,
+ 0xea, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x7f, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20};
diff --git a/vcl/qa/cppunit/graphicfilter/data/xpm/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/xpm/fail/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xpm/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/xpm/fail/gentoo22729-1.xpm b/vcl/qa/cppunit/graphicfilter/data/xpm/fail/gentoo22729-1.xpm
new file mode 100644
index 000000000..ca2d777a1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xpm/fail/gentoo22729-1.xpm
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/xpm/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/xpm/indeterminate/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xpm/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/xpm/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/xpm/pass/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xpm/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/xpm/pass/tdf111925-1.xpm b/vcl/qa/cppunit/graphicfilter/data/xpm/pass/tdf111925-1.xpm
new file mode 100644
index 000000000..b5eab3e33
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/xpm/pass/tdf111925-1.xpm
@@ -0,0 +1,306 @@
+/* XPM */
+static char * example_xpm[] = {
+"150 100 203 2",
+" c #E6DECA",
+". c #E5DDC9",
+"+ c #E4DCC8",
+"@ c #E3DBC7",
+"# c #E3DAC5",
+"$ c #E2D9C4",
+"% c #E1D8C3",
+"& c #E1D7C1",
+"* c #DFD6C1",
+"= c #DFD5BF",
+"- c #DED4BE",
+"; c #DDD3BD",
+"> c #DDD2BB",
+", c #DCD1BA",
+"' c #DBCFB9",
+") c #DACFB8",
+"! c #D9CDB7",
+"~ c #D8CDB6",
+"{ c #D6CAB2",
+"] c #D7CBB3",
+"^ c #D7CCB5",
+"/ c #D5C9B1",
+"( c #D4C8B0",
+"_ c #D3C7AF",
+": c #D3C6AD",
+"< c #D2C5AC",
+"[ c #D1C3AB",
+"} c #D0C2AA",
+"| c #CFC1A9",
+"1 c #CEC0A8",
+"2 c #CDBFA7",
+"3 c #CBBDA5",
+"4 c #CCBEA6",
+"5 c #CABBA2",
+"6 c #C9BAA1",
+"7 c #CBBCA3",
+"8 c #C8B9A0",
+"9 c #C7B89F",
+"0 c #C6B79E",
+"a c #C5B69D",
+"b c #C5B59B",
+"c c #C4B49A",
+"d c #C3B399",
+"e c #C2B298",
+"f c #C1B197",
+"g c #C0B096",
+"h c #BFAF95",
+"i c #BEAE94",
+"j c #BDAD93",
+"k c #BDAC91",
+"l c #BCAB90",
+"m c #BBAA8F",
+"n c #BAA98E",
+"o c #B9A88D",
+"p c #B2A186",
+"q c #B3A287",
+"r c #B8A78C",
+"s c #B6A58A",
+"t c #B2A084",
+"u c #B09E82",
+"v c #AF9D81",
+"w c #B5A489",
+"x c #7F6B4B",
+"y c #5F4E2D",
+"z c #5E4D2C",
+"A c #614F2D",
+"B c #A39175",
+"C c #9D8B6F",
+"D c #978265",
+"E c #927E5E",
+"F c #8C7858",
+"G c #857151",
+"H c #7A6746",
+"I c #776443",
+"J c #887454",
+"K c #E7DFCB",
+"L c #1E1800",
+"M c #161100",
+"N c #221B00",
+"O c #AB997D",
+"P c #9A876A",
+"Q c #948060",
+"R c #8A7656",
+"S c #816D4D",
+"T c #796645",
+"U c #715E3D",
+"V c #685534",
+"W c #584826",
+"X c #725F3E",
+"Y c #B19F83",
+"Z c #E8E0CC",
+"` c #B7A68B",
+" . c #120F00",
+".. c #000000",
+"+. c #AC9A7E",
+"@. c #937F5F",
+"#. c #826E4E",
+"$. c #6F5D3D",
+"%. c #E9E1CD",
+"&. c #AD9B7F",
+"*. c #9B896D",
+"=. c #847050",
+"-. c #7A6848",
+";. c #6A5838",
+">. c #61502F",
+",. c #5B4A29",
+"'. c #746140",
+"). c #AE9C80",
+"!. c #968164",
+"~. c #8E7A5A",
+"{. c #897555",
+"]. c #8B7757",
+"^. c #836F4F",
+"/. c #7D6949",
+"(. c #9F8D71",
+"_. c #907C5C",
+":. c #A9977B",
+"<. c #A08E72",
+"[. c #9A8568",
+"}. c #988366",
+"|. c #A29074",
+"1. c #9B886B",
+"2. c #958161",
+"3. c #695635",
+"4. c #665534",
+"5. c #756241",
+"6. c #9C8A6E",
+"7. c #625130",
+"8. c #766342",
+"9. c #6B5939",
+"0. c #7E6A4A",
+"a. c #6A5736",
+"b. c #786544",
+"c. c #A79579",
+"d. c #998467",
+"e. c #B4A388",
+"f. c #A59377",
+"g. c #493A13",
+"h. c #3A2D00",
+"i. c #413509",
+"j. c #362B00",
+"k. c #6D5B3B",
+"l. c #52431E",
+"m. c #382D00",
+"n. c #282000",
+"o. c #403306",
+"p. c #5D4C2B",
+"q. c #73603F",
+"r. c #4A3B14",
+"s. c #1A1500",
+"t. c #544422",
+"u. c #8F7B5B",
+"v. c #7C6948",
+"w. c #51421D",
+"x. c #3C3000",
+"y. c #534321",
+"z. c #241C00",
+"A. c #3E3202",
+"B. c #655433",
+"C. c #574725",
+"D. c #50411C",
+"E. c #53441F",
+"F. c #6E5C3C",
+"G. c #554523",
+"H. c #4D3F19",
+"I. c #4F3F19",
+"J. c #A49276",
+"K. c #A8967A",
+"L. c #302600",
+"M. c #473911",
+"N. c #0E0B00",
+"O. c #3F3203",
+"P. c #080600",
+"Q. c #42340A",
+"R. c #4B3C15",
+"S. c #43350B",
+"T. c #877353",
+"U. c #5C4B2A",
+"V. c #46370E",
+"W. c #4C3E18",
+"X. c #322700",
+"Y. c #50401A",
+"Z. c #645332",
+"`. c #2A2100",
+" + c #2E2500",
+".+ c #645230",
+"++ c #A69478",
+"@+ c #867252",
+"#+ c #5A4826",
+"$+ c #463810",
+"%+ c #A18F73",
+"&+ c #806C4C",
+"*+ c #403204",
+"=+ c #413407",
+"-+ c #9E8C70",
+";+ c #958263",
+">+ c #AA987C",
+",+ c #5A4928",
+"'+ c #564624",
+")+ c #4C3D16",
+"!+ c #483912",
+"~+ c #6C5A3A",
+"{+ c #8D7959",
+" ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + + + + + . . . . . . . . . . . . . . . . . . + + + + + + + . . . . . . . . . . . . . . . . . . + + + + + + + + + + + . . . . + . . . . . ",
+" . . . . . . + . . . . . . . . . . . . . . . . . . . . . . . . + + + + + + + + . . . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ @ @ @ @ @ @ @ + + + + + + + . . . . . . . . ",
+" . . . . . + . + + + @ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ @ @ @ @ @ # # # # # # # # # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # # # # # # # # # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # # # # # # # # # # # # # # @ @ @ @ + @ + + . + . . . . ",
+" . . . . + . + + + + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # # # # # # # # # # # # # # # # $ $ $ $ $ % % % % $ $ $ $ $ # # # # # # # # # # # $ $ $ $ $ $ % % % $ $ $ $ $ # # # # # # # # # # # $ $ $ $ % % % % % % % % % $ $ % $ # # # @ @ @ + + + . . . . . . ",
+" . . . . . + . + @ + @ @ # # # # $ $ $ $ $ $ $ # # # # # # # # # # # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % % % & & & & * * * * * * & & & & % % % $ $ $ $ $ % % % % & & & * * * * * * & & & & % % % $ $ $ $ $ % % % & & & * * * * * = = * * * * & & & % % $ $ # # @ @ + + . + . . . . ",
+" . . . . + + + + @ @ # # $ $ % % % % % % % % % % % % % $ $ $ % % % % % % & & & & & & & & & & & & & & * * * = * = = = = = = = = = * * = * * * & & & & & * * * = * * = = = = = = = = * * = * * * & & & & & * * * = * = = = - - - - - - - - = = * = * * & % % $ # # # @ @ + + . . . . ",
+" . . . . + + @ @ @ # # % % % & & & * * * * * * * * * & & & & & & * * * * = * * * * * * * * * * * * = * = - - ; ; > ; > > , > > > > ; ; - - = = * * * * * = = - - ; ; > ; > > > > ; > ; ; - - = = * * * * * = = - - - ; ; > , ' ' ' ' ' , , > > - - - = * * & & % $ # # @ + + + . . . . ",
+" . . . . + + @ @ # # $ % & & = = * = = = - - - - = = = = = = = = = = = - - - - ; ; ; ; ; ; ; ; ; ; ; ; ; > , ' ' ) ) ) ! ! ! ! ! ! ! ) ' ' , > > ; - - - ; > > , ' ) ) ! ! ! ! ! ! ! ! ) ' ' , > > ; - - ; ; > > , ) ) ) ! ! ! ! ~ ~ ~ ! ! ! ! ) ) ' > ; - = * * & % $ # # @ + + + . . . . ",
+" . . . . + + + # # $ % % & * * = - ; ; ; > > , , > > > ; > ; ; ; ; > ; > , ' ' ) ) ) ) ) ) ) ) ) ) ) ) ) ! ! ! ! ~ ~ { { { { { { { { ] ~ ~ ! ! ) ) ) ) ) ) ' ) ! ! ~ ~ ^ ] { { { { / { { ~ ~ ! ! ) ) ) ) ) ) ) ! ! ) ~ ^ ^ { { / { { / { { / { ] ^ ~ ! ! ) ' ; ; = * * & % $ # # + + + . . . ",
+" . . . + + @ @ # $ % & = * = ; > , ) ) ) ! ! ! ! ! ! ! ! ) ) ) ) ) ! ! ! ) ! ! ~ ~ ^ ^ ^ ^ ^ ^ ~ ~ ~ ^ ^ ] { / { / ( ( _ _ _ ( _ _ : ( ( / { { ] ^ ^ ~ ~ ~ ~ ^ { { { / ( ( _ _ _ _ _ _ ( / / { { ] ^ ^ ~ ~ ~ ~ ^ { { { / ( _ _ _ : _ _ : _ _ _ ( / / { { ~ ! ) ' > - = * & % $ # @ @ + + . . . ",
+" . . . . . @ @ # $ % * * = - ; , ) ! ! ~ ^ ^ { { ] ] { ^ ^ ~ ~ ~ ~ ^ ^ ] { / { { / / ( _ ( _ ( ( ( ( ( ( _ _ _ _ _ < [ [ [ } | | | } [ < < : _ _ ( / / / { / ( ( _ _ _ < [ [ [ } } } } } [ [ : _ _ ( / / / { / ( ( _ _ _ < [ } } 1 | | | | 1 1 } [ < : _ / { ] ~ ! ) > ; * * & % # # @ + + . . ",
+" . . . + + @ @ # % & * * - > ' ) ! ~ { / / / / ( ( ( ( ( / ( ( ( / ( ( _ _ ( _ : [ [ [ [ < < [ [ [ [ [ [ < [ } 1 1 1 2 2 2 3 3 3 3 3 2 2 1 | | [ [ < : _ _ _ _ < < [ 1 | 2 2 2 2 3 3 2 1 2 1 | | [ [ < : _ _ _ _ < < } | 1 1 2 3 3 4 3 3 4 3 3 2 2 | | < < _ ( { ^ ! ) , - * * & $ # # + + + . . . ",
+" . . . + @ # $ $ & * = ; > ' ) ~ { { ( _ _ : < [ [ [ [ [ [ < < < [ [ [ [ [ | | | 1 2 2 2 1 2 2 2 2 1 1 2 2 2 2 3 4 5 5 6 5 6 6 6 6 6 6 5 7 4 2 1 1 | | | | | | 1 2 1 3 3 5 5 5 5 5 6 5 5 7 5 4 2 1 1 | | | | | | 1 2 2 4 5 7 5 5 8 8 6 8 8 6 5 5 5 4 2 2 | [ : ( { ] ! ) , - = * % $ # @ @ . . . ",
+" . . . + + @ # $ % * * - ; ) ! ] { / ( < [ [ | | | 1 1 1 1 1 1 1 1 1 2 2 1 2 3 3 5 5 5 5 5 6 6 5 5 7 5 5 5 5 5 5 8 6 9 0 0 a a 0 0 a 0 0 9 9 8 5 5 7 3 3 4 4 3 4 3 7 5 5 8 9 0 0 0 0 0 0 0 9 6 5 5 5 7 3 3 4 4 3 4 3 7 5 5 6 8 0 0 0 a b a a a 0 9 9 6 7 3 2 1 [ < ( { ] ) ' > = * & % # @ + + + . . . ",
+" . . . @ # $ $ % * = ; ' ! ] { ( _ < | 1 2 2 3 3 3 3 7 7 7 7 3 5 7 5 5 6 5 8 8 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b a c c d c c e c c d c b a 0 9 8 6 8 5 5 5 5 8 6 8 9 0 a b c c d d d c c c a 0 9 8 6 8 5 5 5 5 8 6 8 9 0 a b c d d e e e c c c c 0 9 9 5 7 4 1 } < ( { ~ ) ' ; = * % $ # @ + + . . . ",
+" . . + + + @ $ % & * - , ) ~ { ( : < | 1 3 5 5 5 5 6 8 8 8 8 8 8 9 9 0 0 0 a b a b c c d c c c c d d c c d c c d d f f f g g g g g g g f e d c c c b 0 0 0 0 0 0 a b c c d e e g f g f g e e d c c a b 0 0 0 0 0 0 a b c c d f g g g g g g g g f d c b 0 9 6 5 4 1 | < ( ] ~ ) , = * & $ # @ + + + . . ",
+" . . . + + @ # $ % * = ; ) ~ ] ( : } 1 4 7 5 8 0 9 0 0 a a a b b a b c c c d e d f f f g g g g g g g g g g g g g h h i i i j j j j j j i h h g g e c d c c c b c c d d e g g h h i h h i h g g f f e d c c b c c c c d d e f g h h i i j j i i i g g g c c 0 9 8 5 4 1 < _ / ^ ) , - = * % $ # @ + + . . ",
+" . . . . @ # # % * * ; , ) ^ / _ [ 1 4 7 5 8 0 0 a c c d d d e d f e f f f g g i i i i j j j j j j j j j j j j k j j k l k l l l l l k k j j i i g g f f g e e f g g g h h i j j j k k j j j j i i h g f f g e e f g g g h h j j j j l k l j j j j h h f e b a 9 5 7 2 } : ( ] ! ) ; = * % $ @ @ + . . . ",
+" . . + + @ $ % * * ; ' ! ] ( : } 4 3 5 9 0 b d d e f g g g g g h i i j j j j j j k l m l l l l l m l l l l l m m m m n m m m m m m m m l m k j j i h i h h h i h h i j j k k l l m m l l l k k j j i h i h h h i h h j j k j k l m m m m l l k k j i g f d c a 8 5 3 1 [ ( { ^ ' , - & & % # @ + . . . ",
+" . . + + @ # $ % * = , ' ^ { ( [ | 3 5 8 0 b c e g g i i j j j j k k k l k m m m m m n m n m n m n m m n n m m m m m n n n n n n n n m m m m l k l j j j j j j j j j j k k m l m m m m m m m m l l k j j j j j j j j j j k k l m m m m m m m m m k j i h g e c b 0 5 3 1 } _ ( ] ! , ; = & % $ @ + + . . . ",
+" . . + + @ # $ & & = , ) ^ ( : [ 1 7 5 0 b d e g h i j l k m l l m m m n m m m n n m m n n n o o o n n o o o n o n n n n n o o n n m m n m m m m m m l k k k k k l k l l m m m m m m m m m m m m m l l l l k l k k l k l l m m m m m m m m m m m l k j i h f c c a 9 7 4 | : ( ] ! ' ; = & % # @ + + + . . ",
+" . . + + @ # $ & * - , ) ] ( [ | 2 5 8 0 c e g h j j k m m m n n m n n n n n n n n n n n n n n m n n n m n n n n n m m n m m m m m m m m m m m m m m m m m m l m m l m m m m m m m m m m m m m m m m m m m m m l m m l m m m m m m m m m m m m m l k j j h g d c a 8 5 3 1 [ _ ] ~ ' ; = * % $ # @ + + . . ",
+". . . . @ @ # % * = - ' ~ / ( < 1 4 6 0 b e f g j j l l m m m n n n o n n n m m n m m m m m m m l m m m m m m m m m m l m m m l l m m m m m m m m m m m m m m m m m m m m l m m m m m m m m m m m m m m m m m m m m m m m m l m m l l l l m m l l l k j j h g f d b 0 6 7 1 [ _ / ^ ' , = & & $ @ @ + . . ",
+". . . . + @ $ % * = > ' ~ / ( } 1 7 6 0 c e g h j k l m m n n n n n n m m m m m l l k k k j j j j j j j k k k k k j j j j j j j j j k k k l m m m m m m m m m m m m l m l l l k k k k l l l l m m m m m m m m m m m m l m l k l k k k k k l l k k k j j j i g f d c 0 5 3 1 } : / ^ ) , - * % $ # @ + . . ",
+". . . . + @ # % * = , ' ~ / : } 1 7 8 0 c e g i j k l m m n n m m m m m l k k j j i i h g g g g g g g g g g h h g g g g g g g g h i i j j j k k l m m m m m m m m l k k k j j j j j j j j j k k l l m m m m m m m m l k k k j j j j j j j j j j j j j j i h g g d c 0 9 5 4 | < ( ] ! ' - * & % # @ + . . ",
+". . + + # $ % & = , ' ^ / < | 1 5 9 b c f g i j k l m m m m m l l k j j i h g g g e d d d d c c c c c d d d d d d d c c d d d e e g g g h j j j k l k l l k k k k j j j h h g g g h g h i i j j k k k l l l k k k k j i i h h h g g g h g h h i i j i i h g f d c a 9 6 3 | < _ { ~ ' ; * * % # # + + + . ",
+". . + + # $ & & = , ' ^ ( : | 4 5 9 a c e g i j j k k l l k k j i h h g f e d c c a 0 0 0 0 9 9 9 9 0 0 0 0 0 0 0 0 0 0 0 a a b c c d e g g h i i j j j j j j j i h h g g f e e e e f f g g h i i j j j j j j j j i h g g f f e f e e f f g g g h g h h g g f e c 0 9 5 4 1 [ _ / ^ ) , = & & $ @ @ + . . ",
+". . + @ @ $ % & - , ' ^ ( : 1 2 5 9 a c e g h i j j j j j i i g g f e c b a 0 9 8 5 5 5 5 7 7 7 7 7 7 7 7 5 5 5 5 5 5 5 5 6 8 9 9 0 a c c d e g g g i h h h h g g f e d c c b c b c c c d d e g g g h h h h h h g g f e d c c c b c c c c d e f g g g g g g f d c b 9 8 7 2 | < / ^ ) , - * & $ # @ + + . ",
+". . + @ @ # % & = , ! ] ( < | 4 5 9 a c e f g h i i h h h g f e d b a 0 9 6 5 7 4 2 2 1 1 | | | | | | | | 1 1 1 1 1 1 2 2 4 3 7 5 6 8 0 0 b c c e e f f f f e e d c b a 0 0 0 9 9 0 0 0 a b c c d e f g f f f e e d c c a a 0 0 0 0 0 0 a b c d d e f g g f f d d b 0 6 5 4 | < ( ] ~ ' ; * * % $ # @ + + ",
+". . + + @ @ $ & * - , ! ] ( < | 2 5 8 0 c d e g g g g g f e e c b 0 9 8 5 3 4 1 1 | [ < : : _ _ ( ( ( ( _ _ _ _ : : < < < } } | 1 2 4 7 5 6 9 0 a b c c c c c b b a 0 9 8 6 5 5 5 5 5 5 8 8 9 0 0 a c c c c c c b b 0 0 9 8 8 6 5 5 5 6 8 9 9 a b c d d f f f e d c b 0 8 5 3 1 [ ( / ^ ' , - * & $ # @ + + ",
+". . + + @ @ $ & * - , ! { ( : 1 2 5 8 0 b c d e e f e e d c a 0 8 6 5 3 1 1 } < _ ( ( / { ] ^ ] ] ] ] ] ] ] { { ] { { / ( ( _ : < } | 1 4 3 5 5 8 9 9 0 0 0 0 0 8 8 5 5 7 3 4 2 2 2 2 4 3 7 5 6 6 8 0 0 0 0 0 0 9 8 8 5 5 7 3 3 4 4 3 3 7 5 5 9 0 a b c d d e e d c c a 9 5 7 2 | < / ] ! ' - = * % $ # @ + ",
+". . + + @ # $ & & - , ! ] / : 1 4 5 6 0 a c c d d c c c b 0 9 6 5 3 1 | [ : ( ( ] ^ ~ ! ) ) ' ) ' ' ' ' ) ) ) ' ) ) ! ~ ^ ^ ] { ( ( : [ } 1 2 4 7 7 5 5 5 5 5 5 3 3 2 2 1 1 } | } } | | 1 1 2 4 3 7 5 5 5 5 5 5 5 3 3 2 2 1 | | | | | 1 1 4 7 5 6 0 0 b c d d e d c c a 0 8 5 4 | [ _ / ^ ) , - * & $ $ @ + ",
+". . + + @ # $ & & = , ! ] ( : | 2 7 8 9 a b c c c c a 0 0 8 5 3 2 1 [ : ( / ] ~ ! ' , , > ; ; - - - - - - - ; ; ; > > , , ' ! ! ^ { / ( _ < } } 1 1 1 2 2 2 1 1 1 | } [ < : _ _ ( _ _ : < < } | | 1 2 2 2 2 2 1 1 1 | | [ < : : : : < < } 1 1 3 5 6 9 0 b c c d d d c b 0 8 6 3 2 | < ( ] ! ) ; = * % $ $ @ ",
+". . + + @ # $ % & = , ! { / : | 2 7 5 9 0 a b b a a 0 9 6 5 4 1 } : ( / ] ~ ) ' > - - = * & & & % % % % & & & & * * = = - ; > , ) ! ~ ] { ( _ _ < [ } } } } [ [ < _ _ ( ( / / { { { / / / ( _ : : < [ } } } } } [ < : _ ( ( ( ( ( ( ( ( _ < } 1 4 5 5 9 0 a c c c c c b a 0 6 7 4 | } ( ( ] ) ' - * & % $ # ",
+". . + + @ # $ % & = , ! ] / : | 1 3 5 9 0 0 0 a 0 9 8 5 7 4 1 } : ( { ^ ) ' > - = * & % $ # # # # @ @ # # # # # $ $ % % & * = - ; > ' ! ~ ^ ] / ( ( ( ( ( ( ( ( ( / { ] ^ ^ ~ ~ ~ ~ ~ ^ ] ^ { / ( ( ( ( ( ( ( ( ( ( / { { ] ( ( ( ( ( / ( _ : [ 1 4 5 6 0 0 b c c c c c b 0 9 5 3 1 } < ( ] ^ ) ; = * & $ # ",
+". . + + @ # $ & & = , ! ] / : | 2 5 6 9 0 a a a a 0 9 5 3 1 [ : ( ] ~ ' , - = & % $ # @ @ + + + . . . . + + + + + @ @ # $ $ % & = - ; > , ) ! ~ ^ ] ] ] { ] ] ^ ^ ~ ! ) ' , , ' , ' , , ' ) ! ~ ^ ^ ] ] { { ] ] ^ ^ ~ ! ! | m p q q m 1 { / ( : [ 1 3 5 8 0 0 b c c c c b 0 0 8 5 3 1 } _ ( ^ ) ' ; = * % $ ",
+". . + + @ @ $ & & = , ! ] / : 2 a i m r s q t u v v w b 1 } : ( ] ~ ' > - = % % # @ + . . . . . + + @ # $ % & * = ; > , , ' ' ) ) ) ) ' ' , > , > ; ; - - - - - ; ; > , ' , ' ' ) ) ) ) ' ' , , > ' j x y z A x l ] ^ / ( < | 1 3 5 9 0 a b c c c c b a 8 6 3 2 } [ ( ] ^ ) ; = * % $ ",
+". . + + @ @ $ & * - , ) ] / : 6 t B C D E F G x H I J s 1 < ( / ~ ) , - * % # # + . . K K K K K K K K K K K K K . . + @ # $ % & & * = - ; ; ; > > > ; ; - - = = * * & & & & & * * = = - - ; ; > > > > ; ; - - = , s y L M N A w ^ ) ^ / _ < 1 4 7 6 0 a b c c c c b 0 9 8 7 4 1 [ _ / ] ) , - * & $ ",
+". . + @ @ # % & = , ! ^ / : 0 O P Q R S T U V y W X Y 1 _ ( ] ) , ; * % $ @ + . K K Z Z Z Z Z Z Z Z Z Z Z Z Z Z K K K . . + @ @ # $ % % & & * * * * * * * & & % % $ $ $ $ # $ $ $ $ % % & & * * * * * * * * & & % - ` z ...M y s ) ' ! ] ( : } 1 3 6 9 0 b c c c c c a 0 9 5 3 1 } < ( ] ! ' ; = * & ",
+". . + @ # $ % & = , ) ~ / : 9 +.P @.R #.T $.V z W X Y 1 ( / ~ ' > - & $ # + . K K Z Z %.%.%.%.%.%.%.%.%.%.%.Z Z Z Z K K K . + + @ @ # # $ $ $ $ $ $ $ $ # # # @ @ @ @ + + @ @ @ @ # # # $ $ $ $ $ $ $ $ $ $ # # * r z ...M z s ' > ' ~ { ( [ | 4 5 8 0 a c c c c c c 0 0 6 7 4 1 [ _ ] ^ ' , = * % ",
+". . + + # $ % & = > ' ~ / _ 9 &.*.Q F =.-.X ;.>.,.'.t | ( ] ! , - * % # @ . . K Z Z %.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.Z Z Z K K . . + + + @ @ @ @ @ @ + + + + . . . . . . . . . . . + + + @ @ @ @ @ @ @ @ + + + % o y ...M y ` > - , ! ] ( : } 2 7 6 0 a c c d d c b a 0 8 5 4 1 [ _ ( ] ) , - * & ",
+". . . + # # % & * > ' ~ ] ( 8 ).C !.~.{.].{.^./.H R r [ / ^ ) > - & % # + . K Z Z %.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.Z Z Z Z K K K . . . . . . . . . . . . . . . . . . . . . . . $ n y ...M y r ; - > ) ~ / _ } 1 3 6 9 0 b c c d c d a 0 8 5 3 2 | : / ^ ! ' - * & ",
+". . . . + @ # % & * > , ! ] ( 6 v (.D _.Q :.q q p p r 6 < _ / ^ ! ' = $ # + . . . + + . . Z Z Z K . . . K K . . . . . Z K K K + + @ @ @ . . @ # # # + . . + @ @ @ . K K @ @ @ @ @ + + @ # # # @ . K @ m y ...M y r - = ; ' ^ / < 1 3 5 9 0 b c d d d c c b 0 0 5 3 1 } : / ] ) ' ; = & ",
+". . . . @ @ # % & * > , ~ ] ( 5 Y <.[.@.}.s 9 6 5 7 4 | 1 g ` w s l 2 ; @ + . & [ g l l h 2 & Z * } c j h 9 / ^ b l l l a > Z Z > b m m m c ) ; | e j d [ * + * } d j c _ $ K K Z K , b m m m c ! ; 1 f j e | - + @ m A ...M y r - * - ' ~ _ 5 j q u u q m g d d d c c b 0 0 5 3 1 } : / ^ ! ' ; = & ",
+" . . + + @ # $ & * - , ! ] ( 5 q |.1.2.[.r 9 6 5 7 1 | 0 <.H 3.4.5.6.5 & + % 3 *.X >.7.8.B ( . , k !.I V 9.S (.O 0.7.A 7.^.a a ^.7.A 7.S r o !.I a.T *.0 { j !.b.;.H (.4 @ Z %. a ^.7.A 7.S o r Q 5.3.b.!.j , K + m A ...M A o = & - , ( d c.~.T X I G d.&.l f d c c b 0 0 5 3 1 } : / ] ) ' ; = & ",
+" . . + + @ @ $ % * = , ) ~ / 3 e.f.C !.d.&.s s e.n 8 } 3 O 5.g.h.i.9.:.( $ ( c.4.j.M h.k.t , - n ^.l.m.L n.o.p.q.r.M .L 7.k . . k 7.L .s.t.u.v.w.m.N x.y D :.=.y.m.z.A.B.c.^ K %.. k 7.L .s.C.@.0.D.j.N m.E.G l = Z + m A ...M A o = * - ^ e [.F.G.H.I.E.z $.R J.m e c b c 0 9 5 3 2 | : / ^ ! ' - * & ",
+" . . + + # # % & = > , ! { 4 ` K.(.[.2.2.E F J @.m [ < c }.p.A.L.M.x n ( r H o.N.s.y.d.| $ 5 u.I.s.........z.O.N .... .A l . . l A ...P.x.t.Q.M ....P.m.,.;.R.L ....P.S.T.5 %.. l A ...P.o.U.M.s.......L D.E 3 . . m A ...M A o * * ; 3 C V M.i.V.R.D.t.p.9.J K.j c c a 9 9 5 3 1 [ _ ( ] ' , = & & ",
+" . . . . @ @ $ % & * ; , ! ] 1 o O |.1.2.~.G v.5.=.s } _ [ r =.W.X.X.t.@.p _.Y.M N.Q.S h & > v Z.n.......P.N.N.N....... .A l . . l A ..... .z.s.P.......N.`.m.N P....... +U f . %.. l A .....M +L N.P.......`.V p - + l A ...M A o * * ~ w I M.A.S.y.B.a.>.z .+5.Q q d c 0 9 6 5 2 1 < _ ] ^ ' , = * % ",
+" . . . + + @ # % & & - , ' ^ } l &.++C D _.T.0.8.@+s | _ ( 4 c.9.o.`.m.A #.p.`.P. +4.O ! . < !.W.N...N.h.D.#+D.h.N..... .A l . . l A .....N $+l.V.L ......N M.E.$+N ....s.Z.j . %.. l A ..... .x.w.#+D.m.N...N.I.d._ @ l A ...M A o * = 1 1.W x.A.D.x C C ^.V Z.F.@+:.h a 0 8 5 3 2 } < ( ] ! ' ; = * & ",
+" . . + + @ # $ % & * ; , ! [ i Y :.%+[.@.].#.H J ` [ ( / / c Q C.X.z.x.g.m.N.s.D.2.4 + 9 &+*+P...m.;.*.v *.a.m..... .A l . . l A ...P.$+=.(.^.V.P...P.M.@+%+@+M.P... .>.l . %.. l A .....m.9.6.v 1.3.j...P.=+^.8 # l A ...M A o * - c G g.m.*+z *.j l *.X 4.k.&+(.k 0 9 6 5 4 1 [ _ / ^ ) ' - * & $ ",
+" . . . + @ $ % & & - , ) : g q +.B -+C P ;+_.}.k [ ( / ~ ( s /.$+z.L s. .N.=+v.m & Z . f $. +..N.I.d.4 ; 4 d.I.N... .A l . . l A ... .W O } >+W ... .W O [ O W ... .A l . %.. l A ...N.Y.[.2 ; 3 }.I.N...L.X e # l A ...M A o * ; k '.i.j.*+z D +.O d.X V F./.[.n 0 0 5 3 2 | < _ / ^ ' , - * & % ",
+" . . . + + @ @ $ % & = > ' ( d s v c.c.` i j m i 7 : / ] ~ ! 1 %+y j.s. .N.z.p.J.{ K Z . j 4.L .. .,+Y = K = Y ,+ ... .A l . . l A ... .y o = o y ... .y o = o y ... .A l . %.. l A ... .,.t = K = Y ,+ ...N V i $ l A ...M A o * ; o a.x.j.A.R..+F.X $.4.V $./.!.r 0 6 5 4 1 [ < ( ^ ! ' ; = * & $ ",
+" . . . + + @ # $ % & * ; , ( c r u :.O e 1 | | | < _ / ] ~ ) / q U O.L M N.j.F.r * Z Z . k .+s... .z ` # Z # ` z ... .A l . . l A ... .A m $ m A ... .A m $ m A ... .A l . %.. l A ... .z r # Z # ` z ...s..+j $ l A ...M A o * ; r 4.m.j.A.Q.R.D.'+p..+a.X /.;+o 0 5 5 2 1 [ ( / ^ ) , ; = & % $ ",
+" . . . + + @ $ % & * = , / b o p O &.c | [ < < _ ( / ] ! ) 1 %+A j.L M N.z.p.J.{ K Z . j V N .. .#+v - K = u ,+ ... .A l . . l A ... .A l $ l A ... .A l $ l A ... .A l . %.. l A ... .,+Y = K - v #+ ...N V j $ l A ...M A o * ; o 9.A.j.A.R..+F.'.b./.S J ~.-+l 9 5 7 2 | : ( / ^ ' , = * & % # ",
+" . . . @ @ # $ & * = > ] 0 m q +.&.c | | } [ [ _ ( ] ~ ( ` 0.M.`.n.X.L N.=+v.m & Z . e X L...N.H.!.7 - 4 }.I.N... .A l . . l A ... .A l $ l A ... .A l $ l A ... .A l . %.. l A ...N.I.}.2 - 7 !.H.N...L.X e # l A ...M A o * - j I Q.j.o.p.2.O v u u v t q o c 6 5 4 2 } : ( { ~ ' , = * & % # ",
+" . . . + @ @ # $ % & * > ] 0 m q &.+.m f h j l g 2 / ] ] b ;+#+h.L.M.p.M.L L D.2.4 + 8 ^.=+P...j.V P v *.;.m..... .A l . . l A ... .A l $ l A ... .A l $ l A ... .A l . %.. l A .....m.;.*.v P V j...P.=+^.6 # l A ...M A o * - a {.)+m.o.,.;+n a e o t Y q m b 6 5 3 1 } _ ( ] ^ ' ; = * & $ $ ",
+" . . . + @ @ # $ % & * > ] 0 m q +.++f.<.P ;+_.d.h ( { 1 :.F.S.X.i.F.}.I =+N. +4.O ! : }.I.N...N.m.D.#+w.h.N..... .A l . . l A ... .A l $ l A ... .A l $ l A ... .A l . %.. l A ..... .x.w.#+D.m.N... .Y.[._ @ l A ...M A o * = | -+,.A.*+H.q.[.:.f.D {.{.@.++h 6 5 4 2 } : ( { ^ ' , = * & $ # ",
+" . . . @ @ # $ & * = > ] 0 m q +.B *.2.F =.-.{.o : < o @+w.A.x.p.1.f |.z n.N.Q.S i * > t 4.n.......P.N. .N....... .A l . . l A ... .A l $ l A ... .A l $ l A ... .A l . %.. l A .....s.j.N .P.......L.;.q - @ m A ...M A o = = ~ r -.r.o.S.D.Z.U '.U F.5.{.c.f 8 5 7 2 } < ( / ^ ' > - & & % # ",
+" . . . + + @ $ % & * = , / b n p >+|.P @.].S T J r } b P .+S.O.I.T.g ! c R r. .s.y.}.1 % 5 _.Y.s.......P. +Q.n..... .A l . . l A ... .A m % m A ... .A m % m A ... .A l . %.. l A ...P.i.>.g.s.......N E.Q 3 @ @ m y ...M y r - = > 4 %+9.g.S.!+H.y.,+7.9.v.D w b 9 5 7 2 1 [ _ / ^ ' , - * & % $ ",
+" . . . + + @ # $ % & * ; ' ( c r Y :.%+[.@.R S T T.r 7 ).H D.i.M.X ).] % ! t $.x.M h.~+Y ' ; n =.w.j.L n.i.7.T W.s. .L 7.k . . l 7.L .L 7.l % l 7.L .L 7.l % l 7.L .L 7.k . %.+ m A ... .'+Q 0.Y.X.N h.t.J j - @ m >.L .N >.o - = > ^ c 6.'.#+D.D.t.z ;.-.Q ).g 0 0 6 5 4 1 } : / ] ! ' ; = * & # ",
+" . . . + + @ @ $ % & = > ' / 9 k s u >+B *.D E F !.l b B &+F.;.I -+5 ; % & 1 (.X A >.5.|.: # ! m 2.5.4.9.^.B &.0.7.A 7.^.b . . b #.7.A 7.#.c $ c #.7.A 7.#.c $ c #.7.A 7.^.b . Z + m A ... .z v s E X V I D j ' @ + # c S >.y >.S g ; - , ! ( c O E /.5.5.0.{+C t i c a 0 8 5 3 2 | < _ / ^ ' , - * & % ",
+" . . . @ @ # % & * - , ! ] < 4 5 0 d g j m n r k 5 4 f r w s m 7 ! * & % ; } i r o k 5 ; + # > 2 f l j 0 ( { c m m m c ' ' c m m m c ) + ) c n m m c ) + ) c m m m c ' K @ m y ... .y r ~ 4 g k f 1 ; @ @ @ @ ~ e r r r g / - ; , ~ ] : 5 j w Y v Y e.l f c c c 0 0 9 5 4 1 } _ / ] ) ' ; = & % ",
+" . . . + + @ # % * = - , ! ] / _ [ 1 1 4 3 3 3 4 4 1 [ < : ( / ^ ) > ; = = * * - = = = & $ $ $ % & & & & % # # % $ $ $ $ + + + + $ $ % % % @ @ # & & & & % @ @ @ $ $ $ $ $ + + . $ n y ... .y r * % * * * & % $ % $ % % - - ; ; , ; , ' ) ^ / _ } 2 5 8 0 b c c c d c c a 0 9 6 3 4 1 [ ( ] ^ ) ; = * & ",
+" . . . + + @ # $ & & = , ' ~ ] ( : [ | 1 4 4 3 4 4 1 1 } < ( / ] ~ ' , ; ; - = * * & & & % % % % % % $ $ $ # # # @ @ @ + + + + + + @ @ @ @ # # # # $ $ $ # # # # @ @ @ + + + + + + % r y ... .z r = $ % % % % % % & & & & * * = = ; > , ) ~ { ( : [ 1 3 5 8 0 a c c d c c c a a 9 6 3 1 } _ ( ] ) , - * & ",
+" . . . + @ # # $ & * - , ) ^ / ( : | 1 4 3 7 5 7 7 3 2 1 } < ( / ] ^ ! ) ' , , > > ; ; ; - - - - = = = * * * & % % % $ $ $ # # $ $ $ $ % % & & & * * * * * & & & % % $ $ # # # # # = r z ... .z s > = = = - - - - - ; ; ; > > , , ) ! ~ ^ / ( : [ 1 4 7 8 0 a c d d e e d d c a 9 8 7 1 } < ( ] ! ' - * * ",
+" . . . . + @ $ % & * ; , ! ] ( : [ | 2 4 7 5 5 5 5 7 4 2 1 } : _ ( { ] ^ ~ ! ) ) ) ' ' ' ' ' ' ' , , , > > ; - - = = * * & & & & * * * = = - - ; ; ; ; ; ; ; - - = * * & & & & & & ; s z ... .z e.! > , , , ' ' ' , ' ' ' ) ) ! ! ^ ^ { ( ( : [ | 2 7 5 9 a b c e f f f f d c c a 9 5 4 1 < _ ] ~ ' ; * * ",
+" . . + + @ # % * = > , ~ { ( : } 1 4 7 5 5 8 8 6 5 5 3 4 1 | [ : _ ( / / { ] ] ] ^ ^ ^ ^ ^ ^ ~ ~ ~ ! ) ) ' , , , > > ; ; ; ; ; ; ; > , , , , ' ' ' ' ' ' ' , , , > ; ; - - - - - ' w y L .N y q ] ! ! ~ ~ ^ ^ ^ ^ ^ ^ ^ ] ] { { / ( ( : < } 1 2 7 5 9 0 b d e f g g g g f e c b 0 6 3 2 } _ ( ] ' , - * ",
+" . . + + @ # $ % & = > ' ~ { _ [ | 1 3 5 8 8 8 9 9 8 6 5 5 3 2 1 | } [ < : : _ _ ( ( ( ( ( ( ( ( ( / / { ] ] ^ ~ ! ! ) ' ' ' ' ' ' ) ) ! ~ ^ ^ ] ] ^ ^ ^ ] ^ ^ ~ ! ) ' , , > > > > ! k x z p.z /.n ( { / / ( ( ( ( ( ( ( ( ( _ : : < [ } } 1 2 4 7 6 9 0 b c d f g g h g g g e c b 0 8 3 1 } : / ^ ) , - * ",
+" . . + + @ # $ & & - , ) ~ { _ [ 1 3 7 6 8 0 0 0 0 0 9 8 6 5 7 7 4 2 1 1 1 | | } } } } } } } [ [ < < : : _ ( ( / / { ] ] ^ ^ ^ ^ ^ ] { / ( / ( ( ( ( ( ( ( ( / / { ] ^ ~ ! ~ ! ! ~ ~ 1 n t Y u r 5 : _ : < [ [ } } } [ } } } | 1 1 1 1 2 4 7 5 5 9 0 a c c e f g g h i h g g e d c a 8 7 2 | < ( ] ! ' ; * ",
+" . . + + @ # $ % * = , ) ~ / _ [ 1 3 5 6 0 0 0 b b b a 0 0 9 8 6 5 5 5 7 7 7 7 3 3 4 3 3 3 4 4 4 2 1 1 1 | } } < : : _ ( ( ( ( ( ( _ : : < [ } | } } } } } } < : : _ ( / / / { { / ( ( [ } } 1 1 | 1 1 1 1 2 4 4 3 3 3 3 3 3 7 3 7 7 5 6 6 9 0 0 a c c e g g h i j j i i h g f d c 0 8 5 4 1 < ( ] ! ' - * ",
+" . . + + @ @ $ % * = , ' ^ / _ [ 2 3 5 8 0 a b c c c c c b b a a 0 0 0 9 9 9 9 9 8 8 9 9 8 8 8 6 5 6 5 5 7 3 4 2 1 1 | } | } } | } | 1 1 1 2 4 4 3 3 3 3 4 4 2 1 1 } [ [ : : _ _ : < [ [ | | 1 2 3 7 5 5 6 6 8 8 9 9 9 9 9 9 0 9 0 0 0 0 a b c c d e f g h i j j j j j i i g f e c a 0 5 4 1 [ ( ] ! ' - * ",
+" . . + + @ @ $ % * = , ) ^ / _ } 2 7 5 8 0 b c d d e e e d d d c c c c c c c b c c c c b b b a b a 0 0 0 9 8 6 5 5 5 3 4 3 4 4 3 4 3 7 5 5 5 6 8 8 8 8 6 8 5 5 7 3 4 2 1 1 | | | | 1 1 2 4 3 5 5 6 9 0 0 0 a a b b c c b c c c c c c d d d e f g g h h i j j j k k j j j j g g e c b 8 5 3 1 [ ( ] ! ' - * ",
+" . . + + @ # $ & * - , ) ^ / : | 1 7 5 9 0 c d e f f g g g g g f f g f g g f g g f f f f f f f f e e d c c b b a 0 0 9 8 6 8 8 6 8 9 9 0 0 0 a b b b b a a 0 0 8 6 5 5 7 3 4 4 4 4 3 7 5 6 8 9 0 a b c c d e f f f g g f g g g g g g h g h i i i j j j k k l l l l l k j j h f f c 0 9 5 4 | [ ( ] ) ' - * ",
+" . . + + @ # $ & & - , ) ^ / : [ 2 7 5 0 0 c e f g g h h h i i h i i i i i i i i i i i i i j i i i h g g f f e d c c c b b b b b b c c d d d e f f e e e d d c c a 0 0 9 6 6 6 6 6 8 8 0 a a c c e f g g g h i i i j j j j j j j j j j j j k k k k l l m m m m l l m k j j g g e c 0 8 7 2 } : / ^ ) ' - * ",
+" . . + + @ # $ % & = , ' ~ / _ [ 1 3 5 9 a c d g g h i j j j j j k k k k l l l l l m m m m l l l k k j j j j i h g g g g f e e f g g g g g h i i i i i h h g g f d d c b a 0 a a 0 b b c c e f g g i j j k k k l l l m m m m m m m m m m m m m m m m m n m m m m m k k j i g f c b 0 6 5 1 | _ ( ^ ) ' - & ",
+" . . + + @ # % * = , , ^ { _ [ 1 4 5 9 a c e g h i j j k l l l m m m m m m m m n m m m m m n m m m m l m l k k j j j i j i i j i j j j k j k k k k k j j j i h g f f e d c d d c d e f g g h i j k k l m m m m n m n n m n n n n o n n n o n n n n n n n n m m m k k i h g e c a 0 5 7 2 [ : / ] ) , - * ",
+" . . . . + @ $ % * * ; ' ~ ] ( < | 2 5 8 0 c d g h j j k l l m m n n n n o o o o o o r o o r r o o o o n m n n m m m l l l k k l l m l m m m m m m m m m m l k j j i i g g g g g g g g h i j k l l m m n n n o o r o r r r r r r r r r o o r r r o o o o m m m m k j j i g f d b 0 8 5 4 | : ( { ! ) , = * ",
+" . . . + @ # # % & * - , ) ^ / _ } 2 5 8 0 b d f g i j l l m m m n o o o o o r r o r r r r r r r o o o o o o o n n m n n n m m n m m n n n n n n n n m m m m l l k j j j i i i i i j j j k k m m m m n o o o r r r r r r r r r r r r o o r o o o n n n m m m m k j j h g g e c a 9 5 3 1 [ : ( ] ! , ; = & ",
+" . . . + + @ # $ & * - > ) ^ / _ < 1 3 5 9 b c e g h j l l m m m n n n o o o o o o o n o n n n n n n n n o n n n n o o o o n n o o o o n o n n n n n n n m m m m l k k k j j j j j k k l l m l m m m m m m n m n m n n n n o o o o n n n m n m m m m m m l k j j h h g f e c 0 9 8 7 2 1 < ( { ^ ) , - * & ",
+" . . + + + @ $ % * = ; ' ! ] ( < | 2 7 8 0 b d f h i j k m m n m m n m m m m m n m m m m m m m m m m m n m n m n n o n o n n o n n n n n n n m n m m m m m m m l l l l l l l l l l l l l l m l m m m m m m m m m m m m m m m m m l m l m l m k k l k k j j j h g g e c b a 9 6 5 4 1 } : ( { ) ) ; = * & ",
+" . . . @ # # % * * - , ' ^ ( : [ 1 3 5 8 0 c d g g j j k k l m l l m l l m k l l k k l l l k k l k l m l m m m m n m m n n m m m m m m m m l l m l l k l l l m l l l m l l l l l l l l m l m l k k l k k j k j k l j j j j j j j j j j j j i j i h h g g f f e c b b 0 9 5 7 4 1 } < ( ] ! ! ' - * * % ",
+" . . . + + @ # $ & * = ; ) ! ^ ( : | 1 3 8 0 b c e g h i j j j j j k k k j i j j i h i h h h g i h i j i j j j j k k k k k k l k k l k j k j j j j j j j j j j k l k l l l l l l l k k k j k j j j i i i i h g g g h g g g h h h h g g g g g g g f e e d c c c b 0 0 9 6 7 4 1 | < < ( { ~ ) ' - = * & $ ",
+" . . . + + + @ # $ * * - , ) ^ { ( [ | 4 5 6 0 b c f f g g i i i h h g g g g f e e e f d d d e d f e g f f g g g g i h i i i i j h g g g g g g g g g g h g h i i j k j k k l m k k j j j j h g g g g f e e e c d c d c c c d d d d d c c c c c b b c a 0 0 9 0 6 6 5 5 4 2 1 | < _ ( { ~ ) ) ; = * & % # ",
+" . . . + + @ # $ & * * ; ' ! ] ( : [ 1 4 5 8 0 a c c d e g g f g e e d d c b a a a 0 0 0 0 0 0 0 a 0 b b c c c d c d e e e e e d d c c c c c c c d c c e g f h g h j j j j j j j j h h g f f d c b b a 0 0 0 0 0 0 9 9 9 9 0 0 0 0 0 9 9 0 8 8 8 9 5 5 6 5 5 7 3 2 1 | | < : _ / { ~ ! ' ; - * * % $ # ",
+" . . . + + + @ # % & * = ; ) ~ ] ( _ } 1 3 5 9 9 a b c c d c c c c c 0 0 0 9 8 8 6 6 5 6 5 5 6 5 6 6 6 8 8 0 0 0 0 0 0 b b 0 0 0 0 0 0 9 9 9 9 9 9 a a b b c e d f g g h h h h g g e e c c b a 0 0 9 6 5 5 6 7 5 5 5 5 5 5 7 7 7 7 7 7 3 3 3 3 3 3 2 2 2 2 1 1 1 [ [ < _ _ / / ^ ~ ! ' ; = * * % $ $ # ",
+" . . + + @ # $ % & * ; ' ) ^ ] ( : } 2 3 5 5 9 0 a 0 0 a 0 0 9 8 6 6 5 5 3 3 3 2 2 2 2 2 2 2 2 2 3 3 3 7 5 5 5 5 6 5 5 6 5 5 5 5 5 5 5 5 5 7 5 5 6 8 9 0 a c c e f g f f g d c c b a 0 9 8 5 5 7 3 4 2 2 2 1 1 1 1 1 1 1 1 1 1 1 | | | 1 1 | 1 } } [ [ [ : : _ ( / / { ^ ! ! ) , ; - * * % $ # @ @ ",
+" . . . + + @ # $ $ & * * ; ' ) ] { ( : } 1 4 5 5 6 9 8 8 9 6 6 5 7 3 3 2 2 | 1 } [ [ [ } } } [ [ } [ } 1 1 | 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 4 7 5 5 6 9 a a b c c c c b a a 0 8 6 5 7 4 1 | | } [ [ [ < [ : : : : : : : : : : _ _ _ _ _ _ : _ _ ( ( { { { ] ~ ! ! ! ' , ; - * = & % $ # @ @ @ ",
+" . . . + + + @ # % & * = ; ) ! ] { ( : } 1 2 4 7 7 5 5 7 7 4 4 1 1 | [ [ : _ _ ( ( / ( / / ( ( ( _ ( _ _ _ _ : : : : : : : : : : _ _ _ : : < [ [ | | 1 4 3 5 6 8 9 0 0 0 0 9 8 5 5 3 2 1 | | < < _ _ ( / / { / { { { { / / / / / / / { { { { { ] { ^ ~ ~ ! ! ! ! ) ' , ; - = * = * & % $ $ @ @ @ . ",
+" . . . . . + @ # $ % * * - ; ' ! ] / ( < [ | 1 1 2 1 2 1 2 1 | [ [ : _ / / { { ] ^ ^ ~ ~ ~ ~ ~ ^ ^ ^ ] { / { / / { { { { { / / / / / / { / / / _ _ < [ } 1 4 3 7 5 5 5 5 5 5 7 3 4 1 } [ < _ ( / { ] { ~ ~ ! ~ ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ) ) ) ' ) ' , > ; ; = = * = * & % $ $ # # @ + . + ",
+" . . . . . @ @ # $ % & * = , ) ! ] { ( _ < < [ | | | [ < [ : ( / { { ^ ! ! ! ) ) ) ' ' ' ' ' ) ' ) ) ) ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ~ { { / _ _ < | | 1 1 4 3 3 4 1 1 | [ < _ ( { / ~ ! ! ! ) ) ' , , > > > > > > > > > > > > > > > > > ; ; ; ; - - - = = = * * & % % $ $ # @ @ @ + . . . ",
+" . . + + + # # $ % & * - , ) ! ~ { / ( ( _ _ < : _ ( _ / { { ~ ! ! ) , > ; - - - = - = - - - ; ; ; ; > > ; > > > > > > ; ; ; ; > > , ' ) ! ! ^ { / ( _ < < [ | | | | [ < < _ ( { { ~ ! ) ' , ; ; ; - - - = = = = = = = = = = = = = = = = = * * * = = * * * & & % % $ $ # # @ @ + @ + . . . ",
+" . . + + + @ # $ & * * - > ' ! ~ ] { { / / / / { { ] ^ ! ! ' ' ; - - * * = * * * * * * * * * = = = * * = = = = = = = * * * = = = - - ; > ' ) ) ~ ] { / ( _ _ _ _ _ _ ( { { ] ~ ! ' , ; - = = * * & * & & & & & & & & & & & & & & & & & & & & % % % % % $ $ $ $ # # # @ @ + @ + . + . . . ",
+" . . . . . + @ @ # $ & * * - ; ' ) ! ! ~ ^ ] ] ^ ~ ! ) ) ' , ; - = * * * % % % % % % % % % % % % % % % & & & & & & & & & & & & & & & * * = - ; , ' ! ! ~ ] { { { { { { ] ~ ! ! ) , ; - * * & & & % % % $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ # # # # # # @ @ @ @ + @ + + . + . . . . ",
+" . . . . . + @ @ # $ & * * = - ; ' ) ) ! ! ! ! ) ' ' > - = = = * & $ $ $ # # # # # # # # # # # # # # # $ $ $ $ $ $ $ $ $ $ $ $ $ % % & * = = = - > , ) ! ) ! ! ! ! ) ) ) , > - = * * & % % # # # # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + + + + . . . . . . . ",
+" . . . . + @ @ # $ % & * * = - ; ; > > > > ; ; - = = = * & % $ # # @ @ @ @ @ + + + + + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # # $ $ % & & * * - ; ; > , ' ' ' ' , > ; ; = * * & % % $ # # @ @ @ + + + + + + + + + + + + + + + + + + + + + + + + + + + . . . . + . . . . . ",
+" . . + . + @ @ $ $ % & & * * = = - - - - = = * * & & % # # # @ @ + + + + . . . . . . . + + + + + + + + + + + + + + + + + + @ @ # # $ % % & * * * = - - ; ; - - = * * * & % % $ # @ @ + + + + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . + . + + @ # # $ % % & * * * * * * & * & % % $ $ # @ @ @ + + + . . . . . . . . . . . . . . . . . . . . . . . . . + + + + @ @ # # $ % % & * * = * * * * = * * & % % $ # # @ @ + + + + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "};
diff --git a/vcl/qa/cppunit/graphicfilter/filters-dxf-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-dxf-test.cxx
new file mode 100644
index 000000000..7a1335008
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-dxf-test.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <filter/DxfReader.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class DxfFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ DxfFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(DxfFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool DxfFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportDxfGraphic(aFileStream, aGraphic);
+}
+
+void DxfFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/dxf/"));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DxfFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-eps-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-eps-test.cxx
new file mode 100644
index 000000000..34d7bab5d
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-eps-test.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <filter/EpsReader.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class EpsFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ EpsFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(EpsFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool EpsFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportEpsGraphic(aFileStream, aGraphic);
+}
+
+void EpsFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/eps/"));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(EpsFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-met-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-met-test.cxx
new file mode 100644
index 000000000..ff00920ed
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-met-test.cxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <filter/MetReader.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class MetFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ MetFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(MetFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool MetFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportMetGraphic(aFileStream, aGraphic);
+}
+
+void MetFilterTest::testCVEs()
+{
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/met/"));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(MetFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-pcd-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-pcd-test.cxx
new file mode 100644
index 000000000..bd100c8f2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-pcd-test.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <filter/PcdReader.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class PcdFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ PcdFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(PcdFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool PcdFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportPcdGraphic(aFileStream, aGraphic, nullptr);
+}
+
+void PcdFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/pcd/"));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PcdFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-pcx-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-pcx-test.cxx
new file mode 100644
index 000000000..529763151
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-pcx-test.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <filter/PcxReader.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class PcxFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ PcxFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(PcxFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool PcxFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportPcxGraphic(aFileStream, aGraphic);
+}
+
+void PcxFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/pcx/"));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PcxFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-pict-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-pict-test.cxx
new file mode 100644
index 000000000..a24f2d324
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-pict-test.cxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <test/xmltesttools.hxx>
+#include <tools/stream.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/metaactiontypes.hxx>
+
+#include <filter/PictReader.hxx>
+
+using namespace ::com::sun::star;
+
+/* Implementation of Filters test */
+
+class PictFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+ , public XmlTestTools
+{
+public:
+ PictFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ OUString pictURL()
+ {
+ return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/pict/");
+ }
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ void testDontClipTooMuch();
+
+ CPPUNIT_TEST_SUITE(PictFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST(testDontClipTooMuch);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool PictFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportPictGraphic(aFileStream, aGraphic);
+}
+
+void PictFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(), pictURL());
+#endif
+}
+
+void PictFilterTest::testDontClipTooMuch()
+{
+ SvFileStream aFileStream(pictURL() + "clipping-problem.pct", StreamMode::READ);
+ GDIMetaFile aGDIMetaFile;
+ ReadPictFile(aFileStream, aGDIMetaFile);
+
+ MetafileXmlDump dumper;
+ dumper.filterAllActionTypes();
+ dumper.filterActionType(MetaActionType::CLIPREGION, false);
+ xmlDocUniquePtr pDoc = dumpAndParse(dumper, aGDIMetaFile);
+
+ CPPUNIT_ASSERT (pDoc);
+
+ assertXPath(pDoc, "/metafile/clipregion[5]", "top", "0");
+ assertXPath(pDoc, "/metafile/clipregion[5]", "left", "0");
+ assertXPath(pDoc, "/metafile/clipregion[5]", "bottom", "empty");
+ assertXPath(pDoc, "/metafile/clipregion[5]", "right", "empty");
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PictFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-ppm-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-ppm-test.cxx
new file mode 100644
index 000000000..c9c93a687
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-ppm-test.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <filter/PbmReader.hxx>
+
+using namespace ::com::sun::star;
+
+/* Implementation of Filters test */
+
+class PpmFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ PpmFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(PpmFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool PpmFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportPbmGraphic(aFileStream, aGraphic);
+}
+
+void PpmFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/ppm/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/pbm/"));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PpmFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-psd-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-psd-test.cxx
new file mode 100644
index 000000000..bf181f811
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-psd-test.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <filter/PsdReader.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class PsdFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ PsdFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ OUString getUrl() const
+ {
+ return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/psd/");
+ }
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+ void testTdf142629();
+
+ CPPUNIT_TEST_SUITE(PsdFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST(testTdf142629);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool PsdFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportPsdGraphic(aFileStream, aGraphic);
+}
+
+void PsdFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(), getUrl());
+#endif
+}
+
+void PsdFilterTest::testTdf142629()
+{
+ OUString aURL = getUrl() + "tdf142629.psd";
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+
+ // Without the fix in place, the following asserts would have failed
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ CPPUNIT_ASSERT(aGraphic.IsAlpha());
+ CPPUNIT_ASSERT(aGraphic.IsTransparent());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PsdFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-ras-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-ras-test.cxx
new file mode 100644
index 000000000..d986c7d0d
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-ras-test.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <filter/RasReader.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class RasFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ RasFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(RasFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool RasFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportRasGraphic(aFileStream, aGraphic);
+}
+
+void RasFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/ras/"));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RasFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-test.cxx
new file mode 100644
index 000000000..e065cf6b5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-test.cxx
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <cstdlib>
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+
+#include <comphelper/fileformat.h>
+#include <comphelper/propertyvalue.hxx>
+
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+using namespace ::com::sun::star;
+
+/* Implementation of Filters test */
+
+class VclFiltersTest :
+ public test::FiltersTest,
+ public test::BootstrapFixture
+{
+ std::unique_ptr<GraphicFilter> mpGraphicFilter;
+public:
+ VclFiltersTest() :
+ BootstrapFixture(true, false),
+ mpGraphicFilter(new GraphicFilter(false))
+ {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ void checkExportImport(std::u16string_view aFilterShortName);
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ void testScaling();
+ void testExportImport();
+
+ CPPUNIT_TEST_SUITE(VclFiltersTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST(testScaling);
+ CPPUNIT_TEST(testExportImport);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool VclFiltersTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ bool bRetval(ERRCODE_NONE == mpGraphicFilter->ImportGraphic(aGraphic, rURL, aFileStream));
+
+ if (!bRetval)
+ {
+ // if error occurred, we are done
+ return bRetval;
+ }
+
+ // if not and we have an embedded Vector Graphic Data, trigger it's interpretation
+ // to check for error. Graphic with VectorGraphicData (Svg/Emf/Wmf) load without error
+ // as long as one of the three types gets detected. Thus, cycles like load/save in
+ // other format will work (what may be wanted). For the test framework it was indirectly
+ // intended to trigger an error when load in the sense of deep data interpretation fails,
+ // so we need to trigger this here
+ if (aGraphic.getVectorGraphicData())
+ {
+ if (aGraphic.getVectorGraphicData()->getRange().isEmpty())
+ {
+ // invalid file or file with no content
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void VclFiltersTest::testScaling()
+{
+ for (BmpScaleFlag i = BmpScaleFlag::Default; i <= BmpScaleFlag::BiLinear; i = static_cast<BmpScaleFlag>(static_cast<int>(i) + 1))
+ {
+ Bitmap aBitmap(Size(413, 409), vcl::PixelFormat::N24_BPP);
+ BitmapEx aBitmapEx( aBitmap );
+
+ fprintf( stderr, "scale with type %d\n", int( i ) );
+ CPPUNIT_ASSERT( aBitmapEx.Scale( 0.1937046, 0.193154, i ) );
+ Size aAfter( aBitmapEx.GetSizePixel() );
+ fprintf( stderr, "size %" SAL_PRIdINT64 ", %" SAL_PRIdINT64 "\n", sal_Int64(aAfter.Width()), sal_Int64(aAfter.Height()) );
+ CPPUNIT_ASSERT( std::abs (aAfter.Height() - aAfter.Width()) <= 1 );
+ }
+}
+
+void VclFiltersTest::checkExportImport(std::u16string_view aFilterShortName)
+{
+ Bitmap aBitmap(Size(100, 100), vcl::PixelFormat::N24_BPP);
+ aBitmap.Erase(COL_WHITE);
+
+ SvMemoryStream aStream;
+ aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
+
+ css::uno::Sequence< css::beans::PropertyValue > aFilterData{
+ comphelper::makePropertyValue("Interlaced", sal_Int32(0)),
+ comphelper::makePropertyValue("Compression", sal_Int32(1)),
+ comphelper::makePropertyValue("Quality", sal_Int32(90))
+ };
+
+ sal_uInt16 aFilterType = mpGraphicFilter->GetExportFormatNumberForShortName(aFilterShortName);
+ mpGraphicFilter->ExportGraphic(BitmapEx(aBitmap), u"", aStream, aFilterType, &aFilterData );
+
+ CPPUNIT_ASSERT(aStream.Tell() > 0);
+
+ aStream.Seek( STREAM_SEEK_TO_BEGIN );
+
+ Graphic aLoadedGraphic;
+ mpGraphicFilter->ImportGraphic( aLoadedGraphic, u"", aStream );
+
+ BitmapEx aLoadedBitmapEx = aLoadedGraphic.GetBitmapEx();
+ Size aSize = aLoadedBitmapEx.GetSizePixel();
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aSize.Height());
+}
+
+void VclFiltersTest::testExportImport()
+{
+ fprintf(stderr, "Check ExportImport JPG\n");
+ checkExportImport(u"jpg");
+ fprintf(stderr, "Check ExportImport PNG\n");
+ checkExportImport(u"png");
+ fprintf(stderr, "Check ExportImport BMP\n");
+ checkExportImport(u"bmp");
+ fprintf(stderr, "Check ExportImport TIF\n");
+ checkExportImport(u"tif");
+ fprintf(stderr, "Check ExportImport WEBP\n");
+ checkExportImport(u"webp");
+}
+
+void VclFiltersTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/wmf/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/emf/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/png/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/jpg/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/gif/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/bmp/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/xbm/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/xpm/"));
+
+ testDir(OUString(),
+ m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/svm/"));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclFiltersTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-tga-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-tga-test.cxx
new file mode 100644
index 000000000..d0611aa56
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-tga-test.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <filter/TgaReader.hxx>
+
+using namespace ::com::sun::star;
+
+/* Implementation of Filters test */
+
+class TgaFilterTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ TgaFilterTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(TgaFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool TgaFilterTest::load(const OUString &,
+ const OUString &rURL, const OUString &,
+ SfxFilterFlags, SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportTgaGraphic(aFileStream, aGraphic);
+}
+
+void TgaFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(), m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/tga/"));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TgaFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx
new file mode 100644
index 000000000..411386b28
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx
@@ -0,0 +1,316 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <graphic/GraphicFormatDetector.hxx>
+
+#include <filter/TiffReader.hxx>
+
+using namespace ::com::sun::star;
+
+/* Implementation of Filters test */
+
+class TiffFilterTest : public test::FiltersTest, public test::BootstrapFixture
+{
+public:
+ TiffFilterTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ virtual bool load(const OUString&, const OUString& rURL, const OUString&, SfxFilterFlags,
+ SotClipboardFormatId, unsigned int) override;
+
+ OUString getUrl() const
+ {
+ return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/tiff/");
+ }
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+ void testTdf126460();
+ void testTdf115863();
+ void testTdf138818();
+ void testTdf149418();
+ void testTdf74331();
+ void testRoundtrip();
+ void testRGB8bits();
+ void testRGB16bits();
+
+ CPPUNIT_TEST_SUITE(TiffFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST(testTdf126460);
+ CPPUNIT_TEST(testTdf115863);
+ CPPUNIT_TEST(testTdf138818);
+ CPPUNIT_TEST(testTdf149418);
+ CPPUNIT_TEST(testTdf74331);
+ CPPUNIT_TEST(testRoundtrip);
+ CPPUNIT_TEST(testRGB8bits);
+ CPPUNIT_TEST(testRGB16bits);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool TiffFilterTest::load(const OUString&, const OUString& rURL, const OUString&, SfxFilterFlags,
+ SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportTiffGraphicImport(aFileStream, aGraphic);
+}
+
+void TiffFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(), getUrl());
+#endif
+}
+
+void TiffFilterTest::testTdf126460()
+{
+ OUString aURL = getUrl() + "tdf126460.tif";
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ // Without the fix in place, the following asserts would have failed
+ CPPUNIT_ASSERT(aGraphic.IsAlpha());
+ CPPUNIT_ASSERT(aGraphic.IsTransparent());
+}
+
+void TiffFilterTest::testTdf115863()
+{
+ OUString aURL = getUrl() + "tdf115863.tif";
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 0x0(Error Area:Io Class:NONE Code:0)
+ // - Actual : 0x8203(Error Area:Vcl Class:General Code:3)
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(528), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(618), aSize.Height());
+}
+
+void TiffFilterTest::testTdf138818()
+{
+ OUString aURL = getUrl() + "tdf138818.tif";
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 46428
+ // - Actual : 45951
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(46428), aGraphic.GetGfxLink().GetDataSize());
+}
+
+void TiffFilterTest::testTdf149418()
+{
+ OUString aURL = getUrl() + "tdf149418.tif";
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 50938
+ // - Actual : 50029
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(50938), aGraphic.GetGfxLink().GetDataSize());
+}
+
+void TiffFilterTest::testTdf74331()
+{
+ OUString aURL = getUrl() + "tdf74331.tif";
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aSize.Height());
+
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+
+ // Check the image contains different kinds of grays
+ int nGrayCount = 0;
+ int nGray3Count = 0;
+ int nGray7Count = 0;
+ int nLightGrayCount = 0;
+
+ for (tools::Long nX = 1; nX < aSize.Width() - 1; ++nX)
+ {
+ for (tools::Long nY = 1; nY < aSize.Height() - 1; ++nY)
+ {
+ const Color aColor = pReadAccess->GetColor(nY, nX);
+ if (aColor == COL_GRAY)
+ ++nGrayCount;
+ else if (aColor == COL_GRAY3)
+ ++nGray3Count;
+ else if (aColor == COL_GRAY7)
+ ++nGray7Count;
+ else if (aColor == COL_LIGHTGRAY)
+ ++nLightGrayCount;
+ }
+ }
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 313
+ // - Actual : 0
+ CPPUNIT_ASSERT_EQUAL(313, nGrayCount);
+ CPPUNIT_ASSERT_EQUAL(71, nGray3Count);
+ CPPUNIT_ASSERT_EQUAL(227, nGray7Count);
+ CPPUNIT_ASSERT_EQUAL(165, nLightGrayCount);
+}
+
+void TiffFilterTest::testRoundtrip()
+{
+ Bitmap aBitmap(Size(2, 2), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->SetPixel(0, 0, COL_WHITE);
+ pAccess->SetPixel(0, 1, COL_BLACK);
+ pAccess->SetPixel(1, 0, COL_LIGHTRED);
+ pAccess->SetPixel(1, 1, COL_LIGHTGREEN);
+ }
+
+ SvMemoryStream aStream;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName(u"tif");
+ rFilter.ExportGraphic(Graphic(BitmapEx(aBitmap)), u"none", aStream, nFilterFormat);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ Graphic aGraphic;
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"none", aStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ CPPUNIT_ASSERT_EQUAL(GfxLinkType::NativeTif, aGraphic.GetGfxLink().GetType());
+ Bitmap aResultBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ CPPUNIT_ASSERT_EQUAL(Size(2, 2), aResultBitmap.GetSizePixel());
+
+ {
+ Bitmap::ScopedReadAccess pAccess(aResultBitmap);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, Color(pAccess->GetPixel(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, Color(pAccess->GetPixel(0, 1)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, Color(pAccess->GetPixel(1, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, Color(pAccess->GetPixel(1, 1)));
+ }
+
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+ vcl::GraphicFormatDetector aDetector(aStream, "");
+
+ CPPUNIT_ASSERT_EQUAL(true, aDetector.detect());
+ CPPUNIT_ASSERT_EQUAL(true, aDetector.checkTIF());
+ CPPUNIT_ASSERT_EQUAL(OUString(u"TIF"), aDetector.msDetectedFormat);
+}
+
+void TiffFilterTest::testRGB8bits()
+{
+ const std::initializer_list<std::u16string_view> aNames = {
+ u"red8.tif",
+ u"green8.tif",
+ u"blue8.tif",
+ };
+
+ for (const auto& rName : aNames)
+ {
+ OUString aURL = getUrl() + rName;
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aSize.Height());
+
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ const Color aColor = pReadAccess->GetColor(5, 5);
+
+ if (rName == u"red8.tif")
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aColor);
+ else if (rName == u"green8.tif")
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aColor);
+ else
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aColor);
+ }
+}
+
+void TiffFilterTest::testRGB16bits()
+{
+ const std::initializer_list<std::u16string_view> aNames = {
+ u"red16.tif",
+ u"green16.tif",
+ u"blue16.tif",
+ };
+
+ for (const auto& rName : aNames)
+ {
+ OUString aURL = getUrl() + rName;
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aSize.Height());
+
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ const Color aColor = pReadAccess->GetColor(5, 5);
+
+ if (rName == u"red16.tif")
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, aColor);
+ else if (rName == u"green16.tif")
+ // tdf#142151: Without the fix in place, this test would have failed with
+ // - Expected: rgba[00ff00ff]
+ // - Actual : rgba[000000ff]
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aColor);
+ else
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, aColor);
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TiffFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx
new file mode 100644
index 000000000..f9d0bfa84
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <graphic/GraphicFormatDetector.hxx>
+#include <filter/WebpReader.hxx>
+#include <comphelper/propertyvalue.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class WebpFilterTest : public test::FiltersTest, public test::BootstrapFixture
+{
+public:
+ WebpFilterTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ virtual bool load(const OUString&, const OUString& rURL, const OUString&, SfxFilterFlags,
+ SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ void testRoundtripLossless();
+ void testRoundtripLossy();
+ void testReadAlphaLossless();
+ void testReadAlphaLossy();
+ void testReadNoAlphaLossless();
+ void testReadNoAlphaLossy();
+
+ CPPUNIT_TEST_SUITE(WebpFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST(testRoundtripLossless);
+ CPPUNIT_TEST(testRoundtripLossy);
+ CPPUNIT_TEST(testReadAlphaLossless);
+ CPPUNIT_TEST(testReadAlphaLossy);
+ CPPUNIT_TEST(testReadNoAlphaLossless);
+ CPPUNIT_TEST(testReadNoAlphaLossy);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ void testRoundtrip(bool lossy);
+ void testRead(bool lossy, bool alpha);
+};
+
+bool WebpFilterTest::load(const OUString&, const OUString& rURL, const OUString&, SfxFilterFlags,
+ SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportWebpGraphic(aFileStream, aGraphic);
+}
+
+void WebpFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(), m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/webp/"));
+#endif
+}
+
+void WebpFilterTest::testRoundtripLossless() { testRoundtrip(false); }
+
+void WebpFilterTest::testRoundtripLossy() { testRoundtrip(true); }
+
+void WebpFilterTest::testRoundtrip(bool lossy)
+{
+ // Do not use just 2x2, lossy saving would change colors.
+ Bitmap aBitmap(Size(20, 20), vcl::PixelFormat::N24_BPP);
+ AlphaMask aAlpha(Size(20, 20));
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->SetFillColor(COL_WHITE);
+ pAccess->FillRect(tools::Rectangle(Point(0, 0), Size(10, 10)));
+ pAccess->SetFillColor(COL_BLACK);
+ pAccess->FillRect(tools::Rectangle(Point(10, 0), Size(10, 10)));
+ pAccess->SetFillColor(COL_LIGHTRED);
+ pAccess->FillRect(tools::Rectangle(Point(0, 10), Size(10, 10)));
+ pAccess->SetFillColor(COL_BLUE);
+ pAccess->FillRect(tools::Rectangle(Point(10, 10), Size(10, 10)));
+ AlphaScopedWriteAccess pAccessAlpha(aAlpha);
+ pAccessAlpha->SetFillColor(BitmapColor(0)); // opaque
+ pAccessAlpha->FillRect(tools::Rectangle(Point(0, 0), Size(10, 10)));
+ pAccessAlpha->FillRect(tools::Rectangle(Point(10, 0), Size(10, 10)));
+ pAccessAlpha->FillRect(tools::Rectangle(Point(0, 10), Size(10, 10)));
+ pAccessAlpha->SetFillColor(BitmapColor(64, 64, 64));
+ pAccessAlpha->FillRect(tools::Rectangle(Point(10, 10), Size(10, 10)));
+ }
+ BitmapEx aBitmapEx(aBitmap, aAlpha);
+
+ SvMemoryStream aStream;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName(u"webp");
+ css::uno::Sequence<css::beans::PropertyValue> aFilterData{
+ comphelper::makePropertyValue("Lossless", !lossy),
+ comphelper::makePropertyValue("Quality", sal_Int32(100))
+ };
+ rFilter.ExportGraphic(Graphic(aBitmapEx), u"none", aStream, nFilterFormat, &aFilterData);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ Graphic aGraphic;
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"none", aStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ CPPUNIT_ASSERT_EQUAL(GfxLinkType::NativeWebp, aGraphic.GetGfxLink().GetType());
+ BitmapEx aResultBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(Size(20, 20), aResultBitmap.GetSizePixel());
+ CPPUNIT_ASSERT(aResultBitmap.IsAlpha());
+
+ {
+ Bitmap tmpBitmap = aResultBitmap.GetBitmap();
+ Bitmap::ScopedReadAccess pAccess(tmpBitmap);
+ // Note that x,y are swapped.
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, Color(pAccess->GetPixel(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, Color(pAccess->GetPixel(0, 19)));
+ if (lossy)
+ {
+ CPPUNIT_ASSERT_LESS(sal_uInt16(3),
+ pAccess->GetPixel(19, 0).GetColorError(COL_LIGHTRED));
+ CPPUNIT_ASSERT_LESS(sal_uInt16(3), pAccess->GetPixel(19, 19).GetColorError(COL_BLUE));
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, Color(pAccess->GetPixel(19, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, Color(pAccess->GetPixel(19, 19)));
+ }
+ AlphaMask tmpAlpha = aResultBitmap.GetAlpha();
+ AlphaMask::ScopedReadAccess pAccessAlpha(tmpAlpha);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), pAccessAlpha->GetPixelIndex(0, 0));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), pAccessAlpha->GetPixelIndex(0, 19));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), pAccessAlpha->GetPixelIndex(19, 0));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(64), pAccessAlpha->GetPixelIndex(19, 19));
+ }
+
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+ vcl::GraphicFormatDetector aDetector(aStream, "");
+
+ CPPUNIT_ASSERT_EQUAL(true, aDetector.detect());
+ CPPUNIT_ASSERT_EQUAL(true, aDetector.checkWEBP());
+ CPPUNIT_ASSERT_EQUAL(OUString(u"WEBP"), aDetector.msDetectedFormat);
+}
+
+void WebpFilterTest::testReadAlphaLossless() { testRead(false, true); }
+
+void WebpFilterTest::testReadAlphaLossy() { testRead(true, true); }
+
+void WebpFilterTest::testReadNoAlphaLossless() { testRead(false, false); }
+
+void WebpFilterTest::testReadNoAlphaLossy() { testRead(true, false); }
+
+void WebpFilterTest::testRead(bool lossy, bool alpha)
+{
+ // Read a file created in GIMP and check it's read correctly.
+ OUString file = m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/webp/")
+ + (alpha ? u"alpha" : u"noalpha") + "_" + (lossy ? u"lossy" : u"lossless")
+ + ".webp";
+ SvFileStream aFileStream(file, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"none", aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ CPPUNIT_ASSERT_EQUAL(GfxLinkType::NativeWebp, aGraphic.GetGfxLink().GetType());
+ BitmapEx aResultBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), aResultBitmap.GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL(alpha, aResultBitmap.IsAlpha());
+
+ {
+ Bitmap tmpBitmap = aResultBitmap.GetBitmap();
+ Bitmap::ScopedReadAccess pAccess(tmpBitmap);
+ // Note that x,y are swapped.
+ if (lossy)
+ CPPUNIT_ASSERT_LESS(sal_uInt16(2), pAccess->GetPixel(0, 0).GetColorError(COL_LIGHTRED));
+ else
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, Color(pAccess->GetPixel(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, Color(pAccess->GetPixel(9, 9)));
+ if (alpha)
+ {
+ AlphaMask tmpAlpha = aResultBitmap.GetAlpha();
+ AlphaMask::ScopedReadAccess pAccessAlpha(tmpAlpha);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), pAccessAlpha->GetPixelIndex(0, 0));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(255), pAccessAlpha->GetPixelIndex(0, 9));
+ }
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(WebpFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/implanimview.cxx b/vcl/qa/cppunit/implanimview.cxx
new file mode 100644
index 000000000..01386fac0
--- /dev/null
+++ b/vcl/qa/cppunit/implanimview.cxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <vcl/animate/Animation.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/virdev.hxx>
+
+#include <impanmvw.hxx>
+
+namespace
+{
+class TestRenderingContext : public OutputDevice
+{
+public:
+ TestRenderingContext()
+ : OutputDevice(OutDevType::OUTDEV_VIRDEV)
+ {
+ }
+
+ void SaveBackground(VirtualDevice&, const Point&, const Size&, const Size&) const override {}
+ bool AcquireGraphics() const override { return true; }
+ void ReleaseGraphics(bool) override {}
+ bool UsePolyPolygonForComplexGradient() override { return false; }
+};
+}
+
+class VclImplAnimViewTest : public test::BootstrapFixture
+{
+public:
+ VclImplAnimViewTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testMatching();
+ void testDrawToPos();
+ void testGetPosSizeWindow();
+
+ CPPUNIT_TEST_SUITE(VclImplAnimViewTest);
+ CPPUNIT_TEST(testMatching);
+ CPPUNIT_TEST(testDrawToPos);
+ CPPUNIT_TEST(testGetPosSizeWindow);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ Animation createAnimation();
+};
+
+void VclImplAnimViewTest::testMatching()
+{
+ Animation aTestAnim = createAnimation();
+ ScopedVclPtrInstance<TestRenderingContext> pTestRC;
+
+ ImplAnimView* pImplAnimView
+ = new ImplAnimView(&aTestAnim, pTestRC, Point(0, 0), Size(10, 10), 5);
+ CPPUNIT_ASSERT(pImplAnimView->matches(pTestRC, 5));
+ CPPUNIT_ASSERT(!pImplAnimView->matches(pTestRC, 10));
+
+ // caller ID of 0 only matches the OutputDevice
+ CPPUNIT_ASSERT(pImplAnimView->matches(pTestRC, 0));
+}
+
+void VclImplAnimViewTest::testDrawToPos()
+{
+ Animation aTestAnim = createAnimation();
+ ScopedVclPtrInstance<VirtualDevice> pTestRC;
+
+ ImplAnimView* pImplAnimView
+ = new ImplAnimView(&aTestAnim, pTestRC.get(), Point(0, 0), Size(10, 10), 5);
+ pImplAnimView->drawToPos(0);
+ pImplAnimView->drawToPos(1);
+ pImplAnimView->drawToPos(2);
+ pImplAnimView->drawToPos(10);
+
+ CPPUNIT_ASSERT_EQUAL(Size(1, 1), pTestRC->GetOutputSizePixel());
+}
+
+void VclImplAnimViewTest::testGetPosSizeWindow()
+{
+ Animation aTestAnim = createAnimation();
+ ScopedVclPtrInstance<TestRenderingContext> pTestRC;
+
+ ImplAnimView* pImplAnimView
+ = new ImplAnimView(&aTestAnim, pTestRC, Point(0, 0), Size(10, 10), 5);
+ AnimationBitmap aAnimBmp(BitmapEx(Size(3, 4), vcl::PixelFormat::N24_BPP), Point(0, 0),
+ Size(10, 10));
+ Point aPos;
+ Size aSize;
+
+ pImplAnimView->getPosSize(aAnimBmp, aPos, aSize);
+
+ CPPUNIT_ASSERT_EQUAL(Point(0, 0), aPos);
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), aSize);
+}
+
+Animation VclImplAnimViewTest::createAnimation()
+{
+ Animation aAnimation;
+
+ aAnimation.Insert(AnimationBitmap(BitmapEx(Size(3, 4), vcl::PixelFormat::N24_BPP), Point(0, 0),
+ Size(10, 10)));
+ aAnimation.Insert(AnimationBitmap(BitmapEx(Size(3, 3), vcl::PixelFormat::N24_BPP), Point(0, 0),
+ Size(10, 10)));
+
+ return aAnimation;
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclImplAnimViewTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx b/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx
new file mode 100644
index 000000000..0900c02d4
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <unotest/bootstrapfixturebase.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <tools/stream.hxx>
+
+constexpr OUStringLiteral gaDataUrl(u"/vcl/qa/cppunit/jpeg/data/");
+
+class JpegReaderTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(gaDataUrl) + sFileName;
+ }
+
+ Graphic loadJPG(const OUString& aURL);
+
+public:
+ void testReadRGB();
+ void testReadGray();
+ void testReadCMYK();
+ void testTdf138950();
+
+ CPPUNIT_TEST_SUITE(JpegReaderTest);
+ CPPUNIT_TEST(testReadRGB);
+ CPPUNIT_TEST(testReadGray);
+ CPPUNIT_TEST(testReadCMYK);
+ CPPUNIT_TEST(testTdf138950);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+static int deltaColor(BitmapColor aColor1, BitmapColor aColor2)
+{
+ int deltaR = std::abs(aColor1.GetRed() - aColor2.GetRed());
+ int deltaG = std::abs(aColor1.GetGreen() - aColor2.GetGreen());
+ int deltaB = std::abs(aColor1.GetBlue() - aColor2.GetBlue());
+
+ return std::max(std::max(deltaR, deltaG), deltaB);
+}
+
+static bool checkRect(Bitmap& rBitmap, int aLayerNumber, tools::Long nAreaHeight,
+ tools::Long nAreaWidth, Color aExpectedColor, int nMaxDelta)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ tools::Long nWidth = std::min(nAreaWidth, pAccess->Width());
+ tools::Long nHeight = std::min(nAreaHeight, pAccess->Height());
+
+ tools::Long firstX = 0 + aLayerNumber;
+ tools::Long firstY = 0 + aLayerNumber;
+
+ tools::Long lastX = nWidth - 1 - aLayerNumber;
+ tools::Long lastY = nHeight - 1 - aLayerNumber;
+
+ int delta;
+
+ for (tools::Long y = firstY; y <= lastY; y++)
+ {
+ Color aColorFirst = pAccess->GetPixel(y, firstX);
+ delta = deltaColor(aColorFirst, aExpectedColor);
+ if (delta > nMaxDelta)
+ return false;
+
+ Color aColorLast = pAccess->GetPixel(y, lastX);
+ delta = deltaColor(aColorLast, aExpectedColor);
+ if (delta > nMaxDelta)
+ return false;
+ }
+ for (tools::Long x = firstX; x <= lastX; x++)
+ {
+ Color aColorFirst = pAccess->GetPixel(firstY, x);
+ delta = deltaColor(aColorFirst, aExpectedColor);
+ if (delta > nMaxDelta)
+ return false;
+
+ Color aColorLast = pAccess->GetPixel(lastY, x);
+ delta = deltaColor(aColorLast, aExpectedColor);
+ if (delta > nMaxDelta)
+ return false;
+ }
+ return true;
+}
+
+static int getNumberOfImageComponents(const Graphic& rGraphic)
+{
+ GfxLink aLink = rGraphic.GetGfxLink();
+ SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(aLink.GetData()), aLink.GetDataSize(),
+ StreamMode::READ | StreamMode::WRITE);
+ GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
+ CPPUNIT_ASSERT(aDescriptor.Detect(true));
+ return aDescriptor.GetNumberOfImageComponents();
+}
+
+Graphic JpegReaderTest::loadJPG(const OUString& aURL)
+{
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ return aGraphic;
+}
+
+void JpegReaderTest::testReadRGB()
+{
+ Graphic aGraphic = loadJPG(getFullUrl(u"JPEGTestRGB.jpeg"));
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Height());
+
+ int nMaxDelta = 1; // still acceptable color error
+ CPPUNIT_ASSERT(checkRect(aBitmap, 0, 8, 8, Color(0xff, 0xff, 0xff), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0xff, 0x00, 0x00), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0x00, 0xff, 0x00), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x00, 0x00, 0xff), nMaxDelta));
+
+ CPPUNIT_ASSERT_EQUAL(3, getNumberOfImageComponents(aGraphic));
+}
+
+void JpegReaderTest::testReadGray()
+{
+ Graphic aGraphic = loadJPG(getFullUrl(u"JPEGTestGray.jpeg"));
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Height());
+
+ aBitmap.Convert(
+ BmpConversion::N24Bit); // convert to 24bit so we don't need to deal with palette
+
+ int nMaxDelta = 1;
+ CPPUNIT_ASSERT(checkRect(aBitmap, 0, 8, 8, Color(0xff, 0xff, 0xff), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0x36, 0x36, 0x36), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0xb6, 0xb6, 0xb6), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x12, 0x12, 0x12), nMaxDelta));
+
+ CPPUNIT_ASSERT_EQUAL(1, getNumberOfImageComponents(aGraphic));
+}
+
+void JpegReaderTest::testReadCMYK()
+{
+ Graphic aGraphic = loadJPG(getFullUrl(u"JPEGTestCMYK.jpeg"));
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Height());
+
+ int maxDelta = 1;
+ CPPUNIT_ASSERT(checkRect(aBitmap, 0, 8, 8, Color(0xff, 0xff, 0xff), maxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0xff, 0x00, 0x00), maxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0x00, 0xff, 0x00), maxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x00, 0x00, 0xff), maxDelta));
+
+ CPPUNIT_ASSERT_EQUAL(4, getNumberOfImageComponents(aGraphic));
+}
+
+void JpegReaderTest::testTdf138950()
+{
+ Graphic aGraphic = loadJPG(getFullUrl(u"tdf138950.jpeg"));
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(720), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(1280), aSize.Height());
+
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ int nBlackCount = 0;
+ for (tools::Long nY = 0; nY < aSize.Height(); ++nY)
+ {
+ for (tools::Long nX = 0; nX < aSize.Width(); ++nX)
+ {
+ const Color aColor = pReadAccess->GetColor(nY, nX);
+ if ((aColor.GetRed() == 0x00) && (aColor.GetGreen() == 0x00)
+ && (aColor.GetBlue() == 0x00))
+ ++nBlackCount;
+ }
+ }
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 0
+ // - Actual : 921600
+ CPPUNIT_ASSERT_EQUAL(0, nBlackCount);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(JpegReaderTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx b/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx
new file mode 100644
index 000000000..f9b58c308
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <unotest/bootstrapfixturebase.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <tools/stream.hxx>
+#include <graphic/GraphicFormatDetector.hxx>
+
+constexpr OUStringLiteral gaDataUrl(u"/vcl/qa/cppunit/jpeg/data/");
+
+class JpegWriterTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(gaDataUrl) + sFileName;
+ }
+
+ BitmapEx load(const OUString& aURL);
+ BitmapEx roundtripJPG(const BitmapEx& bitmap);
+ BitmapEx roundtripJPG(const OUString& aURL);
+
+public:
+ void testWrite8BitGrayscale();
+ void testWrite8BitNonGrayscale();
+
+ CPPUNIT_TEST_SUITE(JpegWriterTest);
+ CPPUNIT_TEST(testWrite8BitGrayscale);
+ CPPUNIT_TEST(testWrite8BitNonGrayscale);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+BitmapEx JpegWriterTest::load(const OUString& aURL)
+{
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ return aGraphic.GetBitmapEx();
+}
+
+BitmapEx JpegWriterTest::roundtripJPG(const OUString& aURL) { return roundtripJPG(load(aURL)); }
+
+BitmapEx JpegWriterTest::roundtripJPG(const BitmapEx& bitmap)
+{
+ // EXPORT JPEG
+ SvMemoryStream aStream;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 exportFormatJPG = rFilter.GetExportFormatNumberForShortName(JPG_SHORTNAME);
+ Graphic aExportGraphic(bitmap);
+ ErrCode bResult = rFilter.ExportGraphic(aExportGraphic, u"memory", aStream, exportFormatJPG);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ //Detect the magic bytes - we need to be sure the file is actually a JPEG
+ aStream.Seek(0);
+ vcl::GraphicFormatDetector aDetector(aStream, "");
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkJPG());
+ // IMPORT JPEG
+ aStream.Seek(0);
+ Graphic aImportGraphic;
+ sal_uInt16 importFormatJPG = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME);
+ bResult = rFilter.ImportGraphic(aImportGraphic, u"memory", aStream, importFormatJPG);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ return aImportGraphic.GetBitmapEx();
+}
+
+void JpegWriterTest::testWrite8BitGrayscale()
+{
+ Bitmap bitmap = roundtripJPG(getFullUrl(u"8BitGrayscale.jpg")).GetBitmap();
+ Bitmap::ScopedReadAccess access(bitmap);
+ const ScanlineFormat format = access->GetScanlineFormat();
+ // Check that it's still 8bit grayscale.
+ CPPUNIT_ASSERT_EQUAL(ScanlineFormat::N8BitPal, format);
+ CPPUNIT_ASSERT(bitmap.HasGreyPalette8Bit());
+ // Check that the content is valid.
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, access->Width() - 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(access->Height() - 1, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK),
+ access->GetColor(access->Height() - 1, access->Width() - 1));
+}
+
+void JpegWriterTest::testWrite8BitNonGrayscale()
+{
+ Bitmap bitmap = roundtripJPG(getFullUrl(u"8BitNonGrayscale.gif")).GetBitmap();
+ Bitmap::ScopedReadAccess access(bitmap);
+ const ScanlineFormat format = access->GetScanlineFormat();
+ // Check that it's still 8bit grayscale.
+ CPPUNIT_ASSERT_EQUAL(ScanlineFormat::N8BitPal, format);
+ // The original image has grayscale palette, just with entries in a different order.
+ // Do not check for grayscale 8bit, the roundtrip apparently fixes that. What's important
+ // is the content.
+ CPPUNIT_ASSERT(bitmap.HasGreyPaletteAny());
+ // CPPUNIT_ASSERT(bitmap.HasGreyPalette8Bit());
+ // Check that the content is valid.
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, access->Width() - 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(access->Height() - 1, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK),
+ access->GetColor(access->Height() - 1, access->Width() - 1));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(JpegWriterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/jpeg/data/8BitGrayscale.jpg b/vcl/qa/cppunit/jpeg/data/8BitGrayscale.jpg
new file mode 100644
index 000000000..91541e4a8
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/8BitGrayscale.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/8BitNonGrayscale.gif b/vcl/qa/cppunit/jpeg/data/8BitNonGrayscale.gif
new file mode 100644
index 000000000..295310949
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/8BitNonGrayscale.gif
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/JPEGTestCMYK.jpeg b/vcl/qa/cppunit/jpeg/data/JPEGTestCMYK.jpeg
new file mode 100644
index 000000000..81cca025e
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/JPEGTestCMYK.jpeg
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/JPEGTestGray.jpeg b/vcl/qa/cppunit/jpeg/data/JPEGTestGray.jpeg
new file mode 100644
index 000000000..014825f42
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/JPEGTestGray.jpeg
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/JPEGTestRGB.jpeg b/vcl/qa/cppunit/jpeg/data/JPEGTestRGB.jpeg
new file mode 100644
index 000000000..3cfe1dda2
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/JPEGTestRGB.jpeg
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/tdf138950.jpeg b/vcl/qa/cppunit/jpeg/data/tdf138950.jpeg
new file mode 100644
index 000000000..d0296077c
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/tdf138950.jpeg
Binary files differ
diff --git a/vcl/qa/cppunit/lifecycle.cxx b/vcl/qa/cppunit/lifecycle.cxx
new file mode 100644
index 000000000..853cef382
--- /dev/null
+++ b/vcl/qa/cppunit/lifecycle.cxx
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/wrkwin.hxx>
+#include <vcl/toolkit/edit.hxx>
+#include <vcl/toolkit/button.hxx>
+#include <vcl/toolkit/combobox.hxx>
+#include <vcl/toolkit/dialog.hxx>
+#include <vcl/toolkit/field.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/layout.hxx>
+#include <vcl/scheduler.hxx>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+class LifecycleTest : public test::BootstrapFixture
+{
+ void testWidgets(vcl::Window *pParent);
+
+public:
+ LifecycleTest() : BootstrapFixture(true, false) {}
+
+ void testCast();
+ void testVirtualDevice();
+ void testMultiDispose();
+ void testIsolatedWidgets();
+ void testParentedWidgets();
+ void testChildDispose();
+ void testPostDispose();
+ void testLeakage();
+ void testToolkit();
+
+ CPPUNIT_TEST_SUITE(LifecycleTest);
+ CPPUNIT_TEST(testCast);
+ CPPUNIT_TEST(testVirtualDevice);
+ CPPUNIT_TEST(testMultiDispose);
+ CPPUNIT_TEST(testIsolatedWidgets);
+ CPPUNIT_TEST(testParentedWidgets);
+ CPPUNIT_TEST(testChildDispose);
+ CPPUNIT_TEST(testPostDispose);
+ CPPUNIT_TEST(testLeakage);
+ CPPUNIT_TEST(testToolkit);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+// A compile time sanity check
+void LifecycleTest::testCast()
+{
+ ScopedVclPtrInstance< PushButton > xButton( nullptr, 0 );
+ ScopedVclPtr<vcl::Window> xWindow(xButton);
+
+ ScopedVclPtrInstance< MetricField > xField( nullptr, 0 );
+ ScopedVclPtr<SpinField> xSpin(xField);
+ ScopedVclPtr<Edit> xEdit(xField);
+
+// the following line should NOT compile
+// VclPtr<PushButton> xButton2(xWindow);
+}
+
+void LifecycleTest::testVirtualDevice()
+{
+ VclPtr<VirtualDevice> pVDev = VclPtr< VirtualDevice >::Create();
+ ScopedVclPtrInstance< VirtualDevice > pVDev2;
+ VclPtrInstance<VirtualDevice> pVDev3;
+ VclPtrInstance<VirtualDevice> pVDev4(DeviceFormat::DEFAULT);
+ CPPUNIT_ASSERT(!!pVDev);
+ CPPUNIT_ASSERT(!!pVDev2);
+ CPPUNIT_ASSERT(!!pVDev3);
+ CPPUNIT_ASSERT(!!pVDev4);
+ pVDev.disposeAndClear();
+ pVDev4.disposeAndClear();
+}
+
+void LifecycleTest::testMultiDispose()
+{
+ VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
+ CPPUNIT_ASSERT(xWin);
+ xWin->disposeOnce();
+ xWin->disposeOnce();
+ xWin->disposeOnce();
+ CPPUNIT_ASSERT(!xWin->GetWindow(GetWindowType::Parent));
+ CPPUNIT_ASSERT(!xWin->GetChild(0));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(0), xWin->GetChildCount());
+}
+
+void LifecycleTest::testWidgets(vcl::Window *pParent)
+{
+ {
+ ScopedVclPtrInstance< PushButton > aPtr( pParent );
+ (void)aPtr; // silence unused variable warning
+ }
+ {
+ ScopedVclPtrInstance< OKButton > aPtr( pParent );
+ (void)aPtr; // silence unused variable warning
+ }
+ {
+ ScopedVclPtrInstance< CancelButton > aPtr( pParent );
+ (void)aPtr; // silence unused variable warning
+ }
+ {
+ ScopedVclPtrInstance< HelpButton > aPtr( pParent );
+ (void)aPtr; // silence unused variable warning
+ }
+
+ // Some widgets really insist on adoption.
+ if (pParent)
+ {
+ {
+ ScopedVclPtrInstance< CheckBox > aPtr( pParent );
+ (void)aPtr; // silence unused variable warning
+ }
+ {
+ ScopedVclPtrInstance< Edit > aPtr( pParent );
+ (void)aPtr; // silence unused variable warning
+ }
+ {
+ ScopedVclPtrInstance< ComboBox > aPtr( pParent );
+ (void)aPtr; // silence unused variable warning
+ }
+ {
+ ScopedVclPtrInstance< RadioButton > aPtr( pParent, true, 0 );
+ (void)aPtr; // silence unused variable warning
+ }
+ }
+}
+
+void LifecycleTest::testIsolatedWidgets()
+{
+ testWidgets(nullptr);
+}
+
+void LifecycleTest::testParentedWidgets()
+{
+ ScopedVclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
+ CPPUNIT_ASSERT(xWin);
+ xWin->Show();
+ testWidgets(xWin);
+}
+
+namespace {
+
+class DisposableChild : public vcl::Window
+{
+public:
+ explicit DisposableChild(vcl::Window *pParent) : vcl::Window(pParent) {}
+ virtual ~DisposableChild() override
+ {
+ disposeOnce();
+ }
+};
+
+}
+
+void LifecycleTest::testChildDispose()
+{
+ VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
+ CPPUNIT_ASSERT(xWin);
+ VclPtrInstance< DisposableChild > xChild( xWin.get() );
+ xWin->Show();
+ xChild->disposeOnce();
+ xWin->disposeOnce();
+}
+
+void LifecycleTest::testPostDispose()
+{
+ VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
+ xWin->disposeOnce();
+
+ // check selected methods continue to work post-dispose
+ CPPUNIT_ASSERT(!xWin->GetParent());
+ xWin->Show();
+ CPPUNIT_ASSERT(!xWin->IsReallyShown());
+ CPPUNIT_ASSERT(!xWin->IsEnabled());
+ CPPUNIT_ASSERT(!xWin->IsInputEnabled());
+ CPPUNIT_ASSERT(!xWin->GetChild(0));
+ CPPUNIT_ASSERT(!xWin->GetWindow(GetWindowType::Parent));
+}
+
+namespace {
+
+template <class vcl_type>
+class LeakTestClass : public vcl_type
+{
+ bool &mrDeleted;
+public:
+ template<typename... Arg>
+ LeakTestClass(bool &bDeleted, Arg &&... arg) :
+ vcl_type(std::forward<Arg>(arg)...),
+ mrDeleted(bDeleted)
+ {
+ mrDeleted = false;
+ }
+ ~LeakTestClass()
+ {
+ mrDeleted = true;
+ }
+};
+
+class LeakTestObject
+{
+ bool mbDeleted;
+ VclPtr<vcl::Window> mxRef;
+ void *mpRef;
+ LeakTestObject()
+ : mbDeleted(false)
+ , mpRef(nullptr)
+ {
+ }
+public:
+ template<typename vcl_type, typename... Arg> static LeakTestObject *
+ Create(Arg &&... arg)
+ {
+ LeakTestObject *pNew = new LeakTestObject();
+ pNew->mxRef = VclPtr< LeakTestClass< vcl_type > >::Create( pNew->mbDeleted,
+ std::forward<Arg>(arg)...);
+ pNew->mpRef = static_cast<void *>(static_cast<vcl::Window *>(pNew->mxRef));
+ return pNew;
+ }
+ const VclPtr<vcl::Window>& getRef() const { return mxRef; }
+ void disposeAndClear()
+ {
+ mxRef.disposeAndClear();
+ }
+ void assertDeleted()
+ {
+ if (!mbDeleted)
+ {
+ OUStringBuffer aMsg = "Type '";
+ vcl::Window *pWin = static_cast<vcl::Window *>(mpRef);
+ aMsg.appendAscii(typeid(*pWin).name());
+ aMsg.append("' not freed after dispose");
+ CPPUNIT_FAIL(OUStringToOString(aMsg.makeStringAndClear(),
+ RTL_TEXTENCODING_UTF8).getStr());
+ }
+ }
+};
+
+}
+
+void LifecycleTest::testLeakage()
+{
+ std::vector<LeakTestObject *> aObjects;
+
+ // Create objects
+ aObjects.push_back(LeakTestObject::Create<WorkWindow>(nullptr, WB_APP|WB_STDWORK));
+ VclPtr<vcl::Window> xParent = aObjects.back()->getRef();
+
+ aObjects.push_back(LeakTestObject::Create<PushButton>(xParent));
+ aObjects.push_back(LeakTestObject::Create<CheckBox>(xParent));
+ aObjects.push_back(LeakTestObject::Create<Edit>(xParent));
+ aObjects.push_back(LeakTestObject::Create<ComboBox>(xParent));
+ aObjects.push_back(LeakTestObject::Create<RadioButton>(xParent, true, 0));
+
+ { // something that looks like a dialog
+ aObjects.push_back(LeakTestObject::Create<Dialog>(xParent,WB_CLIPCHILDREN|WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE|WB_SIZEABLE));
+ VclPtr<vcl::Window> xDlgParent = aObjects.back()->getRef();
+ aObjects.push_back(LeakTestObject::Create<VclVBox>(xDlgParent));
+ VclPtr<vcl::Window> xVBox = aObjects.back()->getRef();
+ aObjects.push_back(LeakTestObject::Create<VclVButtonBox>(xVBox));
+ }
+
+ aObjects.push_back(LeakTestObject::Create<Dialog>(xParent, u"PrintProgressDialog", "vcl/ui/printprogressdialog.ui"));
+ xParent.clear();
+
+ for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
+ (*i)->getRef()->Show();
+
+ for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
+ (*i)->disposeAndClear();
+
+ for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
+ (*i)->assertDeleted();
+
+ for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
+ delete *i;
+}
+
+void LifecycleTest::testToolkit()
+{
+ LeakTestObject *pVclWin = LeakTestObject::Create<WorkWindow>(nullptr, WB_APP|WB_STDWORK);
+ css::uno::Reference<css::awt::XWindow> xWindow(pVclWin->getRef()->GetComponentInterface(), css::uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xWindow.is());
+
+ // test UNO dispose
+ css::uno::Reference<css::lang::XComponent> xWinComponent = xWindow;
+ CPPUNIT_ASSERT(xWinComponent.is());
+ CPPUNIT_ASSERT(!pVclWin->getRef()->isDisposed());
+ xWinComponent->dispose();
+ CPPUNIT_ASSERT(pVclWin->getRef()->isDisposed());
+
+ // test UNO cleanup
+ xWinComponent.clear();
+ xWindow.clear();
+ pVclWin->disposeAndClear();
+ pVclWin->assertDeleted();
+
+ delete pVclWin;
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LifecycleTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/mnemonic.cxx b/vcl/qa/cppunit/mnemonic.cxx
new file mode 100644
index 000000000..5a2131da2
--- /dev/null
+++ b/vcl/qa/cppunit/mnemonic.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/cppunittraitshelper.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <vcl/mnemonic.hxx>
+
+class VclMnemonicTest : public test::BootstrapFixture
+{
+public:
+ VclMnemonicTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testMnemonic();
+
+ CPPUNIT_TEST_SUITE(VclMnemonicTest);
+ CPPUNIT_TEST(testMnemonic);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclMnemonicTest::testMnemonic()
+{
+ MnemonicGenerator aGenerator;
+
+ {
+ OUString sResult = aGenerator.CreateMnemonic(u"ßa");
+ CPPUNIT_ASSERT_EQUAL(u'~', sResult[1]);
+ }
+
+ {
+ static constexpr OUStringLiteral TEST = u"\u4E00b";
+ OUString sResult = aGenerator.CreateMnemonic(TEST);
+ CPPUNIT_ASSERT_EQUAL(u'~', sResult[1]);
+ }
+
+ {
+ static constexpr OUStringLiteral TEST = u"\u4E00";
+ OUString sResult = aGenerator.CreateMnemonic(TEST);
+ CPPUNIT_ASSERT_EQUAL(OUString("(~C)"), sResult.copy(sResult.getLength() - 4));
+ sResult = MnemonicGenerator::EraseAllMnemonicChars(sResult);
+ CPPUNIT_ASSERT_EQUAL(OUString(TEST), sResult);
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclMnemonicTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/outdev.cxx b/vcl/qa/cppunit/outdev.cxx
new file mode 100644
index 000000000..79fe71431
--- /dev/null
+++ b/vcl/qa/cppunit/outdev.cxx
@@ -0,0 +1,2237 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <test/outputdevice.hxx>
+
+#include <sal/log.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/vector/b2enums.hxx>
+
+#include <vcl/gradient.hxx>
+#include <vcl/lineinfo.hxx>
+#include <vcl/print.hxx>
+#include <vcl/rendercontext/RasterOp.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/window.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/metaact.hxx>
+
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <bufferdevice.hxx>
+#include <window.h>
+
+const size_t INITIAL_SETUP_ACTION_COUNT = 5;
+
+class VclOutdevTest : public test::BootstrapFixture
+{
+public:
+ VclOutdevTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testVirtualDevice();
+ void testUseAfterDispose();
+ void testPrinterBackgroundColor();
+ void testWindowBackgroundColor();
+ void testGetReadableFontColorPrinter();
+ void testGetReadableFontColorWindow();
+ void testDrawInvertedBitmap();
+ void testDrawBlackBitmap();
+ void testDrawWhiteBitmap();
+ void testDrawGrayBitmap();
+ void testDrawBitmap();
+ void testDrawScaleBitmap();
+ void testDrawScalePartBitmap();
+ void testDrawTransformedBitmapEx();
+ void testDrawTransformedBitmapExFlip();
+ void testRTL();
+ void testRTLGuard();
+ void testDefaultFillColor();
+ void testTransparentFillColor();
+ void testFillColor();
+ void testDefaultLineColor();
+ void testTransparentLineColor();
+ void testLineColor();
+ void testFont();
+ void testTransparentFont();
+ void testDefaultRefPoint();
+ void testRefPoint();
+ void testRasterOp();
+ void testOutputFlag();
+ void testAntialias();
+ void testDrawMode();
+ void testLayoutMode();
+ void testDigitLanguage();
+ void testStackFunctions();
+ void testSystemTextColor();
+ void testShouldDrawWavePixelAsRect();
+ void testGetWaveLineSize();
+ void testErase();
+ void testDrawPixel();
+ void testDrawLine();
+ void testDrawRect();
+ void testDrawArc();
+ void testDrawEllipse();
+ void testDrawPie();
+ void testDrawChord();
+ void testDrawCheckered();
+ void testDrawBorder();
+ void testDrawWaveLine();
+ void testDrawPolyLine();
+ void testDrawPolygon();
+ void testDrawPolyPolygon();
+ void testDrawGradient_drawmode();
+ void testDrawGradient_rect_linear();
+ void testDrawGradient_rect_axial();
+ void testDrawGradient_polygon_linear();
+ void testDrawGradient_polygon_axial();
+ void testDrawGradient_rect_complex();
+
+ CPPUNIT_TEST_SUITE(VclOutdevTest);
+ CPPUNIT_TEST(testVirtualDevice);
+ CPPUNIT_TEST(testUseAfterDispose);
+ CPPUNIT_TEST(testPrinterBackgroundColor);
+ CPPUNIT_TEST(testWindowBackgroundColor);
+ CPPUNIT_TEST(testDrawInvertedBitmap);
+ CPPUNIT_TEST(testDrawBlackBitmap);
+ CPPUNIT_TEST(testDrawWhiteBitmap);
+ CPPUNIT_TEST(testDrawGrayBitmap);
+ CPPUNIT_TEST(testDrawBitmap);
+ CPPUNIT_TEST(testDrawScaleBitmap);
+ CPPUNIT_TEST(testDrawScalePartBitmap);
+ CPPUNIT_TEST(testGetReadableFontColorPrinter);
+ CPPUNIT_TEST(testGetReadableFontColorWindow);
+ CPPUNIT_TEST(testDrawTransformedBitmapEx);
+ CPPUNIT_TEST(testDrawTransformedBitmapExFlip);
+ CPPUNIT_TEST(testRTL);
+ CPPUNIT_TEST(testRTLGuard);
+ CPPUNIT_TEST(testDefaultFillColor);
+ CPPUNIT_TEST(testTransparentFillColor);
+ CPPUNIT_TEST(testFillColor);
+ CPPUNIT_TEST(testDefaultLineColor);
+ CPPUNIT_TEST(testTransparentLineColor);
+ CPPUNIT_TEST(testLineColor);
+ CPPUNIT_TEST(testFont);
+ CPPUNIT_TEST(testTransparentFont);
+ CPPUNIT_TEST(testDefaultRefPoint);
+ CPPUNIT_TEST(testRefPoint);
+ CPPUNIT_TEST(testRasterOp);
+ CPPUNIT_TEST(testOutputFlag);
+ CPPUNIT_TEST(testAntialias);
+ CPPUNIT_TEST(testDrawMode);
+ CPPUNIT_TEST(testLayoutMode);
+ CPPUNIT_TEST(testDigitLanguage);
+ CPPUNIT_TEST(testStackFunctions);
+ CPPUNIT_TEST(testSystemTextColor);
+ CPPUNIT_TEST(testShouldDrawWavePixelAsRect);
+ CPPUNIT_TEST(testGetWaveLineSize);
+ CPPUNIT_TEST(testErase);
+ CPPUNIT_TEST(testDrawPixel);
+ CPPUNIT_TEST(testDrawLine);
+ CPPUNIT_TEST(testDrawRect);
+ CPPUNIT_TEST(testDrawArc);
+ CPPUNIT_TEST(testDrawEllipse);
+ CPPUNIT_TEST(testDrawPie);
+ CPPUNIT_TEST(testDrawChord);
+ CPPUNIT_TEST(testDrawCheckered);
+ CPPUNIT_TEST(testDrawBorder);
+ CPPUNIT_TEST(testDrawWaveLine);
+ CPPUNIT_TEST(testDrawPolyLine);
+ CPPUNIT_TEST(testDrawPolygon);
+ CPPUNIT_TEST(testDrawPolyPolygon);
+ CPPUNIT_TEST(testDrawGradient_drawmode);
+ CPPUNIT_TEST(testDrawGradient_rect_linear);
+ CPPUNIT_TEST(testDrawGradient_rect_axial);
+ CPPUNIT_TEST(testDrawGradient_polygon_linear);
+ CPPUNIT_TEST(testDrawGradient_polygon_axial);
+ CPPUNIT_TEST(testDrawGradient_rect_complex);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclOutdevTest::testGetReadableFontColorPrinter()
+{
+ ScopedVclPtrInstance<Printer> pPrinter;
+ CPPUNIT_ASSERT_EQUAL(pPrinter->GetReadableFontColor(COL_WHITE, COL_WHITE), COL_BLACK);
+}
+
+void VclOutdevTest::testGetReadableFontColorWindow()
+{
+ ScopedVclPtrInstance<vcl::Window> pWindow(nullptr, WB_APP | WB_STDWORK);
+ CPPUNIT_ASSERT_EQUAL(pWindow->GetOutDev()->GetReadableFontColor(COL_WHITE, COL_BLACK),
+ COL_WHITE);
+ CPPUNIT_ASSERT_EQUAL(pWindow->GetOutDev()->GetReadableFontColor(COL_WHITE, COL_WHITE),
+ COL_BLACK);
+ CPPUNIT_ASSERT_EQUAL(pWindow->GetOutDev()->GetReadableFontColor(COL_BLACK, COL_BLACK),
+ COL_WHITE);
+}
+
+void VclOutdevTest::testPrinterBackgroundColor()
+{
+ ScopedVclPtrInstance<Printer> pPrinter;
+ CPPUNIT_ASSERT_EQUAL(pPrinter->GetBackgroundColor(), COL_WHITE);
+}
+
+void VclOutdevTest::testWindowBackgroundColor()
+{
+ ScopedVclPtrInstance<vcl::Window> pWindow(nullptr, WB_APP | WB_STDWORK);
+ pWindow->SetBackground(Wallpaper(COL_WHITE));
+ CPPUNIT_ASSERT_EQUAL(pWindow->GetBackgroundColor(), COL_WHITE);
+}
+
+void VclOutdevTest::testVirtualDevice()
+{
+// TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
+#ifndef MACOSX
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ pVDev->SetOutputSizePixel(Size(32, 32));
+ pVDev->SetBackground(Wallpaper(COL_WHITE));
+
+ CPPUNIT_ASSERT_EQUAL(pVDev->GetBackgroundColor(), COL_WHITE);
+
+ pVDev->Erase();
+ pVDev->DrawPixel(Point(1, 2), COL_BLUE);
+ pVDev->DrawPixel(Point(31, 30), COL_RED);
+
+ Size aSize = pVDev->GetOutputSizePixel();
+ CPPUNIT_ASSERT_EQUAL(Size(32, 32), aSize);
+
+ Bitmap aBmp = pVDev->GetBitmap(Point(), aSize);
+
+#if 0
+ OUString rFileName("/tmp/foo-unx.png");
+ try {
+ vcl::PNGWriter aWriter( aBmp );
+ SvFileStream sOutput( rFileName, StreamMode::WRITE );
+ aWriter.Write( sOutput );
+ sOutput.Close();
+ } catch (...) {
+ SAL_WARN("vcl", "Error writing png to " << rFileName);
+ }
+#endif
+
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(0, 0)));
+#if !defined _WIN32 //TODO: various failures on Windows tinderboxes
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, pVDev->GetPixel(Point(1, 2)));
+ CPPUNIT_ASSERT_EQUAL(COL_RED, pVDev->GetPixel(Point(31, 30)));
+#endif
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(30, 31)));
+
+ // Gotcha: y and x swap for BitmapReadAccess: deep joy.
+ Bitmap::ScopedReadAccess pAcc(aBmp);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, static_cast<Color>(pAcc->GetPixel(0, 0)));
+#if !defined _WIN32 //TODO: various failures on Windows tinderboxes
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<Color>(pAcc->GetPixel(2, 1)));
+ CPPUNIT_ASSERT_EQUAL(COL_RED, static_cast<Color>(pAcc->GetPixel(30, 31)));
+#endif
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, static_cast<Color>(pAcc->GetPixel(31, 30)));
+
+#if 0
+ VclPtr<vcl::Window> pWin = VclPtr<WorkWindow>::Create( (vcl::Window *)nullptr );
+ CPPUNIT_ASSERT( pWin );
+ OutputDevice *pOutDev = pWin.get();
+#endif
+#endif
+}
+
+void VclOutdevTest::testUseAfterDispose()
+{
+ // Create a virtual device, enable map mode then dispose it.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ pVDev->EnableMapMode();
+
+ pVDev->disposeOnce();
+
+ // Make sure that these don't crash after dispose.
+ pVDev->GetInverseViewTransformation();
+
+ pVDev->GetViewTransformation();
+}
+
+void VclOutdevTest::testDrawInvertedBitmap()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetRasterOp(RasterOp::Invert);
+ pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
+ MetaActionType::BMP);
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::RASTEROP, pAction->GetType());
+ auto pRasterOpAction = static_cast<MetaRasterOpAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(RasterOp::Invert, pRasterOpAction->GetRasterOp());
+
+ pAction = aMtf.GetAction(1);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::RECT, pAction->GetType());
+ auto pRectAction = static_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(10, 10)), pRectAction->GetRect());
+}
+
+void VclOutdevTest::testDrawBlackBitmap()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+ aBitmap.Erase(COL_RED);
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetDrawMode(DrawModeFlags::BlackBitmap);
+ pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
+ MetaActionType::BMP);
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::PUSH, pAction->GetType());
+ auto pPushAction = static_cast<MetaPushAction*>(pAction);
+ bool bLineFillFlag
+ = ((vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR) == pPushAction->GetFlags());
+ CPPUNIT_ASSERT_MESSAGE("Push flags not LINECOLOR | FILLCOLOR", bLineFillFlag);
+
+ pAction = aMtf.GetAction(1);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
+ auto pLineColorAction = static_cast<MetaLineColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pLineColorAction->GetColor());
+
+ pAction = aMtf.GetAction(2);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
+ auto pFillColorAction = static_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pFillColorAction->GetColor());
+
+ pAction = aMtf.GetAction(3);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::RECT, pAction->GetType());
+ auto pRectAction = static_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(10, 10)), pRectAction->GetRect());
+
+ pAction = aMtf.GetAction(4);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::POP, pAction->GetType());
+
+ // test to see if the color is black
+ Bitmap aBlackBmp(pVDev->GetBitmap(Point(0, 0), Size(10, 10)));
+ Bitmap::ScopedReadAccess pReadAccess(aBlackBmp);
+ const BitmapColor& rColor = pReadAccess->GetColor(0, 0);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK), rColor);
+}
+
+void VclOutdevTest::testDrawWhiteBitmap()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetDrawMode(DrawModeFlags::WhiteBitmap);
+ pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
+ MetaActionType::BMP);
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::PUSH, pAction->GetType());
+ auto pPushAction = static_cast<MetaPushAction*>(pAction);
+ bool bLineFillFlag
+ = ((vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR) == pPushAction->GetFlags());
+ CPPUNIT_ASSERT_MESSAGE("Push flags not LINECOLOR | FILLCOLOR", bLineFillFlag);
+
+ pAction = aMtf.GetAction(1);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
+ auto pLineColorAction = static_cast<MetaLineColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, pLineColorAction->GetColor());
+
+ pAction = aMtf.GetAction(2);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
+ auto pFillColorAction = static_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, pFillColorAction->GetColor());
+
+ pAction = aMtf.GetAction(3);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::RECT, pAction->GetType());
+ auto pRectAction = static_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(10, 10)), pRectAction->GetRect());
+
+ pAction = aMtf.GetAction(4);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::POP, pAction->GetType());
+
+ // test to see if the color is white
+ Bitmap aWhiteBmp(pVDev->GetBitmap(Point(0, 0), Size(10, 10)));
+ Bitmap::ScopedReadAccess pReadAccess(aWhiteBmp);
+ const BitmapColor& rColor = pReadAccess->GetColor(0, 0);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), rColor);
+}
+
+void VclOutdevTest::testDrawBitmap()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
+ MetaActionType::BMP);
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::BMP, pAction->GetType());
+ auto pBmpAction = static_cast<MetaBmpAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(Size(16, 16), pBmpAction->GetBitmap().GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL(Point(0, 0), pBmpAction->GetPoint());
+}
+
+void VclOutdevTest::testDrawScaleBitmap()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->DrawBitmap(Point(5, 5), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
+ MetaActionType::BMPSCALE);
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPSCALE, pAction->GetType());
+ auto pBmpScaleAction = static_cast<MetaBmpScaleAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(Size(16, 16), pBmpScaleAction->GetBitmap().GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL(Point(5, 5), pBmpScaleAction->GetPoint());
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), pBmpScaleAction->GetSize());
+}
+
+void VclOutdevTest::testDrawScalePartBitmap()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(5, 5), Size(10, 10), aBitmap,
+ MetaActionType::BMPSCALEPART);
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPSCALEPART, pAction->GetType());
+ auto pBmpScalePartAction = static_cast<MetaBmpScalePartAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(Size(16, 16), pBmpScalePartAction->GetBitmap().GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL(Point(5, 5), pBmpScalePartAction->GetSrcPoint());
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), pBmpScalePartAction->GetSrcSize());
+ CPPUNIT_ASSERT_EQUAL(Point(0, 0), pBmpScalePartAction->GetDestPoint());
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), pBmpScalePartAction->GetDestSize());
+}
+
+void VclOutdevTest::testDrawGrayBitmap()
+{
+ // draw a red 1x1 bitmap
+ Bitmap aBmp(Size(1, 1), vcl::PixelFormat::N24_BPP);
+ aBmp.Erase(COL_RED);
+
+ // check to ensure that the bitmap is red
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aBmp);
+ const BitmapColor& rColor = pReadAccess->GetColor(0, 0);
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), rColor);
+ }
+
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ pVDev->SetDrawMode(DrawModeFlags::GrayBitmap);
+ pVDev->DrawBitmap(Point(0, 0), Size(1, 1), Point(0, 0), Size(1, 1), aBmp, MetaActionType::BMP);
+
+ // should be a grey
+ Bitmap aVDevBmp(pVDev->GetBitmap(Point(), Size(1, 1)));
+ {
+ Bitmap::ScopedReadAccess pReadAccess(aVDevBmp);
+ const BitmapColor& rColor = pReadAccess->GetColor(0, 0);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x26), sal_Int32(rColor.GetRed()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x26), sal_Int32(rColor.GetGreen()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x26), sal_Int32(rColor.GetBlue()));
+ }
+}
+
+void VclOutdevTest::testDrawTransformedBitmapEx()
+{
+ // Create a virtual device, and connect a metafile to it.
+ // Also create a 16x16 bitmap.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+ {
+ // Fill the top left quarter with black.
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(COL_WHITE);
+ for (int i = 0; i < 8; ++i)
+ {
+ for (int j = 0; j < 8; ++j)
+ {
+ pWriteAccess->SetPixel(j, i, COL_BLACK);
+ }
+ }
+ }
+ BitmapEx aBitmapEx(aBitmap);
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.scale(8, 8);
+ // Rotate 90 degrees clockwise, so the black part goes to the top right.
+ aMatrix.rotate(M_PI / 2);
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ // Draw the rotated bitmap on the vdev.
+ pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf.GetActionSize());
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE, pAction->GetType());
+ auto pBitmapAction = static_cast<MetaBmpExScaleAction*>(pAction);
+ const BitmapEx& rBitmapEx = pBitmapAction->GetBitmapEx();
+ Size aTransformedSize = rBitmapEx.GetSizePixel();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 16x16
+ // - Actual : 8x8
+ // I.e. the bitmap before scaling was already scaled down, just because it was rotated.
+ CPPUNIT_ASSERT_EQUAL(Size(16, 16), aTransformedSize);
+
+ aBitmap = rBitmapEx.GetBitmap();
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ for (int i = 0; i < 16; ++i)
+ {
+ for (int j = 0; j < 16; ++j)
+ {
+ BitmapColor aColor = pAccess->GetPixel(j, i);
+ Color aExpected = i >= 8 && j < 8 ? COL_BLACK : COL_WHITE;
+ std::stringstream ss;
+ ss << "Color is expected to be ";
+ ss << ((aExpected == COL_WHITE) ? "white" : "black");
+ ss << ", is " << aColor.AsRGBHexString();
+ ss << " (row " << j << ", col " << i << ")";
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: c[00000000]
+ // - Actual : c[ffffff00]
+ // - Color is expected to be black, is ffffff (row 0, col 8)
+ // i.e. the top right quarter of the image was not fully black, there was a white first
+ // row.
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(ss.str(), aExpected, Color(aColor));
+ }
+ }
+}
+
+void VclOutdevTest::testDrawTransformedBitmapExFlip()
+{
+ // Create a virtual device, and connect a metafile to it.
+ // Also create a 16x16 bitmap.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
+ {
+ // Fill the top left quarter with black.
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(COL_WHITE);
+ for (int i = 0; i < 8; ++i)
+ {
+ for (int j = 0; j < 8; ++j)
+ {
+ pWriteAccess->SetPixel(j, i, COL_BLACK);
+ }
+ }
+ }
+ BitmapEx aBitmapEx(aBitmap);
+ basegfx::B2DHomMatrix aMatrix;
+ // Negative y scale: bitmap should be upside down, so the black part goes to the bottom left.
+ aMatrix.scale(8, -8);
+ // Rotate 90 degrees clockwise, so the black part goes back to the top left.
+ aMatrix.rotate(M_PI / 2);
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ // Draw the scaled and rotated bitmap on the vdev.
+ pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf.GetActionSize());
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE, pAction->GetType());
+ auto pBitmapAction = static_cast<MetaBmpExScaleAction*>(pAction);
+ const BitmapEx& rBitmapEx = pBitmapAction->GetBitmapEx();
+
+ aBitmap = rBitmapEx.GetBitmap();
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ int nX = 8 * 0.25;
+ int nY = 8 * 0.25;
+ BitmapColor aColor = pAccess->GetPixel(nY, nX);
+ std::stringstream ss;
+ ss << "Color is expected to be black, is " << aColor.AsRGBHexString();
+ ss << " (row " << nY << ", col " << nX << ")";
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: c[00000000]
+ // - Actual : c[ffffff00]
+ // - Color is expected to be black, is ffffff (row 2, col 2)
+ // i.e. the top left quarter of the image was not black, due to a missing flip.
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(ss.str(), COL_BLACK, Color(aColor));
+}
+
+void VclOutdevTest::testRTL()
+{
+ ScopedVclPtrInstance<vcl::Window> pWindow(nullptr, WB_APP | WB_STDWORK);
+ pWindow->EnableRTL();
+ vcl::RenderContext& rRenderContext = *pWindow->GetOutDev();
+ vcl::BufferDevice pBuffer(pWindow, rRenderContext);
+
+ // Without the accompanying fix in place, this test would have failed, because the RTL status
+ // from pWindow was not propagated to pBuffer.
+ CPPUNIT_ASSERT(pBuffer->IsRTLEnabled());
+}
+
+void VclOutdevTest::testRTLGuard()
+{
+ ScopedVclPtrInstance<vcl::Window> pWindow(nullptr, WB_APP | WB_STDWORK);
+ pWindow->EnableRTL();
+ pWindow->RequestDoubleBuffering(true);
+ ImplFrameData* pFrameData = pWindow->ImplGetWindowImpl()->mpFrameData;
+ vcl::PaintBufferGuard aGuard(pFrameData, pWindow);
+ // Without the accompanying fix in place, this test would have failed, because the RTL status
+ // from pWindow was not propagated to aGuard.
+ CPPUNIT_ASSERT(aGuard.GetRenderContext()->IsRTLEnabled());
+}
+
+void VclOutdevTest::testDefaultFillColor()
+{
+ // Create a virtual device, and connect a metafile to it.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ CPPUNIT_ASSERT(pVDev->IsFillColor());
+ CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0xFF, 0xFF), pVDev->GetFillColor());
+
+ pVDev->SetFillColor();
+ CPPUNIT_ASSERT(!pVDev->IsFillColor());
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetFillColor());
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
+ auto pFillAction = static_cast<MetaFillColorAction*>(pAction);
+ const Color& rColor = pFillAction->GetColor();
+ CPPUNIT_ASSERT_EQUAL(Color(), rColor);
+}
+
+void VclOutdevTest::testTransparentFillColor()
+{
+ // Create a virtual device, and connect a metafile to it.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ CPPUNIT_ASSERT(pVDev->IsFillColor());
+ CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0xFF, 0xFF), pVDev->GetFillColor());
+
+ pVDev->SetFillColor(COL_TRANSPARENT);
+ CPPUNIT_ASSERT(!pVDev->IsFillColor());
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetFillColor());
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
+ auto pFillAction = static_cast<MetaFillColorAction*>(pAction);
+ const Color& rColor = pFillAction->GetColor();
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, rColor);
+}
+
+void VclOutdevTest::testFillColor()
+{
+ // Create a virtual device, and connect a metafile to it.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ CPPUNIT_ASSERT(pVDev->IsFillColor());
+ CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0xFF, 0xFF), pVDev->GetFillColor());
+
+ pVDev->SetFillColor(COL_RED);
+ CPPUNIT_ASSERT(pVDev->IsFillColor());
+ CPPUNIT_ASSERT_EQUAL(COL_RED, pVDev->GetFillColor());
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
+ auto pFillAction = static_cast<MetaFillColorAction*>(pAction);
+ const Color& rColor = pFillAction->GetColor();
+ CPPUNIT_ASSERT_EQUAL(COL_RED, rColor);
+}
+
+void VclOutdevTest::testDefaultLineColor()
+{
+ // Create a virtual device, and connect a metafile to it.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ CPPUNIT_ASSERT(pVDev->IsLineColor());
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetLineColor());
+
+ pVDev->SetLineColor();
+ CPPUNIT_ASSERT(!pVDev->IsLineColor());
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetLineColor());
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
+ auto pLineAction = static_cast<MetaLineColorAction*>(pAction);
+ const Color& rColor = pLineAction->GetColor();
+ CPPUNIT_ASSERT_EQUAL(Color(), rColor);
+}
+
+void VclOutdevTest::testTransparentLineColor()
+{
+ // Create a virtual device, and connect a metafile to it.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ CPPUNIT_ASSERT(pVDev->IsLineColor());
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetLineColor());
+
+ pVDev->SetLineColor(COL_TRANSPARENT);
+ CPPUNIT_ASSERT(!pVDev->IsLineColor());
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetLineColor());
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
+ auto pLineAction = static_cast<MetaLineColorAction*>(pAction);
+ const Color& rColor = pLineAction->GetColor();
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, rColor);
+}
+
+void VclOutdevTest::testLineColor()
+{
+ // Create a virtual device, and connect a metafile to it.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ CPPUNIT_ASSERT(pVDev->IsLineColor());
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetLineColor());
+
+ pVDev->SetLineColor(COL_RED);
+ CPPUNIT_ASSERT(pVDev->IsLineColor());
+ CPPUNIT_ASSERT_EQUAL(COL_RED, pVDev->GetLineColor());
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
+ auto pLineAction = static_cast<MetaLineColorAction*>(pAction);
+ const Color& rColor = pLineAction->GetColor();
+ CPPUNIT_ASSERT_EQUAL(COL_RED, rColor);
+}
+
+void VclOutdevTest::testFont()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ // Use Dejavu fonts, they are shipped with LO, so they should be ~always available.
+ // Use Sans variant for simpler glyph shapes (no serifs).
+ vcl::Font font("DejaVu Sans", "Book", Size(0, 36));
+ font.SetColor(COL_BLACK);
+ font.SetFillColor(COL_RED);
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetFont(font);
+ bool bSameFont(font == pVDev->GetFont());
+ CPPUNIT_ASSERT_MESSAGE("Font is not the same", bSameFont);
+
+ // four actions:
+ // 1. Font action
+ // 2. Text alignment action
+ // 3. Text fill color action
+ // 4. As not COL_TRANSPARENT (means use system font color), font color action
+ size_t nActionsExpected = 4;
+ CPPUNIT_ASSERT_EQUAL(nActionsExpected, aMtf.GetActionSize());
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::FONT, pAction->GetType());
+ auto pFontAction = static_cast<MetaFontAction*>(pAction);
+ bool bSameMetaFont = (font == pFontAction->GetFont());
+ CPPUNIT_ASSERT_MESSAGE("Metafile font is not the same", bSameMetaFont);
+
+ pAction = aMtf.GetAction(1);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::TEXTALIGN, pAction->GetType());
+ auto pTextAlignAction = static_cast<MetaTextAlignAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(font.GetAlignment(), pTextAlignAction->GetTextAlign());
+
+ pAction = aMtf.GetAction(2);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::TEXTFILLCOLOR, pAction->GetType());
+ auto pTextFillColorAction = static_cast<MetaTextFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(COL_RED, pTextFillColorAction->GetColor());
+
+ pAction = aMtf.GetAction(3);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::TEXTCOLOR, pAction->GetType());
+ auto pTextColorAction = static_cast<MetaTextColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pTextColorAction->GetColor());
+}
+
+void VclOutdevTest::testTransparentFont()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ // Use Dejavu fonts, they are shipped with LO, so they should be ~always available.
+ // Use Sans variant for simpler glyph shapes (no serifs).
+ vcl::Font font("DejaVu Sans", "Book", Size(0, 36));
+ font.SetColor(COL_TRANSPARENT);
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetFont(font);
+
+ // three actions as it sets the colour to the default system color (and doesn't add a text color action):
+ // 1. Font action
+ // 2. Text alignment action
+ // 3. Text fill color action
+ size_t nActionsExpected = 3;
+ CPPUNIT_ASSERT_EQUAL(nActionsExpected, aMtf.GetActionSize());
+}
+
+void VclOutdevTest::testDefaultRefPoint()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetRefPoint();
+
+ CPPUNIT_ASSERT(!pVDev->IsRefPoint());
+ CPPUNIT_ASSERT_EQUAL(Point(), pVDev->GetRefPoint());
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::REFPOINT, pAction->GetType());
+ auto pRefPointAction = static_cast<MetaRefPointAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(Point(), pRefPointAction->GetRefPoint());
+}
+
+void VclOutdevTest::testRefPoint()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetRefPoint(Point(10, 20));
+
+ CPPUNIT_ASSERT(pVDev->IsRefPoint());
+ CPPUNIT_ASSERT_EQUAL(Point(10, 20), pVDev->GetRefPoint());
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::REFPOINT, pAction->GetType());
+ auto pRefPointAction = static_cast<MetaRefPointAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(Point(10, 20), pRefPointAction->GetRefPoint());
+}
+
+void VclOutdevTest::testRasterOp()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetRasterOp(RasterOp::Invert);
+
+ CPPUNIT_ASSERT_EQUAL(RasterOp::Invert, pVDev->GetRasterOp());
+ CPPUNIT_ASSERT(pVDev->IsLineColor());
+ CPPUNIT_ASSERT(pVDev->IsFillColor());
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::RASTEROP, pAction->GetType());
+ auto pRasterOpAction = static_cast<MetaRasterOpAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(RasterOp::Invert, pRasterOpAction->GetRasterOp());
+}
+
+void VclOutdevTest::testOutputFlag()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ CPPUNIT_ASSERT(pVDev->IsOutputEnabled());
+ CPPUNIT_ASSERT(pVDev->IsDeviceOutputNecessary());
+
+ pVDev->EnableOutput(false);
+
+ CPPUNIT_ASSERT(!pVDev->IsOutputEnabled());
+ CPPUNIT_ASSERT(!pVDev->IsDeviceOutputNecessary());
+}
+
+void VclOutdevTest::testAntialias()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ CPPUNIT_ASSERT_EQUAL(AntialiasingFlags::NONE, pVDev->GetAntialiasing());
+
+ pVDev->SetAntialiasing(AntialiasingFlags::Enable);
+
+ CPPUNIT_ASSERT_EQUAL(AntialiasingFlags::Enable, pVDev->GetAntialiasing());
+}
+
+void VclOutdevTest::testDrawMode()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ CPPUNIT_ASSERT_EQUAL(DrawModeFlags::Default, pVDev->GetDrawMode());
+
+ pVDev->SetDrawMode(DrawModeFlags::BlackLine);
+
+ CPPUNIT_ASSERT_EQUAL(DrawModeFlags::BlackLine, pVDev->GetDrawMode());
+}
+
+void VclOutdevTest::testLayoutMode()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ CPPUNIT_ASSERT_EQUAL(vcl::text::ComplexTextLayoutFlags::Default, pVDev->GetLayoutMode());
+
+ pVDev->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::BiDiRtl);
+
+ CPPUNIT_ASSERT_EQUAL(vcl::text::ComplexTextLayoutFlags::BiDiRtl, pVDev->GetLayoutMode());
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::LAYOUTMODE, pAction->GetType());
+ auto pLayoutModeAction = static_cast<MetaLayoutModeAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(vcl::text::ComplexTextLayoutFlags::BiDiRtl,
+ pLayoutModeAction->GetLayoutMode());
+}
+
+void VclOutdevTest::testDigitLanguage()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ CPPUNIT_ASSERT_EQUAL(LANGUAGE_SYSTEM, pVDev->GetDigitLanguage());
+
+ pVDev->SetDigitLanguage(LANGUAGE_GERMAN);
+
+ CPPUNIT_ASSERT_EQUAL(LANGUAGE_GERMAN, pVDev->GetDigitLanguage());
+
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL(MetaActionType::TEXTLANGUAGE, pAction->GetType());
+ auto pTextLanguageAction = static_cast<MetaTextLanguageAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL(LANGUAGE_GERMAN, pTextLanguageAction->GetTextLanguage());
+}
+
+void VclOutdevTest::testStackFunctions()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->Push();
+ MetaAction* pAction = aMtf.GetAction(0);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Push action", MetaActionType::PUSH, pAction->GetType());
+
+ pVDev->SetLineColor(COL_RED);
+ pVDev->SetFillColor(COL_GREEN);
+ pVDev->SetTextColor(COL_BROWN);
+ pVDev->SetTextFillColor(COL_BLUE);
+ pVDev->SetTextLineColor(COL_MAGENTA);
+ pVDev->SetOverlineColor(COL_YELLOW);
+ pVDev->SetTextAlign(TextAlign::ALIGN_TOP);
+ pVDev->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::BiDiRtl);
+ pVDev->SetDigitLanguage(LANGUAGE_FRENCH);
+ pVDev->SetRasterOp(RasterOp::N0);
+ pVDev->SetMapMode(MapMode(MapUnit::MapTwip));
+ pVDev->SetRefPoint(Point(10, 10));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Text color", COL_BROWN, pVDev->GetTextColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Text fill color", COL_BLUE, pVDev->GetTextFillColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Text line color", COL_MAGENTA, pVDev->GetTextLineColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Text overline color", COL_YELLOW, pVDev->GetOverlineColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Layout mode", vcl::text::ComplexTextLayoutFlags::BiDiRtl,
+ pVDev->GetLayoutMode());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Language", LANGUAGE_FRENCH, pVDev->GetDigitLanguage());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Raster operation", RasterOp::N0, pVDev->GetRasterOp());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Map mode", MapMode(MapUnit::MapTwip), pVDev->GetMapMode());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Ref point", Point(10, 10), pVDev->GetRefPoint());
+
+ pVDev->Pop();
+ pAction = aMtf.GetAction(13);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pop action", MetaActionType::POP, pAction->GetType());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default line color", COL_BLACK, pVDev->GetLineColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default fill color", COL_WHITE, pVDev->GetFillColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default text color", COL_BLACK, pVDev->GetTextColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default text fill color", Color(ColorTransparency, 0xFFFFFFFF),
+ pVDev->GetTextFillColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default text line color", Color(ColorTransparency, 0xFFFFFFFF),
+ pVDev->GetTextLineColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default overline color", Color(ColorTransparency, 0xFFFFFFFF),
+ pVDev->GetOverlineColor());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default layout mode", vcl::text::ComplexTextLayoutFlags::Default,
+ pVDev->GetLayoutMode());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default language", LANGUAGE_SYSTEM, pVDev->GetDigitLanguage());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default raster operation", RasterOp::OverPaint,
+ pVDev->GetRasterOp());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default map mode", MapMode(MapUnit::MapPixel),
+ pVDev->GetMapMode());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Default ref point", Point(0, 0), pVDev->GetRefPoint());
+}
+
+void VclOutdevTest::testSystemTextColor()
+{
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+
+ pVDev->SetSystemTextColor(SystemTextColorFlags::NONE, true);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetTextColor());
+ pVDev->SetSystemTextColor(SystemTextColorFlags::Mono, false);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetTextColor());
+ }
+
+ {
+ ScopedVclPtrInstance<Printer> pPrinter;
+ pPrinter->SetSystemTextColor(SystemTextColorFlags::NONE, true);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPrinter->GetTextColor());
+ }
+}
+
+namespace
+{
+class WaveLineTester : public OutputDevice
+{
+public:
+ WaveLineTester()
+ : OutputDevice(OUTDEV_VIRDEV)
+ {
+ }
+
+ bool AcquireGraphics() const { return true; }
+ void ReleaseGraphics(bool) {}
+ bool UsePolyPolygonForComplexGradient() { return false; }
+
+ bool testShouldDrawWavePixelAsRect(tools::Long nLineWidth)
+ {
+ return shouldDrawWavePixelAsRect(nLineWidth);
+ }
+
+ Size testGetWaveLineSize(tools::Long nLineWidth) { return GetWaveLineSize(nLineWidth); }
+};
+
+class WaveLineTesterPrinter : public Printer
+{
+public:
+ WaveLineTesterPrinter() {}
+
+ bool AcquireGraphics() const { return true; }
+ void ReleaseGraphics(bool) {}
+ bool UsePolyPolygonForComplexGradient() { return false; }
+
+ Size testGetWaveLineSize(tools::Long nLineWidth) { return GetWaveLineSize(nLineWidth); }
+};
+}
+
+void VclOutdevTest::testShouldDrawWavePixelAsRect()
+{
+ ScopedVclPtrInstance<WaveLineTester> pTestOutDev;
+
+ CPPUNIT_ASSERT(!pTestOutDev->testShouldDrawWavePixelAsRect(0));
+ CPPUNIT_ASSERT(!pTestOutDev->testShouldDrawWavePixelAsRect(1));
+
+ CPPUNIT_ASSERT(pTestOutDev->testShouldDrawWavePixelAsRect(10));
+}
+
+void VclOutdevTest::testGetWaveLineSize()
+{
+ {
+ ScopedVclPtrInstance<WaveLineTester> pTestOutDev;
+
+ pTestOutDev->SetDPIX(96);
+ pTestOutDev->SetDPIY(96);
+
+ CPPUNIT_ASSERT_EQUAL(Size(1, 1), pTestOutDev->testGetWaveLineSize(0));
+ CPPUNIT_ASSERT_EQUAL(Size(1, 1), pTestOutDev->testGetWaveLineSize(1));
+
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), pTestOutDev->testGetWaveLineSize(10));
+ }
+
+ {
+ ScopedVclPtrInstance<WaveLineTesterPrinter> pTestOutDev;
+
+ pTestOutDev->SetDPIX(96);
+ pTestOutDev->SetDPIY(96);
+
+ CPPUNIT_ASSERT_EQUAL(Size(0, 0), pTestOutDev->testGetWaveLineSize(0));
+ CPPUNIT_ASSERT_EQUAL(Size(1, 1), pTestOutDev->testGetWaveLineSize(1));
+
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), pTestOutDev->testGetWaveLineSize(10));
+ }
+}
+
+void VclOutdevTest::testErase()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ // this actually triggers Erase()
+ pVDev->SetOutputSizePixel(Size(10, 10));
+ pVDev->Erase();
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action (start)", MetaActionType::LINECOLOR,
+ pAction->GetType());
+
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (start)", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rect action", MetaActionType::RECT, pAction->GetType());
+
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 3);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action (end)", MetaActionType::LINECOLOR,
+ pAction->GetType());
+
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 4);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (end)", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+}
+
+void VclOutdevTest::testDrawPixel()
+{
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ // triggers an Erase()
+ pVDev->SetOutputSizePixel(Size(10, 10));
+ pVDev->SetLineColor(COL_RED);
+ pVDev->DrawPixel(Point(0, 0), COL_GREEN);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Color not green", COL_GREEN, pVDev->GetPixel(Point(0, 0)));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a pixel action", MetaActionType::PIXEL,
+ pAction->GetType());
+ MetaPixelAction* pPixelAction = dynamic_cast<MetaPixelAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pixel action has incorrect position", Point(0, 0),
+ pPixelAction->GetPoint());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pixel action is wrong color", COL_GREEN,
+ pPixelAction->GetColor());
+ }
+
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(1, 1));
+ pVDev->SetLineColor(COL_RED);
+ pVDev->DrawPixel(Point(0, 0));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Color not red", COL_RED, pVDev->GetPixel(Point(0, 0)));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a point action", MetaActionType::POINT,
+ pAction->GetType());
+ MetaPointAction* pPointAction = dynamic_cast<MetaPointAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pixel action has incorrect position", Point(0, 0),
+ pPointAction->GetPoint());
+ }
+}
+
+void VclOutdevTest::testDrawLine()
+{
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(10, 100));
+ pVDev->DrawLine(Point(0, 0), Point(0, 50));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line action", MetaActionType::LINE, pAction->GetType());
+ MetaLineAction* pLineAction = dynamic_cast<MetaLineAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line start has incorrect position", Point(0, 0),
+ pLineAction->GetStartPoint());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line start has incorrect position", Point(0, 50),
+ pLineAction->GetEndPoint());
+ }
+
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ LineInfo aLineInfo(LineStyle::Dash, 10);
+ aLineInfo.SetDashCount(5);
+ aLineInfo.SetDashLen(10);
+ aLineInfo.SetDotCount(3);
+ aLineInfo.SetDotLen(13);
+ aLineInfo.SetDistance(8);
+ aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Bevel);
+ aLineInfo.SetLineCap(css::drawing::LineCap_BUTT);
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawLine(Point(0, 0), Point(0, 50), aLineInfo);
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line action", MetaActionType::LINE, pAction->GetType());
+ MetaLineAction* pLineAction = dynamic_cast<MetaLineAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line start has incorrect position", Point(0, 0),
+ pLineAction->GetStartPoint());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line start has incorrect position", Point(0, 50),
+ pLineAction->GetEndPoint());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dash count wrong", static_cast<sal_uInt16>(5),
+ pLineAction->GetLineInfo().GetDashCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dash len wrong", static_cast<double>(10),
+ pLineAction->GetLineInfo().GetDashLen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dot count wrong", static_cast<sal_uInt16>(3),
+ pLineAction->GetLineInfo().GetDotCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dot len wrong", static_cast<double>(13),
+ pLineAction->GetLineInfo().GetDotLen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Distance wrong", static_cast<double>(8),
+ pLineAction->GetLineInfo().GetDistance());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line join", basegfx::B2DLineJoin::Bevel,
+ pLineAction->GetLineInfo().GetLineJoin());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line cap", css::drawing::LineCap_BUTT,
+ pLineAction->GetLineInfo().GetLineCap());
+ }
+}
+
+void VclOutdevTest::testDrawRect()
+{
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawRect(tools::Rectangle(Point(0, 0), Size(50, 60)));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rect action", MetaActionType::RECT, pAction->GetType());
+ MetaRectAction* pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rectangle wrong", tools::Rectangle(Point(0, 0), Size(50, 60)),
+ pRectAction->GetRect());
+ }
+
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawRect(tools::Rectangle(Point(0, 0), Size(50, 60)), 5, 10);
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rect action", MetaActionType::ROUNDRECT,
+ pAction->GetType());
+ MetaRoundRectAction* pRectAction = dynamic_cast<MetaRoundRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rectangle wrong", tools::Rectangle(Point(0, 0), Size(50, 60)),
+ pRectAction->GetRect());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Horizontal round rect wrong", static_cast<sal_uInt32>(5),
+ pRectAction->GetHorzRound());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Vertical round rect wrong", static_cast<sal_uInt32>(10),
+ pRectAction->GetVertRound());
+ }
+}
+
+void VclOutdevTest::testDrawEllipse()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawEllipse(tools::Rectangle(Point(0, 0), Size(50, 60)));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a ellipse action", MetaActionType::ELLIPSE,
+ pAction->GetType());
+ MetaEllipseAction* pEllipseAction = dynamic_cast<MetaEllipseAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Ellipse rect wrong", tools::Rectangle(Point(0, 0), Size(50, 60)),
+ pEllipseAction->GetRect());
+}
+
+void VclOutdevTest::testDrawPie()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ tools::Rectangle aRect(Point(0, 0), Size(50, 60));
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawPie(aRect, aRect.TopRight(), aRect.TopCenter());
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a pie action", MetaActionType::PIE, pAction->GetType());
+ MetaPieAction* pPieAction = dynamic_cast<MetaPieAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pie rect wrong", aRect, pPieAction->GetRect());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pie start point wrong", aRect.TopRight(),
+ pPieAction->GetStartPoint());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pie end point wrong", aRect.TopCenter(),
+ pPieAction->GetEndPoint());
+}
+
+void VclOutdevTest::testDrawChord()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ tools::Rectangle aRect(Point(21, 22), Size(4, 4));
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawChord(aRect, Point(30, 31), Point(32, 33));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a chord action", MetaActionType::CHORD, pAction->GetType());
+ MetaChordAction* pChordAction = dynamic_cast<MetaChordAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Chord rect wrong", aRect, pChordAction->GetRect());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Chord start point wrong", Point(30, 31),
+ pChordAction->GetStartPoint());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Chord end point wrong", Point(32, 33),
+ pChordAction->GetEndPoint());
+}
+
+void VclOutdevTest::testDrawArc()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ tools::Rectangle aRect(Point(1, 2), Size(4, 4));
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawArc(aRect, Point(10, 11), Point(12, 13));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a arc action", MetaActionType::ARC, pAction->GetType());
+ MetaArcAction* pArcAction = dynamic_cast<MetaArcAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Arc rect wrong", aRect, pArcAction->GetRect());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Arc start point wrong", Point(10, 11),
+ pArcAction->GetStartPoint());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Arc end point wrong", Point(12, 13), pArcAction->GetEndPoint());
+}
+
+void VclOutdevTest::testDrawCheckered()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawCheckered(Point(0, 0), Size(100, 100), 20, COL_BLACK, COL_WHITE);
+
+ size_t nIndex = INITIAL_SETUP_ACTION_COUNT;
+
+ MetaAction* pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not push action", MetaActionType::PUSH, pAction->GetType());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color", MetaActionType::LINECOLOR, pAction->GetType());
+
+ // Row 1
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 1",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ MetaFillColorAction* pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 1", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not first rect, row 1", MetaActionType::RECT, pAction->GetType());
+ MetaRectAction* pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 1 not correct",
+ tools::Rectangle(Point(0, 0), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 2",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 1", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not second rect, row 1", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 1 not correct",
+ tools::Rectangle(Point(0, 20), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 3",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 1", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not third rect, row 1", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 1 not correct",
+ tools::Rectangle(Point(0, 40), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 4",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 4", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not fourth rect, row 1", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 1 not correct",
+ tools::Rectangle(Point(0, 60), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 5",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 5", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not fifth rect, row 1", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 5, row 1 not correct",
+ tools::Rectangle(Point(0, 80), Size(21, 21)),
+ pRectAction->GetRect());
+
+ // Row 2
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 1",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 1", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, first rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 2 not correct",
+ tools::Rectangle(Point(20, 0), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 2",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 1", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, second rect", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 2 not correct",
+ tools::Rectangle(Point(20, 20), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 3",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 1", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, third rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 2 not correct",
+ tools::Rectangle(Point(20, 40), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 4",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 4", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, fourth rect", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 2 not correct",
+ tools::Rectangle(Point(20, 60), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 5",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 5", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, fifth rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 5, row 2 not correct",
+ tools::Rectangle(Point(20, 80), Size(21, 21)),
+ pRectAction->GetRect());
+
+ // Row 3
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 1",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 1", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, first rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 3 not correct",
+ tools::Rectangle(Point(40, 0), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 2",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 1", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, second rect", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 3 not correct",
+ tools::Rectangle(Point(40, 20), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 3",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 1", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, third rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 3 not correct",
+ tools::Rectangle(Point(40, 40), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 4",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 4", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, fourth rect", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 3 not correct",
+ tools::Rectangle(Point(40, 60), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 5",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 5", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, fifth rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 5, row 3 not correct",
+ tools::Rectangle(Point(40, 80), Size(21, 21)),
+ pRectAction->GetRect());
+
+ // Row 4
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 1",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 1", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, first rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 4 not correct",
+ tools::Rectangle(Point(60, 0), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 2",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 1", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, second rect", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 2 not correct",
+ tools::Rectangle(Point(60, 20), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 3",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 1", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, third rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 4 not correct",
+ tools::Rectangle(Point(60, 40), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 4",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 4", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, fourth rect", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 4 not correct",
+ tools::Rectangle(Point(60, 60), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 5",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 5", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, fifth rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 5, row 4 not correct",
+ tools::Rectangle(Point(60, 80), Size(21, 21)),
+ pRectAction->GetRect());
+
+ // Row 5
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 5, rect 1",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 5, rect 1", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 5, first rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 5 not correct",
+ tools::Rectangle(Point(80, 0), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 5, rect 2",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 5, rect 1", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, second rect", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 2 not correct",
+ tools::Rectangle(Point(80, 20), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 3",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 1", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, third rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 2 not correct",
+ tools::Rectangle(Point(80, 40), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 4",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 4", COL_BLACK,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, fourth rect", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 2 not correct",
+ tools::Rectangle(Point(80, 60), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 5",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 5", COL_WHITE,
+ pFillColorAction->GetColor());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, fifth rect", MetaActionType::RECT, pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 5, row 2 not correct",
+ tools::Rectangle(Point(80, 80), Size(21, 21)),
+ pRectAction->GetRect());
+
+ nIndex++;
+ pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not pop", MetaActionType::POP, pAction->GetType());
+}
+
+void VclOutdevTest::testDrawBorder()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawBorder(tools::Rectangle(Point(0, 0), Size(50, 60)));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action (light gray)", MetaActionType::LINECOLOR,
+ pAction->GetType());
+ MetaLineColorAction* pLineColorAction = dynamic_cast<MetaLineColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not light gray", COL_LIGHTGRAY, pLineColorAction->GetColor());
+
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rect action (light gray border)", MetaActionType::RECT,
+ pAction->GetType());
+ MetaRectAction* pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rectangle wrong", tools::Rectangle(Point(1, 1), Size(49, 59)),
+ pRectAction->GetRect());
+
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action (gray)", MetaActionType::LINECOLOR,
+ pAction->GetType());
+ pLineColorAction = dynamic_cast<MetaLineColorAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not gray", COL_GRAY, pLineColorAction->GetColor());
+
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 3);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rect action (gray border)", MetaActionType::RECT,
+ pAction->GetType());
+ pRectAction = dynamic_cast<MetaRectAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Rectangle wrong", tools::Rectangle(Point(0, 0), Size(49, 59)),
+ pRectAction->GetRect());
+}
+
+void VclOutdevTest::testDrawWaveLine()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->DrawWaveLine(Point(0, 0), Point(50, 0));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a bitmap action", MetaActionType::BMPEXSCALEPART,
+ pAction->GetType());
+}
+
+void VclOutdevTest::testDrawPolyLine()
+{
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ tools::Polygon aPolygon(vcl::test::OutputDeviceTestCommon::createClosedBezierLoop(
+ tools::Rectangle(Point(10, 10), Size(80, 8))));
+
+ pVDev->DrawPolyLine(aPolygon);
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYLINE,
+ pAction->GetType());
+ MetaPolyLineAction* pPolyLineAction = dynamic_cast<MetaPolyLineAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Polygon in polyline action is wrong", aPolygon,
+ pPolyLineAction->GetPolygon());
+ }
+
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+
+ tools::Polygon aPolygon(vcl::test::OutputDeviceTestCommon::createClosedBezierLoop(
+ tools::Rectangle(Point(10, 10), Size(80, 8))));
+
+ LineInfo aLineInfo(LineStyle::Dash, 10);
+ aLineInfo.SetDashCount(5);
+ aLineInfo.SetDashLen(10);
+ aLineInfo.SetDotCount(3);
+ aLineInfo.SetDotLen(13);
+ aLineInfo.SetDistance(8);
+ aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Bevel);
+ aLineInfo.SetLineCap(css::drawing::LineCap_BUTT);
+
+ pVDev->DrawPolyLine(aPolygon, aLineInfo);
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYLINE,
+ pAction->GetType());
+ MetaPolyLineAction* pPolyLineAction = dynamic_cast<MetaPolyLineAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Polygon in polyline action is wrong", aPolygon,
+ pPolyLineAction->GetPolygon());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dash count wrong", static_cast<sal_uInt16>(5),
+ pPolyLineAction->GetLineInfo().GetDashCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dash len wrong", static_cast<double>(10),
+ pPolyLineAction->GetLineInfo().GetDashLen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dot count wrong", static_cast<sal_uInt16>(3),
+ pPolyLineAction->GetLineInfo().GetDotCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dot len wrong", static_cast<double>(13),
+ pPolyLineAction->GetLineInfo().GetDotLen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Distance wrong", static_cast<double>(8),
+ pPolyLineAction->GetLineInfo().GetDistance());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line join", basegfx::B2DLineJoin::Bevel,
+ pPolyLineAction->GetLineInfo().GetLineJoin());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line cap", css::drawing::LineCap_BUTT,
+ pPolyLineAction->GetLineInfo().GetLineCap());
+ }
+
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+
+ basegfx::B2DPolygon aPolygon(vcl::test::OutputDeviceTestCommon::createClosedBezierLoop(
+ tools::Rectangle(Point(10, 10), Size(80, 8)))
+ .getB2DPolygon());
+
+ LineInfo aLineInfo(LineStyle::Dash, 10);
+ aLineInfo.SetDashCount(5);
+ aLineInfo.SetDashLen(10);
+ aLineInfo.SetDotCount(3);
+ aLineInfo.SetDotLen(13);
+ aLineInfo.SetDistance(8);
+ aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Bevel);
+ aLineInfo.SetLineCap(css::drawing::LineCap_BUTT);
+
+ pVDev->DrawPolyLine(aPolygon, 3, basegfx::B2DLineJoin::Bevel, css::drawing::LineCap_BUTT,
+ basegfx::deg2rad(15.0));
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYLINE,
+ pAction->GetType());
+ MetaPolyLineAction* pPolyLineAction = dynamic_cast<MetaPolyLineAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Polygon in polyline action is wrong", aPolygon,
+ pPolyLineAction->GetPolygon().getB2DPolygon());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Width wrong", static_cast<double>(3),
+ pPolyLineAction->GetLineInfo().GetWidth());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dash count wrong", static_cast<sal_uInt16>(0),
+ pPolyLineAction->GetLineInfo().GetDashCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dash len wrong", static_cast<double>(0),
+ pPolyLineAction->GetLineInfo().GetDashLen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dot count wrong", static_cast<sal_uInt16>(0),
+ pPolyLineAction->GetLineInfo().GetDotCount());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Dot len wrong", static_cast<double>(0),
+ pPolyLineAction->GetLineInfo().GetDotLen());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Distance wrong", static_cast<double>(0),
+ pPolyLineAction->GetLineInfo().GetDistance());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line join", basegfx::B2DLineJoin::Bevel,
+ pPolyLineAction->GetLineInfo().GetLineJoin());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line cap", css::drawing::LineCap_BUTT,
+ pPolyLineAction->GetLineInfo().GetLineCap());
+ }
+}
+
+void VclOutdevTest::testDrawPolygon()
+{
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ tools::Polygon aPolygon(vcl::test::OutputDeviceTestCommon::createClosedBezierLoop(
+ tools::Rectangle(Point(10, 10), Size(80, 8))));
+
+ pVDev->DrawPolygon(aPolygon);
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+ MetaPolygonAction* pPolygonAction = dynamic_cast<MetaPolygonAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Polygon in polygon action is wrong", aPolygon,
+ pPolygonAction->GetPolygon());
+ }
+
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ tools::Polygon aPolygon(vcl::test::OutputDeviceTestCommon::createClosedBezierLoop(
+ tools::Rectangle(Point(10, 10), Size(80, 8))));
+
+ pVDev->DrawPolygon(aPolygon);
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
+ pAction->GetType());
+ MetaPolygonAction* pPolygonAction = dynamic_cast<MetaPolygonAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Polygon in polygon action is wrong", aPolygon,
+ pPolygonAction->GetPolygon());
+ }
+}
+
+static tools::PolyPolygon createPolyPolygon()
+{
+ tools::Polygon aPolygon(4);
+
+ aPolygon.SetPoint(Point(1, 8), 0);
+ aPolygon.SetPoint(Point(2, 7), 1);
+ aPolygon.SetPoint(Point(3, 6), 2);
+ aPolygon.SetPoint(Point(4, 5), 3);
+
+ tools::PolyPolygon aPolyPolygon(aPolygon);
+ aPolyPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ return aPolyPolygon;
+}
+
+void VclOutdevTest::testDrawPolyPolygon()
+{
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+
+ tools::PolyPolygon aPolyPolygon = createPolyPolygon();
+
+ pVDev->DrawPolyPolygon(aPolyPolygon);
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYPOLYGON,
+ pAction->GetType());
+
+ MetaPolyPolygonAction* pPolyPolygonAction = dynamic_cast<MetaPolyPolygonAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not the same polypolygon in polypolygon action", aPolyPolygon,
+ pPolyPolygonAction->GetPolyPolygon());
+ }
+
+ {
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+
+ tools::PolyPolygon aPolyPolygon = createPolyPolygon();
+
+ basegfx::B2DPolyPolygon aB2DPolyPolygon(aPolyPolygon.getB2DPolyPolygon());
+
+ pVDev->DrawPolyPolygon(aB2DPolyPolygon);
+
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYPOLYGON,
+ pAction->GetType());
+
+ /* these should match, but the equality operator does not work on PolyPolygon for some reason
+
+ MetaPolyPolygonAction* pPolyPolygonAction = dynamic_cast<MetaPolyPolygonAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not the same polypolygon in polypolygon action", aPolyPolygon,
+ pPolyPolygonAction->GetPolyPolygon());
+ */
+ }
+}
+
+static size_t ClipGradientTest(GDIMetaFile& rMtf, size_t nIndex)
+{
+ MetaAction* pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a comment action", MetaActionType::COMMENT,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a gradientex action", MetaActionType::GRADIENTEX,
+ pAction->GetType());
+
+ // clip gradient
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
+ MetaPushAction* pPushAction = dynamic_cast<MetaPushAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not using XOR push flags", vcl::PushFlags::RASTEROP,
+ pPushAction->GetFlags());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rasterop action", MetaActionType::RASTEROP,
+ pAction->GetType());
+ MetaRasterOpAction* pRasterOpAction = dynamic_cast<MetaRasterOpAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not an XOR rasterop", RasterOp::Xor,
+ pRasterOpAction->GetRasterOp());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a gradient action", MetaActionType::GRADIENT,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rasterop action", MetaActionType::RASTEROP,
+ pAction->GetType());
+ pRasterOpAction = dynamic_cast<MetaRasterOpAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not an N0 rasterop", RasterOp::N0,
+ pRasterOpAction->GetRasterOp());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYPOLYGON,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rasterop action", MetaActionType::RASTEROP,
+ pAction->GetType());
+ pRasterOpAction = dynamic_cast<MetaRasterOpAction*>(pAction);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not an XOR rasterop", RasterOp::Xor,
+ pRasterOpAction->GetRasterOp());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a gradient action", MetaActionType::GRADIENT,
+ pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a pop action", MetaActionType::POP, pAction->GetType());
+
+ nIndex++;
+ pAction = rMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a comment action", MetaActionType::COMMENT,
+ pAction->GetType());
+
+ return nIndex;
+}
+
+void VclOutdevTest::testDrawGradient_drawmode()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+ pVDev->SetDrawMode(DrawModeFlags::BlackGradient);
+
+ tools::Rectangle aRect(Point(10, 10), Size(40, 40));
+ pVDev->DrawGradient(aRect, Gradient());
+ MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action (drawmode is black gradient)",
+ MetaActionType::PUSH, pAction->GetType());
+ MetaPushAction* pPushAction = dynamic_cast<MetaPushAction*>(pAction);
+ vcl::PushFlags eFlags = vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Push flags wrong (drawmode is black gradient)", eFlags,
+ pPushAction->GetFlags());
+
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action (drawmode is black gradient)",
+ MetaActionType::LINECOLOR, pAction->GetType());
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (drawmode is black gradient)",
+ MetaActionType::FILLCOLOR, pAction->GetType());
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 3);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action (drawmode is black gradient)",
+ MetaActionType::POLYPOLYGON, pAction->GetType());
+ pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 4);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a pop action (drawmode is black gradient)",
+ MetaActionType::POP, pAction->GetType());
+}
+
+void VclOutdevTest::testDrawGradient_rect_linear()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ tools::Rectangle aRect(Point(10, 10), Size(40, 40));
+ pVDev->SetOutputSizePixel(Size(100, 100));
+
+ Gradient aGradient(GradientStyle::Linear, COL_RED, COL_WHITE);
+ aGradient.SetBorder(100);
+
+ pVDev->DrawGradient(aRect, aGradient);
+
+ size_t nIndex = INITIAL_SETUP_ACTION_COUNT;
+
+ MetaAction* pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a gradient action (rectangle area)", MetaActionType::GRADIENT,
+ pAction->GetType());
+}
+
+void VclOutdevTest::testDrawGradient_rect_axial()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ tools::Rectangle aRect(Point(10, 10), Size(40, 40));
+ pVDev->SetOutputSizePixel(Size(100, 100));
+
+ Gradient aGradient(GradientStyle::Axial, COL_RED, COL_WHITE);
+ aGradient.SetBorder(100);
+
+ pVDev->DrawGradient(aRect, aGradient);
+
+ size_t nIndex = INITIAL_SETUP_ACTION_COUNT;
+
+ MetaAction* pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a gradient action (rectangle area)", MetaActionType::GRADIENT,
+ pAction->GetType());
+}
+
+void VclOutdevTest::testDrawGradient_polygon_linear()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ tools::PolyPolygon aPolyPolygon = createPolyPolygon();
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+
+ Gradient aGradient(GradientStyle::Linear, COL_RED, COL_WHITE);
+ aGradient.SetBorder(100);
+
+ pVDev->DrawGradient(aPolyPolygon, aGradient);
+
+ ClipGradientTest(aMtf, INITIAL_SETUP_ACTION_COUNT);
+}
+
+void VclOutdevTest::testDrawGradient_polygon_axial()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ tools::PolyPolygon aPolyPolygon = createPolyPolygon();
+
+ pVDev->SetOutputSizePixel(Size(100, 100));
+
+ Gradient aGradient(GradientStyle::Axial, COL_RED, COL_WHITE);
+ aGradient.SetBorder(100);
+
+ pVDev->DrawGradient(aPolyPolygon, aGradient);
+
+ ClipGradientTest(aMtf, INITIAL_SETUP_ACTION_COUNT);
+}
+
+void VclOutdevTest::testDrawGradient_rect_complex()
+{
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ tools::Rectangle aRect(Point(10, 10), Size(40, 40));
+ pVDev->SetOutputSizePixel(Size(1000, 1000));
+
+ Gradient aGradient(GradientStyle::Square, COL_RED, COL_WHITE);
+ aGradient.SetBorder(10);
+ pVDev->DrawGradient(aRect, aGradient);
+
+ size_t nIndex = INITIAL_SETUP_ACTION_COUNT;
+
+ MetaAction* pAction = aMtf.GetAction(nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a gradient action (rectangle area)", MetaActionType::GRADIENT,
+ pAction->GetType());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclOutdevTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/pdfexport/data/6m-wide.odg b/vcl/qa/cppunit/pdfexport/data/6m-wide.odg
new file mode 100644
index 000000000..49fb9bfff
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/6m-wide.odg
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odt b/vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odt
new file mode 100644
index 000000000..2e87c33c7
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/ComplexContentDictionary.pdf b/vcl/qa/cppunit/pdfexport/data/ComplexContentDictionary.pdf
new file mode 100644
index 000000000..950eef1e1
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/ComplexContentDictionary.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt b/vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt
new file mode 100644
index 000000000..78f05b09e
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdf b/vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdf
new file mode 100644
index 000000000..315cdc36e
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf b/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf
new file mode 100644
index 000000000..af665fcba
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt b/vcl/qa/cppunit/pdfexport/data/TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt
new file mode 100644
index 000000000..1b13a4fd5
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt
@@ -0,0 +1,560 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:initial-creator>Christophe Strobbe</meta:initial-creator><meta:creation-date>2022-05-14T18:39:40.868000000</meta:creation-date><meta:editing-cycles>18</meta:editing-cycles><meta:editing-duration>PT21M55S</meta:editing-duration><dc:title>Test File for Simple Tables With or Without a Properly Marked Header Row</dc:title><dc:date>2022-05-17T16:43:48.919000000</dc:date><dc:creator>Christophe Strobbe</dc:creator><meta:generator>LibreOfficeDev/7.5.0.0.alpha0$Linux_X86_64 LibreOffice_project/54178896aba2ded7b57479dad435607b73dc89fa</meta:generator><meta:document-statistic meta:table-count="3" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="28" meta:word-count="329" meta:character-count="1794" meta:non-whitespace-character-count="1502"/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="MS Gothic" svg:font-family="'MS Gothic'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol" style:font-charset="x-symbol"/>
+ <style:font-face style:name="Segoe UI" svg:font-family="'Segoe UI'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Tahoma1" svg:font-family="Tahoma" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="GB" style:letter-kerning="true" style:font-name-asian="Segoe UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Tahoma1" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="GB" style:letter-kerning="true" style:font-name-asian="Segoe UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Tahoma1" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
+ <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:keep-with-next="always"/>
+ <style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="14pt" style:font-name-asian="MS Gothic" style:font-family-asian="'MS Gothic'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="Tahoma1" style:font-family-complex="Tahoma" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
+ <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.247cm" style:contextual-spacing="false" fo:line-height="115%"/>
+ </style:style>
+ <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
+ <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
+ <style:text-properties fo:font-size="28pt" fo:font-weight="bold" style:font-size-asian="28pt" style:font-weight-asian="bold" style:font-size-complex="28pt" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
+ <style:paragraph-properties fo:orphans="0" fo:widows="0" text:number-lines="false" text:line-number="0"/>
+ </style:style>
+ <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
+ <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/>
+ <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra">
+ <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/>
+ <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text">
+ <style:paragraph-properties fo:margin-top="0.353cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/>
+ <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text">
+ <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-charset="x-symbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-charset-asian="x-symbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol" style:font-charset-complex="x-symbol"/>
+ </style:style>
+ <text:outline-style style:name="Outline">
+ <text:outline-level-style text:level="1" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="2" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="3" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="4" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="5" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="6" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="7" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="8" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="9" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="10" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ </text:outline-style>
+ <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ <style:style style:name="Default_20_Style.1" style:display-name="Default Style.1" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-top="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.2" style:display-name="Default Style.2" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.3" style:display-name="Default Style.3" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.4" style:display-name="Default Style.4" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-right="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.5" style:display-name="Default Style.5" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.6" style:display-name="Default Style.6" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.7" style:display-name="Default Style.7" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.8" style:display-name="Default Style.8" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.9" style:display-name="Default Style.9" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.10" style:display-name="Default Style.10" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-right="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.11" style:display-name="Default Style.11" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-top="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.12" style:display-name="Default Style.12" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-right="0.51pt solid #000000" fo:border-top="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.13" style:display-name="Default Style.13" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.14" style:display-name="Default Style.14" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-right="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.15" style:display-name="Default Style.15" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-top="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <style:style style:name="Default_20_Style.16" style:display-name="Default Style.16" style:family="table-cell">
+ <style:table-cell-properties fo:border-left="0.51pt solid #000000" fo:border-bottom="0.51pt solid #000000"/>
+ </style:style>
+ <table:table-template table:name="Default Style" table:first-row-end-column="row" table:first-row-start-column="row" table:last-row-end-column="row" table:last-row-start-column="row">
+ <table:first-row table:style-name="Default_20_Style.1"/>
+ <table:last-row table:style-name="Default_20_Style.2"/>
+ <table:first-column table:style-name="Default_20_Style.3"/>
+ <table:last-column table:style-name="Default_20_Style.4"/>
+ <table:body table:style-name="Default_20_Style.9"/>
+ <table:even-rows table:style-name="Default_20_Style.5"/>
+ <table:odd-rows table:style-name="Default_20_Style.6"/>
+ <table:even-columns table:style-name="Default_20_Style.7"/>
+ <table:odd-columns table:style-name="Default_20_Style.8"/>
+ <table:background table:style-name="Default_20_Style.10"/>
+ </table:table-template>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="Table1" style:family="table">
+ <style:table-properties style:width="17cm" table:align="margins"/>
+ </style:style>
+ <style:style style:name="Table1.A" style:family="table-column">
+ <style:table-column-properties style:column-width="5.667cm" style:rel-column-width="21845*"/>
+ </style:style>
+ <style:style style:name="Table1.1" style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:style>
+ <style:style style:name="Table1.A1" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="none" fo:border-top="0.5pt solid #000000" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table1.C1" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table1.A2" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table1.C2" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="0.5pt solid #000000" fo:border-top="none" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table2" style:family="table">
+ <style:table-properties table:align="margins"/>
+ </style:style>
+ <style:style style:name="Table2.A" style:family="table-column">
+ <style:table-column-properties style:rel-column-width="21845*"/>
+ </style:style>
+ <style:style style:name="Table2.A1" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="none" fo:border-top="0.5pt solid #000000" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table2.C1" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table2.A2" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table2.C2" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="0.5pt solid #000000" fo:border-top="none" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table3" style:family="table">
+ <style:table-properties table:align="margins"/>
+ </style:style>
+ <style:style style:name="Table3.A" style:family="table-column">
+ <style:table-column-properties style:rel-column-width="21845*"/>
+ </style:style>
+ <style:style style:name="Table3.A1" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="none" fo:border-top="0.5pt solid #000000" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table3.C1" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table3.A2" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="Table3.C2" style:family="table-cell">
+ <style:table-cell-properties fo:background-color="transparent" fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="0.5pt solid #000000" fo:border-top="none" fo:border-bottom="0.5pt solid #000000" style:writing-mode="page">
+ <style:background-image/>
+ </style:table-cell-properties>
+ </style:style>
+ <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Table_20_Contents">
+ <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
+ <style:text-properties fo:color="#000000" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Serif" fo:font-size="12pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:font-size-asian="12pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-size-complex="12pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Standard" style:list-style-name="L1"/>
+ <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Standard" style:list-style-name="L2"/>
+ <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Standard" style:list-style-name="L3"/>
+ <text:list-style style:name="L1">
+ <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:list-style style:name="L2">
+ <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:list-style style:name="L3">
+ <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/>
+ </style:list-level-properties>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm">
+ <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:page-layout-properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page">
+ <style:drawing-page-properties draw:background-size="full"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:sequence-decls>
+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+ </text:sequence-decls>
+ <text:p text:style-name="Title"><text:title>Test File for Simple Tables With or Without a Properly Marked Header Row</text:title></text:p>
+ <text:h text:style-name="Heading_20_1" text:outline-level="1">Table with Header Row (Repeat First Row)</text:h>
+ <table:table table:name="Table1" table:style-name="Table1" table:template-name="Default Style">
+ <table:table-column table:style-name="Table1.A" table:number-columns-repeated="3"/>
+ <table:table-header-rows>
+ <table:table-row table:style-name="Table1.1">
+ <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <text:p text:style-name="P1"/>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <text:p text:style-name="P1">Average starting score</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table1.C1" office:value-type="string">
+ <text:p text:style-name="P1">Average improved score</text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table-header-rows>
+ <table:table-row table:style-name="Table1.1">
+ <table:table-cell table:style-name="Table1.A2" office:value-type="string">
+ <text:p text:style-name="P1">Images</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table1.A2" office:value-type="string">
+ <text:p text:style-name="P1">35%</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table1.C2" office:value-type="string">
+ <text:p text:style-name="P1">91%</text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table>
+ <text:list text:style-name="L1">
+ <text:list-item>
+ <text:p text:style-name="P4">This table is fine and the LibreOffice Accessibility Checker does not flag it.</text:p>
+ </text:list-item>
+ <text:list-item>
+ <text:p text:style-name="P4">After exporting the file to PDF (PDF/UA), the first row is tagged as a TR with tree TH elements. This is as expected.</text:p>
+ </text:list-item>
+ <text:list-item>
+ <text:p text:style-name="P4">When the PDF file is checked with PAC2021, there is an error for each TH element because the scope attribute is set to “None” instead of “Column”. This is a bug in LibreOffice’s PDF export.</text:p>
+ </text:list-item>
+ </text:list>
+ <text:h text:style-name="Heading_20_1" text:outline-level="1">Table with Table Heading Style in First Row (Repeat First Row not set)</text:h>
+ <table:table table:name="Table2" table:style-name="Table2" table:template-name="Default Style">
+ <table:table-column table:style-name="Table2.A" table:number-columns-repeated="3"/>
+ <table:table-row>
+ <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <text:p text:style-name="Table_20_Heading"/>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <text:p text:style-name="Table_20_Heading">Average starting score</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table2.C1" office:value-type="string">
+ <text:p text:style-name="Table_20_Heading">Average improved score</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row>
+ <table:table-cell table:style-name="Table2.A2" office:value-type="string">
+ <text:p text:style-name="P1">Images</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table2.A2" office:value-type="string">
+ <text:p text:style-name="P1">35%</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table2.C2" office:value-type="string">
+ <text:p text:style-name="P1">91%</text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table>
+ <text:list text:style-name="L2">
+ <text:list-item>
+ <text:p text:style-name="P6">For this table, the LibreOffice Accessibility Checker should warn the author that the first row should be marked as a repeatable row in the Table Properties.</text:p>
+ </text:list-item>
+ <text:list-item>
+ <text:p text:style-name="P6">After exporting the file to PDF (PDF/UA), the first row is tagged as a TR with tree TH elements. This is good, even though it is not what was expected.</text:p>
+ </text:list-item>
+ <text:list-item>
+ <text:p text:style-name="P6">When the PDF file is checked with PAC2021, there is an error for each TH element because the scope attribute is set to “None” instead of “Column”. This is a bug in LibreOffice’s PDF export.</text:p>
+ </text:list-item>
+ </text:list>
+ <text:h text:style-name="Heading_20_1" text:outline-level="1">Table with Heading 2 Style in First Row (Repeat First Row not set)</text:h>
+ <table:table table:name="Table3" table:style-name="Table3" table:template-name="Default Style">
+ <table:table-column table:style-name="Table3.A" table:number-columns-repeated="3"/>
+ <table:table-row>
+ <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <text:h text:style-name="Heading_20_2" text:outline-level="2"/>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <text:h text:style-name="Heading_20_2" text:outline-level="2">Average starting score</text:h>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table3.C1" office:value-type="string">
+ <text:h text:style-name="Heading_20_2" text:outline-level="2">Average improved score</text:h>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row>
+ <table:table-cell table:style-name="Table3.A2" office:value-type="string">
+ <text:p text:style-name="P1">Images</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table3.A2" office:value-type="string">
+ <text:p text:style-name="P1">35%</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Table3.C2" office:value-type="string">
+ <text:p text:style-name="P1">91%</text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table>
+ <text:list text:style-name="L3">
+ <text:list-item>
+ <text:p text:style-name="P7">Error flagged by the LibreOffice Accessibility Checker: “Tables must not contain headings.” This error is justified.</text:p>
+ </text:list-item>
+ <text:list-item>
+ <text:p text:style-name="P7">After exporting the file to PDF (PDF/UA), the first row is tagged as a TR with tree TD elements, each of which contains a H2 element. This is as expected: Heading x styles should not be used to mark table headings.</text:p>
+ </text:list-item>
+ <text:list-item>
+ <text:p text:style-name="P7">When the PDF file is checked with PAC2021, no errors are reported for this table. This is a shortcoming of PAC2021, which is outside the scope of LibreOffice.</text:p>
+ </text:list-item>
+ </text:list>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt b/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt
new file mode 100644
index 000000000..05e2bb184
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/alternativeText.fodp b/vcl/qa/cppunit/pdfexport/data/alternativeText.fodp
new file mode 100644
index 000000000..d77b63140
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/alternativeText.fodp
@@ -0,0 +1,489 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:meta><meta:creation-date>2022-05-19T20:19:11.610154378</meta:creation-date><dc:date>2022-05-20T10:09:03.143295257</dc:date><meta:editing-duration>PT4M52S</meta:editing-duration><meta:editing-cycles>5</meta:editing-cycles><meta:generator>LibreOfficeDev/7.4.0.0.alpha1$Linux_X86_64 LibreOffice_project/5f2dac9510bb511eaf08418342218000945cf180</meta:generator><meta:document-statistic meta:object-count="24"/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="Bitstream Vera Sans" svg:font-family="'Bitstream Vera Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Lohit Devanagari" svg:font-family="'Lohit Devanagari'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Sans" svg:font-family="'Noto Sans'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Sans CJK SC" svg:font-family="'Noto Sans CJK SC'" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <draw:gradient draw:name="Filled" draw:style="linear" draw:start-color="#ffffff" draw:end-color="#cccccc" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Filled_20_Blue" draw:display-name="Filled Blue" draw:style="linear" draw:start-color="#729fcf" draw:end-color="#355269" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Filled_20_Green" draw:display-name="Filled Green" draw:style="linear" draw:start-color="#77bc65" draw:end-color="#127622" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Filled_20_Red" draw:display-name="Filled Red" draw:style="linear" draw:start-color="#ff6d6d" draw:end-color="#c9211e" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Filled_20_Yellow" draw:display-name="Filled Yellow" draw:style="linear" draw:start-color="#ffde59" draw:end-color="#b47804" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Shapes" draw:style="rectangular" draw:cx="50%" draw:cy="50%" draw:start-color="#cccccc" draw:end-color="#ffffff" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="0deg" draw:border="0%"/>
+ <draw:marker draw:name="Arrow" svg:viewBox="0 0 20 30" svg:d="M10 0l-10 30h20z"/>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:punctuation-wrap="simple" style:line-break="strict" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:font-name="Liberation Serif" fo:font-size="24pt" fo:language="es" fo:country="ES" style:font-name-asian="DejaVu Sans" style:font-size-asian="24pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Bitstream Vera Sans" style:font-size-complex="24pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:style style:name="standard" style:family="graphic">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-width="0cm" svg:stroke-color="#3465a4" draw:marker-start-width="0.2cm" draw:marker-start-center="false" draw:marker-end-width="0.2cm" draw:marker-end-center="false" draw:fill="solid" draw:fill-color="#729fcf" draw:textarea-horizontal-align="justify" fo:padding-top="0.125cm" fo:padding-bottom="0.125cm" fo:padding-left="0.25cm" fo:padding-right="0.25cm" fo:wrap-option="wrap" draw:shadow="hidden" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080">
+ <text:list-style style:name="standard">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" fo:text-indent="0cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="18pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:font-name-asian="Noto Sans CJK SC" style:font-family-asian="'Noto Sans CJK SC'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="18pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Lohit Devanagari" style:font-family-complex="'Lohit Devanagari'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="18pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="objectwithoutfill" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:fill="none"/>
+ </style:style>
+ <style:style style:name="Object_20_with_20_no_20_fill_20_and_20_no_20_line" style:display-name="Object with no fill and no line" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="Text" style:family="graphic">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-color="#cccccc" draw:fill="solid" draw:fill-color="#eeeeee"/>
+ <style:text-properties style:font-name="Noto Sans" fo:font-family="'Noto Sans'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ </style:style>
+ <style:style style:name="A4" style:family="graphic" style:parent-style-name="Text">
+ <style:graphic-properties draw:fill="none"/>
+ <style:text-properties fo:font-size="18pt"/>
+ </style:style>
+ <style:style style:name="Title_20_A4" style:display-name="Title A4" style:family="graphic" style:parent-style-name="A4">
+ <style:graphic-properties draw:stroke="none"/>
+ <style:text-properties fo:font-size="44pt"/>
+ </style:style>
+ <style:style style:name="Heading_20_A4" style:display-name="Heading A4" style:family="graphic" style:parent-style-name="A4">
+ <style:graphic-properties draw:stroke="none"/>
+ <style:text-properties fo:font-size="24pt"/>
+ </style:style>
+ <style:style style:name="Text_20_A4" style:display-name="Text A4" style:family="graphic" style:parent-style-name="A4">
+ <style:graphic-properties draw:stroke="none"/>
+ </style:style>
+ <style:style style:name="A4" style:family="graphic" style:parent-style-name="Text">
+ <style:graphic-properties draw:fill="none"/>
+ <style:text-properties fo:font-size="18pt"/>
+ </style:style>
+ <style:style style:name="Title_20_A0" style:display-name="Title A0" style:family="graphic" style:parent-style-name="A4">
+ <style:graphic-properties draw:stroke="none"/>
+ <style:text-properties fo:font-size="96pt"/>
+ </style:style>
+ <style:style style:name="Heading_20_A0" style:display-name="Heading A0" style:family="graphic" style:parent-style-name="A4">
+ <style:graphic-properties draw:stroke="none"/>
+ <style:text-properties fo:font-size="71.9000015258789pt"/>
+ </style:style>
+ <style:style style:name="Text_20_A0" style:display-name="Text A0" style:family="graphic" style:parent-style-name="A4">
+ <style:graphic-properties draw:stroke="none"/>
+ </style:style>
+ <style:style style:name="Graphic" style:family="graphic">
+ <style:graphic-properties draw:fill="solid" draw:fill-color="#ffffff"/>
+ <style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="18pt"/>
+ </style:style>
+ <style:style style:name="Shapes" style:family="graphic" style:parent-style-name="Graphic">
+ <style:graphic-properties draw:stroke="none" draw:fill="gradient" draw:fill-gradient-name="Shapes"/>
+ <style:text-properties fo:font-size="14pt" fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="Filled" style:family="graphic" style:parent-style-name="Shapes">
+ <style:graphic-properties draw:fill="gradient" draw:fill-gradient-name="Filled"/>
+ </style:style>
+ <style:style style:name="Filled_20_Blue" style:display-name="Filled Blue" style:family="graphic" style:parent-style-name="Filled">
+ <style:graphic-properties draw:fill-gradient-name="Filled_20_Blue"/>
+ <style:text-properties fo:color="#ffffff" loext:opacity="100%" loext:color-lum-mod="100%" loext:color-lum-off="0%"/>
+ </style:style>
+ <style:style style:name="Filled_20_Green" style:display-name="Filled Green" style:family="graphic" style:parent-style-name="Filled">
+ <style:graphic-properties draw:fill-gradient-name="Filled_20_Green"/>
+ <style:text-properties fo:color="#ffffff" loext:opacity="100%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ </style:style>
+ <style:style style:name="Filled_20_Red" style:display-name="Filled Red" style:family="graphic" style:parent-style-name="Filled">
+ <style:graphic-properties draw:fill-gradient-name="Filled_20_Red"/>
+ <style:text-properties fo:color="#ffffff" loext:opacity="100%" loext:color-lum-mod="100%" loext:color-lum-off="0%"/>
+ </style:style>
+ <style:style style:name="Filled_20_Yellow" style:display-name="Filled Yellow" style:family="graphic" style:parent-style-name="Filled">
+ <style:graphic-properties draw:fill-gradient-name="Filled_20_Yellow"/>
+ <style:text-properties fo:color="#ffffff" loext:opacity="100%" loext:color-lum-mod="100%" loext:color-lum-off="0%"/>
+ </style:style>
+ <style:style style:name="Outlined" style:family="graphic" style:parent-style-name="Shapes">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-width="0.081cm" svg:stroke-color="#000000" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="Outlined_20_Blue" style:display-name="Outlined Blue" style:family="graphic" style:parent-style-name="Outlined">
+ <style:graphic-properties svg:stroke-color="#355269"/>
+ <style:text-properties fo:color="#355269" loext:opacity="100%" loext:color-lum-mod="100%" loext:color-lum-off="0%"/>
+ </style:style>
+ <style:style style:name="Outlined_20_Green" style:display-name="Outlined Green" style:family="graphic" style:parent-style-name="Outlined">
+ <style:graphic-properties svg:stroke-color="#127622"/>
+ <style:text-properties fo:color="#127622" loext:opacity="100%" loext:color-lum-mod="100%" loext:color-lum-off="0%"/>
+ </style:style>
+ <style:style style:name="Outlined_20_Red" style:display-name="Outlined Red" style:family="graphic" style:parent-style-name="Outlined">
+ <style:graphic-properties svg:stroke-color="#c9211e"/>
+ <style:text-properties fo:color="#c9211e" loext:opacity="100%" loext:color-lum-mod="100%" loext:color-lum-off="0%"/>
+ </style:style>
+ <style:style style:name="Outlined_20_Yellow" style:display-name="Outlined Yellow" style:family="graphic" style:parent-style-name="Outlined">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-color="#b47804"/>
+ <style:text-properties fo:color="#b47804" loext:opacity="100%" loext:color-lum-mod="100%" loext:color-lum-off="0%"/>
+ </style:style>
+ <style:style style:name="Lines" style:family="graphic" style:parent-style-name="Graphic">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-color="#000000" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="Arrow_20_Line" style:display-name="Arrow Line" style:family="graphic" style:parent-style-name="Lines">
+ <style:graphic-properties draw:marker-start="Arrow" draw:marker-start-width="0.2cm" draw:marker-end="Arrow" draw:marker-end-width="0.2cm" draw:show-unit="true"/>
+ </style:style>
+ <style:style style:name="Arrow_20_Dashed" style:display-name="Arrow Dashed" style:family="graphic" style:parent-style-name="Lines">
+ <style:graphic-properties draw:stroke="dash"/>
+ </style:style>
+ <style:style style:name="Default-background" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:text-properties style:letter-kerning="true"/>
+ </style:style>
+ <style:style style:name="Default-backgroundobjects" style:family="presentation">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:shadow="hidden" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
+ <style:text-properties style:letter-kerning="true"/>
+ </style:style>
+ <style:style style:name="Default-notes" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-left="0.6cm" fo:margin-right="0cm" fo:text-indent="-0.6cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="20pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" fo:background-color="transparent" style:font-name-asian="Noto Sans CJK SC" style:font-family-asian="'Noto Sans CJK SC'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="20pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Lohit Devanagari" style:font-family-complex="'Lohit Devanagari'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="20pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="Default-outline1" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:auto-grow-height="false" draw:fit-to-size="false" style:shrink-to-fit="true">
+ <text:list-style style:name="Default-outline1">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.3cm" text:min-label-width="0.9cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="–">
+ <style:list-level-properties text:space-before="1.5cm" text:min-label-width="0.9cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="75%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.8cm" text:min-label-width="0.8cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="–">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="75%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="6.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="7.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="9cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="10.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="11.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-top="0.5cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="32pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" fo:background-color="transparent" style:font-name-asian="Noto Sans CJK SC" style:font-family-asian="'Noto Sans CJK SC'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="32pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Lohit Devanagari" style:font-family-complex="'Lohit Devanagari'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="32pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="Default-outline2" style:family="presentation" style:parent-style-name="Default-outline1">
+ <style:paragraph-properties fo:margin-top="0.4cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="28pt" style:font-size-asian="28pt" style:font-size-complex="28pt"/>
+ </style:style>
+ <style:style style:name="Default-outline3" style:family="presentation" style:parent-style-name="Default-outline2">
+ <style:paragraph-properties fo:margin-top="0.3cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="24pt" style:font-size-asian="24pt" style:font-size-complex="24pt"/>
+ </style:style>
+ <style:style style:name="Default-outline4" style:family="presentation" style:parent-style-name="Default-outline3">
+ <style:paragraph-properties fo:margin-top="0.2cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline5" style:family="presentation" style:parent-style-name="Default-outline4">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline6" style:family="presentation" style:parent-style-name="Default-outline5">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline7" style:family="presentation" style:parent-style-name="Default-outline6">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline8" style:family="presentation" style:parent-style-name="Default-outline7">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline9" style:family="presentation" style:parent-style-name="Default-outline8">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-subtitle" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-vertical-align="middle">
+ <text:list-style style:name="Default-subtitle">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-align="center" fo:text-indent="0cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="32pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" fo:background-color="transparent" style:font-name-asian="Noto Sans CJK SC" style:font-family-asian="'Noto Sans CJK SC'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="32pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Lohit Devanagari" style:font-family-complex="'Lohit Devanagari'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="32pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="Default-title" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-vertical-align="middle">
+ <text:list-style style:name="Default-title">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:text-align="center"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="44pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" fo:background-color="transparent" style:font-name-asian="Noto Sans CJK SC" style:font-family-asian="'Noto Sans CJK SC'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="44pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Lohit Devanagari" style:font-family-complex="'Lohit Devanagari'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="44pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:presentation-page-layout style:name="AL0T26">
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="1.743cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="1.743cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="3.612cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="3.612cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="5.481cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="5.481cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ </style:presentation-page-layout>
+ <style:presentation-page-layout style:name="AL1T0">
+ <presentation:placeholder presentation:object="title" svg:x="2.058cm" svg:y="1.743cm" svg:width="23.912cm" svg:height="3.507cm"/>
+ <presentation:placeholder presentation:object="subtitle" svg:x="2.058cm" svg:y="5.838cm" svg:width="23.912cm" svg:height="13.23cm"/>
+ </style:presentation-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+ <style:page-layout style:name="PM0">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="21cm" fo:page-height="29.7cm" style:print-orientation="portrait"/>
+ </style:page-layout>
+ <style:page-layout style:name="PM1">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="28cm" fo:page-height="15.75cm" style:print-orientation="landscape"/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page">
+ <style:drawing-page-properties draw:background-size="border" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="dp2" style:family="drawing-page">
+ <style:drawing-page-properties presentation:display-header="true" presentation:display-footer="true" presentation:display-page-number="false" presentation:display-date-time="true"/>
+ </style:style>
+ <style:style style:name="dp3" style:family="drawing-page">
+ <style:drawing-page-properties presentation:background-visible="true" presentation:background-objects-visible="true" presentation:display-footer="true" presentation:display-page-number="false" presentation:display-date-time="true"/>
+ </style:style>
+ <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="gr2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="bottom" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="gr3" style:family="graphic" style:parent-style-name="Object_20_with_20_no_20_fill_20_and_20_no_20_line">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-horizontal-align="center" draw:textarea-vertical-align="middle" draw:color-mode="standard" draw:luminance="0%" draw:contrast="0%" draw:gamma="100%" draw:red="0%" draw:green="0%" draw:blue="0%" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:image-opacity="100%" style:mirror="none"/>
+ </style:style>
+ <style:style style:name="gr4" style:family="graphic">
+ <style:graphic-properties style:protect="size"/>
+ </style:style>
+ <style:style style:name="pr1" style:family="presentation" style:parent-style-name="Default-backgroundobjects">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.086cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="pr2" style:family="presentation" style:parent-style-name="Default-backgroundobjects">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="pr3" style:family="presentation" style:parent-style-name="Default-backgroundobjects">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="bottom" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="pr4" style:family="presentation" style:parent-style-name="Default-notes">
+ <style:graphic-properties draw:fill-color="#ffffff" fo:min-height="13.364cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="P1" style:family="paragraph">
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="P3" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="end" style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <draw:layer-set>
+ <draw:layer draw:name="layout"/>
+ <draw:layer draw:name="background"/>
+ <draw:layer draw:name="backgroundobjects"/>
+ <draw:layer draw:name="controls"/>
+ <draw:layer draw:name="measurelines"/>
+ </draw:layer-set>
+ <style:handout-master presentation:presentation-page-layout-name="AL0T26" style:page-layout-name="PM0" draw:style-name="dp2">
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="5.061cm" svg:x="1cm" svg:y="3.742cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="5.061cm" svg:x="1cm" svg:y="12.318cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="5.061cm" svg:x="1cm" svg:y="20.894cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="5.061cm" svg:x="11cm" svg:y="3.742cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="5.061cm" svg:x="11cm" svg:y="12.318cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="5.061cm" svg:x="11cm" svg:y="20.894cm"/>
+ <draw:frame draw:style-name="gr1" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="0cm" svg:y="0cm" presentation:class="header">
+ <draw:text-box>
+ <text:p text:style-name="P1"><text:span text:style-name="T1"><presentation:header/></text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr1" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="11.886cm" svg:y="0cm" presentation:class="date-time">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:span text:style-name="T1"><presentation:date-time/></text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr2" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="0cm" svg:y="28.215cm" presentation:class="footer">
+ <draw:text-box>
+ <text:p text:style-name="P1"><text:span text:style-name="T1"><presentation:footer/></text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr2" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="11.886cm" svg:y="28.215cm" presentation:class="page-number">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:span text:style-name="T1"><text:page-number>&lt;number&gt;</text:page-number></text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ </style:handout-master>
+ </office:master-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1" draw:style-name="dp3" draw:master-page-name="Default" presentation:presentation-page-layout-name="AL1T0">
+ <draw:frame draw:style-name="gr3" draw:text-style-name="P10" draw:layer="layout" svg:width="17.752cm" svg:height="2.832cm" svg:x="6.248cm" svg:y="4.168cm">
+ <draw:image draw:mime-type="image/png">
+ <office:binary-data>iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAAEElEQVR4nGJgAQAAAP//AwAA
+ BgAFV7+r1AAAAABJRU5ErkJggg==
+ </office:binary-data>
+ <text:p/>
+ </draw:image>
+ <svg:title>This is the text alternative</svg:title>
+ <svg:desc>This is the description</svg:desc>
+ </draw:frame>
+ <presentation:notes draw:style-name="dp2">
+ <draw:page-thumbnail draw:style-name="gr4" draw:layer="layout" svg:width="19.798cm" svg:height="11.136cm" svg:x="0.6cm" svg:y="2.257cm" draw:page-number="1" presentation:class="page"/>
+ <draw:frame presentation:style-name="pr4" draw:text-style-name="P11" draw:layer="layout" svg:width="16.799cm" svg:height="13.364cm" svg:x="2.1cm" svg:y="14.107cm" presentation:class="notes" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ </presentation:notes>
+ </draw:page>
+ <presentation:settings presentation:mouse-visible="false"/>
+ </office:presentation>
+ </office:body>
+</office:document>
diff --git a/vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odt b/vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odt
new file mode 100644
index 000000000..da9b167fd
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/flowframe_null_ptr_deref.sample b/vcl/qa/cppunit/pdfexport/data/flowframe_null_ptr_deref.sample
new file mode 100644
index 000000000..4610ae5d1
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/flowframe_null_ptr_deref.sample
@@ -0,0 +1,654 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <head>
+ <head>
+ <head>
+ <title>KDE::Enterprise Homepage - Business Directory</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+
+ <meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline DE v2.0" l gen true for "http://www.kde.org" r (nz 1 vz 1 lz 1 oz 1 cb 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://www.kde.org" r (n 0 s 0 v 0 l 0))' />
+
+ <meta name="trademark" content="KDE e.V." />
+ <meta name="description" content="K Desktop Environment Homepage, KDE.org" />
+ <meta name="MSSmartTagsPreventParsing" content="true" />
+ <meta name="robots" content="all" />
+
+ <link rel="shortcut icon" href="favicon.ico" />
+
+<link rel="stylesheet" media="screen" type="text/css" title="Default: KDE Window Colors" href="/media/styles/standard.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Black and white" href="/media/styles/blackwhite.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Blue, mellow" href="/media/styles/bluemellow.css" /><head>
+ <title>KDE::Enterprise Homepage - Business Directory</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+
+ <meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline DE v2.0" l gen true for "http://www.kde.org" r (nz 1 vz 1 lz 1 oz 1 cb 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://www.kde.org" r (n 0 s 0 v 0 l 0))' />
+
+ <meta name="trademark" content="KDE e.V." />
+ <meta name="description" content="K Desktop Environment Homepage, KDE.org" />
+ <meta name="MSSmartTagsPreventParsing" content="true" />
+ <meta name="robots" content="all" />
+
+ <link rel="shortcut icon" href="favicon.ico" />
+
+<link rel="stylesheet" media="screen" type="text/css" title="Default: KDE Window Colors" href="/media/styles/standard.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Black and white" href="/media/styles/blackwhite.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Blue, mellow" href="/media/styles/bluemellow.css" /><head>
+ <title>KDE::Enterprise Homepage - Business Directory</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+
+ <meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline DE v2.0" l gen true for "http://www.kde.org" r (nz 1 vz 1 lz 1 oz 1 cb 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://www.kde.org" r (n 0 s 0 v 0 l 0))' />
+
+ <meta name="trademark" content="KDE e.V." />
+ <meta name="description" content="K Desktop Environment Homepage, KDE.org" />
+ <meta name="MSSmartTagsPreventParsing" content="true" />
+ <meta name="robots" content="all" />
+
+ <link rel="shortcut icon" href="favicon.ico" />
+
+<link rel="stylesheet" media="screen" type="text/css" title="Default: KDE Window Colors" href="/media/styles/standard.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Black and white" href="/media/styles/blackwhite.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Blue, mellow" href="/media/styles/bluemellow.css" /><head>
+ <title>KDE::Enterprise Homepage - Business Directory</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+
+ <meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline DE v2.0" l gen true for "http://www.kde.org" r (nz 1 vz 1 lz 1 oz 1 cb 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://www.kde.org" r (n 0 s 0 v 0 l 0))' />
+
+ <meta name="trademark" content="KDE e.V." />
+ <meta name="description" content="K Desktop Environment Homepage, KDE.org" />
+ <meta name="MSSmartTagsPreventParsing" content="true" />
+ <meta name="robots" content="all" />
+
+ <link rel="shortcut icon" href="favicon.ico" />
+
+<link rel="stylesheet" media="screen" type="text/css" title="Default: KDE Window Colors" href="/media/styles/standard.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Black and white" href="/media/styles/blackwhite.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Blue, mellow" href="/media/styles/bluemellow.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Classic Blue" href="/media/styles/classic.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Orange" href="/media/styles/endres.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Yellow" href="/media/styles/yellow.css" />
+
+ <link rel="stylesheet" media="print" type="text/css" href="/media/styles/print.css" />
+</head><link rel="alternate stylesheet" media="screen" type="text/css" title="Classic Blue" href="/media/styles/classic.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Orange" href="/media/styles/endres.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Yellow" href="/media/styles/yellow.css" />
+
+ <link rel="stylesheet" media="print" type="text/css" href="/media/styles/print.css" />
+</head><link rel="alternate stylesheet" media="screen" type="text/css" title="Classic Blue" href="/media/styles/classic.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Orange" href="/media/styles/endres.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Yellow" href="/media/styles/yellow.css" />
+
+ <link rel="stylesheet" media="print" type="text/css" href="/media/styles/print.css" />
+</head><link rel="alternate stylesheet" media="screen" type="text/css" title="Classic Blue" href="/media/styles/classic.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Orange" href="/media/styles/endres.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Yellow" href="/media/styles/yellow.css" />
+
+ <link rel="stylesheet" media="print" type="text/css" href="/media/styles/print.css" />
+</head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+
+ <meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline DE v2.0" l gen true for "http://www.kde.org" r (nz 1 vz 1 lz 1 oz 1 cb 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://www.kde.org" r (n 0 s 0 v 0 l 0))' />
+
+ <meta name="trademark" content="KDE e.V." />
+ <meta name="description" content="K Desktop Environment Homepage, KDE.org" />
+ <meta name="MSSmartTagsPreventParsing" content="true" />
+ <meta name="robots" content="all" />
+
+ <link rel="shortcut icon" href="favicon.ico" />
+
+<link rel="stylesheet" media="screen" type="text/css" title="Default: KDE Window Colors" href="/media/styles/standard.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Black and white" href="/media/styles/blackwhite.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Blue, mellow" href="/media/styles/bluemellow.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Classic Blue" href="/media/styles/classic.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Orange" href="/media/styles/endres.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Yellow" href="/media/styles/yellow.css" />
+
+ <link rel="stylesheet" media="print" type="text/css" href="/media/styles/print.css" />
+</head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+
+ <meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline DE v2.0" l gen true for "http://www.kde.org" r (nz 1 vz 1 lz 1 oz 1 cb 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://www.kde.org" r (n 0 s 0 v 0 l 0))' />
+
+ <meta name="trademark" content="KDE e.V." />
+ <meta name="description" content="K Desktop Environment Homepage, KDE.org" />
+ <meta name="MSSmartTagsPreventParsing" content="true" />
+ <meta name="robots" content="all" />
+
+ <link rel="shortcut icon" href="favicon.ico" />
+
+<link rel="stylesheet" media="screen" type="text/css" title="Default: KDE Window Colors" href="/media/styles/standard.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Black and white" href="/media/styles/blackwhite.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Blue, mellow" href="/media/styles/bluemellow.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Classic Blue" href="/media/styles/classic.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Orange" href="/media/styles/endres.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Yellow" href="/media/styles/yellow.css" />
+
+ <link rel="stylesheet" media="print" type="text/css" href="/media/styles/print.css" />
+</head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+
+ <meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline DE v2.0" l gen true for "http://www.kde.org" r (nz 1 vz 1 lz 1 oz 1 cb 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://www.kde.org" r (n 0 s 0 v 0 l 0))' />
+
+ <meta name="trademark" content="KDE e.V." />
+ <meta name="description" content="K Desktop Environment Homepage, KDE.org" />
+ <meta name="MSSmartTagsPreventParsing" content="true" />
+ <meta name="robots" content="all" />
+
+ <link rel="shortcut icon" href="favicon.ico" />
+
+<link rel="stylesheet" media="screen" type="text/css" title="Default: KDE Window Colors" href="/media/styles/standard.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Black and white" href="/media/styles/blackwhite.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Blue, mellow" href="/media/styles/bluemellow.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Classic Blue" href="/media/styles/classic.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Orange" href="/media/styles/endres.css" />
+<link rel="alternate stylesheet" media="screen" type="text/css" title="Yellow" href="/media/styles/yellow.css" />
+
+ <link rel="stylesheet" media="print" type="text/css" href="/media/styles/print.css" />
+</head>
+
+<body id="enterprisekdeorg"><table border="0" cellpadding="0" cellspacing="0" width="100%">
+<tr id="header">
+ <td id="headerpath">
+ <span class="invisible"><a href="#main" accesskey="2"><span class="invisible"><a href="#main" accesskey="2"><span class="invisible"><a href="#main" accesskey="2"><span class="invisible"><a href="#main" accesskey="2">Skip to Content</a> |</span></a> |</span></a> |</span></a> |</span>
+ Location: <a href="/" accesskey="1">KDE::Enterprise Homepage</a> / Business Directory </td>
+
+ <td id="headermenu">
+ <a href="/media/settings.php" accesskey="7" title="Customize content and look &amp; feel of the KDE.org Webpages">Settings</a><a href="/media/settings.php" accesskey="7" title="Customize content and look &amp; feel of the KDE.org Webpages">Settings</a> |
+ <a href="http://www.kde.org/family/" accesskey="3" title="A complete structural overview of the KDE.org web pages">Sitemap</a> |
+ <a href="http://www.kde.org/documentation/" accesskey="6" title="Having problems? Read the documentation">Help</a> |
+ <a href="http://www.kde.org/contact/" accesskey="10" title="Contact information for all areas of KDE">Contact Us</a>
+ </td>
+</tr>
+
+<tr id="logo">
+ <td valign="top" colspan="2">
+ <a href="../"><img alt="KDE::Enterprise Homepage" src="/media/images/kde_logo.jpg" width="296" height="79" border="0" /></a>
+ </td>
+
+ </tr>
+
+</table><table border="0" cellpadding="0" cellspacing="0" width="100%">
+<tr>
+ <td valign="top" class="menuheader" height="0"></td>
+
+ <td id="contentcolumn" valign="top" rowspan="2">
+ <div id="contentheader">&nbsp;</div>
+ <div class="invisible"><a href="#navigation" accesskey="5">Skip to Link Menu</a></div>
+ <div id="content"><div style="width:100%;">
+ <a name="main" />
+
+ <h1>Business Directory</h1>
+
+<h4>A problem has been detected with your submission</h4>
+<p>In the <b>Business Name</b> box you did not enter a valid name.</p>
+<p>Please correct the problem below and resubmit.</p>
+ <form action="addbiz.php" method="POST">
+ <table cellpadding="5">
+ <tr>
+ <td><font color="#ff0000">--&gt; </font></td>
+ <td>Business Name</td>
+ <td>
+ <input type="text" name="nameBox" maxlength="20" value="">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Contact Name</td>
+ <td>
+ <input type="text" name="contactBox" maxlength="50" value="Waldo Bastian">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Email Address</td>
+ <td>
+ <input type="text" name="emailBox" maxlength="50" value="bastian@kde.org">
+ <input type="checkbox" name="showEmailBox" value="">Publish e-mail address </td>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Website</td>
+ <td>
+ <input type="text" name="websiteBox" maxlength="50" value="">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Address</td>
+ <td>
+ <input type="text" name="add1Box" maxlength="50" value="9 Le Val Renard">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td>
+ <input type="text" name="add2Box" maxlength="50" value="Taden">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td>
+ <input type="text" name="add3Box" maxlength="50" value="">
+ <p>
+ If more than one address, please add your head office.
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Postcode / Zip Code</td>
+ <td>
+ <input type="text" name="postcodeBox" maxlength="20" value="22100">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Country</td>
+ <td>
+ <select name="countryBox">
+<OPTION>Unspecified</OPTION>
+<OPTION>Afghanistan</OPTION>
+<OPTION>Albania</OPTION>
+<OPTION>Algeria</OPTION>
+<OPTION>Angola</OPTION>
+<OPTION>Anguilla</OPTION>
+<OPTION>Antarctic</OPTION>
+<OPTION>Antigua and Barbuda</OPTION>
+<OPTION>Argentina</OPTION>
+<OPTION>Armenia</OPTION>
+<OPTION>Aruba</OPTION>
+<OPTION>Australia</OPTION>
+<OPTION>Austria</OPTION>
+<OPTION>Azerbaijan</OPTION>
+<OPTION>Bahamas</OPTION>
+<OPTION>Bahrain</OPTION>
+<OPTION>Bangladesh</OPTION>
+<OPTION>Barbados</OPTION>
+<OPTION>Belarus</OPTION>
+<OPTION>Belgium</OPTION>
+<OPTION>Belize</OPTION>
+<OPTION>Benin</OPTION>
+<OPTION>Bermuda</OPTION>
+<OPTION>Bolivia</OPTION>
+<OPTION>Bosia and Herzegovina</OPTION>
+<OPTION>Botswana</OPTION>
+<OPTION>Bouvet Island</OPTION>
+<OPTION>Brazil</OPTION>
+<OPTION>British Indian Ocean Territory</OPTION>
+<OPTION>Brunei Darussalam</OPTION>
+<OPTION>Bulgaria</OPTION>
+<OPTION>Burkina Faso</OPTION>
+<OPTION>Burundi</OPTION>
+<OPTION>Cambodia</OPTION>
+<OPTION>Cameroon</OPTION>
+<OPTION>Canada</OPTION>
+<OPTION>Cape Verde</OPTION>
+<OPTION>Cayman Islands</OPTION>
+<OPTION>Central African Republic</OPTION>
+<OPTION>Chad</OPTION>
+<OPTION>Chile</OPTION>
+<OPTION>China</OPTION>
+<OPTION>Christmas Island</OPTION>
+<OPTION>Colombia</OPTION>
+<OPTION>Comoros</OPTION>
+<OPTION>Congo</OPTION>
+<OPTION>Cook Islands</OPTION>
+<OPTION>Costa Rica</OPTION>
+<OPTION>Cote D'Ivoire</OPTION>
+<OPTION>Croatia</OPTION>
+<OPTION>Cuba</OPTION>
+<OPTION>Cyprus</OPTION>
+<OPTION>Czech Republic</OPTION>
+<OPTION>Denmark</OPTION>
+<OPTION>Djibouti</OPTION>
+<OPTION>Dominica</OPTION>
+<OPTION>Dominican Republic</OPTION>
+<OPTION>East Timor</OPTION>
+<OPTION>Ecuador</OPTION>
+<OPTION>Egypt</OPTION>
+<OPTION>El Salvador</OPTION>
+<OPTION>Equatorial Guinea</OPTION>
+<OPTION>Estonia</OPTION>
+<OPTION>Ethiopia</OPTION>
+<OPTION>Falkland Islands (Malvinas)</OPTION>
+<OPTION>Fiji</OPTION>
+<OPTION>Finland</OPTION>
+<OPTION selected>France</OPTION>
+<OPTION>French Guiana</OPTION>
+<OPTION>French Polynesia</OPTION>
+<OPTION>French Southern Territories</OPTION>
+<OPTION>Gabon</OPTION>
+<OPTION>Gambia</OPTION>
+<OPTION>Georgia</OPTION>
+<OPTION>Germany</OPTION>
+<OPTION>Ghana</OPTION>
+<OPTION>Gibraltar</OPTION>
+<OPTION>Greece</OPTION>
+<OPTION>Greenland</OPTION>
+<OPTION>Grenada</OPTION>
+<OPTION>Guadeloupe</OPTION>
+<OPTION>Guatemala</OPTION>
+<OPTION>Guinea</OPTION>
+<OPTION>Guinea-Bissau</OPTION>
+<OPTION>Guyana</OPTION>
+<OPTION>Haiti</OPTION>
+<OPTION>Honduras</OPTION>
+<OPTION>Hong Kong</OPTION>
+<OPTION>Hungary</OPTION>
+<OPTION>Iceland</OPTION>
+<OPTION>India</OPTION>
+<OPTION>Indonesia</OPTION>
+<OPTION>Iran, Islamic Republic of</OPTION>
+<OPTION>Iraq</OPTION>
+<OPTION>Ireland</OPTION>
+<OPTION>Israel</OPTION>
+<OPTION>Italy</OPTION>
+<OPTION>Jamaica</OPTION>
+<OPTION>Japan</OPTION>
+<OPTION>Jordan</OPTION>
+<OPTION>Kazakhstan</OPTION>
+<OPTION>Kenya</OPTION>
+<OPTION>Kiribati</OPTION>
+<OPTION>Korea, Democratic People's Republic of</OPTION>
+<OPTION>Korea, Republic of</OPTION>
+<OPTION>Kuwait</OPTION>
+<OPTION>Kyrgyzstan</OPTION>
+<OPTION>Lao People's Democratic Republic</OPTION>
+<OPTION>Latvia</OPTION>
+<OPTION>Lebanon</OPTION>
+<OPTION>Lesotho</OPTION>
+<OPTION>Liberia</OPTION>
+<OPTION>Libyan Arab Jamahiriya</OPTION>
+<OPTION>Lithuania</OPTION>
+<OPTION>Luxembourg</OPTION>
+<OPTION>Macau</OPTION>
+<OPTION>Macedonia, the Former Yugoslav Republic of</OPTION>
+<OPTION>Madagascar</OPTION>
+<OPTION>Malawi</OPTION>
+<OPTION>Malaysia</OPTION>
+<OPTION>Maldives</OPTION>
+<OPTION>Mali</OPTION>
+<OPTION>Malta</OPTION>
+<OPTION>Marshall Islands</OPTION>
+<OPTION>Martinique</OPTION>
+<OPTION>Mauritania</OPTION>
+<OPTION>Mauritius</OPTION>
+<OPTION>Mexico</OPTION>
+<OPTION>Mirconesia, Federated States of</OPTION>
+<OPTION>Moldova, Republic of</OPTION>
+<OPTION>Mongolia</OPTION>
+<OPTION>Morocco</OPTION>
+<OPTION>Mozambique</OPTION>
+<OPTION>Myanmar</OPTION>
+<OPTION>Namibia</OPTION>
+<OPTION>Nauru</OPTION>
+<OPTION>Nepal</OPTION>
+<OPTION>Netherlands</OPTION>
+<OPTION>Netherlands Antilles</OPTION>
+<OPTION>New Caledonia</OPTION>
+<OPTION>New Zealand</OPTION>
+<OPTION>Nicaragua</OPTION>
+<OPTION>Niger</OPTION>
+<OPTION>Nigeria</OPTION>
+<OPTION>Norway</OPTION>
+<OPTION>Oman</OPTION>
+<OPTION>Pakistan</OPTION>
+<OPTION>Panama</OPTION>
+<OPTION>Papua New Guinea</OPTION>
+<OPTION>Paraguay</OPTION>
+<OPTION>Peru</OPTION>
+<OPTION>Philippines</OPTION>
+<OPTION>Pitcairn</OPTION>
+<OPTION>Poland</OPTION>
+<OPTION>Portugal</OPTION>
+<OPTION>Puerto Rico</OPTION>
+<OPTION>Qatar</OPTION>
+<OPTION>Reunion</OPTION>
+<OPTION>Romania</OPTION>
+<OPTION>Russian Federation</OPTION>
+<OPTION>Rwanda</OPTION>
+<OPTION>Saint Kitts and Nevis</OPTION>
+<OPTION>Saint Lucia</OPTION>
+<OPTION>Saint Pierre and Miquelon</OPTION>
+<OPTION>Saint Vincent and the Grenadines</OPTION>
+<OPTION>Samoa</OPTION>
+<OPTION>Sao Tome and Principe</OPTION>
+<OPTION>Saudi Arabia</OPTION>
+<OPTION>Senegal</OPTION>
+<OPTION>Seychelles</OPTION>
+<OPTION>Sierra Leone</OPTION>
+<OPTION>Singapore</OPTION>
+<OPTION>Slovakia</OPTION>
+<OPTION>Slovenia</OPTION>
+<OPTION>Solomon Islands</OPTION>
+<OPTION>Somalia</OPTION>
+<OPTION>South Africa</OPTION>
+<OPTION>South Georgia and the South Sandwich Islands</OPTION>
+<OPTION>Spain</OPTION>
+<OPTION>Sri Lanka</OPTION>
+<OPTION>Sudan</OPTION>
+<OPTION>Suriname</OPTION>
+<OPTION>Swaziland</OPTION>
+<OPTION>Sweden</OPTION>
+<OPTION>Switzerland</OPTION>
+<OPTION>Syrian Arab Republic</OPTION>
+<OPTION>Taiwan</OPTION>
+<OPTION>Tajikistan</OPTION>
+<OPTION>Tanzania, United Republic of</OPTION>
+<OPTION>Thailand</OPTION>
+<OPTION>Togo</OPTION>
+<OPTION>Tokelau</OPTION>
+<OPTION>Tonga</OPTION>
+<OPTION>Trinidad and Tobago</OPTION>
+<OPTION>Tunisia</OPTION>
+<OPTION>Turkey</OPTION>
+<OPTION>Turkmenistan</OPTION>
+<OPTION>Turks and Caicos Islands</OPTION>
+<OPTION>Tuvalu</OPTION>
+<OPTION>Uganda</OPTION>
+<OPTION>Ukraine</OPTION>
+<OPTION>United Arab Emirates</OPTION>
+<OPTION>United Kingdom</OPTION>
+<OPTION>United States</OPTION>
+<OPTION>United States Minor Outlying Islands</OPTION>
+<OPTION>Uruguay</OPTION>
+<OPTION>Uzbekistan</OPTION>
+<OPTION>Vanuatu</OPTION>
+<OPTION>Venezuela</OPTION>
+<OPTION>Viet Nam</OPTION>
+<OPTION>Virgin Islands, British</OPTION>
+<OPTION>Western Sahara</OPTION>
+<OPTION>Yemen</OPTION>
+<OPTION>Yugoslavia</OPTION>
+<OPTION>Zaire</OPTION>
+<OPTION>Zambia</OPTION>
+<OPTION>Zimbabwe</OPTION>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Phone Number</td>
+ <td>
+ <input type="text" name="phoneBox" maxlength="20" value="000000">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Fax Number</td>
+ <td>
+ <input type="text" name="faxBox" maxlength="20" value="111111">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Business Services</td>
+ <td>
+ <table>
+ <tr>
+ <td>On Site Support</td>
+ <td><input type="checkbox" name="onsitesupportBox" maxlength="20" value="1" ></td>
+ </tr>
+ <tr>
+ <td>Phone Support</td>
+ <td><input type="checkbox" name="phonesupportBox" maxlength="20" value="1" "></td>
+ </tr>
+ <tr>
+ <td>Distribution</td>
+ <td><input type="checkbox" name="distributionBox" maxlength="20" value="1" "></td>
+ </tr>
+ <tr>
+ <td>Free software development</td>
+ <td><input type="checkbox" name="freedevBox" maxlength="20" value="1" "></td>
+ </tr>
+ <tr>
+ <td>Commercial development</td>
+ <td><input type="checkbox" name="commdevBox" maxlength="20" value="1" "></td>
+ </tr>
+ <tr>
+ <td>Consulting</td>
+ <td><input type="checkbox" name="consultingBox" maxlength="20" value="1" "></td>
+ </tr>
+ <tr>
+ <td>Retail</td>
+ <td><input type="checkbox" name="retailBox" maxlength="20" value="1" "></td>
+ </tr>
+ <tr>
+ <td>Other</td>
+ <td>
+ <input type="text" name="otherservBox" maxlength="20" value="1" checked ">
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Comments</td>
+ <td>
+ <textarea cols="50" rows="10" name="commentsBox">Hello?</textarea>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td>
+ <input type="submit" name="submit" value="Add!">
+ <input type="reset" name="reset">
+ </td>
+ </tr>
+ </table>
+ </form>
+ <p>
+ <a href="./">Back to the Business Directory</a>
+ </div></div>
+
+
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" id="leftmenu" width="25%">
+ <a name="navigation"></a>
+ <h2 id="h_inform">Inform</h2>
+<ul>
+<li>
+<a href="/">Home</a>
+</li>
+<li>
+<a href="http://www.kde.org/">KDE Home</a>
+</li>
+<li>
+<a href="/news.php">News</a>
+</li>
+<li>
+<a href="/info">Information</a>
+</li>
+<li>
+<a href="/faq">FAQ</a>
+</li>
+<li>
+<a href="http://events.kde.org/calendar/index.phtml">Events</a>
+</li>
+<li>
+<a href="/mailinglist">Mailing List</a>
+</li>
+</ul>
+<h2 id="h_kdeenterprise">KDE::Enterprise</h2>
+<ul>
+<li>
+<a href="/articles/">Articles</a>
+</li>
+<li>
+<a href="/bizcase">Business Cases</a>
+</li>
+<li>
+<a href="/bizdir">Business Directory</a>
+</li>
+<li>
+<a href="/interviews/">Interviews</a>
+</li>
+<li>
+<a href="/focus/">Focus On...</a>
+</li>
+<li>
+<a href="/bizcontact">Business Contacts</a>
+</li>
+</ul>
+
+
+ <h2 id="t_search">Search</h2>
+<div id="search">
+<form method="get" name="Searchform" action="/media/search.php">
+<span class="invisible"><label for="Input" accesskey="4">Search:</label></span>
+<input type="text" size="10" name="q" id="Input" value="" /><br />
+<span class="invisible"><label for="Select"> in </label></span>
+<select size="1" name="Select" id="Select" title="Select what or where you want to search">
+<option value="kdenet" selected="selected">kde.org</option>
+<option value="kdelook">kde-look.org</option>
+<option value="kdedoc">Documentation</option>
+</select><br />
+<input type="submit" value=" Search " name="Button" id="searchButton" />
+</form>
+</div>
+
+ <div class="invisible">
+ <a href="http://www.kde.org/" accesskey="8">KDE Home</a> |
+ <a href="http://accessibility.kde.org/" accesskey="9">KDE Accessibility Home</a> |
+ <a href="/media/accesskeys.php" accesskey="0">Description of Access Keys</a>
+ </div>
+ </td>
+</tr>
+
+
+<tr>
+ <td colspan="2">
+ <div id="footer">
+ Maintained by <a href="mailto:webmaster@kde.org">enterprise.kde.org Webmaster</a><br />
+ KDE and K Desktop Environment are trademarks of <a href="http://www.kde.org/areas/kde-ev/" title="Homepage of the KDE non-profit Organization">KDE e.V</a> |
+ <a href="http://www.kde.org/contact/impressum.php">Legal</a>
+ </div>
+ </td>
+</tr>
+
+</table></body>
+
+</html>
diff --git a/vcl/qa/cppunit/pdfexport/data/forcepoint71.key b/vcl/qa/cppunit/pdfexport/data/forcepoint71.key
new file mode 100644
index 000000000..716fe5848
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/forcepoint71.key
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf b/vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf
new file mode 100644
index 000000000..319f6f571
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf
@@ -0,0 +1 @@
+{\rtf1\cnsi \ansicpg1252\stshfloch0{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green102\blue204;\red102\green99\blue98;\red143\green142\blue142;\red75\green60\blue52;}{\fonttbl{\f0\froman\cpg1257\fcharset186 Palatino Linotype;}{\f1\froman\cpg0\fcharset0 Palatino Linotype;}{\f2\froman\cpg1252\fcharset0 Palatino Linotype;}{\f3\fswiss\cpg1257\fcharset186 Arial Black;}{\f4\fswiss\cpg0\fcharset0 Arial Black;}{\f5\fswiss\cpg1252\fcharset0 Arial Black;}{\f6\fro-an\cpg1257\fcharset186 Times New Roman;}{\f7\froman\cpg0\fcharset0 Times New Roman;}{\f8\froman\cpg1252\fcharset0 Times New Roman;}{\f9\fmodern\cpg1257\fcharset186 Courier New;}{\f10\fmodern\cpg0\fcharset0 Courier New;}{\f11\fmodern\cpg1252\fcharset0 Courier New;}}{\stylesheet {\ql Normal;}{\s1\sbasedon0\ql\fi-120\sl-276\slmult0 Style1;}{\s2\sbasedon0\qj\fi560\sl-300\slmult0 Style2;}{\s3\sbasedon0\ql\sl-264\slmult0 Style3;}{\s4\sbasedon0\ql\fi-1088\sl-320\slmult0 Style4;}{\s5\sbasedon0\ql Style5;}{\s6\sbasedon0\ql Style6;}{\s7\sbasedon0\ql\sl-320\slmult0 Style7;}{\s8\sbasedon0\qr Style8;}{\s9\sbasedon0\ql Style9;}{\s10\sbasedon0\qj\sl-264\slmult0 Style10;}{\s11\sbasedon0\qj\sl-298\slmult0 Style11;}{\s12\sbasedon0\qj\sl-288\slmult0 Style12;}{\s13\sbasedon0\ql Style13;}{\s14\sbasedon0\ql\fi600\sl-329\slmult0 Style14;}{\s15\sbasedon0\ql\sl-240\slmult0 Style15;}{\s16\sbasedon0\ql Style16;}{\s17\sbasedon0\ql\fi576\sl-328\slmult0 Style17;}{\s18\sbasedon0\ql Style18;}{\s19\sbasedon0\ql\sl-271\slmult0 Style19;}{\s20\sbasedon0\ql\fi2406\sl-339\slmult0 Style20;}{\s21\sbasedon0\ql Style21;}{\s22\sbasedon0\ql\fi2821\sl-161\slmult0 Style22;}{\s23\sbasedon0\ql\fi568\sl-306\slmult0 Style23;}{\s24\sbasedon0\ql Style24;}{\s25\sbasedon0\ql Style25;}{\s26\sbasedon0\ql Style26;}{\s27\sbasedon0\ql Style27;}{\s28\sbasedon0\qj\sl-271\slmult0 Style28;}{\s29\sbasedon0\ql\fi568\sl-322\slmult0 Style29;}{\s30\sbasedon0\ql Style30;}{\s31\sbasedon0\ql Style31;}{\s32\sbasedon0\ql Style32;}{\s33\sbasedon0\ql Style33;}{\s34\sbasedon0\ql Style34;}{\s35\sbasedon0\ql Style35;}{\*\cs36\additive Default Paragraph Font;}{\*\cs37\sbasedon36\additive\b\charscalex120\f2\fs58 Font Style37;}{\*\cs38\sbasedon36\additive\b\charscalex30\f2\fs400 Font Style38;}{\*\cs39\sbasedon36\additive\i\f2\fs22 Font Style39;}{\*\cs40\sbasedon36\additive\scaps\f8\fs8 Font Style40;}{\*\cs41\sbasedon36\additive\i\b\f2\fs10 Font Style41;}{\*\cs42\sbasedon36\additive\f5\fs8 Font Style42;}{\*\cs43\sbasedon36\additive\b\expndtw200\f2\fs10 Font Style43;}{\*\cs44\sbasedon36\additive\f2\fs22 Font Style44;}{\*\cs45\sbasedon36\additive\b\expndtw-10\f2\fs22 Font Style45;}{\*\cs46\sbasedon36\additive\scaps\f2\fs20 Font Style46;}{\*\cs47\sbasedon36\additive\charscalex20\f2\fs104 Font Style47;}{\*\cs48\sbasedon36\additive\b\f2\fs20 Font Style48;}{\*\cs49\sbasedon36\additive\f2\fs22 Font Style49;}{\*\cs50\sbasedon36\additive\b\f2\fs38 Font Style50;}{\*\cs51\sbasedon36\additive\f2\fs20 Font Style51;}{\*\cs52\sbasedon36\additive\expndtw-20\f2\fs30 Font Style52;}{\*\cs53\sbasedon36\additive\i\expndtw-10\f2\fs22 Font Style53;}{\*\cs54\sbasedon36\additive\i\expndtw-20\f2\fs22 Font Style54;}{\*\cs55\sbasedon36\additive\f2\fs22 Font Style55;}{\*\cs56\sbasedon36\additive\f2\fs18 Font Style56;}{\*\cs57\sbasedon36\additive\b\expndtw10\f2\fs16 Font Style57;}{\*\cs58\sbasedon36\additive\b\f2\fs20 Font Style58;}{\*\cs59\sbasedon36\additive\i\b\expndtw-10\f11\fs22 Font Style59;}{\*\cs60\sbasedon36\additive\f2\fs20 Font Style60;}{\*\cs61\sbasedon36\additive\f2\fs12 Font Style61;}{\*\cs62\sbasedon36\additive\f2\fs18 Font Style62;}{\*\cs63\sbasedon36\additive\i\expndtw-20\f2\fs22 Font Style63;}{\*\cs64\sbasedon36\additive\b\expndtw-20\f2\fs26 Font Style64;}}\fet2{\*\ftnsep {\chftnsep\par }}{\*\aftnsep {\chftnsep\par }}\expshrtn\widowctrl\paperw20384\paperh12312\margl360\margr360\margt360\margb360 \sectd \sbknone\pgwsxn20384\pghsxn12312\marglsxn360\margrsxn360\margtsxn360\margbsxn360\titlepg\cols2\colno1\colw8632\colsr2104\colno2\colw8928 {\headerf }{\footerf }{\header \pard \plain \s11\ql\li720\fi0\ri9\sb0\sa0\tx2120 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \'e1\f0\cchs186 Ma\ul b\f0\cchs186 \'fb\f0\cchs186 s vaikai:\ul0 {\charscalex100\expndtw0\tab }\ul ir galimyb\f0\cchs186 \'eb\f0\cchs186 s\par }{\footer \pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0 \pvpara\phcol\posnegx0\posnegy0\absw0\absh-254\nowrap\dfrmtxtx34\dfrmtxty0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 {\field{\*\fldinst{PAGE}}{\fldrslt 100}}\par \pard \plain \s21\qr\li720\fi0\ri9{\sl-240\slmult0\fs20\par }\sb90\sa0 \cs61\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs12 101\par }\pard\sl-4680\slmult0\sb0\keepn\pvpara\dropcapli7\dropcapt1{\b\i0\ul0\cf0\highlight0\charscalex30\f0\fs400{i}\par}\pard \plain \s1\ql\li880\fi-880\ri0\sb0\sa0\sl-272\slmult0 \cs37\i0\strike0\nosupersub\b\scaps0\charscalex120\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs58 Hfc \cs55\0\super\charscalex100\fs22 mddj8\nosupersub \super tUn\nosupersub \super tam\nosupersub \super dkrts\nosupersub identifikacijos proced\f0\cchs186 \'fb\f0\cchs186 ras, vadinasi \cs60\fs20 ivuiiy* toje \cs55\fs22 programoje \cs53\i\expndtw-10 asmenys \cs55\i0\expndtw0 turi mok\f0\cchs186 \'eb\f0\cchs186 ti naudotis identifikacijos \f0\cchs186 \'e1\f0\cchs186 ran-\cs60\fs20 *>*\f0\cchs186 \'ab\'f8\f0\cchs186 geb\f0\cchs186 \'eb\f0\cchs186 ti \cs55\fs22 analizuoti mokini\f0\cchs186 \'f8\f0\cchs186 veiklos produktus ir pati mokymosi proces\f0\cchs186 \'e0\f0\cchs186 , \cs60\f0\cchs186\fs20 \'95\f0\cchs186 tpaftistant \cs55\fs22 kriterijus, pagal kuriuos vaikas gali b\f0\cchs186 \'fb\f0\cchs186 ti priskirtas gabi\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 grupei. \cs60\fs20 Vargu, ar \cs55\fs22 bc specialaus \cs53\i\expndtw-10 pasirengimo \cs55\i0\expndtw0 gali dirbti mokytojas. Pavyzd\f0\cchs186 \'fe\f0\cchs186 iui, Clark modelyje numatyta, kad mokytojas turi b\f0\cchs186 \'fb\f0\cchs186 ti \f0\cchs186 \'e1\f0\cchs186 vald\f0\cchs186 \'e6\f0\cchs186 s \f0\cchs186 \'e1\f0\cchs186 tampos klas\f0\cchs186 \'eb\f0\cchs186 je suma\f0\cchs186 \'fe\f0\cchs186 i\-nimo strategijas (autogenin\f0\cchs186 \'e6\f0\cchs186 treniruot\f0\cchs186 \'e6\f0\cchs186 , meditacij\f0\cchs186 \'e0\f0\cchs186 ), turi geb\f0\cchs186 \'eb\f0\cchs186 ti parinkti mo\-kymo med\f0\cchs186 \'fe\f0\cchs186 iag\f0\cchs186 \'e0\f0\cchs186 , pratimus ir u\f0\cchs186 \'fe\f0\cchs186 duotis, kurioms atlikti b\f0\cchs186 \'fb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 naudojama abiej\f0\cchs186 \'f8 \f0\cchs186 smegen\f0\cchs186 \'f8\f0\cchs186 pusrutuli\f0\cchs186 \'f8\f0\cchs186 veikla, geb\f0\cchs186 \'eb\f0\cchs186 ti \f0\cchs186 \'e1\f0\cchs186 ugdymo turin\f0\cchs186 \'e1\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 traukti pratimus, kurie, panaudojant fizin\f0\cchs186 \'e1\f0\cchs186 k\f0\cchs186 \'fb\f0\cchs186 n\f0\cchs186 \'e0\f0\cchs186 , abstraktaus ir simbolinio lygmens \cs39\i informacij\f0\cchs186 \'e0\f0\cchs186 , \cs55\i0 trans\-formuoja \f0\cchs186 \'e1\f0\cchs186 konkretesn\f0\cchs186 \'e1\f0\cchs186 lygmen\f0\cchs186 \'e1\f0\cchs186 ir pan. Kai kurie autoriai, pavyzd\f0\cchs186 \'fe\f0\cchs186 iui, Wil-liams, netgi nurodo mokymo strategijas, kurias \cs39\i naudoti savo \cs55\i0 darbe turi mok\f0\cchs186 \'eb\f0\cchs186 ti \cs60\fs20 mokytojas, \cs55\fs22 kiti savo darbo komand\f0\cchs186 \'e0\f0\cchs186 apmoko. Renzulli modelio realizavimo komand\f0\cchs186 \'e0\f0\cchs186 sudaro ne tik mokytojai, bet ir t\f0\cchs186 \'eb\f0\cchs186 vai, bendruomen\f0\cchs186 \'eb\f0\cchs186 s ekspertai, mo\-kyklos administracija ir kt. personalas. Modelio veikimo efektyvum\f0\cchs186 \'e0\f0\cchs186 vertina \cs53\i\expndtw-10 visi \cs39\expndtw0 jo \cs53\expndtw-10 dalyviai, pagal tokios analiz\f0\cchs186 \'eb\f0\cchs186 s \cs55\i0\expndtw0 rezultatus bei mokini\f0\cchs186 \'f8\f0\cchs186 pageidavimus ar pakitusius poreikius ugdymo programa modifikuojama.\par \pard \plain \s2\ql\li576\fi560\ri0\sb0\sa0\sl-296\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Atskirai reik\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 pamin\f0\cchs186 \'eb\f0\cchs186 ti Taylor model\f0\cchs186 \'e1\f0\cchs186 . Jis vadinamas ir muititalento, ir k\f0\cchs186 \'fb\f0\cchs186 rybinio bei kritinio m\f0\cchs186 \'e0\f0\cchs186 stymo modeliu. \cs39\i Laikoma, kad \cs55\i0 bent vienai (j\f0\cchs186 \'f8\f0\cchs186 nuro\-domos net devynios) gabumo sri\f0\cchs186 \'e8\f0\cchs186 iai yra gabus kiekvienas vaikas. Toks gabi\f0\cchs186 \'f8 \f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 \cs53\i\expndtw-10 ugdymo modelis tur\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 b\f0\cchs186 \'fb\f0\cchs186 ti \cs39\expndtw0 priimtinas ir \cs55\i0\f0\cchs186 \'fe\f0\cchs186 mon\f0\cchs186 \'eb\f0\cchs186 ms, kurie mano, jog visi vaikai \cs60\fs20 turi \cs55\fs22 tam \cs53\i\expndtw-10 tikr\f0\cchs186 \'f8\f0\cchs186 \cs55\i0\expndtw0 gabum\f0\cchs186 \'f8\f0\cchs186 , ir d\f0\cchs186 \'eb\f0\cchs186 l koki\f0\cchs186 \'f8\f0\cchs186 nors prie\f0\cchs186 \'fe\f0\cchs186 as\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 nenori pripa\-\cs60\f0\cchs186\fs20 \'fe\f0\cchs186 inti \cs55\fs22 gabum\f0\cchs186 \'f8\f0\cchs186 \cs53\i\expndtw-10 lygmens \cs55\i0\expndtw0 skirtum\f0\cchs186 \'f8\f0\cchs186 . Modelio autorius nurodo \f0\cchs186 \'f0\f0\cchs186 ias gabum\f0\cchs186 \'f8\f0\cchs186 sritis: akademin\f0\cchs186 \'eb\f0\cchs186 s srities, \cs53\i\expndtw-10 produktyviojo \cs55\i0\expndtw0 m\f0\cchs186 \'e0\f0\cchs186 stymo, komuniJcavimo, prognozavimo, \cs53\i\expndtw-10 sprendim\f0\cchs186 \'f8\f0\cchs186 pri\f0\cchs186 \'eb\f0\cchs186 mimo, plan\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 gyvendinimo, \cs55\i0\expndtw0\f0\cchs186 \'fe\f0\cchs186 mogi\f0\cchs186 \'f0\f0\cchs186 k\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 , galimybi\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\'fe\f0\cchs186 vel\-gimo \cs39\i\expndtw-20 (ir.\expndtw0 2.2.1 \cs53\expndtw-10 lentel\f0\cchs186 \'e6\f0\cchs186 ).\par \pard \plain \s11\qj\li6976\fi0\ri0{\sl-240\slmult0\fs20\par }\sb72\sa0 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 2.2.1 \cs55 lentel\f0\cchs186 \'eb\par \pard \plain \s8\qj\li0\fi0\ri0\sb0\sa0 \pvpara\phcol\posnegx6464\posnegy688\absw0\absh-256\dfrmtxtx40\dfrmtxty0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 U\f0\cchs186 \'fe\f0\cchs186 duo\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 pavyzd\f0\cchs186 \'fe\f0\cchs186 iai\par \pard \plain \s4\qc\li2112\fi0\ri2232\sb0\sa0\sl-320\slmult0 \cs53\b0\strike0\nosupersubLi\scaps0\charscalex100\expndtw-10\dn0\f0\cchs186\lang1063\langfe1063\s22 Gabum\f0\cchs186 \'f8\f0\cchs186 \cs44\i0\expndtw0 ugdymas pagal Taylor \cs55 model\f0\cchs186 \'e1 \f0\cchs186 (pagal TayJor, 1986)\par \pard \plain \s9\qj\li0\fi0\ri0\sb0\sa0 \pvpara\phcol\posnegx2648\posnegy368\absw0\absh-328\dfrmtxtx40\dfrmtxty0 \cs53\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-10\dn0\f0\cchs186\lang1063\langfe1063\fs22 Geb\f0\cchs186 \'eb\f0\cchs186 jimas \cs55\i0\expndtw0 susikurti \cs39\i atitinka- \{\f0\cchs186 \'84\f0\cchs186 Surinkite informacij\f0\cchs186 \'e0\f0\cchs186 apie... ii\par \pard \plain \s6\qj\li304\fi0\ri0\sb16\sa0 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 I \cs53\expndtw-10 Gabum\f0\cchs186 \'f8\f0\cchs186 sritis Paai\f0\cchs186 \'f0\f0\cchs186 kinimas\par \pard \plain \s10\qj\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \pvpara\phcol\posnegx6032\posnegy328\absw2600\absh-544\dfrmtxtx40\dfrmtxty0 \cs53\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-10\dn0\f0\cchs186\lang1063\langfe1063\fs22 j mos temos \f0\cchs186 \'fe\f0\cchs186 ini\f0\cchs186 \'f8\f0\cchs186 ir \f0\cchs186 \'e1\f0\cchs186 g\f0\cchs186 \'fb\f0\cchs186 d\f0\cchs186 \'fe\f0\cchs186 i\f0\cchs186 \'f8 \cs55\i0\expndtw0\f0\cchs186 'baz\f0\cchs186 \'e6\f0\cchs186 .\par \pard \plain \s12\qj\li0\fi0\ri0\sb0\sa0\sl-288\slmult0 \pvpara\phcol\posnegx5672\posnegy384\absw2960\absh-584\dfrmtxtx40\dfrmtxty0 \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 kuo \f0\cchs186 \'e1\f0\cchs186 vairesni\f0\cchs186 \'80008\f0\cchs186 \f0\cchs186 \'f0\f0\cchs186 altini\f0\cchs186 \'f8\f0\cchs186 ir j\f0\cchs186 \'e0\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 a\-nalizuokite".\par \pard \plain \s11\ql\li0\fi0\ri0\sb0\sa0\sl-296\slmult0\tlul\tx2520 \pvpara\phcol\posnegx5856\posnegy896\absw2776\absh-1656\dfrmtxtx40\dfrmtxty0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 f Geb\f0\cchs186 \'eb\f0\cchs186 jimas generuoti \cs60\fs20 ne-\line \cs55\fs22 f \f0\cchs186 \'e1\f0\cchs186 prastas, originalias i\f0\cchs186 \'eb\f0\cchs186 /as,\line \cs60\fs20 f\cs53\i\expndtw-10\fs22 pasteb\f0\cchs186 \'eb\'fb\f0\cchs186 naujus \cs55\i0\expndtw0 s\f0\cchs186 \'e0\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 ius,\line \cs53\i\expndtw-10 | papildyti detal\f0\cchs186 \'eb\f0\cchs186 mis, \cs55\i0\expndtw0 kurios\line \cs53\i\expndtw-10\f0\cchs186 \'c1\f0\cchs186 pa\f0\cchs186 \'e1\f0\cchs186 vairioa id\f0\cchs186 \'eb\f0\cchs186 jas,\expndtw0 {\charscalex100\expndtw0\tab }\par \pard \plain \s6\qj\li232\fi0\ri0\sb0\sa0 \cs53\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-10\dn0\f0\cchs186\lang1063\langfe1063\fs22 'Akademin\f0\cchs186 \'eb\par \pard \plain \s12\qj\li0\fi0\ri0\sb0\sa0\sl-272\slmult0 \pvpara\phcol\posnegx5264\posnegy160\absw3368\absh-648\dfrmtxtx40\dfrmtxty0 \cs39\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \'84\f0\cchs186 Sukurkite, kuo \cs60\i0\fs20 pakeisti \f0\cchs186 \'e1\f0\cchs186 prastas energijos r\f0\cchs186 \'fb\'f0\f0\cchs186 is".\par \pard \plain \s7\ql\li0\fi0\ri0\sb0\sa0\sl-320\slmult0 \cs39\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 (K\f0\cchs186 \'fb\f0\cchs186 rybos, produktyvioio\par \pard \plain \s13\qj\li5816\fi0\ri0\sb88\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 2.2.1 icntcU\par \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-240\slmult0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Gabum\f0\cchs186 \'f8\f0\cchs186 \cs60\fs20 sritis\par \pard \plain \s15\ql\li0\fi40\ri0\sb0\sa0\sl-240\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Sprendim\f0\cchs186 \'f8 \f0\cchs186 pri\f0\cchs186 \'eb\f0\cchs186 mimo\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-248\slmult0\tlul\tx2736 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Paai\f0\cchs186 \'f0\f0\cchs186 kinimas {\charscalex100\expndtw0\tab }Ll\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-248\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas rasti alternatyvas, \cs55\fs22 l.,\par \pard \plain \s15\ql\li32\fi-32\ri0\sb0\sa0\sl-248\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 jas \f0\cchs186 \'e1\f0\cchs186 vertinti ir priimti tinka- \cs55\fs22 t \cs60\fs20 r m\f0\cchs186 \'e0\f0\cchs186 problemos sprendim\f0\cchs186 \'e0\f0\cchs186 . 1 \cs41\b\i\f0\cchs186\fs10 \'e1\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs5u\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 J\f0\cchs186 \'fe\f0\cchs186 duo\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 pavyzd\f0\cchs186 \'fe\f0\cchs186 iai Nurodykite \cs60\fs20 savo \cs55\fs22 m\f0\cchs186 \'eb\f0\cchs186 giamiausi\f0\cchs186 \'e0\f0\cchs186 \cs60\fs20 I\par \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 a\f0\cchs186 \'f0\f0\cchs186 y toj\f0\cchs186 \'e0\f0\cchs186 , ai\f0\cchs186 \'f0\f0\cchs186 kiai pagr\f0\cchs186 \'e1\f0\cchs186 sdami at- t \cs60\fs20 rumentais \cs55\fs22 savo pasirinkim\f0\cchs186 \'e0\f0\cchs186 it\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 itmetim\f0\cchs186 \'e0\f0\cchs186 ".\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Planavimo\cell \pard \plain \s15\ql\li16\fi-16\ri0\sb0\sa0\sl-248\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas numatyti kelius ir b\f0\cchs186 \'fb\f0\cchs186 dus id\f0\cchs186 \'eb\f0\cchs186 jai \f0\cchs186 \'e1\f0\cchs186 gyvendinti, nustatant, koki\f0\cchs186 \'f8\f0\cchs186 reikia resur- \cs55\fs22 1 \cs60\fs20 s\f0\cchs186 \'f8\f0\cchs186 , \f0\cchs186 \'e1\'fe\f0\cchs186 velgiant, kokios gali\-mos problemos, ir numatant \f0\cchs186 \'fe\f0\cchs186 ingsnius j\f0\cchs186 \'f8\f0\cchs186 sprendimui, to\-kiu b\f0\cchs186 \'fb\f0\cchs186 du patobulinant plan\f0\cchs186 \'e0\f0\cchs186 .\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-256\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 .I\f0\cchs186 \'f0\f0\cchs186 studijav\f0\cchs186 \'e6\f0\cchs186 \cs55\fs22 mitus apie \f0\cchs186 \'f0\f0\cchs186 ik\f0\cchs186 \'f0\f0\cchs186 nos\-\cs60\fs20 parnius, \cs55\fs22 sukurkite tyrimo plan\f0\cchs186 \'e0\f0\cchs186 \cs62\fs18 1\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-256\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 savo draug\f0\cchs186 \'f8\f0\cchs186 \cs55\fs22 nuomonei \cs60\fs20 apie \f0\cchs186 \'f0\f0\cchs186 iuos gyv\f0\cchs186 \'fb\f0\cchs186 nus i\f0\cchs186 \'f0\f0\cchs186 tirti\super 41\nosupersub , \f0\cchs186 \'84\f0\cchs186 Sukurkite akcijos prie\f0\cchs186 \'f0\f0\cchs186 \cs55\fs22 r\f0\cchs186 \'fb\f0\cchs186 kym\f0\cchs186 \'e0\f0\cchs186 \cs62\fs18 1 \cs60\fs20 plan\f0\cchs186 \'e0\f0\cchs186 ".\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Prognozavimo\cell \pard \plain \s15\ql\li0\fi8\ri0\sb0\sa0\sl-248\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas numatyti ir pati\-krinti prie\f0\cchs186 \'fe\f0\cchs186 asties ir pasekm\f0\cchs186 \'eb\f0\cchs186 s s\f0\cchs186 \'e0\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 ius.\cell \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'84\f0\cchs186 I\f0\cchs186 \'f0\f0\cchs186 studijuokite N sutart\f0\cchs186 \'e1\f0\cchs186 ir nurodykite \f0\cchs186 \'e1\f0\cchs186 vairias galimas jos i ratifikavimo pasekmes".\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Komunikavimo\cell \pard \plain \s15\ql\li0\fi16\ri0\sb0\sa0\sl-256\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas reik\f0\cchs186 \'f0\f0\cchs186 ti savo id\f0\cchs186 \'eb\f0\cchs186 jas, jausmus, poreikius ir suprasti kitus, vartojant verbalin\f0\cchs186 \'e6\f0\cchs186 ir neverbalin\f0\cchs186 \'e6\f0\cchs186 kalb\f0\cchs186 \'e0\f0\cchs186 .\cell \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'84\f0\cchs186 Pademonstruokite savo jaus- \cs55\fs22 1 \cs60\fs20 mus, kai su\f0\cchs186 \'fe\f0\cchs186 inote apie ... \f0\cchs186 \'84\f0\cchs186 Papasakokite apie \f0\cchs186 \'e1\f0\cchs186 vyk\f0\cchs186 \'e1\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 vaiko i ir i\f0\cchs186 \'f0\f0\cchs186 suaugusiojo pozicini". i\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Plan\f0\cchs186 \'f8\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'e1\f0\cchs186 gyvendinimo\cell \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas \f0\cchs186 \'e1\f0\cchs186 gyvendinti plan\f0\cchs186 \'e0\cell \pard \plain \s16\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs43\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw200\dn0\f0\cchs186\lang1063\langfe1063\fs10 \'97\f0\cchs186 \f0\cchs186 \'97\f0\cchs186 \f1\cchs186 \u9632\'3f\f0\cchs186 - \f0\cchs186 \'97\'97\f0\cchs186  \expndtw0 *-\expndtw200 \expndtw0 L-\expndtw200 \expndtw0 -\expndtw200 \cs42\b0\expndtw0\f3\cchs186\fs8 i \f4\cchs186 \u9632\'3f\f3\cchs186 \f4\cchs186 \u9632\'3f\f3\cchs186 \cs41\b\i\f0\cchs186\fs10 a \cs40\b0\i0\scaps\f6\cchs186\fs8 - ii \f7\cchs186 \u9632\'3f\f6\cchs186 \cs62\scaps0\f0\cchs186\fs18 1\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'84\f0\cchs186 Sukurkite ir \f0\cchs186 \'e1\f0\cchs186 gyvendinkite N 1 renginio plan\f0\cchs186 \'e0\f0\cchs186 ".\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li32\fi-32\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Galimybi\f0\cchs186 \'f8 \'e1\'fe\f0\cchs186 velgimo\cell \pard \plain \s15\ql\li0\fi40\ri0\sb0\sa0\sl-272\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas identifikuoti gali\-myb\f0\cchs186 \'e6\f0\cchs186 ir ja pasinaudoti.\cell \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-272\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'84\f0\cchs186 I\f0\cchs186 \'f0\f0\cchs186 tirkite ispan\f0\cchs186 \'f8\f0\cchs186 kalbos mokymo(si) poreik\f0\cchs186 \'e1\f0\cchs186 mokykloje ir inicijuokite atitinkamos pro\-gramos \f0\cchs186 \'e1\f0\cchs186 gyvendinim\f0\cchs186 \'e0\f0\cchs186 ".\cell \pard\intbl\row \pard\pard \plain \s14\ql\li0\fi600\ri0\sb232\sa0\sl-328\slmult0 \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Taylor siekia ugdyti kuo daugiau gabum\f0\cchs186 \'f8\f0\cchs186 , kuriais, jo manymu, pasi\f0\cchs186 \'fe\f0\cchs186 ymi vaikai. Tad kuo \f0\cchs186 \'e1\f0\cchs186 vairesniems vaik\f0\cchs186 \'f8\f0\cchs186 gabumams mokytojas skirs d\f0\cchs186 \'eb\f0\cchs186 mes\f0\cchs186 \'e1\f0\cchs186 , tuo daugiau galimybi\f0\cchs186 \'f8\f0\cchs186 , kad vaikas ras srit\f0\cchs186 \'e1\f0\cchs186 , kurios \f0\cchs186 \'fe\f0\cchs186 inovu jis gali tapti. Ta\f0\cchs186 \'e8\f0\cchs186 iau pir\-masis \f0\cchs186 \'f0\f0\cchs186 io modelio etapas - tai vis d\f0\cchs186 \'eb\f0\cchs186 lto akademini\f0\cchs186 \'f8\f0\cchs186 gabum\f0\cchs186 \'f8\f0\cchs186 ugdymas. Kitas \f0\cchs186 \'fe\f0\cchs186 ingsnis, skirtas mokytojui apsispr\f0\cchs186 \'e6\f0\cchs186 sti, kuri\f0\cchs186 \'e0\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 likusi\f0\cchs186 \'f8\f0\cchs186 a\f0\cchs186 \'f0\f0\cchs186 tuoni\f0\cchs186 \'f8\f0\cchs186 gabum\f0\cchs186 \'f8\f0\cchs186 sri\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8 \f0\cchs186 jis imasi ugdyti. Paprastai seka, anot autoriaus, tur\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 b\f0\cchs186 \'fb\f0\cchs186 ti tokia: produktyvusis m\f0^cchs186 \'e0\f0\cchs186 stymas, planavimas, sprendim\f0\cchs186 \'f8\f0\cchs186 pri\f0\cchs186 \'eb\f0\cchs186 mimas, pian\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 gyvendinimas, \f0\cchs186 \'e1\'fe\f0\cchs186 valgos. Akivaizdu, jog dirbti pagal \f0\cchs186 \'f0\'e1\f0\cchs186 model\f0\cchs186 \'e1\f0\cchs186 mokytojas tur\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 b\f0\cchs186 \'fb\f0\cchs186 ti specialiai pasi\-reng\f0\cchs186 \'e6\f0\cchs186 s, tad modelio autorius si\f0\cchs186 \'fb\f0\cchs186 lo kelet\f0\cchs186 \'e0\f0\cchs186 mokytojo darbo metod\f0\cchs186 \'f8\f0\cchs186 . Pirmuouiu atveju si\f0\cchs186 \'fb\f0\cchs186 loma papildom\f0\cchs186 \'f8\f0\cchs186 gabum\f0\cchs186 \'f8\f0\cchs186 ugdym\f0\cchs186 \'e0\f0\cchs186 organizuoti baigiantis pamokoms. \f0\cchs186 \'c1\f0\cchs186 prastinis mokymo turinys \f0\cchs186 \'84\f0\cchs186 suspaud\f0\cchs186 \'fe\f0\cchs186 iamas" laike, o atsiradusias 5\f0\cchs186 \'97\f0\cchs186 10 laisvuj minu\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 mokytojas gali i\f0\cchs186 \'f0\f0\cchs186 naudoti pasirinkto gabumo ugdymui. Kai \cs48\b\fs20 mokytojui \cs44\b0\fs22 atrodo, kad jau pasiekta tam tikra pa\f0\cchs186 \'fe\f0\cchs186 anga ugdant pirm\f0\cchs186 \'e0\f0\cchs186 j\f0\cchs186 \'e1\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 o pasirinkt\f0\cchs186 \'f8\f0\cchs186 ga\-\par \sect\soctd \sbkpage\pgwsxn20855\pghsxn13316\marglsxn1080\margrsxn8026\margtsxn360\margbsxn360\cols2\colno1\colw7936\colsr2482\colno2\colw1329 {\header \pard \plain \s11\ql\li0\fi0\ri-7657\sb0\sa0\tx2245 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \'e1\f0\cchs186 Ma\ul b\f0\cchs186 \'fb\f0\cchs186 s vaikai:\ul0 {\charscalex100\expndtw0\tab }\ul ir galimyb\f0\cchs186 \'eb\f0\cchs186 s\par }{\footer \par \plain \s11\qj\li0\fi0\ri0\sb0\sa0 \pvpara\phcol\posnegx-720\posnegy0\absw0\absh-254\nowrap\dfrmtxtx34\dfrmtxty0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 {\field{\*\fldinst{PAGE}}{\fldrslt 100}}\par \pard \plain \s21\qr\li0\fi0\ri-7657{\sl-240\slmult0\fs20\par }\sb90\sa0 \cs61\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs12 101\par }{\shp {\*\shpinst \chpleft13358\shptop593\shpright14748\shpbottom830\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz1\shplid1{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 317500}}{\sp{\sn dyWrapDistBottom}{\sv 198755}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s31\qj\li0\fi0\ri0\sb0\sa0 \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Rai\f0\cchs186 \'f0\f0\cchs186 kos \cs51\b0 b\f0\cchs186 \'fb\f0\cchs186 dai\par }}}{\shp {\*\shpinst \shpleft11859\shptop534\shpright13172\shpbottom2169\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz0\shplid0{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 279400}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0\sl-254\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas\par \pard \plain \s13\ql\li0\fi0\ri0\sb17\sa0\sl-271\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Ugdytojo ir ugdytini\f0\cchs186 \'f8 \f0\cchs186 s\f0\cchs186 \'e0\f0\cchs186 veika, ko\-munikacija\par }}}{\shp {\*\shpinst \shp|eft13350\shptop1144\shpright17594\shpbottom2296\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz2\shplid2{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 139700}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPint}{\sv 1}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s12\qj\li0\fi0\ri0\sb0\sa0\sl-271\slmult0 \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Informacijos srautai \f0\cchs186 \'97\f0\cchs186 \cs48\b Asmenvb\f0\cchs186 \'eb\f0\cchs186 s tobuli* tiesioginiai ir \cs60\b0 gr\f0\cchs186 \'e1\'fe\f0\cchs186 tamieji, ir s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 \cs48\b tobulintai pedagogin\f0\cchs186 \'eb\f0\cchs186 \cs60\b0 sistema sudarymas: \cs48\b\f0\cchs186 \'fb\f0\cchs186 ssionj\par \pard \plain \s33\ql\li2499\fi0\ri0\sb93\sa0 \cs51\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 - b. \cs60 y\super 1\nosupersub "\super 0\nosupersub \cs51 HBB\par }}}{\shp {\*\shpinst \shpleft13299\shptop2228\shpright14205\shpbottom2474\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz4\shplid4{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 0}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Saviugda\par }}}{\shp {\*\shpinst \shpleft15874\shptop2279\shpright17187\shpbottom2524\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz5\shplid5{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 0}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s12\qj\li0\fi0\ri0\sb0\sa0 \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Tobulinimasis\par }}}{\shp {\*\shpinst \shpleft11867\shptop2152\shpright13078\shpbottom2812\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz3\shplid3{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 640080}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0\sl-280\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Individo as\-menyb\f0\cchs186 \'eb\par }}}{\shpgrp{\*\shpinst \shpleft-720\shptop3939\shpright7878\shpbottom12384\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz6\shplid6{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 0}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn groupLeft}{\sv 1067}}{\sp{\sn groupTop}{\sv 6209}}{\sp{\sn groupRight}{\sv 9665}}{\sp{\sn groupBottom}{\sv 14654}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 1067}}{\sp{\sn relTop}{\sv 6429}}{\sp{\sn relRight}{\sv 9665}}{\sp{\sn relBottom}{\sv 14654}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1889 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx3354 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx5836 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8597 \pard \plain \s19\ql\li474\fi0\ri0\sb0\sa0\sl-271\slmult0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1 \cs48\b\fs20 Ugdymo \cs49\b0\fs22 res \cs46\scaps\fs20 f\cs48\b\scaps0 lyb\f0\cchs186 \'eb\f0\cchs186 s lygmu\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 i- \cs49\b0\fs22 Strukt\f0\cchs186 \'fb\f0\cchs186 rini \cs48\b\fs20 o elementas\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 s Rai\f0\cchs186 \'f0\f0\cchs186 kos b\f0\cchs186 \'fb\f0\cchs186 dai\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Funkcijos\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1889 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx3354 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx5836 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8597 \pard \plain \s19\ql\li440\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 j \cs48\b\fs20 Valstybinis\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Valstyb\f0\cchs186 \'eb\f0\cchs186 s politika\cell \pard \plain \s19\ql\li0\fi8\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'d0\f0\cchs186 vietimo politika ir j\f0\cchs186 \'e0 \f0\cchs186 atspindintys \f0\cchs186 \'e1\f0\cchs186 statymai\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-288\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Teisinis reguliavimas, u\f0\cchs186 \'fe\f0\cchs186 tikrinantis kiekvie\-nam vaikui (vadinasi, ir gabiam) teis\f0\cchs186 \'e6\f0\cchs186 gauti jo poreikius ir galimybes atitinkant\f0\cchs186 \'e1\f0\cchs186 ugdym\f0\cchs186 \'e0\f0\cchs186 ir ug\-dymosi s\f0\cchs186 \'e0\f0\cchs186 lygas\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1889 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx3354 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx5836 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8597 \pard \plain \s19\ql\li390\fi0\ri0\sb0\sa0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langde1063\fs20 Visuomeninis\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Visuomen\f0\cchs186 \'eb\f0\cchs186 s institutai\cell \pard \plain \s19\ql\li0\fi68\ri0\sb0\sa0\sl-288\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Vyriausybines insti\-tucijos/ visuomenini\f0\cchs186 \'f8 \f0\cchs186 organizacij\f0\cchs186 \'f8\f0\cchs186 /paramos fond\f0\cchs186 \'f8\f0\cchs186 /auk\f0\cchs186 \'f0\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 moky\-kl\f0\cchs186 \'f8\f0\cchs186 /mokslo institucij\f0\cchs186 \'f8 \cs39\b0\i\f0\cchs186\fs22 tikslin\f0\cchs186 \'eb\f0\cchs186 \cs48\i0\b\fs20 veikla\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-296\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Veiklos inicijavimas; koordinavimas, organi\-zavimas, informacijos kaupimas, analiz\f0\cchs186 \'eb\f0\cchs186 ir sklai\-da; gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 paie\f0\cchs186 \'f0\f0\cchs186 kos programos, identifikavi\-mas, globa; mokytoj\f0\cchs186 \'f8\f0\cchs186 ir kit\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'f0\f0\cchs186 vietimo darbuotoj\f0\cchs186 \'f8 \f0\cchs186 rengi mas;ugdymo t\f0\cchs186 \'e6\f0\cchs186 sti\-numo u\f0\cchs186 \'fe\f0\cchs186 tikrinimas; kt.\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1889 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx3354 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx5836 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8597 \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 1 Institucinis\par \pard \plain \s25\ql\li0\fi0\ri0\sb0\sa0\sl-983\slmult0 \intbl \cs47\b0\i0\strike0\nosupersub\scaps0\charscalex20\expndtw0\dn19\f0\cchs186\lang1063\langfe1063\fs104 1\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-305\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Ugdymo nstituci\f0\cchs186 \'e1\f0\cchs186 os\par \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-305\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 i \cs49\b0\fs22 1 \cs48\b\fs20 i\par \pard \plain \s26\ql\li0\fi0\ri0\sb0\sa0\sl-381\slmult0 \intbl \cs50\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn5\f0\cchs186\lang1063\langfe1063\fs38 !\cell \pard \plain \s19\ql\li25\fi-25\ri0\sb0\sa0\sl-296\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo modelis institucijos lygmeniu \f0\cchs186 \'97\f0\cchs186 mokyklos, papildomojo ugdymo mokyklos, technin\f0\cchs186 \'eb\f0\cchs186 s \{\f0\cchs186 \'fb\f0\cchs186 rybos namai, klas\f0\cchs186 \'eb\f0\cchs186 s, tovyklos, kursai, kon\-kursai ir kt.\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-305\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw-5420746430195647047\dn0\f0\cchs186\lang1063\langfe1063\fs20 Ugdymo proceso opti\-mizavimas: optimalios ugdymo(si) aplinkos sudarymas, ugdymas, mo\-kymas, veiklos rezultat\f0\cchs186 \'f8 \f0\cchs186 vertinimas, mokymo dife\-rencijavimas ir kt.\cell \pard\intbl\row \pard}}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 3371}}{\sp{\sn relTop}{\sv 6209}}{\sp{\sn relRight}{\sv 7988}}{\sp{\sn relBotto}}{\sv 6497}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s18\qj\li0\fi0\ri0\sb0\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Gabi\f0\cchs186 \'f8\f0\cchs186 \cs49 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo ir jo s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 modelis\par }}}}}\pard \plain \s14\qr\li0\fi0\ri0\sb0\sa0\sl-305\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 m\f0\cchs186 \'e0\f0\cchs186 gali apib\f0\cchs186 \'fb\f0\cchs186 dinti asmenyb\f0\cchs186 \'eb\f0\cchs186 s saviugda, iritrapersonaliniame lygmenyje \f0\cchs186 \'e1\f0\cchs186 gyjanti gryn\f0\cchs186 \'e0\f0\cchs186 rai\f0\cchs186 \'f0\f0\cchs186 k\f0\cchs186 \'e0\f0\cchs186 . \cs45\b\expndtw-10 II \cs55\b0\expndtw0 esm\f0\cchs186 \'eb\f0\cchs186 s \cs53\i\expndtw-10 vis\f0\cchs186 \'f8\f0\cchs186 \cs55\i0\expndtw0 anks\f0\cchs186 \'e8\f0\cchs186 iau min\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 strukt\f0\cchs186 \'fb\f0\cchs186 rini\f0\cchs186 \'f8\f0\cchs186 element\f0\cchs186 \'f8\f0\cchs186 funkcionavi\-mo tikslas \cs49 I \cs55 prigimtini\f0\cchs186 \'f8\f0\cchs186 asmens gali\f0\cchs186 \'f8\f0\cchs186 pl\f0\cchs186 \'eb\f0\cchs186 tra ir i\f0\cchs186 \'f0\f0\cchs186 vystymas jo paties j\f0\cchs186 \'eb\f0\cchsq86 gomis iki maksimalaus tam asmeniui galimo lygio. Literat\f0\cchs186 \'fb\f0\cchs186 roje (Gross, 1995; Almonaitien\f0\cchs186 \'eb\f0\cchs186 , 1997; Heller, 1999; Gagne, 2004 ir kt.) nurodoma, kad gabaus vaiko savirealizaci\-jai turi (takos jo asmenyb\f0\cchs186 \'eb\f0\cchs186 s nekognityvin\f0\cchs186 \'eb\f0\cchs186 s savyb\f0\cchs186 \'eb\f0\cchs186 s - pasiekim\f0\cchs186 \'f8\f0\cchs186 motyvacija, tei\-giamas \cs45\b\expndtw-10 sav\f0\cchs186 \'e6\f0\cchs186 s \cs55\b0\expndtw0 vertinimas, darbingumas, savikontrol\f0\cchs186 \'eb\f0\cchs186 ir kt. Yra pagrindo manyti, kad tinkamas min\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 GAVUS modelio strukt\f0\cchs186 \'fb\f0\cchs186 rini\f0\cchs186 \'f8\f0\cchs186 element\f0\cchs186 \'f8\f0\cchs186 funkcionavimas palankiai veikia gabaus vaiko asmenyb\f0\cchs186 \'e6\f0\cchs186 , taigi skatina \cs45\b\expndtw-10 j\f0\cchs186 \'e1\f0\cchs186 \cs55\b0\expndtw0 tobul\f0\cchs186 \'eb\f0\cchs186 ti.\par \pard \plain \s2\qj\li0\fi584\ri0\sb8\sa0\sl-271\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Apibendrinant tai, kas pasakyta, galima pateikti tok\f0\cchs186 \'e1\f0\cchs186 teorin\f0\cchs186 \'e1\f0\cchs186 gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8 \f0\cchs186 ugdymo ir jo s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 model\f0\cchs186 \'e1\f0\cchs186 :\par \pard \plain \s11\qr\li0\fi0\ri0{\sl-240\slmult0\fs20\par }\sb99\sa0 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 3.1 \cs55 lentel\f0\cchs186 \'eb\par \column \pard \plain \s28\qj\li0\fi0\ri0{\sl-240\slmult0\fs20\par }\sb200\sa0\sl-271\slmult0 \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Ugdymo rea-\ul lyb\f0\cchs186 \'eb\f0\cchs186 s lygmuo\par \pard \plain \s11\qj\li0\fi0\ri0\sb42\sa0\sl-246\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Interpersona-linis\khftn{\footnote\pard \plain \s13 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \chftn Pastaba. Interpersonalinio ir intrapersonalinio \cs48\b\fs20 lygmens \cs55\b0\fs22 elemcr\cs48\b\f0\cchs186\fs20 \'a3\f0\cchs186 E\cs52\b0\expndtw-20\fs30 ^^PK\cs48\b\expndtw0\fs20 ^niaj\par \pard \plain \s13 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 modelio elementai, kuri\f0\cchs186 \'f8\f0\cchs186 optimaliamveikimui \cs49 ir skirtas ug\strike dy\strike0 m\strike o\strike0 \cs55 s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 \cs60\fs20 mo\-\cs55\fs22 delis\par \pard \plain \s23 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 Sukurtasis \expndtw0 GAVUS\expndtw-20 moeelis turi savo strukt\f0\cchs186 \'fb\f0\cchs186 r\f0\cchs186 \'e0\f0\cchs186 , funkcijas \cs53\expndtw-10 ir \cs63\expndtw0 funkcionavimo\expndtw-20 \expndtw0 aptin-\cs53\expndtw-10 k\f0\cchs186 \'e0\f0\cchs186 . \cs63\expndtw-20 Modelis turi \expndtw0 paskirti\expndtw-20 bendr\f0\cchs186 \'e0\f0\cchs186 tiksl\f0\cchs186 \'e0\f0\cchs186 \f0\cchs186 \'97\f0\cchs186 \cs49\i0\expndtw0 sudaryti s\f0\cchs186 \'e0\f0\cchs186 lygas gabiems valkams, nepriklausomai nuo j\f0\cchs186 \'f8\f0\cchs186 socialin\f0\cchs186 \'eb\f0\cchs186 s pad\f0\cchs186 \'eb\f0\cchs186 ties, gyvenamosios vietos, am\-\f0\cchs186 \'fe\f0\cchs186 iaus, lyties ir kt., rinktis j\f0\cchs186 \'f8\f0\cchs186 poreikius atitinkanti ugdym\f0\cchs186 \'e0\f0\cchs186 ir galimybes saviugdai, pad\f0\cchs186 \'eb\f0\cchs186 ti jam ir skatinti vaik\f0\cchs186 \'e0\f0\cchs186 siekti pilno savojo gabum\f0\cchs186 \'f8\f0\cchs186 po\-tencialo realizavimo ir b\f0\cchs186 \'fb\f0\cchs186 ti naudingam visuomenei, Sis tikslas suteikia modeliui vienov\f0\cchs186 \'eb\f0\cchs186 s, vientisumo.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Kiekvienas strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas turi ir papildom\f0\cchs186 \'f8\f0\cchs186 (i\f0\cchs186 \'f0\f0\cchs186 vestini\f0\cchs186 \'f8\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 ben\-drojo) tiksl\f0\cchs186 \'f8\f0\cchs186 , kurie susij\f0\cchs186 \'e6\f0\cchs186 su funkcijomis, kurias atlieka strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas. Modelis skirtas \f0\cchs186 \'fe\f0\cchs186 mogui jame vyksta informacijos perdavimo ir valdymo pro\-cesai \f0\cchs186 \'97\f0\cchs186 tai b\f0\cchs186 \'fb\f0\cchs186 dinga visuomenin\f0\cchs186 \'eb\f0\cchs186 ms sistemoms.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelis sudarytas i\f0\cchs186 \'f0\f0\cchs186 posistemi\f0\cchs186 \'f8\f0\cchs186 (pavyzd\f0\cchs186 \'fe\f0\cchs186 iui, GVU atskiroje ugdymo institucijoje, jo posistem\f0\cchs186 \'eb\f0\cchs186 - pedagogin\f0\cchs186 \'eb\f0\cchs186 sistema, ir kt.). Visi GAVUS elementai yra vienaip ar kitaip susij\f0\cchs186 \'e6\f0\cchs186 su ugdymu ir jo funkcijomis: \f0\cchs186 \'f0\f0\cchs186 vietimu, lavinimu, aukl\f0\cchs186 \'eb\f0\cchs186 jimu, mokymu, globojimu, formavimu ir kt. Kiekviena jo sud\f0\cchs186 \'eb\f0\cchs186 tin\f0\cchs186 \'eb\f0\cchs186 dalis atlieka tam tikr\f0\cchs186 \'e0\f0\cchs186 funkcij\f0\cchs186 \'e0\f0\cchs186 (jas nurod\f0\cchs186 \'eb\f0\cchs186 me aptardami model\f0\cchs186 \'e1\f0\cchs186 ). Tuomet, kai mo\-delio strukt\f0\cchs186 \'fb\f0\cchs186 riniai elementai funkcionuoja visuose ugdymo realyb\f0\cchs186 \'eb\f0\cchs186 s lygmeny\-se, jis apima daugel\f0\cchs186 \'e1\f0\cchs186 aplinkos veiksni\f0\cchs186 \'f8\f0\cchs186 , kurie yra gabumo virsmo pasiekimais katalizatoriai. Funkciniais ry\f0\cchs186 \'f0\f0\cchs186 iais susij\f0\cchs186 \'e6\f0\cchs186 elementai sukuria palaikan\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'e0\f0\cchs186 aplink\f0\cchs186 \'e0 \f0\cchs186 vienas kito veikimui, o tai savo ruo\f0\cchs186 \'fe\f0\cchs186 tu suma\f0\cchs186 \'fe\f0\cchs186 ina atsitiktinum\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 tak\f0\cchs186 \'e0\f0\cchs186 tiesiogi\-\cs44 niam \cs49 ugdymui, t.y. skatina gabaus vaiko saviugd\f0\cchs186 \'e0\f0\cchs186 .\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelio artimiausioji funkcionavimo aplinka yra \f0\cchs186 \'f0\f0\cchs186 vietimo sistema.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelis yra atviras ir dinami\f0\cchs186 \'f0\f0\cchs186 kas. Atviras, nes tai yra socialin\f0\cchs186 \'eb\f0\cchs186 strukt\f0\cchs186 \'fb\f0\cchs186 ra, kuriai \f0\cchs186 \'e1\f0\cchs186 tak\f0\cchs186 \'e0\f0\cchs186 daro aplinka (netgi jo veikimo realyb\f0\cchs186 \'eb\f0\cchs186 je prasme). Modelio struk\-t\f0\cchs186 \'fb\f0\cchs186 riniai elementai turi daug vidini\f0\cchs186 \'f8\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 , o jie savo ruo\f0\cchs186 \'fe\f0\cchs186 tu yra atviri aplinkai, kitoms, i\f0\cchs186 \'f0\f0\cchs186 orin\f0\cchs186 \'eb\f0\cchs186 ms socialin\f0\cchs186 \'eb\f0\cchs186 ms strukt\f0\cchs186 \'fb\f0\cchs186 roms, sistemoms, yra dinami\f0\cchs186 \'f0\f0\cchs186 ki, nes i\f0\cchs186 \'f0\f0\cchs186 likti stati\f0\cchs186 \'f0\f0\cchs186 kam, kai kinta aplinka, n\f0\cchs186 \'eb\f0\cchs186 ra \f0\cchs186 \'e1\f0\cchs186 manoma. Dinami\f0\cchs186 \'f0\f0\cchs186 kas jis ir d\f0\cchs186 \'eb\f0\cchs186 l k\f0\cchs186 \'ab\'a9\f0\cchs186 $}\pAv \pard \plain \s11\qj\li0\fi0\ri0{\sl-240\slmult0\fs20\par }{\sl-240\slmult0\fs20\par }\sb121\sa0\sl-263\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Intrapersona-linis\chftn{\footnote\pard \plain \s13 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \chftn Pastaba. Interpersonalinio ir intrapersonalinio \cs48\b\fs20 lygmens \cs55\b0\fs22 elemcr\cs48\b\f0\cchs186\fs20 \'a3\f0\cchs186 E\cs52\b0\expndtw-20\fs30 ^^PK\cs48\b\expndtw0\fs20 ^niaj\par \pard \plain \s13 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 modelio elementai, kuri\f0\cchs186 \'f8\f0\cchs186 optimaliam veikimui \cs49 ir skirtas ug\strike dy\strike0 m\strike o\strike0 \cs55 s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 \cs60\fs20 mo\-\cs55\fs22 delis\par \pard \plain \s23 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 Sukurtasis \expndtw0 GAVUS\expndtw-20 modelis turi savo strukt\f0\cchs186 \'fb\f0\cchs186 r\f0\cchs186 \'e0\f0\cchs186 , funkcijas \cs53\expndtw-10 ir \cs63\expndtw0 funkcionavimo\expndtw-20 \expndtw0 aptin-\cs53\expndtw-10 k\f0\cchs186 \'e0\f0\cchs186 . \cs63\expndtw-20 Modelis turi \expndtw0 paskirti\expndtw-20 bendr\f0\cchs186 \'e0\f0\cchs186 tiksl\f0\cchs186 \'e0\f0\cchs186 \f0\cchs186 \'97\f0\cchs186 \cs49\i0\expndtw0 sudaryti s\f0\cchs186 \'e0\f0\cchs186 lygas gabiems valkams, nepriklausomai nuo j\f0\cchs186 \'f8\f0\cchs186 socialin\f0\cchs186 \'eb\f0\cchs186 s pad\f0\cchs186 \'eb\f0\cchs186 ties, gyvenamosios vietos, am\-\f0\cchs186 \'fe\f0\cchs186 iaus, lyties ir kt., rinktis j\f0\cchs186 \'f8\f0\cchs186 poreikius atitinkanti ugdym\f0\cchs186 \'e0\f0\cchs186 ir galimybes saviugdai, pad\f0\cchs186 \'eb\f0\cchs186 ti jam ir skatinti vaik\f0\cchs186 \'e0\f0\cchs186 siekti pilno savojo gabum\f0\cchs186 \'f8\f0\cchs186 po\-tencialo realizavimo ir b\f0\cchs186 \'fb\f0\cchs186 ti naudingam visuomenei, Sis tikslas suteikia modeliui vienov\f0\cchs186 \'eb\f0\cchs186 s, vientisumo.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Kiekvienas strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas turi ir papildom\f0\cchs186 \'f8\f0\cchs186 (i\f0\cchs186 \'f0\f0\cchs186 vestini\f0\cchs186 \'f8\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 ben\-drojo) tiksl\f0\cchs186 \'f8\f0\cchs186 , kurie susij\f0\cchs186 \'e6\f0\cchs186 su funkcijomis, kurias atlieka strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas. Modelis skirtas \v0\cchs186 \'fe\f0\cchs186 mogui, jame vyksta informacijos perdavimo ir valdymo pro\-cesai \f0\cchs064 \'97\f0\cchs186 tai b\f0\cchs186 \'fb\f0\cchs186 dinga visuomenin\f0\cchs186 \'eb\f0\cchs186 ms sistemoms.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelis sudarytas i\f0\cchs186 \'f0\f0\cchs186 posistemi\f0\cchs186 \'f8\f0\cchs186 (pavyzd\f0\cchs186 \'fe\f0\cchs186 iui, GVU atskiroje ugdymo institucijoje, jo posistem\f0\cchs186 \'eb\f0\cchs186 - pedagogin\f0\cchs186 \'eb\f0\cchs186 sistema, ir kt.). Visi GAVUS elementai yra vienaip ar kitaip susij\f0\cchs186 \'e6\f0\cchs186 su ugdymu ir jo funkcijomis: \f0\cchs186 \'f0\f0\cchs186 vietimu, lavinimu, aukl\f0\cchs186 \'eb\f0\cchs186 jimu, mokymu, globojimu, formavimu ir kt. Kiekviena jo sudf0\cchs186 \'eb\f0\cchs186 tin\f0\cchs186 \'eb\f0\cchs186 dalis atlieka tam tikr\f0\cchs186 \'e0\f0\cchs186 funkcij\f0\cchs186 \'e0\f0\cchs186 (jas nurod\f0\cchs186 \'eb\f0\cchs186 me aptardami model\f0\cchs186 \'e1\f0\cchs186 ). Tuomet, kai mo\-delio strukt\f0\cchs186 \'fb\f0\cchs186 riniai elementai funkcionuoja visuose ugdymo realyb\f0\cchs186 \'eb\f0\cchs186 s lygmeny\-se, jis apima daugel\f0\cchs186 \'e1\f0\cchs186 aplinkos veiksni\f0\cchs186 \'f8\f0\cchs186 , kurie yra gabumo virsmo pasiekimais katalizatoriai. Funkciniais ry\f0\cchs186 \'f0\f0\cchs186 iais susij\f0\cchs186 \'e6\f0\cchs186 elementai sukuria palaikan\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'e0\f0\cchs186 aplink\f0\cchs186 \'e0 \f0\cchs186 vienas kito vei{imui, o tai savo ruo\f0\cchs186 \'fe\f0\cchs186 tu suma\f0\cchs186 \'fe\f0\cchs186 ina atsitiktinum\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 tak\f0\cchs186 \'e0\f0\cchs186 tiesiogi\-\cs44 niam \cs49 ugdymui, t.y. skatina gabaus vaiko saviugd\f0\cchs186 \'e0\f0\cchs186 .\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelio artimiausioji funkcionavimo aplinka yra \f0\cchs186 \'f0\f0\cchs186 vietimo sistema.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelis yra atviras ir dinami\f0\cchs186 \'f0\f0\cchs186 kas. Atviras, nes tai yra socialin\f0\cchs186 \'eb\f0\cchs186 strukt\f0\cchs186 \'fb\f0\cchs186 ra, kuriai \f0\cchs186 \'e1\f0\cchs186 tak\f0\cchs186 \'e0\f0\cchs186 daro aplinka (netgi jo veikimo realyb\f0\cchs186 \'eb\f0\cchs186 je prasme). Modelio struk\-t\f0\cchs186 \'fb\f0\cchs186 riniai elementai turi daug vidini\f0\cchs186 \'f8\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 , o jie savo ruo\f0\cchs186 \'fe\f0\cchs186 tu yra atviri aplinkai, kitoms, i\f0\cchs186 \'f0\f0\cchs186 orin\f0\cchs186 \'eb\f0\cchs186 ms socialin\f0\cchs186 \'eb\f0\cchs186 ms strukt\f0\cchs186 \'fb\f0\cchs186 roms, sistemoms, yra dinami\f0\cchs186 \'f0\f0\cchs186 ki, nes i\f0\cchs186 \'f0\f0\cchs186 likti stati\f0\cchs186 \'f0\f0\cchs186 kam, kai kinta aplinka, n\f0\cchs186 \'eb\f0\cchs186 ra \f0\cchs186 \'e1\f0\cchs186 manoma. Dinami\f0\cchs186 \'f0\f0\cchs186 kas jis ir d\f0\cchs186 \'eb\f0\cchs186 l k\f0\cchs186 \'ab\'a9\f0\cchs186 $}\par \sect\sectd \sbknone\pgwsxn20126\pghsxn13892\marglsxn733\margrsxn360\margtsxn360\margbsxn360\cols1\colsx60 {\header }{\footer \pard \plain \s27\qr\li0\fi0\ri0\sb0\sa0 \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 {\field{\*\fldinst{PAGE}}{\fldrslt 123}}\par }{\pard\plain \sb1144\sa0\sl-240\slmult0\fs20\par}\pard \plain \s29\qj\li11181\fi0\ri0\sb51\sa102 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 4. \cs55 Gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ufidymo ir jo s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 mo\ul delio rai\f0\cchs186 \'f0\f0\cchs186 kos\ul0 \cs45\b\expndtw-10\f0\cchs186 \'c1\f0\cchs186 \cs55\b0\ul\expndtw0 jetuvo\f0\cchs186 \'e1\f0\cchs186 e \cs60\fs20 pristatymas\par \sect\sectd \sbknone\pgwsxn20126\pghsxn13892\marglsxn733\margrsxn453\margtsxn360\margbsxn360\cols2\colno1\colw8123\colsr2431\colno2\colw8385 {\shpgrp{\*\shpinst \shpleft10622\shptop263\shpright18737\shpbottom1966\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz7\shplid7{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 107315}}{\sp{\sn dyWrapDistBottom}{\sv 48260}}{\sp{\sn groupLeft}{\sv 12045}}{\sp{\sn groupTop}{\sv 2846}}{\sp{\sn groupRight}{\sv 20160}}{\sp{\sn groupBottom}{\sv 4549}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 12045}}{\sp{\sn relTop}{\sv 2922}}{\sp{\sn relRight}{\sv 20160}}{\sp{\sn relBottom}{\sv 4100}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx542 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx6666 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7378 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8115 \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Nr.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0\sl-144\slmult0\tlhyph\tx3744\tlul\tx4574 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn2\f0\cchs186\lang1063\langfe1063\fs22 rr-ri{\charscalex100\expndtw0\tab }\cs61\fs12 _ {\charscalex100\expndtw0\tab } J \f0\cchs186 \'bb\par \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Teiginys \f0\cchs186 \'97\cell \pard \plain \s35\qr\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 mreies\par \pard \plain \s3\qr\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Vid *\cell \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 t\f0\cchs186 \'e6\f0\cchs186 sinys\par \pard \plain \s24\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs61\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs12 Qt \cs60\fs20 n\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx542 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx6666 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7378 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8115 \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 11.\cell \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Tr\f0\cchs186 \'fb\f0\cchs186 ksta mokini\f0\cchs186 \'f8\f0\cchs186 t\f0\cchs186 \'eb\f0\cchs186 v\f0\cchs1:6 \'f8\f0\cchs186 palaikymo, pritarimo\cell \pard \plain \s5\qr\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 00\cs49\fs22 .24\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.21\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx542 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx6666 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7378 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8115 \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 12.\cell \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 [Tr\f0\cchs186 \'fb\f0\cchs186 ksta mokyklos administracijos paskatinimo ir \cs57\expndtw10\fs16 nri\cs58\expndtw0\fs20 -^mn\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\tlhyph\tx5472\tlhyph\tx6107 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 maksimalus \cs60\b0 galimas trukume .v\cs57\b\expndtw10\fs16 .-rr.\cs59\i\expndtw-10\f9\cchs186\fs22 ^-ETrr\cs60\b0\i0\expndtw0\f0\cchs186\fs20 {\charscalex100\expndtw0\tab }rr{\charscalex100\expndtw0\tab }1\cell \pard \plain \s5\qr\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 00\cs49\fs22 .41\cel \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.22\cell \pard\intbl\row \pard}}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 18025}}{\sp{\sn relTop}{\sv 2846}}{\sp{\sn relRight}{\sv 20152}}{\sp{\sn relBottom}{\sv 3117}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}vs\n\{s\{p{ }1s} fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s11\ql\li0\fi0\ri0\sb0\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 4.2.3 lentel\f0\cchs186 \'eb\f0\cchs186 s t\f0\cchs186 \'e6\f0\cchs186 sinys\par }}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 12629}}{\sp{\sn relTop}{\sv 4074}}{\sp{\sn relRight}{\sv 20100}}{\sp{\sn relBottom}{\sv 4549}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s22\ql\li0\fi2821\ri0\sb0\sa0\sl-161\slmult0\tlhyph\tx3456\tldot\tx3812 \cs62\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs18 _ ,{\charscalex100\expndtw0\tab }{\charscalex100\expndtw0\tab }.\f0\cchs186 \'84\'ab\f0\cchs186 , , icigu \expndtw20 trukumoexpndtw0 \cs55fs22 visi\f0\cchs186 \'f0\f0\cchs186 kai nejau\f0\cchs186 -\line \'e8\f0\cchs186 iama \f0\cchs186 \'97\f0\cchs186 vertinimas \cs49\f0\cchs186 \'84\f0\cchs186 -2".\par }}}}}{\shpgrp{\*\shpinst \shpleft-373\shptop6683\shpright8098\shpbottom12511\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr2\shpwrk3\shpz8\shplid8{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 0}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn groupLeft}{\sv 1050}}{\sp{\sn groupTop}{\sv 9267}}{\sp{\sn groupRight}{\sv 9521}}{\sp{\sn groupBottom}{\sv 15095}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 1050}}{\sp{\sn relTop}{\sv 10275}}{\sp{\sn relRight}{\sv 9521}}{\sp{\sn relBottom}{\sv 15095}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdr15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li246\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Nr\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\strike0\nosupersub\scaps0\chrlex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Teiginys\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Vid.*\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 St. n.\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1 \super 1\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta u\f0\cchs186 \'fe\f0\cchs186 mokes\f0\cchs186 \'e8\f0\cchs186 io u\f0\cchs186 \'fe\f0\cchs186 \cs56\fs18 papildom\f0\cchs186 \'e0\f0\cchs186 \cs55\fs22 darb\f0\cchs186 \'e0\f0\cchs186 ,.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.43\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.84\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 12.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta materialinio paskatinimo itin gabiems mokiniams.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.35\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.87\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 13.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-288\slmult0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta bendros itin gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo politikos visos i\f0\cchs186 \'f0\f0\cchs186 liet \cs52\expndtw-20\fs30 j \cs44\expndtw0\fs22 mastu.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.27\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.85\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 14.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 [Tr\f0\cchs186 \'fb\f0\cchs186 ksta apr\f0\cchs186 \'fb\f0\cchs186 pinimo reikalinga mokymo metodine med\f0\cchs186 \'fe\f0\cchs186 iaga\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.22\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.96\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 15.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-296\slmult0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta kvalifikacijos k\f0\cchs186 \'eb\f0\cchs186 limo kurs\f0\cchs186 \'f8\f0\cchs186 itin gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo \cs44 tems.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1\cs49 .20\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.91\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrsbrdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0\sl-407\slmult0 \intbl \cs52\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw-20\up2\f0\cchs186\lang1063\langfe1063\fs30 j \cs44\expndtw0\fs22 6. \cs55 j\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-313\slmult0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta \cs55 bendradarbiavimo tu auk\f0\cchs186 \'f0\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 mokykl\f0\cchs186 \'f8\f0\cchs186 d\f0\cchs186 \'eb\f0\cchs186 stytojais, \cs44 mokalininkaif.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1\cs49 .04\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.99\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-313\slmult0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 7. \cs55 1 \cs44 Tr\f0\cchs186 \'fb\f0\cchs186 ksta literatu \expndtw-20 rot\expndtw0 \cs54\i\expndtw-20 apie itin \cs55\i0\expndtw0 gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 pa\f0\cchs186 \'fe\f0\cchs186 inim\f0\cchs186 \'e0\f0\cchs186 , ugdym\f0\cchs186 \'e0\f0\cchs186 , \cs52\expndtw-20\fs30 j \cs55\expndtw0\fs22 psichologij\f0\cchs186 \'e0\f0\cchs186 , \cs44 kir\f0\cchs186 \'f8\f0\cchs186 \cs55\f0\cchs186 \'f0\f0\cchs186 ali\f0\cchs186 \'f8\f0\cchs186 patirt j.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1\cs49 .00\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.97\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 8. \cs55 j Tr\f0\cchs186 \'fb\f0\cchs186 ksta \cs44 bendradarbiavimo \cs55 su patyrusiais \f0\cchs186 \'f0\f0\cchs186 ioje srityje kolegomis,\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.88\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.02\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s32\ql\li0\fi0\ri0\sb0\sa0\sl-356\slmult0 \intbl \cs52\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw-20\dn4\f0\cchs186\lang1063\langfe1063\fs30 1 \cs49\expndtw0\fs22 1\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtu0\dn0\f0\cchs186\lang1063\langfe1063\fs22 'r\f0\cchs186 \'fb\f0\cchs186 ksta \cs44 tinkamo \cs55 pasirengimo auk\f0\cchs186 \'f0\f0\cchs186 tojoje mokykloje.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.56\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.17\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 10. 7\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 r\f0\cchs186 \'fb\f0\cchs186 ksta galimybi\f0\cchs186 \'f8\f0\cchs186 \cs44 naudotis \cs55 kompiuteriu ir internetu.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 -0.19\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.33\cell \pard\intbl\row \pard}}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 2151}}{\sp{\sn relTop}{\sv 9267}}{\sp{\sn relRight}{\sv 8724}}{\sp{\sn relBottom}{\sv 10300}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s2\qj\li0\fi0\ri0\sb0\sa0\sl-330\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Duomenys apie tai, ko mokytojams tr\f0\cchs186 \'fb\f0\cchs186 ksta darbui su itin\par \pard \plain \s20\ql\li0\fi2406\ri0\sb0\sa0\sl-330\slmult0\tlul\tx805 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 gabiais vaikais\line \lang1033 {\charscalex100\expndtw0\tab }\ul\lang1063 (Narkevi\f0\cchs186 \'e8\f0\cchs186 ien\f0\cchs186 \'eb\f0\cchs186 , Janilionis,\ul0 Almonaitien\f0\cchs186 \'eb\f0\cchs186 , \cs49 2002)\par }}}}}\pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0\sl-322\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 niams, galima manyti, kad jaunesni\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 klasi\f0\cchs186 \'f8\f0\cchs186 gabi\f0\cchs186 \'f8\f0\cchs186 mokini\fcchs186 \'f8\f0\cchs186 ugdymo rezulta\-tai \f0\cchs186\'fe\f0\cchs186 inomi ir fiksuojami tik klases ir mokyklos (atskirais atvejais savivaldyb\f0\cchs186 \'eb\f0\cchs186 s) lygmeniu. be to, olimpiad\f0\cchs186 \'f8\f0\cchs186 rezultatai - tai tik pasiekimai, \cs49 o \cs55 kas daroma klas\f0\cchs186 \'eb\-\f0\cchs186 je, \cs53\i\expndtw-10 mokykloje, \cs55\i0\expndtw0 kad tie pasiekimai b\f0\cchs186 \'fb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 tokie, ir \cs49 ar \cs55 tie pasiekimai \f0\cchs186 \'97\f0\cchs186 tai mokytojo ir mokinio darbo rezultatas ar tik mokinio potencialo \{vertinimas, informaci\-jos taip pat neturime arba turime labai nedaug \cs49 (\f0\cchs186 \'fe\f0\cchs186 r. \cs55 Narkevi\f0\cchs186 \'e8\f0\cchs186 ien\f0\cchs186 \'eb\f0\cchs186 , \cs49 1997,1998, \cs55 2003, Narkevi\f0\cchs186 \'e8\f0\cchs186 ien\f0\cchs186 \'eb\f0\cchs186 , Janilionis, Almonaitien\f0\cchs186 \'eb\f0\cchs186 , \cs49 2002).\par \pard \plain \s2\qj\li0\fi576\ri0\sb0\sa0\sl-322\slmult0 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 Mokytoj\f0\cchs186 \'f8\f0\cchs186 rengimas. \cs55\i0\expndtw0 N\f0\cchs186 \'eb\f0\cchs186 vienas Lietuvos universitetas, rengiantis mokyto\-jus, nesi\f0\cchs186 \'fb\f0\cchs186 lo pirmos ar antros pakopos studij\f0\cchs186 \'f8\f0\cchs186 programos, kurios paskirtis b\f0\cchs186 \'fb\f0\cchs186 t\f0\cchs186 \'f8 \f0\cchs186 ai\f0\cchs186 \'f0\f0\cchs186 kiai orientuota \f0
diff --git a/vcl/qa/cppunit/pdfexport/data/form-font-name.odt b/vcl/qa/cppunit/pdfexport/data/form-font-name.odt
new file mode 100644
index 000000000..a7430c9a8
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/form-font-name.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/image-shape.fodt b/vcl/qa/cppunit/pdfexport/data/image-shape.fodt
new file mode 100644
index 000000000..a0bcfeb0e
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/image-shape.fodt
@@ -0,0 +1,141 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:initial-creator>Gabor Kelemen LO</meta:initial-creator><meta:creation-date>2022-10-12T16:49:07.114000000</meta:creation-date><dc:date>2022-11-18T15:28:13.568307995</dc:date><meta:editing-duration>PT3M39S</meta:editing-duration><meta:editing-cycles>2</meta:editing-cycles><meta:generator>LibreOfficeDev/7.5.0.0.alpha0$Linux_X86_64 LibreOffice_project/867afb8f1cc153fba2c28c85deedda74bd077cf0</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="1" meta:object-count="0" meta:page-count="1" meta:paragraph-count="2" meta:word-count="291" meta:character-count="1541" meta:non-whitespace-character-count="1250"/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Lucida Sans1" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Graphics" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/>
+ </style:style>
+ <text:outline-style style:name="Outline">
+ <text:outline-level-style text:level="1" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="2" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="3" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="4" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="5" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="6" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="7" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="8" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="9" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="10" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ </text:outline-style>
+ <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
+ <style:graphic-properties style:horizontal-pos="center" style:horizontal-rel="paragraph" style:mirror="none" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard" draw:wrap-influence-on-position="once-concurrent"/>
+ </style:style>
+ <style:style style:name="gr1" style:family="graphic">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="2.249cm" fo:min-width="5.212cm" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" style:flow-with-text="false"/>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm">
+ <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:page-layout-properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page">
+ <style:drawing-page-properties draw:background-size="full"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:sequence-decls>
+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+ </text:sequence-decls>
+ <text:p text:style-name="Standard"><draw:custom-shape text:anchor-type="paragraph" draw:z-index="1" draw:name="Shape 1" draw:style-name="gr1" svg:width="5.213cm" svg:height="2.25cm" svg:x="4.299cm" svg:y="12.448cm">
+ <svg:title>This is a blue...</svg:title>
+ <svg:desc>...rectangle</svg:desc>
+ <text:p/>
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape><draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="char" svg:width="11.748cm" svg:height="8.996cm" draw:z-index="0"><draw:image draw:mime-type="image/png">
+ <office:binary-data>iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABGdBTUEAANbY1E9YMgAAABl0
+ RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFpSURBVHjaYvz//z8DtQBAADER
+ o+jjZGuibAQIICZiDOK/cgzFwEnrV/4HYXS1AAHERIxBR58yMiAb2DtzM1b1AAHERIxBIIBu
+ IDYAEEBMxBjE0bgdxcBL3vcZLl16jaEPIICYiDFIU9MSw8BeoeUYhgEEEBMxBnFx8WE1EN3L
+ AAHERIxBIECMgQABxAhKtPgM+vbtE9xmGP/69eMMP+o9wWLW0kD9OlYM/LlHGQECiAndoKg/
+ USgGgTTmdS8C0yA+zIUgdeguBAggljtWdQwMVkDXACWMjd0ZXRun/Id5DWTA9C23GSaVxoEN
+ zISoARvoamnBYF2/hPHs2Z3/z0JdDhBADCBvIuPkhsn/QeDr14//QWwQjY0PVYeiFyCA8OaA
+ 3cdPoEQAiI8PAAQQEwMVAUAAsWATBAX0jx9fsWrAJQ4CAAGE1TBQwOMC9+9fwikHEEBYDQPF
+ IAzIe8TglEMHAAHESM2SFiDAADEwCe4BJwcYAAAAAElFTkSuQmCC
+ </office:binary-data>
+ </draw:image>
+ <svg:title>Image of a house</svg:title>
+ <svg:desc>nice drawing, isn't it?</svg:desc>
+ </draw:frame>He heard quiet steps behind him. That didn't bode well.</text:p>
+ <text:p text:style-name="Standard"><text:s/></text:p>
+ <text:p text:style-name="Standard"/>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/vcl/qa/cppunit/pdfexport/data/link-wrong-page-partial.odg b/vcl/qa/cppunit/pdfexport/data/link-wrong-page-partial.odg
new file mode 100644
index 000000000..1fad913e0
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/link-wrong-page-partial.odg
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/link-wrong-page.odp b/vcl/qa/cppunit/pdfexport/data/link-wrong-page.odp
new file mode 100644
index 000000000..b6787aff6
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/link-wrong-page.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/master.odm b/vcl/qa/cppunit/pdfexport/data/master.odm
new file mode 100644
index 000000000..74016352b
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/master.odm
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odg b/vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odg
new file mode 100644
index 000000000..6dee0145c
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odg
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg b/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg
new file mode 100644
index 000000000..aa0f89300
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf b/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf
new file mode 100644
index 000000000..739a80c47
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-rotate-180.pdf b/vcl/qa/cppunit/pdfexport/data/pdf-image-rotate-180.pdf
new file mode 100644
index 000000000..981ca3206
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/pdf-image-rotate-180.pdf
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/rectangles.pdf b/vcl/qa/cppunit/pdfexport/data/rectangles.pdf
new file mode 100644
index 000000000..6911d229a
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/rectangles.pdf
@@ -0,0 +1,54 @@
+%PDF-1.7
+%
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /MediaBox [0 0 200 300]
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+>>
+endobj
+4 0 obj <<
+ /Length 188
+>>
+stream
+q
+0 0 0 rg
+0 290 10 10 re B*
+10 150 50 30 re B*
+0 0 1 rg
+190 290 10 10 re B*
+70 232 50 30 re B*
+0 1 0 rg
+190 0 10 10 re B*
+130 150 50 30 re B*
+1 0 0 rg
+0 0 10 10 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+xref
+0 5
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000157 00000 n
+0000000226 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 5
+>>
+startxref
+466
+%%EOF
diff --git a/vcl/qa/cppunit/pdfexport/data/reduce-image.fodt b/vcl/qa/cppunit/pdfexport/data/reduce-image.fodt
new file mode 100644
index 000000000..b5737ae27
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/reduce-image.fodt
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ooo="http://openoffice.org/2004/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+ <style:default-style style:family="graphic">
+ </style:default-style>
+ <style:style style:name="Graphics" style:family="graphic">
+ </style:style>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
+ <style:graphic-properties style:run-through="foreground" style:horizontal-pos="center" style:horizontal-rel="paragraph" style:mirror="none" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+ <text:p text:style-name="Standard"><draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="char" svg:width="0.041cm" svg:height="0.041cm" draw:z-index="0"><draw:image loext:mime-type="image/png"><office:binary-data>iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAABmJLR0QA/wD/AP+gvaeTAAAA
+ CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5AEVDCUTfvEVdAAAAYhJREFUeNrt3bEJwzAQ
+ htFckjLreP8Bso5bc2lTpBDG4kfkvQUE5uNUGEnV3TdIufsECBABggARIAgQAYIAESAIEAGC
+ ABEgCBABggARIAgQAYIAESAIEAGCABEgCBABggARIHx7phZ+vF9D13Id217WXW9dExBbMAgQ
+ AYIAESAIEAGCABEgCBABIkAQIAIEASJAECAChKnq6hfTR88gsKarz46YgNiCESAIEAGCABEg
+ CBABwlSx27FStzHxW+oPlgmILRgBggARIAgQAYIAESAIEAGCABEgCBABggARIAgQAYIAESAI
+ EAGCABEgCBABggARIAgQAYIAESACBAEiQBAgAgQBIkAQIAIEASJAECACBAEiQBAgi4u9mJ56
+ oRsTEASIAEGACBABggARIAiQP1LdmR8So39Cjm0v6663rgmILRgEiABBgAgQBIgAQYAIEASI
+ ABEgCBABggARIAgQAcJUsTMhYAIiQAQIAkSAIEAECAJEgCBABAgCRIAgQAQIAkSAIEAECKd9
+ AEYENxB/sygQAAAAAElFTkSuQmCC
+ </office:binary-data></draw:image></draw:frame></text:p>
+ </office:text>
+ </office:body>
+</office:document>
diff --git a/vcl/qa/cppunit/pdfexport/data/reduce-small-image.fodt b/vcl/qa/cppunit/pdfexport/data/reduce-small-image.fodt
new file mode 100644
index 000000000..99ff22746
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/reduce-small-image.fodt
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ooo="http://openoffice.org/2004/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+ <style:default-style style:family="graphic">
+ </style:default-style>
+ <style:style style:name="Graphics" style:family="graphic">
+ </style:style>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
+ <style:graphic-properties style:run-through="foreground" style:horizontal-pos="center" style:horizontal-rel="paragraph" style:mirror="none" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+ <text:p text:style-name="Standard"><draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="char" svg:width="0.041cm" svg:height="0.041cm" draw:z-index="0"><draw:image loext:mime-type="image/png"><office:binary-data>iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMklEQVR42mP4//8/AyWYYXAZ
+ wHSK+z8pbOoaAJIgBWM1gFh/jxqAxwCKYmHgE9KAZSYAhK3Dgc2FxfUAAAAASUVORK5CYII=
+ </office:binary-data></draw:image></draw:frame></text:p>
+ </office:text>
+ </office:body>
+</office:document>
diff --git a/vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odt b/vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odt
new file mode 100644
index 000000000..ecd779537
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105093.odp b/vcl/qa/cppunit/pdfexport/data/tdf105093.odp
new file mode 100644
index 000000000..82ce29cda
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf105093.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105461.odp b/vcl/qa/cppunit/pdfexport/data/tdf105461.odp
new file mode 100644
index 000000000..9c86a3bd7
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf105461.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105954.odt b/vcl/qa/cppunit/pdfexport/data/tdf105954.odt
new file mode 100644
index 000000000..ba5c96de6
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf105954.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105972.fodt b/vcl/qa/cppunit/pdfexport/data/tdf105972.fodt
new file mode 100644
index 000000000..b9f1e29f5
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf105972.fodt
@@ -0,0 +1,175 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:creation-date>2022-05-17T10:53:27.044915889</meta:creation-date><dc:date>2022-05-18T18:02:56.717773462</dc:date><meta:editing-duration>PT3M</meta:editing-duration><meta:editing-cycles>6</meta:editing-cycles><meta:generator>LibreOfficeDev/7.4.0.0.alpha1$Linux_X86_64 LibreOffice_project/9e37c70c5c7413aee31f13fcd154cae30153e8ae</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="2" meta:word-count="0" meta:character-count="0" meta:non-whitespace-character-count="0"/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Lohit Devanagari1" svg:font-family="'Lohit Devanagari'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif CJK SC'" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.1181in" draw:shadow-offset-y="0.1181in" draw:start-line-spacing-horizontal="0.1114in" draw:start-line-spacing-vertical="0.1114in" draw:end-line-spacing-horizontal="0.1114in" draw:end-line-spacing-vertical="0.1114in" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lohit Devanagari1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="0.4925in" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lohit Devanagari1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <text:outline-style style:name="Outline">
+ <text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ </text:outline-style>
+ <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false" text:offset="0.1965in" style:num-format="1" text:number-position="left" text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="gr1" style:family="graphic" style:data-style-name="C10048">
+ <style:graphic-properties style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true" style:flow-with-text="false"/>
+ </style:style>
+ <style:style style:name="gr2" style:family="graphic" style:data-style-name="C63">
+ <style:graphic-properties style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="middle" style:vertical-rel="line" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true" style:flow-with-text="false"/>
+ </style:style>
+ <style:style style:name="gr3" style:family="graphic">
+ <style:graphic-properties style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="middle" style:vertical-rel="line" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true" style:flow-with-text="false"/>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="8.5in" fo:page-height="11in" style:num-format="1" style:print-orientation="portrait" fo:margin-top="0.7874in" fo:margin-bottom="0.7874in" fo:margin-left="0.7874in" fo:margin-right="0.7874in" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.278in" style:layout-grid-ruby-height="0.139in" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0in" loext:margin-gutter="0in">
+ <style:footnote-sep style:width="0.0071in" style:distance-before-sep="0.0398in" style:distance-after-sep="0.0398in" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:page-layout-properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page">
+ <style:drawing-page-properties draw:background-size="full"/>
+ </style:style>
+ <number:time-style style:name="C63" number:language="en" number:country="US">
+ <number:hours number:style="long"/>
+ <number:text>:</number:text>
+ <number:minutes number:style="long"/>
+ <number:text>:</number:text>
+ <number:seconds number:style="long"/>
+ <number:text> </number:text>
+ <number:am-pm/>
+ </number:time-style>
+ <number:date-style style:name="C10048" number:language="de" number:country="DE">
+ <number:year/>
+ <number:text>-</number:text>
+ <number:month number:style="long"/>
+ <number:text>-</number:text>
+ <number:day number:style="long"/>
+ </number:date-style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <office:forms form:automatic-focus="false" form:apply-design-mode="false">
+ <form:form form:name="Form" form:apply-filter="true" form:command-type="table" form:control-implementation="ooo:com.sun.star.form.component.Form" office:target-frame="">
+ <form:properties>
+ <form:property form:property-name="PropertyChangeNotificationEnabled" office:value-type="boolean" office:boolean-value="true"/>
+ <form:property form:property-name="TargetURL" office:value-type="string" office:string-value=""/>
+ </form:properties>
+ <form:formatted-text form:name="CurrencyField" form:control-implementation="ooo:com.sun.star.form.component.CurrencyField" xml:id="control1" form:id="control1" form:current-value="1234" form:input-required="false" form:validation="true" form:min-value="-1000000" form:max-value="1000000">
+ <form:properties>
+ <form:property form:property-name="ControlTypeinMSO" office:value-type="float" office:value="0"/>
+ <form:property form:property-name="CurrencySymbol" office:value-type="string" office:string-value="€"/>
+ <form:property form:property-name="DecimalAccuracy" office:value-type="float" office:value="4"/>
+ <form:property form:property-name="DefaultControl" office:value-type="string" office:string-value="com.sun.star.form.control.CurrencyField"/>
+ <form:property form:property-name="MouseWheelBehavior" office:value-type="float" office:value="0"/>
+ <form:property form:property-name="ObjIDinMSO" office:value-type="float" office:value="65535"/>
+ <form:property form:property-name="PrependCurrencySymbol" office:value-type="boolean" office:boolean-value="true"/>
+ </form:properties>
+ </form:formatted-text>
+ <form:time form:name="TimeField" form:control-implementation="ooo:com.sun.star.form.component.TimeField" xml:id="control2" form:id="control2" form:value="P0D" form:current-value="PT11H" form:max-value="PT23H58M58S" form:input-required="false" form:validation="true">
+ <form:properties>
+ <form:property form:property-name="ControlTypeinMSO" office:value-type="float" office:value="0"/>
+ <form:property form:property-name="DefaultControl" office:value-type="string" office:string-value="com.sun.star.form.control.TimeField"/>
+ <form:property form:property-name="MouseWheelBehavior" office:value-type="float" office:value="0"/>
+ <form:property form:property-name="ObjIDinMSO" office:value-type="float" office:value="65535"/>
+ <form:property form:property-name="Text" office:value-type="string" office:string-value="11:00:00AM"/>
+ </form:properties>
+ </form:time>
+ <form:date form:name="DateField" form:control-implementation="ooo:com.sun.star.form.component.DateField" xml:id="control3" form:id="control3" form:current-value="2022-05-19" form:min-value="1800-01-01" form:input-required="false" form:validation="true">
+ <form:properties>
+ <form:property form:property-name="ControlTypeinMSO" office:value-type="float" office:value="0"/>
+ <form:property form:property-name="DefaultControl" office:value-type="string" office:string-value="com.sun.star.form.control.DateField"/>
+ <form:property form:property-name="MouseWheelBehavior" office:value-type="float" office:value="0"/>
+ <form:property form:property-name="ObjIDinMSO" office:value-type="float" office:value="65535"/>
+ <form:property form:property-name="Text" office:value-type="string" office:string-value="22-05-19"/>
+ </form:properties>
+ </form:date>
+ </form:form>
+ </office:forms>
+ <text:sequence-decls>
+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+ </text:sequence-decls>
+ <text:p text:style-name="Standard"><draw:control text:anchor-type="as-char" draw:z-index="0" draw:name="Control 1" draw:style-name="gr3" draw:text-style-name="P1" svg:width="2.563in" svg:height="0.5732in" draw:control="control1"/></text:p>
+ <text:p text:style-name="Standard"/>
+ <text:p text:style-name="Standard"><draw:control text:anchor-type="paragraph" draw:z-index="2" draw:name="Control 3" draw:style-name="gr1" draw:text-style-name="P1" svg:width="2.4543in" svg:height="0.5732in" svg:x="-0.0102in" svg:y="0.9374in" draw:control="control3"/><draw:control text:anchor-type="as-char" draw:z-index="1" draw:name="Control 2" draw:style-name="gr2" draw:text-style-name="P1" svg:width="2.4543in" svg:height="0.5732in" draw:control="control2"/></text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106059.odt b/vcl/qa/cppunit/pdfexport/data/tdf106059.odt
new file mode 100644
index 000000000..a2c180378
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf106059.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106206.odt b/vcl/qa/cppunit/pdfexport/data/tdf106206.odt
new file mode 100644
index 000000000..3581157de
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf106206.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106693.odt b/vcl/qa/cppunit/pdfexport/data/tdf106693.odt
new file mode 100644
index 000000000..a2c180378
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf106693.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106702.odt b/vcl/qa/cppunit/pdfexport/data/tdf106702.odt
new file mode 100644
index 000000000..da3b7e814
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf106702.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odt b/vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odt
new file mode 100644
index 000000000..d46c93dff
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106972.odt b/vcl/qa/cppunit/pdfexport/data/tdf106972.odt
new file mode 100644
index 000000000..3fa76c49f
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf106972.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf107013.odt b/vcl/qa/cppunit/pdfexport/data/tdf107013.odt
new file mode 100644
index 000000000..644e65c6d
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf107013.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf107018.odt b/vcl/qa/cppunit/pdfexport/data/tdf107018.odt
new file mode 100644
index 000000000..3bfc7b2d7
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf107018.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf107089.odt b/vcl/qa/cppunit/pdfexport/data/tdf107089.odt
new file mode 100644
index 000000000..5aaaab944
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf107089.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf107868.odt b/vcl/qa/cppunit/pdfexport/data/tdf107868.odt
new file mode 100644
index 000000000..8309f4b87
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf107868.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf108963.odp b/vcl/qa/cppunit/pdfexport/data/tdf108963.odp
new file mode 100644
index 000000000..246c0c72a
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf108963.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf109143.odt b/vcl/qa/cppunit/pdfexport/data/tdf109143.odt
new file mode 100644
index 000000000..7d9afa378
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf109143.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf113143.odp b/vcl/qa/cppunit/pdfexport/data/tdf113143.odp
new file mode 100644
index 000000000..5f8a1b10e
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf113143.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf114256.ods b/vcl/qa/cppunit/pdfexport/data/tdf114256.ods
new file mode 100644
index 000000000..1e30a7e31
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf114256.ods
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf115117-1.odt b/vcl/qa/cppunit/pdfexport/data/tdf115117-1.odt
new file mode 100644
index 000000000..63fe82946
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf115117-1.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf115117-2.odt b/vcl/qa/cppunit/pdfexport/data/tdf115117-2.odt
new file mode 100644
index 000000000..c1e1f6d43
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf115117-2.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf115262.ods b/vcl/qa/cppunit/pdfexport/data/tdf115262.ods
new file mode 100644
index 000000000..b401a74ce
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf115262.ods
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf115967.odt b/vcl/qa/cppunit/pdfexport/data/tdf115967.odt
new file mode 100644
index 000000000..39f4ce178
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf115967.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf118244_radioButtonGroup.odt b/vcl/qa/cppunit/pdfexport/data/tdf118244_radioButtonGroup.odt
new file mode 100644
index 000000000..caabc4987
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf118244_radioButtonGroup.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf121615.odt b/vcl/qa/cppunit/pdfexport/data/tdf121615.odt
new file mode 100644
index 000000000..7d2a87cf0
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf121615.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf121962.odt b/vcl/qa/cppunit/pdfexport/data/tdf121962.odt
new file mode 100644
index 000000000..a831b1136
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf121962.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf124272.odt b/vcl/qa/cppunit/pdfexport/data/tdf124272.odt
new file mode 100644
index 000000000..54d4dcb2a
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf124272.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf127217.odt b/vcl/qa/cppunit/pdfexport/data/tdf127217.odt
new file mode 100644
index 000000000..470600a0a
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf127217.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf128445.odp b/vcl/qa/cppunit/pdfexport/data/tdf128445.odp
new file mode 100644
index 000000000..adabdb223
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf128445.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf128630.odp b/vcl/qa/cppunit/pdfexport/data/tdf128630.odp
new file mode 100644
index 000000000..d216504b7
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf128630.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf129085.docx b/vcl/qa/cppunit/pdfexport/data/tdf129085.docx
new file mode 100644
index 000000000..6ac21d8f2
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf129085.docx
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp b/vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp
new file mode 100644
index 000000000..6168dd2a2
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp
@@ -0,0 +1,239 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:meta><meta:creation-date>2020-07-27T11:44:30.444393550</meta:creation-date><meta:editing-duration>PT2M31S</meta:editing-duration><meta:editing-cycles>2</meta:editing-cycles><meta:generator>LibreOfficeDev/7.5.0.0.alpha1$Linux_X86_64 LibreOffice_project/0c0fef37f8ea5528584324f72328f23b7fcc92d7</meta:generator><dc:title>Impress</dc:title><dc:date>2020-07-27T11:47:01.552127285</dc:date><meta:document-statistic meta:object-count="29"/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="Amiri" svg:font-family="Amiri" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <draw:gradient draw:name="Filled" draw:style="linear" draw:start-color="#ffffff" draw:end-color="#cccccc" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Filled_20_Blue" draw:display-name="Filled Blue" draw:style="linear" draw:start-color="#729fcf" draw:end-color="#355269" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Filled_20_Green" draw:display-name="Filled Green" draw:style="linear" draw:start-color="#77bc65" draw:end-color="#127622" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Filled_20_Red" draw:display-name="Filled Red" draw:style="linear" draw:start-color="#ff6d6d" draw:end-color="#c9211e" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Filled_20_Yellow" draw:display-name="Filled Yellow" draw:style="linear" draw:start-color="#ffde59" draw:end-color="#b47804" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="30deg" draw:border="0%"/>
+ <draw:gradient draw:name="Shapes" draw:style="rectangular" draw:cx="50%" draw:cy="50%" draw:start-color="#cccccc" draw:end-color="#ffffff" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="0deg" draw:border="0%"/>
+ <draw:marker draw:name="Arrow" svg:viewBox="0 0 20 30" svg:d="M10 0l-10 30h20z"/>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465af" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" style:writing-mode="lr-tb"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:punctuation-wrap="simple" style:line-break="strict" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:font-name="Liberation Sans" fo:font-size="24pt" fo:language="en" fo:country="GB" style:font-name-asian="Amiri" style:font-size-asian="24pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Amiri" style:font-size-complex="24pt" style:language-complex="ar" style:country-complex="SA"/>
+ </style:default-style>
+ <style:style style:name="standard" style:family="graphic">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-width="0cm" svg:stroke-color="#3465a4" draw:marker-start-width="0.2cm" draw:marker-start-center="false" draw:marker-end-width="0.2cm" draw:marker-end-center="false" draw:fill="solid" draw:fill-color="#729fcf" draw:textarea-horizontal-align="justify" fo:padding-top="0.125cm" fo:padding-bottom="0.125cm" fo:padding-left="0.25cm" fo:padding-right="0.25cm" draw:shadow="hidden" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080">
+ <text:list-style style:name="standard">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" fo:text-indent="0cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="18pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="default" style:family="table-cell">
+ <loext:graphic-properties draw:fill="solid" draw:fill-color="#ccccff" draw:textarea-horizontal-align="left" draw:textarea-vertical-align="top" fo:padding-top="0.13cm" fo:padding-bottom="0.13cm" fo:padding-left="0.25cm" fo:padding-right="0.25cm"/>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" fo:text-indent="0cm" fo:border="0.03pt solid #ffffff"/>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:font-name="DejaVu Sans" fo:font-family="'DejaVu Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="18pt" style:letter-kerning="true" style:font-name-asian="Amiri" style:font-family-asian="Amiri" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="18pt" style:font-name-complex="Amiri" style:font-family-complex="Amiri" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="18pt"/>
+ </style:style>
+ <style:style style:name="gray1" style:family="table-cell" style:parent-style-name="default">
+ <loext:graphic-properties draw:fill="solid" draw:fill-color="#e6e6e6"/>
+ </style:style>
+ <style:style style:name="gray2" style:family="table-cell" style:parent-style-name="default">
+ <loext:graphic-properties draw:fill="solid" draw:fill-color="#cccccc"/>
+ </style:style>
+ <style:style style:name="gray3" style:family="table-cell" style:parent-style-name="default">
+ <loext:graphic-properties draw:fill="solid" draw:fill-color="#b3b3b3"/>
+ </style:style>
+ <table:table-template table:name="default">
+ <table:first-row table:style-name="gray3"/>
+ <table:last-row table:style-name="gray3"/>
+ <table:first-column table:style-name="gray3"/>
+ <table:last-column table:style-name="gray3"/>
+ <table:body table:style-name="gray1"/>
+ <table:odd-rows table:style-name="gray2"/>
+ <table:odd-columns table:style-name="gray2"/>
+ </table:table-template>
+ <style:style style:name="Impress1-notes" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-left="0.6cm" fo:margin-right="0cm" fo:text-indent="0cm"/>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="20pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:presentation-page-layout style:name="AL0T26">
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="1.743cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="1.743cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="3.612cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="3.612cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="5.481cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="5.481cm" svg:width="10.556cm" svg:height="-0.231cm"/>
+ </style:presentation-page-layout>
+ <style:presentation-page-layout style:name="AL1T1">
+ <presentation:placeholder presentation:object="title" svg:x="2.058cm" svg:y="1.743cm" svg:width="23.912cm" svg:height="3.507cm"/>
+ <presentation:placeholder presentation:object="outline" svg:x="2.058cm" svg:y="5.838cm" svg:width="23.912cm" svg:height="13.23cm"/>
+ </style:presentation-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+ <style:page-layout style:name="PM0">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="21cm" fo:page-height="29.7cm" style:print-orientation="portrait"/>
+ </style:page-layout>
+ <style:page-layout style:name="PM1">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="28cm" fo:page-height="21cm" style:print-orientation="landscape"/>
+ </style:page-layout>
+ <style:style style:name="dp2" style:family="drawing-page">
+ <style:drawing-page-properties presentation:display-header="true" presentation:display-footer="true" presentation:display-page-number="false" presentation:display-date-time="true"/>
+ </style:style>
+ <style:style style:name="dp3" style:family="drawing-page">
+ <style:drawing-page-properties presentation:background-visible="true" presentation:background-objects-visible="true" presentation:display-footer="true" presentation:display-page-number="true" presentation:display-date-time="true"/>
+ </style:style>
+ <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="gr2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="bottom" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="gr3" style:family="graphic">
+ <style:graphic-properties style:protect="size"/>
+ </style:style>
+ <style:style style:name="pr5" style:family="presentation" style:parent-style-name="Impress1-notes">
+ <style:graphic-properties draw:fill-color="#ffffff" draw:auto-grow-height="true" fo:min-height="13.364cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="co1" style:family="table-column">
+ <style:table-column-properties style:column-width="6cm" style:use-optimal-column-width="false"/>
+ </style:style>
+ <style:style style:name="ro1" style:family="table-row">
+ <style:table-row-properties style:row-height="1.742cm" style:use-optimal-row-height="false"/>
+ </style:style>
+ <style:style style:name="P1" style:family="paragraph">
+ <style:text-properties fo:font-size="14pt"/>
+ </style:style>
+ <style:style style:name="P3" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="end"/>
+ <style:text-properties fo:font-size="14pt"/>
+ </style:style>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties fo:font-size="14pt"/>
+ </style:style>
+ <style:style style:name="T2" style:family="text">
+ <style:text-properties fo:font-size="18pt" style:font-size-asian="18pt" style:font-size-complex="18pt"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <draw:layer-set>
+ <draw:layer draw:name="layout"/>
+ <draw:layer draw:name="background"/>
+ <draw:layer draw:name="backgroundobjects"/>
+ <draw:layer draw:name="controls"/>
+ <draw:layer draw:name="measurelines"/>
+ </draw:layer-set>
+ <style:handout-master presentation:presentation-page-layout-name="AL0T26" style:page-layout-name="PM0" draw:style-name="dp2">
+ <draw:frame draw:style-name="gr1" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="0cm" svg:y="0cm" presentation:class="header">
+ <draw:text-box>
+ <text:p text:style-name="P1"><text:span text:style-name="T1"><presentation:header/></text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr1" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="11.886cm" svg:y="0cm" presentation:class="date-time">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:span text:style-name="T1"><presentation:date-time/></text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr2" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="0cm" svg:y="28.215cm" presentation:class="footer">
+ <draw:text-box>
+ <text:p text:style-name="P1"><text:span text:style-name="T1"><presentation:footer/></text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr2" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="11.886cm" svg:y="28.215cm" presentation:class="page-number">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:span text:style-name="T1"><text:page-number>&lt;number&gt;</text:page-number></text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="1cm" svg:y="2.898cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="1cm" svg:y="11.474cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="1cm" svg:y="20.05cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="11cm" svg:y="2.898cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="11cm" svg:y="11.474cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="11cm" svg:y="20.05cm"/>
+ </style:handout-master>
+ </office:master-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1" draw:style-name="dp3" draw:master-page-name="Impress1" presentation:presentation-page-layout-name="AL1T1">
+ <office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
+ <draw:frame draw:style-name="standard" draw:layer="layout" svg:width="17.999cm" svg:height="3.483cm" svg:x="2cm" svg:y="6cm" presentation:class="table" presentation:user-transformed="true">
+ <table:table table:template-name="default" table:use-first-row-styles="true" table:use-banding-rows-styles="true">
+ <table:table-column table:style-name="co1"/>
+ <table:table-column table:style-name="co1"/>
+ <table:table-column table:style-name="co1"/>
+ <table:table-row table:style-name="ro1" table:default-cell-style-name="gray3">
+ <table:table-cell/>
+ <table:table-cell>
+ <text:p><text:span text:style-name="T2">Average starting score</text:span></text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p><text:span text:style-name="T2">Average improved score</text:span></text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro1" table:default-cell-style-name="gray2">
+ <table:table-cell>
+ <text:p><text:span text:style-name="T2">Images</text:span></text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p><text:span text:style-name="T2">35%</text:span></text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p><text:span text:style-name="T2">91%</text:span></text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table>
+ </draw:frame>
+ <presentation:notes draw:style-name="dp2">
+ <draw:page-thumbnail draw:style-name="gr3" draw:layer="layout" svg:width="14.848cm" svg:height="11.136cm" svg:x="3.075cm" svg:y="2.257cm" draw:page-number="1" presentation:class="page"/>
+ <draw:frame presentation:style-name="pr5" draw:text-style-name="P5" draw:layer="layout" svg:width="16.799cm" svg:height="13.364cm" svg:x="2.1cm" svg:y="14.107cm" presentation:class="notes" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ </presentation:notes>
+ </draw:page>
+ <presentation:settings presentation:mouse-visible="false"/>
+ </office:presentation>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf135346.ods b/vcl/qa/cppunit/pdfexport/data/tdf135346.ods
new file mode 100644
index 000000000..5f696e550
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf135346.ods
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf139736-1.odt b/vcl/qa/cppunit/pdfexport/data/tdf139736-1.odt
new file mode 100644
index 000000000..f17f60378
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf139736-1.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf141171.odt b/vcl/qa/cppunit/pdfexport/data/tdf141171.odt
new file mode 100644
index 000000000..951f69541
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf141171.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf144222.ods b/vcl/qa/cppunit/pdfexport/data/tdf144222.ods
new file mode 100644
index 000000000..7b572d301
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf144222.ods
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf145274.docx b/vcl/qa/cppunit/pdfexport/data/tdf145274.docx
new file mode 100644
index 000000000..5b3b6afec
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf145274.docx
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf145873.pptx b/vcl/qa/cppunit/pdfexport/data/tdf145873.pptx
new file mode 100644
index 000000000..8a5eaa838
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf145873.pptx
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf147027.ods b/vcl/qa/cppunit/pdfexport/data/tdf147027.ods
new file mode 100644
index 000000000..24e1fde9a
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf147027.ods
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf147164.odp b/vcl/qa/cppunit/pdfexport/data/tdf147164.odp
new file mode 100644
index 000000000..1b593348e
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf147164.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf148442.odt b/vcl/qa/cppunit/pdfexport/data/tdf148442.odt
new file mode 100644
index 000000000..819595df2
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf148442.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf148706.odt b/vcl/qa/cppunit/pdfexport/data/tdf148706.odt
new file mode 100644
index 000000000..974bb9743
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf148706.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf66597-1.odt b/vcl/qa/cppunit/pdfexport/data/tdf66597-1.odt
new file mode 100644
index 000000000..e5cc9bc0b
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf66597-1.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf66597-2.odt b/vcl/qa/cppunit/pdfexport/data/tdf66597-2.odt
new file mode 100644
index 000000000..3d7b5e59c
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf66597-2.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf66597-3.odt b/vcl/qa/cppunit/pdfexport/data/tdf66597-3.odt
new file mode 100644
index 000000000..6db91fe81
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf66597-3.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf84283.doc b/vcl/qa/cppunit/pdfexport/data/tdf84283.doc
new file mode 100644
index 000000000..dc48cfaae
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf84283.doc
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf99680-2.odt b/vcl/qa/cppunit/pdfexport/data/tdf99680-2.odt
new file mode 100644
index 000000000..47c370004
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf99680-2.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf99680.odt b/vcl/qa/cppunit/pdfexport/data/tdf99680.odt
new file mode 100644
index 000000000..de12f9baa
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf99680.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/toc-link.fodt b/vcl/qa/cppunit/pdfexport/data/toc-link.fodt
new file mode 100644
index 000000000..ab29e88a4
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/toc-link.fodt
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"/>
+ <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:default-outline-level="1" style:class="text">
+ <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm"/>
+ </style:style>
+ <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"/>
+ <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index">
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"/>
+ </style:style>
+ <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="Sect1" style:family="section"/>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm"/>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:table-of-content text:style-name="Sect1" text:protected="true" text:name="Table of Contents">
+ <text:table-of-content-source text:outline-level="10">
+ <text:index-title-template text:style-name="Contents_20_Heading">Table of Contents</text:index-title-template>
+ <text:table-of-content-entry-template text:outline-level="1" text:style-name="Contents_20_1">
+ <text:index-entry-link-start/>
+ <text:index-entry-text/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ </text:table-of-content-source>
+ <text:index-body>
+ <text:index-title text:style-name="Sect1" text:name="Table of Contents_Head">
+ <text:p text:style-name="Contents_20_Heading">Table of Contents</text:p>
+ </text:index-title>
+ <text:p text:style-name="Contents_20_1"><text:a xlink:type="simple" xlink:href="#__RefHeading_Toc">Heading 1<text:tab/>1</text:a></text:p>
+ </text:index-body>
+ </text:table-of-content>
+ <text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="__RefHeading_Toc"/>Heading 1<text:bookmark-end text:name="__RefHeading_Toc"/></text:h>
+ </office:text>
+ </office:body>
+</office:document>
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
new file mode 100644
index 000000000..0d67999b2
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -0,0 +1,3990 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+#include <string_view>
+#include <type_traits>
+
+#include <config_features.h>
+#include <config_fonts.h>
+
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/view/XPrintable.hpp>
+#include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+#include <comphelper/scopeguard.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <unotools/tempfile.hxx>
+#include <vcl/filter/pdfdocument.hxx>
+#include <tools/zcodec.hxx>
+#include <tools/XmlWalker.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <unotools/streamwrap.hxx>
+#include <rtl/math.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <vcl/filter/PDFiumLibrary.hxx>
+#include <comphelper/propertyvalue.hxx>
+
+using namespace ::com::sun::star;
+
+static std::ostream& operator<<(std::ostream& rStrm, const Color& rColor)
+{
+ rStrm << "Color: R:" << static_cast<int>(rColor.GetRed())
+ << " G:" << static_cast<int>(rColor.GetGreen())
+ << " B:" << static_cast<int>(rColor.GetBlue())
+ << " A:" << static_cast<int>(255 - rColor.GetAlpha());
+ return rStrm;
+}
+
+namespace
+{
+/// Tests the PDF export filter.
+class PdfExportTest : public test::BootstrapFixture, public unotest::MacrosTest
+{
+protected:
+ uno::Reference<lang::XComponent> mxComponent;
+ utl::TempFile maTempFile;
+ SvMemoryStream maMemory;
+ utl::MediaDescriptor aMediaDescriptor;
+ std::unique_ptr<vcl::pdf::PDFiumDocument> parseExport(const OString& rPassword = OString());
+ std::shared_ptr<vcl::pdf::PDFium> mpPDFium;
+
+public:
+ PdfExportTest();
+ virtual void setUp() override;
+ virtual void tearDown() override;
+ void saveAsPDF(std::u16string_view rFile);
+ void load(std::u16string_view rFile, vcl::filter::PDFDocument& rDocument);
+};
+
+PdfExportTest::PdfExportTest() { maTempFile.EnableKillingFile(); }
+
+std::unique_ptr<vcl::pdf::PDFiumDocument> PdfExportTest::parseExport(const OString& rPassword)
+{
+ SvFileStream aFile(maTempFile.GetURL(), StreamMode::READ);
+ maMemory.WriteStream(aFile);
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPDFium->openDocument(maMemory.GetData(), maMemory.GetSize(), rPassword);
+ CPPUNIT_ASSERT(pPdfDocument);
+ return pPdfDocument;
+}
+
+void PdfExportTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+
+ mpPDFium = vcl::pdf::PDFiumLibrary::get();
+}
+
+void PdfExportTest::tearDown()
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+
+ test::BootstrapFixture::tearDown();
+}
+
+constexpr OUStringLiteral DATA_DIRECTORY = u"/vcl/qa/cppunit/pdfexport/data/";
+
+void PdfExportTest::saveAsPDF(std::u16string_view rFile)
+{
+ // Import the bugdoc and export as PDF.
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + rFile;
+ mxComponent = loadFromDesktop(aURL);
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+}
+
+void PdfExportTest::load(std::u16string_view rFile, vcl::filter::PDFDocument& rDocument)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(rFile);
+
+ // Parse the export result.
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(rDocument.Read(aStream));
+}
+
+/// Tests that a pdf image is roundtripped back to PDF as a vector format.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106059)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ // Explicitly enable the usage of the reference XObject markup.
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "UseReferenceXObject", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"tdf106059.odt");
+
+ // Parse the export result.
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // Assert that the XObject in the page resources dictionary is a reference XObject.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ // The page has one image.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pReferenceXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pReferenceXObject);
+ // The image is a reference XObject.
+ // This dictionary key was missing, so the XObject wasn't a reference one.
+ CPPUNIT_ASSERT(pReferenceXObject->Lookup("Ref"));
+}
+
+/// Tests export of PDF images without reference XObjects.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106693)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf106693.odt", aDocument);
+
+ // Assert that the XObject in the page resources dictionary is a form XObject.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ // The page has one image.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+ // The image is a form XObject.
+ auto pSubtype = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype->GetValue());
+ // This failed: UseReferenceXObject was ignored and Ref was always created.
+ CPPUNIT_ASSERT(!pXObject->Lookup("Ref"));
+
+ // Assert that the form object refers to an inner form object, not a
+ // bitmap.
+ auto pInnerResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject->Lookup("Resources"));
+ CPPUNIT_ASSERT(pInnerResources);
+ auto pInnerXObjects = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pInnerResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pInnerXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pInnerXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pInnerXObject
+ = pInnerXObjects->LookupObject(pInnerXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pInnerXObject);
+ auto pInnerSubtype
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pInnerXObject->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pInnerSubtype);
+ // This failed: this was Image (bitmap), not Form (vector).
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pInnerSubtype->GetValue());
+}
+
+/// Tests that text highlight from Impress is not lost.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf105461)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf105461.odp");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Make sure there is a filled rectangle inside.
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ int nYellowPathCount = 0;
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPdfPageObject = pPdfPage->getObject(i);
+ if (pPdfPageObject->getType() != vcl::pdf::PDFPageObjectType::Path)
+ continue;
+
+ if (pPdfPageObject->getFillColor() == COL_YELLOW)
+ ++nYellowPathCount;
+ }
+
+ // This was 0, the page contained no yellow paths.
+ CPPUNIT_ASSERT_EQUAL(1, nYellowPathCount);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf107868)
+{
+// No need to run it on Windows, since it would use GDI printing, and not trigger PDF export
+// which is the intent of the test.
+// FIXME: Why does this fail on macOS?
+#if !defined MACOSX && !defined _WIN32
+
+ // Import the bugdoc and print to PDF.
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf107868.odt";
+ mxComponent = loadFromDesktop(aURL);
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ uno::Reference<view::XPrintable> xPrintable(mxComponent, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPrintable.is());
+ uno::Sequence<beans::PropertyValue> aOptions(comphelper::InitPropertySequence(
+ { { "FileName", uno::Any(maTempFile.GetURL()) }, { "Wait", uno::Any(true) } }));
+ xPrintable->print(aOptions);
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ if (!pPdfDocument)
+ // Printing to PDF failed in a non-interesting way, e.g. CUPS is not
+ // running, there is no printer defined, etc.
+ return;
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Make sure there is no filled rectangle inside.
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ int nWhitePathCount = 0;
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPdfPageObject = pPdfPage->getObject(i);
+ if (pPdfPageObject->getType() != vcl::pdf::PDFPageObjectType::Path)
+ continue;
+
+ if (pPdfPageObject->getFillColor() == COL_WHITE)
+ ++nWhitePathCount;
+ }
+
+ // This was 4, the page contained 4 white paths at problematic positions.
+ CPPUNIT_ASSERT_EQUAL(0, nWhitePathCount);
+#endif
+}
+
+/// Tests that embedded video from Impress is not exported as a linked one.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf105093)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf105093.odp", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // Get page annotations.
+ auto pAnnots = dynamic_cast<vcl::filter::PDFArrayElement*>(aPages[0]->Lookup("Annots"));
+ CPPUNIT_ASSERT(pAnnots);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pAnnots->GetElements().size());
+ auto pAnnotReference
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pAnnots->GetElements()[0]);
+ CPPUNIT_ASSERT(pAnnotReference);
+ vcl::filter::PDFObjectElement* pAnnot = pAnnotReference->LookupObject();
+ CPPUNIT_ASSERT(pAnnot);
+ CPPUNIT_ASSERT_EQUAL(
+ OString("Annot"),
+ static_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"))->GetValue());
+
+ // Get the Action -> Rendition -> MediaClip -> FileSpec.
+ auto pAction = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pAnnot->Lookup("A"));
+ CPPUNIT_ASSERT(pAction);
+ auto pRendition = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pAction->LookupElement("R"));
+ CPPUNIT_ASSERT(pRendition);
+ auto pMediaClip
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pRendition->LookupElement("C"));
+ CPPUNIT_ASSERT(pMediaClip);
+ auto pFileSpec
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pMediaClip->LookupElement("D"));
+ CPPUNIT_ASSERT(pFileSpec);
+ // Make sure the filespec refers to an embedded file.
+ // This key was missing, the embedded video was handled as a linked one.
+ CPPUNIT_ASSERT(pFileSpec->LookupElement("EF"));
+}
+
+/// Tests export of non-PDF images.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106206)
+{
+ // Import the bugdoc and export as PDF.
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf106206.odt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // The page has a stream.
+ vcl::filter::PDFObjectElement* pContents = aPages[0]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ // Uncompress it.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ // Make sure there is an image reference there.
+ OString aImage("/Im");
+ auto pStart = static_cast<const char*>(aUncompressed.GetData());
+ const char* pEnd = pStart + aUncompressed.GetSize();
+ auto it = std::search(pStart, pEnd, aImage.getStr(), aImage.getStr() + aImage.getLength());
+ CPPUNIT_ASSERT(it != pEnd);
+
+ // And also that it's not an invalid one.
+ OString aInvalidImage("/Im0");
+ it = std::search(pStart, pEnd, aInvalidImage.getStr(),
+ aInvalidImage.getStr() + aInvalidImage.getLength());
+ // This failed, object #0 was referenced.
+ CPPUNIT_ASSERT(bool(it == pEnd));
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf127217)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf127217.odt");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // The page has one annotation.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount());
+ std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnot = pPdfPage->getAnnotation(0);
+
+ // Without the fix in place, this test would have failed here
+ CPPUNIT_ASSERT(!pAnnot->hasKey("DA"));
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf109143)
+{
+ // Import the bugdoc and export as PDF.
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf109143.odt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // Get access to the only image on the only page.
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+
+ // Make sure it's re-compressed.
+ auto pLength = dynamic_cast<vcl::filter::PDFNumberElement*>(pXObject->Lookup("Length"));
+ CPPUNIT_ASSERT(pLength);
+ int nLength = pLength->GetValue();
+ // This failed: cropped TIFF-in-JPEG wasn't re-compressed, so crop was
+ // lost. Size was 59416, now is 11827.
+ CPPUNIT_ASSERT(nLength < 50000);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106972)
+{
+ // Import the bugdoc and export as PDF.
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf106972.odt", aDocument);
+
+ // Get access to the only form object on the only page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+
+ // Get access to the only image inside the form object.
+ auto pFormResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject->Lookup("Resources"));
+ CPPUNIT_ASSERT(pFormResources);
+ auto pImages = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pFormResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pImages);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pImages->GetItems().size());
+ vcl::filter::PDFObjectElement* pImage
+ = pImages->LookupObject(pImages->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pImage);
+
+ // Assert resources of the image.
+ auto pImageResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pImage->Lookup("Resources"));
+ CPPUNIT_ASSERT(pImageResources);
+ // This failed: the PDF image had no Font resource.
+ CPPUNIT_ASSERT(pImageResources->LookupElement("Font"));
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106972Pdf17)
+{
+ // Import the bugdoc and export as PDF.
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf106972-pdf17.odt", aDocument);
+
+ // Get access to the only image on the only page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+
+ // Assert that we now attempt to preserve the original PDF data, even if
+ // the original input was PDF >= 1.4.
+ CPPUNIT_ASSERT(pXObject->Lookup("Resources"));
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testSofthyphenPos)
+{
+// No need to run it on Windows, since it would use GDI printing, and not trigger PDF export
+// which is the intent of the test.
+// FIXME: Why does this fail on macOS?
+#if !defined MACOSX && !defined _WIN32
+
+ // Import the bugdoc and print to PDF.
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "softhyphen_pdf.odt";
+ mxComponent = loadFromDesktop(aURL);
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ uno::Reference<view::XPrintable> xPrintable(mxComponent, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPrintable.is());
+ uno::Sequence<beans::PropertyValue> aOptions(comphelper::InitPropertySequence(
+ { { "FileName", uno::Any(maTempFile.GetURL()) }, { "Wait", uno::Any(true) } }));
+ xPrintable->print(aOptions);
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ if (!pPdfDocument)
+ // Printing to PDF failed in a non-interesting way, e.g. CUPS is not
+ // running, there is no printer defined, etc.
+ return;
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // tdf#96892 incorrect fractional part of font size caused soft-hyphen to
+ // be positioned inside preceding text (incorrect = 11.1, correct = 11.05)
+
+ // there are 3 texts currently, for line 1, soft-hyphen, line 2
+ bool haveText(false);
+
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPdfPageObject = pPdfPage->getObject(i);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Text, pPdfPageObject->getType());
+ haveText = true;
+ double const size = pPdfPageObject->getFontSize();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(11.05, size, 1E-06);
+ }
+
+ CPPUNIT_ASSERT(haveText);
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf107013)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf107013.odt", aDocument);
+
+ // Get access to the only image on the only page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ // This failed, the reference to the image was created, but not the image.
+ CPPUNIT_ASSERT(pXObject);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf107018)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf107018.odt", aDocument);
+
+ // Get access to the only image on the only page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+
+ // Get access to the form object inside the image.
+ auto pXObjectResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject->Lookup("Resources"));
+ CPPUNIT_ASSERT(pXObjectResources);
+ auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pXObjectResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pXObjectForms);
+ vcl::filter::PDFObjectElement* pForm
+ = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pForm);
+
+ // Get access to Resources -> Font -> F1 of the form.
+ auto pFormResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pForm->Lookup("Resources"));
+ CPPUNIT_ASSERT(pFormResources);
+ auto pFonts
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pFormResources->LookupElement("Font"));
+ CPPUNIT_ASSERT(pFonts);
+ auto pF1Ref = dynamic_cast<vcl::filter::PDFReferenceElement*>(pFonts->LookupElement("F1"));
+ CPPUNIT_ASSERT(pF1Ref);
+ vcl::filter::PDFObjectElement* pF1 = pF1Ref->LookupObject();
+ CPPUNIT_ASSERT(pF1);
+
+ // Check that Foo -> Bar of the font is of type Pages.
+ auto pFontFoo = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pF1->Lookup("Foo"));
+ CPPUNIT_ASSERT(pFontFoo);
+ auto pBar = dynamic_cast<vcl::filter::PDFReferenceElement*>(pFontFoo->LookupElement("Bar"));
+ CPPUNIT_ASSERT(pBar);
+ vcl::filter::PDFObjectElement* pObject = pBar->LookupObject();
+ CPPUNIT_ASSERT(pObject);
+ auto pName = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ CPPUNIT_ASSERT(pName);
+ // This was "XObject", reference in a nested dictionary wasn't updated when
+ // copying the page stream of a PDF image.
+ CPPUNIT_ASSERT_EQUAL(OString("Pages"), pName->GetValue());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf148706)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf148706.odt");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // The page has one annotation.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount());
+ std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnot = pPdfPage->getAnnotation(0);
+
+ CPPUNIT_ASSERT(pAnnot->hasKey("V"));
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFObjectType::String, pAnnot->getValueType("V"));
+ OUString aV = pAnnot->getString("V");
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 1821.84
+ // - Actual :
+ CPPUNIT_ASSERT_EQUAL(OUString("1821.84"), aV);
+
+ CPPUNIT_ASSERT(pAnnot->hasKey("DV"));
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFObjectType::String, pAnnot->getValueType("DV"));
+ OUString aDV = pAnnot->getString("DV");
+
+ CPPUNIT_ASSERT_EQUAL(OUString("1821.84"), aDV);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf107089)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf107089.odt", aDocument);
+
+ // Get access to the only image on the only page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+
+ // Get access to the form object inside the image.
+ auto pXObjectResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject->Lookup("Resources"));
+ CPPUNIT_ASSERT(pXObjectResources);
+ auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pXObjectResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pXObjectForms);
+ vcl::filter::PDFObjectElement* pForm
+ = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pForm);
+
+ // Make sure 'Hello' is part of the form object's stream.
+ vcl::filter::PDFStreamElement* pStream = pForm->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream aObjectStream;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ pStream->GetMemory().Seek(0);
+ aZCodec.Decompress(pStream->GetMemory(), aObjectStream);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+ aObjectStream.Seek(0);
+ OString aHello("Hello");
+ auto pStart = static_cast<const char*>(aObjectStream.GetData());
+ const char* pEnd = pStart + aObjectStream.GetSize();
+ auto it = std::search(pStart, pEnd, aHello.getStr(), aHello.getStr() + aHello.getLength());
+ // This failed, 'Hello' was part only a mixed compressed/uncompressed stream, i.e. garbage.
+ CPPUNIT_ASSERT(it != pEnd);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf99680)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf99680.odt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // The page 1 has a stream.
+ vcl::filter::PDFObjectElement* pContents = aPages[0]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+
+ // Uncompress it.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ // tdf#130150 See infos in task - short: tdf#99680 was not the
+ // correct fix, so empty clip regions are valid - allow again in tests
+ // Make sure there are no empty clipping regions.
+ // OString aEmptyRegion("0 0 m h W* n");
+ // auto it = std::search(pStart, pEnd, aEmptyRegion.getStr(), aEmptyRegion.getStr() + aEmptyRegion.getLength());
+ // CPPUNIT_ASSERT_EQUAL_MESSAGE("Empty clipping region detected!", it, pEnd);
+
+ // Count save graphic state (q) and restore (Q) operators
+ // and ensure their amount is equal
+ auto pStart = static_cast<const char*>(aUncompressed.GetData());
+ const char* pEnd = pStart + aUncompressed.GetSize();
+ size_t nSaveCount = std::count(pStart, pEnd, 'q');
+ size_t nRestoreCount = std::count(pStart, pEnd, 'Q');
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Save/restore graphic state operators count mismatch!", nSaveCount,
+ nRestoreCount);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf99680_2)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf99680-2.odt", aDocument);
+
+ // For each document page
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aPages.size());
+ for (size_t nPageNr = 0; nPageNr < aPages.size(); nPageNr++)
+ {
+ // Get page contents and stream.
+ vcl::filter::PDFObjectElement* pContents = aPages[nPageNr]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+
+ // Uncompress the stream.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ // tdf#130150 See infos in task - short: tdf#99680 was not the
+ // correct fix, so empty clip regions are valid - allow again in tests
+ // Make sure there are no empty clipping regions.
+ // OString aEmptyRegion("0 0 m h W* n");
+ // auto it = std::search(pStart, pEnd, aEmptyRegion.getStr(), aEmptyRegion.getStr() + aEmptyRegion.getLength());
+ // CPPUNIT_ASSERT_EQUAL_MESSAGE("Empty clipping region detected!", it, pEnd);
+
+ // Count save graphic state (q) and restore (Q) operators
+ // and ensure their amount is equal
+ auto pStart = static_cast<const char*>(aUncompressed.GetData());
+ const char* pEnd = pStart + aUncompressed.GetSize();
+ size_t nSaveCount = std::count(pStart, pEnd, 'q');
+ size_t nRestoreCount = std::count(pStart, pEnd, 'Q');
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Save/restore graphic state operators count mismatch!",
+ nSaveCount, nRestoreCount);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf108963)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf108963.odp");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Test page size (28x15.75 cm, was 1/100th mm off, tdf#112690)
+ // bad: MediaBox[0 0 793.672440944882 446.428346456693]
+ // good: MediaBox[0 0 793.700787401575 446.456692913386]
+ const double aWidth = pPdfPage->getWidth();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(793.7, aWidth, 0.01);
+ const double aHeight = pPdfPage->getHeight();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(446.46, aHeight, 0.01);
+
+ // Make sure there is a filled rectangle inside.
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ int nYellowPathCount = 0;
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPdfPageObject = pPdfPage->getObject(i);
+ if (pPdfPageObject->getType() != vcl::pdf::PDFPageObjectType::Path)
+ continue;
+
+ if (pPdfPageObject->getFillColor() == COL_YELLOW)
+ {
+ ++nYellowPathCount;
+ // The path described a yellow rectangle, but it was not rotated.
+ int nSegments = pPdfPageObject->getPathSegmentCount();
+ CPPUNIT_ASSERT_EQUAL(5, nSegments);
+ std::unique_ptr<vcl::pdf::PDFiumPathSegment> pSegment
+ = pPdfPageObject->getPathSegment(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Moveto, pSegment->getType());
+ basegfx::B2DPoint aPoint = pSegment->getPoint();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(245.395, aPoint.getX(), 0.0005);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(244.261, aPoint.getY(), 0.0005);
+ CPPUNIT_ASSERT(!pSegment->isClosed());
+
+ pSegment = pPdfPageObject->getPathSegment(1);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Lineto, pSegment->getType());
+ aPoint = pSegment->getPoint();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(275.102, aPoint.getX(), 0.0005);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(267.618, aPoint.getY(), 0.0005);
+ CPPUNIT_ASSERT(!pSegment->isClosed());
+
+ pSegment = pPdfPageObject->getPathSegment(2);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Lineto, pSegment->getType());
+ aPoint = pSegment->getPoint();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(287.518, aPoint.getX(), 0.0005);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(251.829, aPoint.getY(), 0.0005);
+ CPPUNIT_ASSERT(!pSegment->isClosed());
+
+ pSegment = pPdfPageObject->getPathSegment(3);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Lineto, pSegment->getType());
+ aPoint = pSegment->getPoint();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(257.839, aPoint.getX(), 0.0005);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(228.472, aPoint.getY(), 0.0005);
+ CPPUNIT_ASSERT(!pSegment->isClosed());
+
+ pSegment = pPdfPageObject->getPathSegment(4);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Lineto, pSegment->getType());
+ aPoint = pSegment->getPoint();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(245.395, aPoint.getX(), 0.0005);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(244.261, aPoint.getY(), 0.0005);
+ CPPUNIT_ASSERT(pSegment->isClosed());
+ }
+ }
+
+ CPPUNIT_ASSERT_EQUAL(1, nYellowPathCount);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testAlternativeText)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export");
+
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "UseTaggedPDF", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"alternativeText.fodp");
+
+ // Parse the export result.
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "StructElem")
+ {
+ auto pS = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"));
+ if (pS && pS->GetValue() == "Figure")
+ {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"This is the text alternative - This is the description"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pObject->Lookup("Alt"))));
+ }
+ }
+ }
+
+ // tdf#67866 check that Catalog contains Lang
+ auto* pCatalog = aDocument.GetCatalog();
+ CPPUNIT_ASSERT(pCatalog);
+ auto* pCatalogDictionary = pCatalog->GetDictionary();
+ CPPUNIT_ASSERT(pCatalogDictionary);
+ auto pLang = dynamic_cast<vcl::filter::PDFLiteralStringElement*>(
+ pCatalogDictionary->LookupElement("Lang"));
+ CPPUNIT_ASSERT(pLang);
+ CPPUNIT_ASSERT_EQUAL(OString("en-US"), pLang->GetValue());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf105972)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf105972.fodt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ auto pAnnots = dynamic_cast<vcl::filter::PDFArrayElement*>(aPages[0]->Lookup("Annots"));
+ CPPUNIT_ASSERT(pAnnots);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pAnnots->GetElements().size());
+
+ sal_uInt32 nTextFieldCount = 0;
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("FT"));
+ if (pType && pType->GetValue() == "Tx")
+ {
+ ++nTextFieldCount;
+
+ auto pT = dynamic_cast<vcl::filter::PDFLiteralStringElement*>(pObject->Lookup("T"));
+ CPPUNIT_ASSERT(pT);
+ auto pAA = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pObject->Lookup("AA"));
+ CPPUNIT_ASSERT(pAA);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pAA->GetItems().size());
+ auto pF = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pAA->LookupElement("F"));
+ CPPUNIT_ASSERT(pF);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pF->GetItems().size());
+
+ if (nTextFieldCount == 1)
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("CurrencyField"), pT->GetValue());
+
+ auto pJS
+ = dynamic_cast<vcl::filter::PDFLiteralStringElement*>(pF->LookupElement("JS"));
+ CPPUNIT_ASSERT_EQUAL(
+ OString("AFNumber_Format\\(4, 0, 0, 0, \"\\\\u20ac\",true\\);"),
+ pJS->GetValue());
+ }
+ else if (nTextFieldCount == 2)
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("TimeField"), pT->GetValue());
+
+ auto pJS
+ = dynamic_cast<vcl::filter::PDFLiteralStringElement*>(pF->LookupElement("JS"));
+ CPPUNIT_ASSERT_EQUAL(OString("AFTime_FormatEx\\(\"h:MM:sstt\"\\);"),
+ pJS->GetValue());
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("DateField"), pT->GetValue());
+
+ auto pJS
+ = dynamic_cast<vcl::filter::PDFLiteralStringElement*>(pF->LookupElement("JS"));
+ CPPUNIT_ASSERT_EQUAL(OString("AFDate_FormatEx\\(\"yy-mm-dd\"\\);"),
+ pJS->GetValue());
+ }
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf148442)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf148442.odt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ auto pAnnots = dynamic_cast<vcl::filter::PDFArrayElement*>(aPages[0]->Lookup("Annots"));
+ CPPUNIT_ASSERT(pAnnots);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pAnnots->GetElements().size());
+
+ sal_uInt32 nBtnCount = 0;
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("FT"));
+ if (pType && pType->GetValue() == "Btn")
+ {
+ ++nBtnCount;
+ auto pT = dynamic_cast<vcl::filter::PDFLiteralStringElement*>(pObject->Lookup("T"));
+ CPPUNIT_ASSERT(pT);
+ auto pAS = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("AS"));
+ CPPUNIT_ASSERT(pAS);
+
+ auto pAP = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pObject->Lookup("AP"));
+ CPPUNIT_ASSERT(pAP);
+ auto pN = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pAP->LookupElement("N"));
+ CPPUNIT_ASSERT(pN);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pN->GetItems().size());
+
+ if (nBtnCount == 1)
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("Checkbox1"), pT->GetValue());
+ CPPUNIT_ASSERT_EQUAL(OString("Yes"), pAS->GetValue());
+ CPPUNIT_ASSERT(!pN->GetItems().count("ref"));
+ CPPUNIT_ASSERT(pN->GetItems().count("Yes"));
+ CPPUNIT_ASSERT(pN->GetItems().count("Off"));
+ }
+ else if (nBtnCount == 2)
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("Checkbox2"), pT->GetValue());
+ CPPUNIT_ASSERT_EQUAL(OString("Yes"), pAS->GetValue());
+
+ // Without the fix in place, this test would have failed here
+ CPPUNIT_ASSERT(pN->GetItems().count("ref"));
+ CPPUNIT_ASSERT(!pN->GetItems().count("Yes"));
+ CPPUNIT_ASSERT(pN->GetItems().count("Off"));
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("Checkbox3"), pT->GetValue());
+ CPPUNIT_ASSERT_EQUAL(OString("Off"), pAS->GetValue());
+ CPPUNIT_ASSERT(pN->GetItems().count("ref"));
+ CPPUNIT_ASSERT(!pN->GetItems().count("Yes"));
+
+ // tdf#143612: Without the fix in place, this test would have failed here
+ CPPUNIT_ASSERT(!pN->GetItems().count("Off"));
+ CPPUNIT_ASSERT(pN->GetItems().count("refOff"));
+ }
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf118244_radioButtonGroup)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf118244_radioButtonGroup.odt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // There are eight radio buttons.
+ auto pAnnots = dynamic_cast<vcl::filter::PDFArrayElement*>(aPages[0]->Lookup("Annots"));
+ CPPUNIT_ASSERT(pAnnots);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("# of radio buttons", static_cast<size_t>(8),
+ pAnnots->GetElements().size());
+
+ sal_uInt32 nRadioGroups = 0;
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("FT"));
+ if (pType && pType->GetValue() == "Btn")
+ {
+ auto pKids = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject->Lookup("Kids"));
+ if (pKids)
+ {
+ size_t expectedSize = 2;
+ ++nRadioGroups;
+ if (nRadioGroups == 3)
+ expectedSize = 3;
+ CPPUNIT_ASSERT_EQUAL(expectedSize, pKids->GetElements().size());
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("# of radio groups", sal_uInt32(3), nRadioGroups);
+}
+
+/// Test writing ToUnicode CMAP for LTR ligatures.
+// This requires Carlito font, if it is missing the test will most likely
+// fail.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115117_1)
+{
+#if HAVE_MORE_FONTS
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf115117-1.odt", aDocument);
+
+ vcl::filter::PDFObjectElement* pToUnicode = nullptr;
+
+ // Get access to ToUnicode of the first font
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "Font")
+ {
+ auto pToUnicodeRef
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject->Lookup("ToUnicode"));
+ CPPUNIT_ASSERT(pToUnicodeRef);
+ pToUnicode = pToUnicodeRef->LookupObject();
+ break;
+ }
+ }
+
+ CPPUNIT_ASSERT(pToUnicode);
+ auto pStream = pToUnicode->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream aObjectStream;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ pStream->GetMemory().Seek(0);
+ aZCodec.Decompress(pStream->GetMemory(), aObjectStream);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+ aObjectStream.Seek(0);
+ // The first values, <01> <02> etc., are glyph ids, they might change order
+ // if we changed how font subsets are created.
+ // The second values, <00740069> etc., are Unicode code points in hex,
+ // <00740069> is U+0074 and U+0069 i.e. "ti" which is a ligature in
+ // Carlito/Calibri. This test is failing if any of the second values
+ // changed which means we are not detecting ligatures and writing CMAP
+ // entries for them correctly. If glyph order in the subset changes then
+ // the order here will changes and the PDF has to be carefully inspected to
+ // ensure that the new values are correct before updating the string below.
+ OString aCmap("9 beginbfchar\n"
+ "<01> <00740069>\n"
+ "<02> <0020>\n"
+ "<03> <0074>\n"
+ "<04> <0065>\n"
+ "<05> <0073>\n"
+ "<06> <00660069>\n"
+ "<07> <0066006C>\n"
+ "<08> <006600660069>\n"
+ "<09> <00660066006C>\n"
+ "endbfchar");
+ auto pStart = static_cast<const char*>(aObjectStream.GetData());
+ const char* pEnd = pStart + aObjectStream.GetSize();
+ auto it = std::search(pStart, pEnd, aCmap.getStr(), aCmap.getStr() + aCmap.getLength());
+ CPPUNIT_ASSERT(it != pEnd);
+#endif
+}
+
+/// Test writing ToUnicode CMAP for RTL ligatures.
+// This requires DejaVu Sans font, if it is missing the test will most likely
+// fail.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115117_2)
+{
+#if HAVE_MORE_FONTS
+ // See the comments in testTdf115117_1() for explanation.
+
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf115117-2.odt", aDocument);
+
+ vcl::filter::PDFObjectElement* pToUnicode = nullptr;
+
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "Font")
+ {
+ auto pToUnicodeRef
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject->Lookup("ToUnicode"));
+ CPPUNIT_ASSERT(pToUnicodeRef);
+ pToUnicode = pToUnicodeRef->LookupObject();
+ break;
+ }
+ }
+
+ CPPUNIT_ASSERT(pToUnicode);
+ auto pStream = pToUnicode->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream aObjectStream;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ pStream->GetMemory().Seek(0);
+ aZCodec.Decompress(pStream->GetMemory(), aObjectStream);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+ aObjectStream.Seek(0);
+ OString aCmap("7 beginbfchar\n"
+ "<01> <06440627>\n"
+ "<02> <0020>\n"
+ "<03> <0641>\n"
+ "<04> <0642>\n"
+ "<05> <0648>\n"
+ "<06> <06440627>\n"
+ "<07> <0628>\n"
+ "endbfchar");
+ auto pStart = static_cast<const char*>(aObjectStream.GetData());
+ const char* pEnd = pStart + aObjectStream.GetSize();
+ auto it = std::search(pStart, pEnd, aCmap.getStr(), aCmap.getStr() + aCmap.getLength());
+ CPPUNIT_ASSERT(it != pEnd);
+#endif
+}
+
+/// Text extracting LTR text with ligatures.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115117_1a)
+{
+#if HAVE_MORE_FONTS
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf115117-1.odt");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ std::unique_ptr<vcl::pdf::PDFiumTextPage> pPdfTextPage = pPdfPage->getTextPage();
+ CPPUNIT_ASSERT(pPdfTextPage);
+
+ // Extract the text from the page. This pdfium API is a bit higher level
+ // than we want and might apply heuristic that give false positive, but it
+ // is a good approximation in addition to the check in testTdf115117_1().
+ int nChars = pPdfTextPage->countChars();
+ CPPUNIT_ASSERT_EQUAL(44, nChars);
+
+ std::vector<sal_uInt32> aChars(nChars);
+ for (int i = 0; i < nChars; i++)
+ aChars[i] = pPdfTextPage->getUnicode(i);
+ OUString aActualText(aChars.data(), aChars.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("ti ti test ti\r\nti test fi fl ffi ffl test fi"), aActualText);
+#endif
+}
+
+/// Test extracting RTL text with ligatures.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115117_2a)
+{
+#if HAVE_MORE_FONTS
+ // See the comments in testTdf115117_1a() for explanation.
+
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf115117-2.odt");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ std::unique_ptr<vcl::pdf::PDFiumTextPage> pPdfTextPage = pPdfPage->getTextPage();
+ CPPUNIT_ASSERT(pPdfTextPage);
+
+ int nChars = pPdfTextPage->countChars();
+ CPPUNIT_ASSERT_EQUAL(13, nChars);
+
+ std::vector<sal_uInt32> aChars(nChars);
+ for (int i = 0; i < nChars; i++)
+ aChars[i] = pPdfTextPage->getUnicode(i);
+ OUString aActualText(aChars.data(), aChars.size());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"\u0627\u0644 \u0628\u0627\u0644 \u0648\u0642\u0641 \u0627\u0644"), aActualText);
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf145274)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf145274.docx");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ auto pPage = pPdfDocument->openPage(0);
+ CPPUNIT_ASSERT(pPage);
+
+ int nPageObjectCount = pPage->getObjectCount();
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 6
+ // - Actual : 4
+ CPPUNIT_ASSERT_EQUAL(6, nPageObjectCount);
+
+ auto pTextPage = pPage->getTextPage();
+
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Text)
+ continue;
+
+ CPPUNIT_ASSERT_EQUAL(11.0, pPageObject->getFontSize());
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFTextRenderMode::Fill, pPageObject->getTextRenderMode());
+ CPPUNIT_ASSERT_EQUAL(COL_RED, pPageObject->getFillColor());
+ }
+}
+
+/// Test writing ToUnicode CMAP for doubly encoded glyphs.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf66597_1)
+{
+#if HAVE_MORE_FONTS
+ // This requires Amiri font, if it is missing the test will fail.
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf66597-1.odt", aDocument);
+
+ {
+ // Get access to ToUnicode of the first font
+ vcl::filter::PDFObjectElement* pToUnicode = nullptr;
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "Font")
+ {
+ auto pName
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("BaseFont"));
+ auto aName = pName->GetValue().copy(7); // skip the subset id
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected font name", OString("Amiri-Regular"),
+ aName);
+
+ auto pToUnicodeRef
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject->Lookup("ToUnicode"));
+ CPPUNIT_ASSERT(pToUnicodeRef);
+ pToUnicode = pToUnicodeRef->LookupObject();
+ break;
+ }
+ }
+
+ CPPUNIT_ASSERT(pToUnicode);
+ auto pStream = pToUnicode->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream aObjectStream;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ pStream->GetMemory().Seek(0);
+ aZCodec.Decompress(pStream->GetMemory(), aObjectStream);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+ aObjectStream.Seek(0);
+ // The <01> is glyph id, <2044> is code point.
+ // The document has two characters <2044><2215><2044>, but the font
+ // reuses the same glyph for U+2044 and U+2215 so we should have a single
+ // CMAP entry for the U+2044, and U+2215 will be handled with ActualText
+ // (tested below).
+ std::string aCmap("1 beginbfchar\n"
+ "<01> <2044>\n"
+ "endbfchar");
+ std::string aData(static_cast<const char*>(aObjectStream.GetData()),
+ aObjectStream.GetSize());
+ auto nPos = aData.find(aCmap);
+ CPPUNIT_ASSERT(nPos != std::string::npos);
+ }
+
+ {
+ auto aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ // Get page contents and stream.
+ auto pContents = aPages[0]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ auto pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ auto& rObjectStream = pStream->GetMemory();
+
+ // Uncompress the stream.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ // Make sure the expected ActualText is present.
+ std::string aData(static_cast<const char*>(aUncompressed.GetData()),
+ aUncompressed.GetSize());
+
+ std::string aActualText("/Span<</ActualText<");
+ size_t nCount = 0;
+ size_t nPos = 0;
+ while ((nPos = aData.find(aActualText, nPos)) != std::string::npos)
+ {
+ nCount++;
+ nPos += aActualText.length();
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("The should be one ActualText entry!", static_cast<size_t>(1),
+ nCount);
+
+ aActualText = "/Span<</ActualText<FEFF2215>>>";
+ nPos = aData.find(aActualText);
+ CPPUNIT_ASSERT_MESSAGE("ActualText not found!", nPos != std::string::npos);
+ }
+#endif
+}
+
+/// Test writing ActualText for RTL many to one glyph to Unicode mapping.
+// This requires Reem Kufi font, if it is missing the test will fail.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf66597_2)
+{
+#if HAVE_MORE_FONTS
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf66597-2.odt", aDocument);
+
+ {
+ // Get access to ToUnicode of the first font
+ vcl::filter::PDFObjectElement* pToUnicode = nullptr;
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "Font")
+ {
+ auto pName
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("BaseFont"));
+ auto aName = pName->GetValue().copy(7); // skip the subset id
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected font name", OString("ReemKufi-Regular"),
+ aName);
+
+ auto pToUnicodeRef
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject->Lookup("ToUnicode"));
+ CPPUNIT_ASSERT(pToUnicodeRef);
+ pToUnicode = pToUnicodeRef->LookupObject();
+ break;
+ }
+ }
+
+ CPPUNIT_ASSERT(pToUnicode);
+ auto pStream = pToUnicode->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream aObjectStream;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ pStream->GetMemory().Seek(0);
+ aZCodec.Decompress(pStream->GetMemory(), aObjectStream);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+ aObjectStream.Seek(0);
+ std::string aCmap("8 beginbfchar\n"
+ "<02> <0632>\n"
+ "<03> <0020>\n"
+ "<04> <0648>\n"
+ "<05> <0647>\n"
+ "<06> <062F>\n"
+ "<08> <062C>\n"
+ "<0A> <0628>\n"
+ "<0C> <0623>\n"
+ "endbfchar");
+ std::string aData(static_cast<const char*>(aObjectStream.GetData()),
+ aObjectStream.GetSize());
+ auto nPos = aData.find(aCmap);
+ CPPUNIT_ASSERT(nPos != std::string::npos);
+ }
+
+ {
+ auto aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ // Get page contents and stream.
+ auto pContents = aPages[0]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ auto pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ auto& rObjectStream = pStream->GetMemory();
+
+ // Uncompress the stream.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ // Make sure the expected ActualText is present.
+ std::string aData(static_cast<const char*>(aUncompressed.GetData()),
+ aUncompressed.GetSize());
+
+ std::vector<std::string> aCodes({ "0632", "062C", "0628", "0623" });
+ std::string aActualText("/Span<</ActualText<");
+ size_t nCount = 0;
+ size_t nPos = 0;
+ while ((nPos = aData.find(aActualText, nPos)) != std::string::npos)
+ {
+ nCount++;
+ nPos += aActualText.length();
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of ActualText entries does not match!", aCodes.size(),
+ nCount);
+
+ for (const auto& aCode : aCodes)
+ {
+ aActualText = "/Span<</ActualText<FEFF" + aCode + ">>>";
+ nPos = aData.find(aActualText);
+ CPPUNIT_ASSERT_MESSAGE("ActualText not found for " + aCode, nPos != std::string::npos);
+ }
+ }
+#endif
+}
+
+/// Test writing ActualText for LTR many to one glyph to Unicode mapping.
+// This requires Gentium Basic font, if it is missing the test will fail.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf66597_3)
+{
+#if HAVE_MORE_FONTS
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf66597-3.odt", aDocument);
+
+ {
+ // Get access to ToUnicode of the first font
+ vcl::filter::PDFObjectElement* pToUnicode = nullptr;
+ for (const auto& aElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "Font")
+ {
+ auto pName
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("BaseFont"));
+ auto aName = pName->GetValue().copy(7); // skip the subset id
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected font name", OString("GentiumBasic"),
+ aName);
+
+ auto pToUnicodeRef
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject->Lookup("ToUnicode"));
+ CPPUNIT_ASSERT(pToUnicodeRef);
+ pToUnicode = pToUnicodeRef->LookupObject();
+ break;
+ }
+ }
+
+ CPPUNIT_ASSERT(pToUnicode);
+ auto pStream = pToUnicode->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream aObjectStream;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ pStream->GetMemory().Seek(0);
+ aZCodec.Decompress(pStream->GetMemory(), aObjectStream);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+ aObjectStream.Seek(0);
+ std::string aCmap("2 beginbfchar\n"
+ "<01> <1ECB0331030B>\n"
+ "<05> <0020>\n"
+ "endbfchar");
+ std::string aData(static_cast<const char*>(aObjectStream.GetData()),
+ aObjectStream.GetSize());
+ auto nPos = aData.find(aCmap);
+ CPPUNIT_ASSERT(nPos != std::string::npos);
+ }
+
+ {
+ auto aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ // Get page contents and stream.
+ auto pContents = aPages[0]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ auto pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ auto& rObjectStream = pStream->GetMemory();
+
+ // Uncompress the stream.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ // Make sure the expected ActualText is present.
+ std::string aData(static_cast<const char*>(aUncompressed.GetData()),
+ aUncompressed.GetSize());
+
+ std::string aActualText("/Span<</ActualText<FEFF1ECB0331030B>>>");
+ size_t nCount = 0;
+ size_t nPos = 0;
+ while ((nPos = aData.find(aActualText, nPos)) != std::string::npos)
+ {
+ nCount++;
+ nPos += aActualText.length();
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of ActualText entries does not match!",
+ static_cast<size_t>(4), nCount);
+ }
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf105954)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ uno::Sequence<beans::PropertyValue> aFilterData(comphelper::InitPropertySequence(
+ { { "ReduceImageResolution", uno::Any(true) },
+ { "MaxImageResolution", uno::Any(static_cast<sal_Int32>(300)) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"tdf105954.odt");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // There is a single image on the page.
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ CPPUNIT_ASSERT_EQUAL(1, nPageObjectCount);
+
+ // Check width of the image.
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(/*index=*/0);
+ Size aMeta = pPageObject->getImageSize(*pPdfPage);
+ // This was 2000, i.e. the 'reduce to 300 DPI' request was ignored.
+ // This is now around 238 (228 on macOS).
+ CPPUNIT_ASSERT_LESS(static_cast<tools::Long>(250), aMeta.getWidth());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf128445)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export");
+ saveAsPDF(u"tdf128445.odp");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 7
+ // - Actual : 6
+ CPPUNIT_ASSERT_EQUAL(7, pPdfPage->getObjectCount());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf128630)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export");
+ saveAsPDF(u"tdf128630.odp");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ // Assert the size of the only bitmap on the page.
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image)
+ continue;
+
+ std::unique_ptr<vcl::pdf::PDFiumBitmap> pBitmap = pPageObject->getImageBitmap();
+ CPPUNIT_ASSERT(pBitmap);
+ int nWidth = pBitmap->getWidth();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 466
+ // - Actual : 289
+ // i.e. the rotated + scaled arrow was more thin than it should be.
+ CPPUNIT_ASSERT_EQUAL(466, nWidth);
+ int nHeight = pBitmap->getHeight();
+ CPPUNIT_ASSERT_EQUAL(466, nHeight);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106702)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf106702.odt");
+
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has two pages.
+ CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
+
+ // First page already has the correct image position.
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ int nExpected = 0;
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image)
+ continue;
+
+ // Top, but upside down.
+ nExpected = pPageObject->getBounds().getMaxY();
+ break;
+ }
+
+ // Second page had an incorrect image position.
+ pPdfPage = pPdfDocument->openPage(/*nIndex=*/1);
+ CPPUNIT_ASSERT(pPdfPage);
+ int nActual = 0;
+ nPageObjectCount = pPdfPage->getObjectCount();
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image)
+ continue;
+
+ // Top, but upside down.
+ nActual = pPageObject->getBounds().getMaxY();
+ break;
+ }
+
+ // This failed, vertical pos is 818 points, was 1674 (outside visible page
+ // bounds).
+ CPPUNIT_ASSERT_EQUAL(nExpected, nActual);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf113143)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export");
+ uno::Sequence<beans::PropertyValue> aFilterData(comphelper::InitPropertySequence({
+ { "ExportNotesPages", uno::Any(true) },
+ // ReduceImageResolution is on by default and that hides the bug we
+ // want to test.
+ { "ReduceImageResolution", uno::Any(false) },
+ // Set a custom PDF version.
+ { "SelectPdfVersion", uno::Any(static_cast<sal_Int32>(16)) },
+ }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"tdf113143.odp");
+
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has two pages.
+ CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
+
+ // First has the original (larger) image.
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ int nLarger = 0;
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image)
+ continue;
+
+ nLarger = pPageObject->getBounds().getWidth();
+ break;
+ }
+
+ // Second page has the scaled (smaller) image.
+ pPdfPage = pPdfDocument->openPage(/*nIndex=*/1);
+ CPPUNIT_ASSERT(pPdfPage);
+ int nSmaller = 0;
+ nPageObjectCount = pPdfPage->getObjectCount();
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image)
+ continue;
+
+ nSmaller = pPageObject->getBounds().getWidth();
+ break;
+ }
+
+ // This failed, both were 319, now nSmaller is 169.
+ CPPUNIT_ASSERT_LESS(nLarger, nSmaller);
+
+ // The following check used to fail in the past, header was "%PDF-1.5":
+ maMemory.Seek(0);
+ OString aExpectedHeader("%PDF-1.6");
+ OString aHeader(read_uInt8s_ToOString(maMemory, aExpectedHeader.getLength()));
+ CPPUNIT_ASSERT_EQUAL(aExpectedHeader, aHeader);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testForcePoint71)
+{
+ // I just care it doesn't crash
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"forcepoint71.key");
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testForcePoint80)
+{
+ // printing asserted in SwCellFrame::FindStartEndOfRowSpanCell
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"forcepoint80-1.rtf");
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testForcePoint3)
+{
+ // printing asserted in SwFrame::GetNextSctLeaf()
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"flowframe_null_ptr_deref.sample");
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf84283)
+{
+ // Without the fix in place, this test would have crashed
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf84283.doc");
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115262)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export");
+ saveAsPDF(u"tdf115262.ods");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(8, pPdfDocument->getPageCount());
+
+ // Get the 6th page.
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/5);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Look up the position of the first image and the 400th row.
+ std::unique_ptr<vcl::pdf::PDFiumTextPage> pTextPage = pPdfPage->getTextPage();
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ int nFirstImageTop = 0;
+ int nRowTop = 0;
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ // Top, but upside down.
+ float fTop = pPageObject->getBounds().getMaxY();
+
+ if (pPageObject->getType() == vcl::pdf::PDFPageObjectType::Image)
+ {
+ nFirstImageTop = fTop;
+ }
+ else if (pPageObject->getType() == vcl::pdf::PDFPageObjectType::Text)
+ {
+ OUString sText = pPageObject->getText(pTextPage);
+ if (sText == "400")
+ nRowTop = fTop;
+ }
+ }
+ // Make sure that the top of the "400" is below the top of the image (in
+ // bottom-right-corner-based PDF coordinates).
+ // This was: expected less than 144, actual is 199.
+ CPPUNIT_ASSERT_LESS(nFirstImageTop, nRowTop);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf121962)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf121962.odt");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ // Get the first page
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ std::unique_ptr<vcl::pdf::PDFiumTextPage> pTextPage = pPdfPage->getTextPage();
+
+ // Make sure the table sum is displayed as "0", not faulty expression.
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Text)
+ continue;
+ OUString sText = pPageObject->getText(pTextPage);
+ CPPUNIT_ASSERT(sText != "** Expression is faulty **");
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115967)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"tdf115967.odt");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ // Get the first page
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ std::unique_ptr<vcl::pdf::PDFiumTextPage> pTextPage = pPdfPage->getTextPage();
+
+ // Make sure the elements inside a formula in a RTL document are exported
+ // LTR ( m=750abc ) and not RTL ( m=057cba )
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ OUString sText;
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Text)
+ continue;
+ OUString sChar = pPageObject->getText(pTextPage);
+ sText += o3tl::trim(sChar);
+ }
+ CPPUNIT_ASSERT_EQUAL(OUString("m=750abc"), sText);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf124272)
+{
+ // Import the bugdoc and export as PDF.
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf124272.odt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // The page has a stream.
+ vcl::filter::PDFObjectElement* pContents = aPages[0]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ // Uncompress it.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ OString aBitmap("Q q 299.899 782.189 m\n"
+ "55.2 435.889 l 299.899 435.889 l 299.899 782.189 l\n"
+ "h");
+
+ auto pStart = static_cast<const char*>(aUncompressed.GetData());
+ const char* pEnd = pStart + aUncompressed.GetSize();
+ auto it = std::search(pStart, pEnd, aBitmap.getStr(), aBitmap.getStr() + aBitmap.getLength());
+ CPPUNIT_ASSERT(it != pEnd);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf121615)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf121615.odt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // Get access to the only image on the only page.
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+ vcl::filter::PDFStreamElement* pStream = pXObject->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+
+ // Load the embedded image.
+ rObjectStream.Seek(0);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ sal_uInt16 format;
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"import", rObjectStream,
+ GRFILTER_FORMAT_DONTKNOW, &format);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ // The image should be grayscale 8bit JPEG.
+ sal_uInt16 jpegFormat = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME);
+ CPPUNIT_ASSERT(jpegFormat != GRFILTER_FORMAT_NOTFOUND);
+ CPPUNIT_ASSERT_EQUAL(jpegFormat, format);
+ BitmapEx aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(200), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(300), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+ // tdf#121615 was caused by broken handling of data width with 8bit color,
+ // so the test image has some black in the bottomright corner, check it's there
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(0, 299));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(199, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, aBitmap.GetPixelColor(199, 299));
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf141171)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf141171.odt", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // Get access to the only image on the only page.
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+ vcl::filter::PDFStreamElement* pStream = pXObject->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+
+ // Load the embedded image.
+ rObjectStream.Seek(0);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ sal_uInt16 format;
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"import", rObjectStream,
+ GRFILTER_FORMAT_DONTKNOW, &format);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ // The image should be grayscale 8bit JPEG.
+ sal_uInt16 jpegFormat = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME);
+ CPPUNIT_ASSERT(jpegFormat != GRFILTER_FORMAT_NOTFOUND);
+ CPPUNIT_ASSERT_EQUAL(jpegFormat, format);
+ BitmapEx aBitmap = aGraphic.GetBitmapEx();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(878), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(127), aSize.Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
+
+ for (tools::Long nX = 0; nX < aSize.Width(); ++nX)
+ {
+ for (tools::Long nY = 0; nY < aSize.Height(); ++nY)
+ {
+ // Check all pixels in the image are white
+ // Without the fix in place, this test would have failed with
+ // - Expected: Color: R:255 G:255 B:255 A:0
+ // - Actual : Color: R:0 G:0 B:0 A:0
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(nX, nY));
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf129085)
+{
+ vcl::filter::PDFDocument aDocument;
+ load(u"tdf129085.docx", aDocument);
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // Get access to the only image on the only page.
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+
+ // Without the fix in place, this test would have failed here
+ CPPUNIT_ASSERT(pXObjects);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pXObjects->GetItems().size());
+ vcl::filter::PDFObjectElement* pXObject
+ = pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pXObject);
+ vcl::filter::PDFStreamElement* pStream = pXObject->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+
+ // Load the embedded image.
+ rObjectStream.Seek(0);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ sal_uInt16 format;
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"import", rObjectStream,
+ GRFILTER_FORMAT_DONTKNOW, &format);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+
+ sal_uInt16 jpegFormat = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME);
+ CPPUNIT_ASSERT(jpegFormat != GRFILTER_FORMAT_NOTFOUND);
+ CPPUNIT_ASSERT_EQUAL(jpegFormat, format);
+ BitmapEx aBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(884), aBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(925), aBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap.getPixelFormat());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTocLink)
+{
+ // Load the Writer document.
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "toc-link.fodt";
+ mxComponent = loadFromDesktop(aURL);
+
+ // Update the ToC.
+ uno::Reference<text::XDocumentIndexesSupplier> xDocumentIndexesSupplier(mxComponent,
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDocumentIndexesSupplier.is());
+
+ uno::Reference<util::XRefreshable> xToc(
+ xDocumentIndexesSupplier->getDocumentIndexes()->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xToc.is());
+
+ xToc->refresh();
+
+ // Save as PDF.
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Ensure there is a link on the first page (in the ToC).
+ // Without the accompanying fix in place, this test would have failed, as the page contained no
+ // links.
+ CPPUNIT_ASSERT(pPdfPage->hasLinks());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testReduceSmallImage)
+{
+ // Load the Writer document.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"reduce-small-image.fodt");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pPageObject->getType());
+
+ // Make sure we don't scale down a tiny bitmap.
+ std::unique_ptr<vcl::pdf::PDFiumBitmap> pBitmap = pPageObject->getImageBitmap();
+ CPPUNIT_ASSERT(pBitmap);
+ int nWidth = pBitmap->getWidth();
+ int nHeight = pBitmap->getHeight();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 16
+ // - Actual : 6
+ // i.e. the image was scaled down to 300 DPI, even if it had tiny size.
+ CPPUNIT_ASSERT_EQUAL(16, nWidth);
+ CPPUNIT_ASSERT_EQUAL(16, nHeight);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf114256)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export");
+ saveAsPDF(u"tdf114256.ods");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 13
+ // - Actual : 0
+ CPPUNIT_ASSERT_EQUAL(13, pPdfPage->getObjectCount());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf147027)
+{
+ // Load the Calc document.
+ aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export");
+ saveAsPDF(u"tdf147027.ods");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 778
+ // - Actual : 40
+ CPPUNIT_ASSERT_EQUAL(778, pPdfPage->getObjectCount());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135346)
+{
+ // Load the Calc document.
+ aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export");
+ saveAsPDF(u"tdf135346.ods");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 56
+ // - Actual : 0
+ CPPUNIT_ASSERT_EQUAL(56, pPdfPage->getObjectCount());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf147164)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export");
+ saveAsPDF(u"tdf147164.odp");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/1);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 22
+ // - Actual : 16
+ CPPUNIT_ASSERT_EQUAL(22, pPdfPage->getObjectCount());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testReduceImage)
+{
+ // Load the Writer document.
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "reduce-image.fodt";
+ mxComponent = loadFromDesktop(aURL);
+
+ // Save as PDF.
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory = getMultiServiceFactory();
+ uno::Reference<document::XFilter> xFilter(
+ xFactory->createInstance("com.sun.star.document.PDFFilter"), uno::UNO_QUERY);
+ uno::Reference<document::XExporter> xExporter(xFilter, uno::UNO_QUERY);
+ xExporter->setSourceDocument(mxComponent);
+
+ SvFileStream aOutputStream(maTempFile.GetURL(), StreamMode::WRITE);
+ uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aOutputStream));
+
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "ReduceImageResolution", uno::Any(false) } }));
+
+ // This is intentionally in an "unlucky" order, output stream comes before filter data.
+ uno::Sequence<beans::PropertyValue> aDescriptor(comphelper::InitPropertySequence({
+ { "FilterName", uno::Any(OUString("writer_pdf_Export")) },
+ { "OutputStream", uno::Any(xOutputStream) },
+ { "FilterData", uno::Any(aFilterData) },
+ }));
+ xFilter->filter(aDescriptor);
+ aOutputStream.Close();
+
+ // Parse the PDF: get the image.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pPageObject->getType());
+
+ // Make sure we don't scale down a bitmap.
+ std::unique_ptr<vcl::pdf::PDFiumBitmap> pBitmap = pPageObject->getImageBitmap();
+ CPPUNIT_ASSERT(pBitmap);
+ int nWidth = pBitmap->getWidth();
+ int nHeight = pBitmap->getHeight();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 160
+ // - Actual : 6
+ // i.e. the image was scaled down even with ReduceImageResolution=false.
+ CPPUNIT_ASSERT_EQUAL(160, nWidth);
+ CPPUNIT_ASSERT_EQUAL(160, nHeight);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testLinkWrongPage)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export");
+ saveAsPDF(u"link-wrong-page.odp");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has 2 pages.
+ CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
+
+ // First page should have 1 link (2nd slide, 1st was hidden).
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // Without the accompanying fix in place, this test would have failed, as the link of the first
+ // page went to the second page due to the hidden first slide.
+ CPPUNIT_ASSERT(pPdfPage->hasLinks());
+
+ // Second page should have no links (3rd slide).
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage2 = pPdfDocument->openPage(/*nIndex=*/1);
+ CPPUNIT_ASSERT(pPdfPage2);
+ CPPUNIT_ASSERT(!pPdfPage2->hasLinks());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testLinkWrongPagePartial)
+{
+ // Given a Draw document with 3 pages, a link on the 2nd page:
+ // When exporting that the 2nd and 3rd page to pdf:
+ uno::Sequence<beans::PropertyValue> aFilterData = {
+ comphelper::makePropertyValue("PageRange", OUString("2-3")),
+ };
+ aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export");
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"link-wrong-page-partial.odg");
+
+ // Then make sure the we have a link on the 1st page, but not on the 2nd one:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ // Without the accompanying fix in place, this test would have failed, as the link was on the
+ // 2nd page instead.
+ CPPUNIT_ASSERT(pPdfPage->hasLinks());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage2 = pPdfDocument->openPage(/*nIndex=*/1);
+ CPPUNIT_ASSERT(pPdfPage2);
+ CPPUNIT_ASSERT(!pPdfPage2->hasLinks());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testPageRange)
+{
+ // Given a document with 3 pages:
+ // When exporting that document to PDF, skipping the first page:
+ aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export");
+ aMediaDescriptor["FilterOptions"]
+ <<= OUString("{\"PageRange\":{\"type\":\"string\",\"value\":\"2-\"}}");
+ saveAsPDF(u"link-wrong-page-partial.odg");
+
+ // Then make sure the resulting PDF has 2 pages:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 2
+ // - Actual : 3
+ // i.e. FilterOptions was ignored.
+ CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testLargePage)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export");
+ saveAsPDF(u"6m-wide.odg");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has 1 page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ // Check the value (not the unit) of the page size.
+ basegfx::B2DSize aSize = pPdfDocument->getPageSize(0);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 8503.94
+ // - Actual : 17007.875
+ // i.e. the value for 600 cm was larger than the 14 400 limit set in the spec.
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8503.94, aSize.getX(), 0.01);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageResourceInlineXObjectRef)
+{
+ // Create an empty document.
+ mxComponent = loadFromDesktop("private:factory/swriter");
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XText> xText = xTextDocument->getText();
+ uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+
+ // Insert the PDF image.
+ uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xGraphicObject(
+ xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY);
+ OUString aURL
+ = m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf-image-resource-inline-xobject-ref.pdf";
+ xGraphicObject->setPropertyValue("GraphicURL", uno::Any(aURL));
+ uno::Reference<drawing::XShape> xShape(xGraphicObject, uno::UNO_QUERY);
+ xShape->setSize(awt::Size(1000, 1000));
+ uno::Reference<text::XTextContent> xTextContent(xGraphicObject, uno::UNO_QUERY);
+ xText->insertTextContent(xCursor->getStart(), xTextContent, /*bAbsorb=*/false);
+
+ // Save as PDF.
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ // Make sure that the page -> form -> form has a child image.
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pPageObject->getType());
+ // 2: white background and the actual object.
+ CPPUNIT_ASSERT_EQUAL(2, pPageObject->getFormObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject = pPageObject->getFormObject(1);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pFormObject->getType());
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 1
+ // - Actual : 0
+ // i.e. the sub-form was missing its image.
+ CPPUNIT_ASSERT_EQUAL(1, pFormObject->getFormObjectCount());
+
+ // Check if the inner form object (original page object in the pdf image) has the correct
+ // rotation.
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pInnerFormObject = pFormObject->getFormObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pInnerFormObject->getType());
+ CPPUNIT_ASSERT_EQUAL(1, pInnerFormObject->getFormObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pImage = pInnerFormObject->getFormObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pImage->getType());
+ basegfx::B2DHomMatrix aMat = pInnerFormObject->getMatrix();
+ basegfx::B2DTuple aScale;
+ basegfx::B2DTuple aTranslate;
+ double fRotate = 0;
+ double fShearX = 0;
+ aMat.decompose(aScale, aTranslate, fRotate, fShearX);
+ int nRotateDeg = basegfx::rad2deg(fRotate);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: -90
+ // - Actual : 0
+ // i.e. rotation was lost on pdf export.
+ CPPUNIT_ASSERT_EQUAL(-90, nRotateDeg);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testDefaultVersion)
+{
+ // Create an empty document.
+ mxComponent = loadFromDesktop("private:factory/swriter");
+
+ // Save as PDF.
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ int nFileVersion = pPdfDocument->getFileVersion();
+ CPPUNIT_ASSERT_EQUAL(16, nFileVersion);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testVersion15)
+{
+ // Create an empty document.
+ mxComponent = loadFromDesktop("private:factory/swriter");
+
+ // Save as PDF.
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aFilterData(comphelper::InitPropertySequence(
+ { { "SelectPdfVersion", uno::Any(static_cast<sal_Int32>(15)) } }));
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ int nFileVersion = pPdfDocument->getFileVersion();
+ CPPUNIT_ASSERT_EQUAL(15, nFileVersion);
+}
+
+// Check round-trip of importing and exporting the PDF with PDFium filter,
+// which imports the PDF document as multiple PDFs as graphic object.
+// Each page in the document has one PDF graphic object which content is
+// the corresponding page in the PDF. When such a document is exported,
+// the PDF graphic gets embedded into the exported PDF document (as a
+// Form XObject).
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testMultiPagePDF)
+{
+// setenv only works on unix based systems
+#ifndef _WIN32
+ // We need to enable PDFium import (and make sure to disable after the test)
+ bool bResetEnvVar = false;
+ if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
+ {
+ bResetEnvVar = true;
+ setenv("LO_IMPORT_USE_PDFIUM", "1", false);
+ }
+ comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() {
+ if (bResetEnvVar)
+ unsetenv("LO_IMPORT_USE_PDFIUM");
+ });
+
+ // Load the PDF and save as PDF
+ vcl::filter::PDFDocument aDocument;
+ load(u"SimpleMultiPagePDF.pdf", aDocument);
+
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aPages.size());
+
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3),
+ pXObjects->GetItems().size()); // 3 PDFs as Form XObjects
+
+ std::vector<OString> rIDs;
+ for (auto const& rPair : pXObjects->GetItems())
+ {
+ rIDs.push_back(rPair.first);
+ }
+
+ // Let's check the embedded PDF pages - just make sure the size differs,
+ // which should indicate we don't have 3 times the same page.
+
+ { // embedded PDF page 1
+ vcl::filter::PDFObjectElement* pXObject1 = pXObjects->LookupObject(rIDs[0]);
+ CPPUNIT_ASSERT(pXObject1);
+ CPPUNIT_ASSERT_EQUAL(OString("Im19"), rIDs[0]);
+
+ auto pSubtype1 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject1->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype1);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype1->GetValue());
+
+ auto pXObjectResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject1->Lookup("Resources"));
+ CPPUNIT_ASSERT(pXObjectResources);
+ auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pXObjectResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pXObjectForms);
+ vcl::filter::PDFObjectElement* pForm
+ = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pForm);
+
+ vcl::filter::PDFStreamElement* pStream = pForm->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ rObjectStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Just check that the size of the page stream is what is expected.
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(230), rObjectStream.remainingSize());
+ }
+
+ { // embedded PDF page 2
+ vcl::filter::PDFObjectElement* pXObject2 = pXObjects->LookupObject(rIDs[1]);
+ CPPUNIT_ASSERT(pXObject2);
+ CPPUNIT_ASSERT_EQUAL(OString("Im24"), rIDs[1]);
+
+ auto pSubtype2 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject2->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype2);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype2->GetValue());
+
+ auto pXObjectResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject2->Lookup("Resources"));
+ CPPUNIT_ASSERT(pXObjectResources);
+ auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pXObjectResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pXObjectForms);
+ vcl::filter::PDFObjectElement* pForm
+ = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pForm);
+
+ vcl::filter::PDFStreamElement* pStream = pForm->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ rObjectStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Just check that the size of the page stream is what is expected
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(309), rObjectStream.remainingSize());
+ }
+
+ { // embedded PDF page 3
+ vcl::filter::PDFObjectElement* pXObject3 = pXObjects->LookupObject(rIDs[2]);
+ CPPUNIT_ASSERT(pXObject3);
+ CPPUNIT_ASSERT_EQUAL(OString("Im4"), rIDs[2]);
+
+ auto pSubtype3 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject3->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype3);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype3->GetValue());
+
+ auto pXObjectResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject3->Lookup("Resources"));
+ CPPUNIT_ASSERT(pXObjectResources);
+ auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pXObjectResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pXObjectForms);
+ vcl::filter::PDFObjectElement* pForm
+ = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pForm);
+
+ vcl::filter::PDFStreamElement* pStream = pForm->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ rObjectStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Just check that the size of the page stream is what is expected
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(193), rObjectStream.remainingSize());
+ }
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testFormFontName)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ saveAsPDF(u"form-font-name.odt");
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ // The page has one annotation.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount());
+ std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnot = pPdfPage->getAnnotation(0);
+
+ // Examine the default appearance.
+ CPPUNIT_ASSERT(pAnnot->hasKey("DA"));
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFObjectType::String, pAnnot->getValueType("DA"));
+ OUString aDA = pAnnot->getString("DA");
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 0 0 0 rg /TiRo 12 Tf
+ // - Actual : 0 0 0 rg /F2 12 Tf
+ // i.e. Liberation Serif was exposed as a form font as-is, without picking the closest built-in
+ // font.
+ CPPUNIT_ASSERT_EQUAL(OUString("0 0 0 rg /TiRo 12 Tf"), aDA);
+}
+
+// Check we don't have duplicated objects when we reexport the PDF multiple
+// times or the size will exponentially increase over time.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testReexportPDF)
+{
+// setenv only works on unix based systems
+#ifndef _WIN32
+ // We need to enable PDFium import (and make sure to disable after the test)
+ bool bResetEnvVar = false;
+ if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
+ {
+ bResetEnvVar = true;
+ setenv("LO_IMPORT_USE_PDFIUM", "1", false);
+ }
+ comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() {
+ if (bResetEnvVar)
+ unsetenv("LO_IMPORT_USE_PDFIUM");
+ });
+
+ // Load the PDF and save as PDF
+ vcl::filter::PDFDocument aDocument;
+ load(u"PDFWithImages.pdf", aDocument);
+
+ // Assert that the XObject in the page resources dictionary is a reference XObject.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+
+ // The document has 2 pages.
+ CPPUNIT_ASSERT_EQUAL(size_t(2), aPages.size());
+
+ // PAGE 1
+ {
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+
+ auto pXObjects
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+
+ std::vector<OString> rIDs;
+ for (auto const& rPair : pXObjects->GetItems())
+ rIDs.push_back(rPair.first);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(2), rIDs.size());
+
+ std::vector<int> aBitmapRefs1;
+ std::vector<int> aBitmapRefs2;
+
+ {
+ // FORM object 1
+ OString aID = rIDs[0];
+ CPPUNIT_ASSERT_EQUAL(OString("Im12"), aID);
+ vcl::filter::PDFObjectElement* pXObject = pXObjects->LookupObject(aID);
+ CPPUNIT_ASSERT(pXObject);
+
+ auto pSubtype = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype->GetValue());
+
+ auto pInnerResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject->Lookup("Resources"));
+ CPPUNIT_ASSERT(pInnerResources);
+ auto pInnerXObjects = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pInnerResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pInnerXObjects);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pInnerXObjects->GetItems().size());
+ OString aInnerObjectID = pInnerXObjects->GetItems().begin()->first;
+ CPPUNIT_ASSERT_EQUAL(OString("Im13"), aInnerObjectID);
+
+ vcl::filter::PDFObjectElement* pInnerXObject
+ = pInnerXObjects->LookupObject(aInnerObjectID);
+ CPPUNIT_ASSERT(pInnerXObject);
+
+ auto pInnerSubtype
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pInnerXObject->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pInnerSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pInnerSubtype->GetValue());
+
+ auto pInnerInnerResources = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pInnerXObject->Lookup("Resources"));
+ CPPUNIT_ASSERT(pInnerInnerResources);
+ auto pInnerInnerXObjects = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pInnerInnerResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pInnerInnerXObjects);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pInnerInnerXObjects->GetItems().size());
+
+ std::vector<OString> aBitmapIDs1;
+ for (auto const& rPair : pInnerInnerXObjects->GetItems())
+ aBitmapIDs1.push_back(rPair.first);
+
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("Im11"), aBitmapIDs1[0]);
+ auto pRef = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+ pInnerInnerXObjects->LookupElement(aBitmapIDs1[0]));
+ CPPUNIT_ASSERT(pRef);
+ aBitmapRefs1.push_back(pRef->GetObjectValue());
+ CPPUNIT_ASSERT_EQUAL(0, pRef->GetGenerationValue());
+
+ vcl::filter::PDFObjectElement* pBitmap
+ = pInnerInnerXObjects->LookupObject(aBitmapIDs1[0]);
+ CPPUNIT_ASSERT(pBitmap);
+ auto pBitmapSubtype
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pBitmap->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pBitmapSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Image"), pBitmapSubtype->GetValue());
+ }
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("Im5"), aBitmapIDs1[1]);
+ auto pRef = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+ pInnerInnerXObjects->LookupElement(aBitmapIDs1[1]));
+ CPPUNIT_ASSERT(pRef);
+ aBitmapRefs1.push_back(pRef->GetObjectValue());
+ CPPUNIT_ASSERT_EQUAL(0, pRef->GetGenerationValue());
+
+ vcl::filter::PDFObjectElement* pBitmap
+ = pInnerInnerXObjects->LookupObject(aBitmapIDs1[1]);
+ CPPUNIT_ASSERT(pBitmap);
+ auto pBitmapSubtype
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pBitmap->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pBitmapSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Image"), pBitmapSubtype->GetValue());
+ }
+ }
+
+ {
+ // FORM object 2
+ OString aID = rIDs[1];
+ CPPUNIT_ASSERT_EQUAL(OString("Im4"), aID);
+ vcl::filter::PDFObjectElement* pXObject = pXObjects->LookupObject(aID);
+ CPPUNIT_ASSERT(pXObject);
+
+ auto pSubtype = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype->GetValue());
+
+ auto pInnerResources
+ = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject->Lookup("Resources"));
+ CPPUNIT_ASSERT(pInnerResources);
+ auto pInnerXObjects = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pInnerResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pInnerXObjects);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pInnerXObjects->GetItems().size());
+ OString aInnerObjectID = pInnerXObjects->GetItems().begin()->first;
+ CPPUNIT_ASSERT_EQUAL(OString("Im5"), aInnerObjectID);
+
+ vcl::filter::PDFObjectElement* pInnerXObject
+ = pInnerXObjects->LookupObject(aInnerObjectID);
+ CPPUNIT_ASSERT(pInnerXObject);
+
+ auto pInnerSubtype
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pInnerXObject->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pInnerSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pInnerSubtype->GetValue());
+
+ auto pInnerInnerResources = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pInnerXObject->Lookup("Resources"));
+ CPPUNIT_ASSERT(pInnerInnerResources);
+ auto pInnerInnerXObjects = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+ pInnerInnerResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pInnerInnerXObjects);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pInnerInnerXObjects->GetItems().size());
+
+ std::vector<OString> aBitmapIDs2;
+ for (auto const& rPair : pInnerInnerXObjects->GetItems())
+ aBitmapIDs2.push_back(rPair.first);
+
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("Im11"), aBitmapIDs2[0]);
+ auto pRef = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+ pInnerInnerXObjects->LookupElement(aBitmapIDs2[0]));
+ CPPUNIT_ASSERT(pRef);
+ aBitmapRefs2.push_back(pRef->GetObjectValue());
+ CPPUNIT_ASSERT_EQUAL(0, pRef->GetGenerationValue());
+
+ vcl::filter::PDFObjectElement* pBitmap
+ = pInnerInnerXObjects->LookupObject(aBitmapIDs2[0]);
+ CPPUNIT_ASSERT(pBitmap);
+ auto pBitmapSubtype
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pBitmap->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pBitmapSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Image"), pBitmapSubtype->GetValue());
+ }
+ {
+ CPPUNIT_ASSERT_EQUAL(OString("Im5"), aBitmapIDs2[1]);
+ auto pRef = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+ pInnerInnerXObjects->LookupElement(aBitmapIDs2[1]));
+ CPPUNIT_ASSERT(pRef);
+ aBitmapRefs2.push_back(pRef->GetObjectValue());
+ CPPUNIT_ASSERT_EQUAL(0, pRef->GetGenerationValue());
+
+ vcl::filter::PDFObjectElement* pBitmap
+ = pInnerInnerXObjects->LookupObject(aBitmapIDs2[1]);
+ CPPUNIT_ASSERT(pBitmap);
+ auto pBitmapSubtype
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pBitmap->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pBitmapSubtype);
+ CPPUNIT_ASSERT_EQUAL(OString("Image"), pBitmapSubtype->GetValue());
+ }
+ }
+ // Ref should point to the same bitmap
+ CPPUNIT_ASSERT_EQUAL(aBitmapRefs1[0], aBitmapRefs2[0]);
+ CPPUNIT_ASSERT_EQUAL(aBitmapRefs1[1], aBitmapRefs2[1]);
+ }
+
+#endif
+}
+
+// Check we correctly copy more complex resources (Fonts describing
+// glyphs in recursive arrays) to the target PDF
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testReexportDocumentWithComplexResources)
+{
+// setenv only works on unix based systems
+#ifndef _WIN32
+ // We need to enable PDFium import (and make sure to disable after the test)
+ bool bResetEnvVar = false;
+ if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
+ {
+ bResetEnvVar = true;
+ setenv("LO_IMPORT_USE_PDFIUM", "1", false);
+ }
+ comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() {
+ if (bResetEnvVar)
+ unsetenv("LO_IMPORT_USE_PDFIUM");
+ });
+
+ // Load the PDF and save as PDF
+ vcl::filter::PDFDocument aDocument;
+ load(u"ComplexContentDictionary.pdf", aDocument);
+
+ // Assert that the XObject in the page resources dictionary is a reference XObject.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
+
+ // Go directly to the Font object (24 0) (number could change if we change how PDF export works)
+ auto pFont = aDocument.LookupObject(23);
+ CPPUNIT_ASSERT(pFont);
+
+ // Check it is the Font object (Type = Font)
+ auto pName
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pFont->GetDictionary()->LookupElement("Type"));
+ CPPUNIT_ASSERT(pName);
+ CPPUNIT_ASSERT_EQUAL(OString("Font"), pName->GetValue());
+
+ // Check BaseFont is what we expect
+ auto pBaseFont = dynamic_cast<vcl::filter::PDFNameElement*>(
+ pFont->GetDictionary()->LookupElement("BaseFont"));
+ CPPUNIT_ASSERT(pBaseFont);
+ CPPUNIT_ASSERT_EQUAL(OString("HOTOMR+Calibri,Italic"), pBaseFont->GetValue());
+
+ // Check and get the W array
+ auto pWArray
+ = dynamic_cast<vcl::filter::PDFArrayElement*>(pFont->GetDictionary()->LookupElement("W"));
+ CPPUNIT_ASSERT(pWArray);
+ CPPUNIT_ASSERT_EQUAL(size_t(26), pWArray->GetElements().size());
+
+ // Check the content of W array
+ // ObjectCopier didn't copy this array correctly and the document
+ // had glyphs at the wrong places
+ {
+ // first 2 elements
+ auto pNumberAtIndex0 = dynamic_cast<vcl::filter::PDFNumberElement*>(pWArray->GetElement(0));
+ CPPUNIT_ASSERT(pNumberAtIndex0);
+ CPPUNIT_ASSERT_EQUAL(3.0, pNumberAtIndex0->GetValue());
+
+ auto pArrayAtIndex1 = dynamic_cast<vcl::filter::PDFArrayElement*>(pWArray->GetElement(1));
+ CPPUNIT_ASSERT(pArrayAtIndex1);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pArrayAtIndex1->GetElements().size());
+
+ {
+ auto pNumber
+ = dynamic_cast<vcl::filter::PDFNumberElement*>(pArrayAtIndex1->GetElement(0));
+ CPPUNIT_ASSERT(pNumber);
+ CPPUNIT_ASSERT_EQUAL(226.0, pNumber->GetValue());
+ }
+
+ // last 2 elements
+ auto pNumberAtIndex24
+ = dynamic_cast<vcl::filter::PDFNumberElement*>(pWArray->GetElement(24));
+ CPPUNIT_ASSERT(pNumberAtIndex24);
+ CPPUNIT_ASSERT_EQUAL(894.0, pNumberAtIndex24->GetValue());
+
+ auto pArrayAtIndex25 = dynamic_cast<vcl::filter::PDFArrayElement*>(pWArray->GetElement(25));
+ CPPUNIT_ASSERT(pArrayAtIndex25);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pArrayAtIndex25->GetElements().size());
+
+ {
+ auto pNumber1
+ = dynamic_cast<vcl::filter::PDFNumberElement*>(pArrayAtIndex25->GetElement(0));
+ CPPUNIT_ASSERT(pNumber1);
+ CPPUNIT_ASSERT_EQUAL(303.0, pNumber1->GetValue());
+
+ auto pNumber2
+ = dynamic_cast<vcl::filter::PDFNumberElement*>(pArrayAtIndex25->GetElement(1));
+ CPPUNIT_ASSERT(pNumber2);
+ CPPUNIT_ASSERT_EQUAL(303.0, pNumber2->GetValue());
+ }
+ }
+#endif
+}
+
+// Tests that at export the PDF has the PDF/UA metadata properly set
+// when we enable PDF/UA support.
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfUaMetadata)
+{
+ // Import a basic document (document doesn't really matter)
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"BrownFoxLazyDog.odt");
+
+ // Parse the export result.
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ auto* pCatalog = aDocument.GetCatalog();
+ CPPUNIT_ASSERT(pCatalog);
+ auto* pCatalogDictionary = pCatalog->GetDictionary();
+ CPPUNIT_ASSERT(pCatalogDictionary);
+ auto* pMetadataObject = pCatalogDictionary->LookupObject("Metadata");
+ CPPUNIT_ASSERT(pMetadataObject);
+ auto* pMetadataDictionary = pMetadataObject->GetDictionary();
+ auto* pType
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pMetadataDictionary->LookupElement("Type"));
+ CPPUNIT_ASSERT(pType);
+ CPPUNIT_ASSERT_EQUAL(OString("Metadata"), pType->GetValue());
+
+ auto* pStreamObject = pMetadataObject->GetStream();
+ CPPUNIT_ASSERT(pStreamObject);
+ auto& rStream = pStreamObject->GetMemory();
+ rStream.Seek(0);
+
+ // Search for the PDF/UA marker in the metadata
+
+ tools::XmlWalker aWalker;
+ CPPUNIT_ASSERT(aWalker.open(&rStream));
+ CPPUNIT_ASSERT_EQUAL(OString("xmpmeta"), aWalker.name());
+
+ bool bPdfUaMarkerFound = false;
+ OString aPdfUaPart;
+
+ aWalker.children();
+ while (aWalker.isValid())
+ {
+ if (aWalker.name() == "RDF"
+ && aWalker.namespaceHref() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
+ {
+ aWalker.children();
+ while (aWalker.isValid())
+ {
+ if (aWalker.name() == "Description"
+ && aWalker.namespaceHref() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
+ {
+ aWalker.children();
+ while (aWalker.isValid())
+ {
+ if (aWalker.name() == "part"
+ && aWalker.namespaceHref() == "http://www.aiim.org/pdfua/ns/id/")
+ {
+ aPdfUaPart = aWalker.content();
+ bPdfUaMarkerFound = true;
+ }
+ aWalker.next();
+ }
+ aWalker.parent();
+ }
+ aWalker.next();
+ }
+ aWalker.parent();
+ }
+ aWalker.next();
+ }
+ aWalker.parent();
+
+ CPPUNIT_ASSERT(bPdfUaMarkerFound);
+ CPPUNIT_ASSERT_EQUAL(OString("1"), aPdfUaPart);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf139736)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"tdf139736-1.odt");
+
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ vcl::filter::PDFObjectElement* pContents = aPages[0]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ // Uncompress it.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ auto pStart = static_cast<const char*>(aUncompressed.GetData());
+ const char* const pEnd = pStart + aUncompressed.GetSize();
+
+ enum
+ {
+ Default,
+ Artifact,
+ Tagged
+ } state
+ = Default;
+
+ auto nLine(0);
+ auto nTagged(0);
+ auto nArtifacts(0);
+ while (true)
+ {
+ ++nLine;
+ auto const pLine = ::std::find(pStart, pEnd, '\n');
+ if (pLine == pEnd)
+ {
+ break;
+ }
+ std::string_view const line(pStart, pLine - pStart);
+ pStart = pLine + 1;
+ if (!line.empty() && line[0] != '%')
+ {
+ ::std::cerr << nLine << ": " << line << "\n";
+ if (line == "/Artifact BMC")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state);
+ state = Artifact;
+ ++nArtifacts;
+ }
+ else if (line == "/Standard<</MCID 0>>BDC")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state);
+ state = Tagged;
+ ++nTagged;
+ }
+ else if (line == "EMC")
+ {
+ CPPUNIT_ASSERT_MESSAGE("unexpected end", state != Default);
+ state = Default;
+ }
+ else if (nLine > 1) // first line is expected "0.1 w"
+ {
+ CPPUNIT_ASSERT_MESSAGE("unexpected content outside MCS", state != Default);
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("unclosed MCS", Default, state);
+ CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nTagged)>(1), nTagged); // text in body
+ // 1 image and 1 frame and 1 header text; arbitrary number of aux stuff like borders
+ CPPUNIT_ASSERT(nArtifacts >= 3);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf149140)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt");
+
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ int nTH(0);
+ for (const auto& rDocElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "StructElem")
+ {
+ auto pS = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"));
+ if (pS && pS->GetValue() == "TH")
+ {
+ int nTable(0);
+ auto pAttrs = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject->Lookup("A"));
+ CPPUNIT_ASSERT(pAttrs != nullptr);
+ for (const auto& rAttrRef : pAttrs->GetElements())
+ {
+ auto pARef = dynamic_cast<vcl::filter::PDFReferenceElement*>(rAttrRef);
+ CPPUNIT_ASSERT(pARef != nullptr);
+ auto pAttr = pARef->LookupObject();
+ CPPUNIT_ASSERT(pAttr != nullptr);
+ auto pAttrDict = pAttr->GetDictionary();
+ CPPUNIT_ASSERT(pAttrDict != nullptr);
+ auto pOwner
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pAttrDict->LookupElement("O"));
+ CPPUNIT_ASSERT(pOwner != nullptr);
+ if (pOwner->GetValue() == "Table")
+ {
+ auto pScope = dynamic_cast<vcl::filter::PDFNameElement*>(
+ pAttrDict->LookupElement("Scope"));
+ CPPUNIT_ASSERT(pScope != nullptr);
+ CPPUNIT_ASSERT_EQUAL(OString("Column"), pScope->GetValue());
+ ++nTable;
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(int(1), nTable);
+ ++nTH;
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(int(6), nTH);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135638)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"image-shape.fodt");
+
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ int nFigure(0);
+ for (const auto& rDocElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "StructElem")
+ {
+ auto pS = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"));
+ if (pS && pS->GetValue() == "Figure")
+ {
+ auto pARef = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject->Lookup("A"));
+ CPPUNIT_ASSERT(pARef != nullptr);
+ auto pAttr = pARef->LookupObject();
+ CPPUNIT_ASSERT(pAttr != nullptr);
+ auto pAttrDict = pAttr->GetDictionary();
+ CPPUNIT_ASSERT(pAttrDict != nullptr);
+ auto pOwner
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pAttrDict->LookupElement("O"));
+ CPPUNIT_ASSERT(pOwner != nullptr);
+ CPPUNIT_ASSERT_EQUAL(OString("Layout"), pOwner->GetValue());
+ auto pBBox
+ = dynamic_cast<vcl::filter::PDFArrayElement*>(pAttrDict->LookupElement("BBox"));
+ CPPUNIT_ASSERT(pBBox != nullptr);
+ if (nFigure == 0)
+ {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ 139.5,
+ dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[0])
+ ->GetValue(),
+ 0.01);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ 480.3,
+ dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[1])
+ ->GetValue(),
+ 0.01);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ 472.5,
+ dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[2])
+ ->GetValue(),
+ 0.01);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ 735.3,
+ dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[3])
+ ->GetValue(),
+ 0.01);
+ }
+ else
+ {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ 178.45,
+ dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[0])
+ ->GetValue(),
+ 0.01);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ 318.65,
+ dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[1])
+ ->GetValue(),
+ 0.01);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ 326.35,
+ dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[2])
+ ->GetValue(),
+ 0.01);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ 382.55,
+ dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[3])
+ ->GetValue(),
+ 0.01);
+ }
+ ++nFigure;
+ }
+ }
+ }
+ // the first one is a Writer image, 2nd one SdrRectObj
+ CPPUNIT_ASSERT_EQUAL(int(2), nFigure);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf57423)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"Description PDF Export test .odt");
+
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ int nFigure(0);
+ int nFormula(0);
+ int nDiv(0);
+ for (const auto& rDocElement : aDocument.GetElements())
+ {
+ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get());
+ if (!pObject)
+ continue;
+ auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (pType && pType->GetValue() == "StructElem")
+ {
+ auto pS = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"));
+ if (pS && pS->GetValue() == "Figure")
+ {
+ switch (nFigure)
+ {
+ case 0:
+ CPPUNIT_ASSERT_EQUAL(OUString(u"QR Code - Tells how to get to Mosegaard"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(
+ pObject->Lookup("Alt"))));
+ break;
+ case 1:
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Title: Arrows - Description: Explains the "
+ u"different arrow appearances"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(
+ pObject->Lookup("Alt"))));
+ break;
+ case 2:
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"My blue triangle - Does not need further description"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(
+ pObject->Lookup("Alt"))));
+ break;
+ }
+ ++nFigure;
+ }
+ if (pS && pS->GetValue() == "Formula")
+ {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"Equation 1 - Now we give the full description of eq 1 here"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pObject->Lookup("Alt"))));
+ ++nFormula;
+ }
+ if (pS && pS->GetValue() == "Div")
+ {
+ switch (nDiv)
+ {
+ case 0:
+ CPPUNIT_ASSERT_EQUAL(OUString(u"This frame has a description"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(
+ pObject->Lookup("Alt"))));
+ break;
+ case 1:
+ // no properties set on this
+ CPPUNIT_ASSERT(!pObject->Lookup("Alt"));
+ break;
+ case 2:
+ CPPUNIT_ASSERT_EQUAL(OUString(u"My textbox - Has a light background"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(
+ pObject->Lookup("Alt"))));
+ break;
+ case 3:
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Hey! There is no alternate text for Frame "
+ u"// but maybe not needed?"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(
+ pObject->Lookup("Alt"))));
+ break;
+ }
+ ++nDiv;
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(int(3), nFigure);
+ CPPUNIT_ASSERT_EQUAL(int(1), nFormula);
+ CPPUNIT_ASSERT_EQUAL(int(4), nDiv);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135192)
+{
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ saveAsPDF(u"tdf135192-1.fodp");
+
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ int nTable(0);
+ for (const auto& rDocElement : aDocument.GetElements())
+ {
+ auto pObject1 = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get());
+ if (!pObject1)
+ continue;
+ auto pType1 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1->Lookup("Type"));
+ if (pType1 && pType1->GetValue() == "StructElem")
+ {
+ auto pS1 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1->Lookup("S"));
+ if (pS1 && pS1->GetValue() == "Table")
+ {
+ int nTR(0);
+ auto pKids1 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject1->Lookup("K"));
+ CPPUNIT_ASSERT(pKids1);
+ // there can be additional children, such as MCID ref
+ for (auto pKid1 : pKids1->GetElements())
+ {
+ auto pRefKid1 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKid1);
+ if (pRefKid1)
+ {
+ auto pObject2 = pRefKid1->LookupObject();
+ if (pObject2)
+ {
+ auto pType2 = dynamic_cast<vcl::filter::PDFNameElement*>(
+ pObject2->Lookup("Type"));
+ if (pType2 && pType2->GetValue() == "StructElem")
+ {
+ auto pS2 = dynamic_cast<vcl::filter::PDFNameElement*>(
+ pObject2->Lookup("S"));
+ if (pS2 && pS2->GetValue() == "TR")
+ {
+ int nTD(0);
+ auto pKids2 = dynamic_cast<vcl::filter::PDFArrayElement*>(
+ pObject2->Lookup("K"));
+ CPPUNIT_ASSERT(pKids2);
+ for (auto pKid2 : pKids2->GetElements())
+ {
+ auto pRefKid2
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+ pKid2);
+ if (pRefKid2)
+ {
+ auto pObject3 = pRefKid2->LookupObject();
+ if (pObject3)
+ {
+ auto pType3
+ = dynamic_cast<vcl::filter::PDFNameElement*>(
+ pObject3->Lookup("Type"));
+ if (pType3 && pType3->GetValue() == "StructElem")
+ {
+ auto pS3 = dynamic_cast<
+ vcl::filter::PDFNameElement*>(
+ pObject3->Lookup("S"));
+ if (nTR == 0 && pS3 && pS3->GetValue() == "TH")
+ {
+ int nOTable(0);
+ auto pAttrs = dynamic_cast<
+ vcl::filter::PDFArrayElement*>(
+ pObject3->Lookup("A"));
+ CPPUNIT_ASSERT(pAttrs != nullptr);
+ for (const auto& rAttrRef :
+ pAttrs->GetElements())
+ {
+ auto pARef = dynamic_cast<
+ vcl::filter::PDFReferenceElement*>(
+ rAttrRef);
+ CPPUNIT_ASSERT(pARef != nullptr);
+ auto pAttr = pARef->LookupObject();
+ CPPUNIT_ASSERT(pAttr != nullptr);
+ auto pAttrDict = pAttr->GetDictionary();
+ CPPUNIT_ASSERT(pAttrDict != nullptr);
+ auto pOwner = dynamic_cast<
+ vcl::filter::PDFNameElement*>(
+ pAttrDict->LookupElement("O"));
+ CPPUNIT_ASSERT(pOwner != nullptr);
+ if (pOwner->GetValue() == "Table")
+ {
+ auto pScope = dynamic_cast<
+ vcl::filter::PDFNameElement*>(
+ pAttrDict->LookupElement(
+ "Scope"));
+ CPPUNIT_ASSERT(pScope != nullptr);
+ CPPUNIT_ASSERT_EQUAL(
+ OString("Column"),
+ pScope->GetValue());
+ ++nOTable;
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(int(1), nOTable);
+ ++nTD;
+ }
+ else if (nTR != 0 && pS3
+ && pS3->GetValue() == "TD")
+ {
+ ++nTD;
+ }
+ }
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(int(3), nTD);
+ ++nTR;
+ }
+ }
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(int(2), nTR);
+ ++nTable;
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(int(1), nTable);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142129)
+{
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "master.odm";
+ mxComponent = loadFromDesktop(aURL);
+
+ // update linked section
+ dispatchCommand(mxComponent, ".uno:UpdateAllLinks", {});
+
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // Enable Outlines export
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "ExportBookmarks", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result.
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ auto* pCatalog = aDocument.GetCatalog();
+ CPPUNIT_ASSERT(pCatalog);
+ auto* pCatalogDictionary = pCatalog->GetDictionary();
+ CPPUNIT_ASSERT(pCatalogDictionary);
+ auto* pOutlinesObject = pCatalogDictionary->LookupObject("Outlines");
+ CPPUNIT_ASSERT(pOutlinesObject);
+ auto* pOutlinesDictionary = pOutlinesObject->GetDictionary();
+#if 0
+ // Type isn't actually written currently
+ auto* pType
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pOutlinesDictionary->LookupElement("Type"));
+ CPPUNIT_ASSERT(pType);
+ CPPUNIT_ASSERT_EQUAL(OString("Outlines"), pType->GetValue());
+#endif
+
+ auto* pFirst = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+ pOutlinesDictionary->LookupElement("First"));
+ CPPUNIT_ASSERT(pFirst);
+ auto* pFirstD = pFirst->LookupObject()->GetDictionary();
+ CPPUNIT_ASSERT(pFirstD);
+ //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast<vcl::filter::PDFNameElement*>(pFirstD->LookupElement("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Preface"), ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(
+ pFirstD->LookupElement("Title"))));
+
+ auto* pFirst1
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pFirstD->LookupElement("First"));
+ CPPUNIT_ASSERT(pFirst1);
+ auto* pFirst1D = pFirst1->LookupObject()->GetDictionary();
+ CPPUNIT_ASSERT(pFirst1D);
+ // here is a hidden section with headings "Copyright" etc.; check that
+ // there are no outline entries for it
+ //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast<vcl::filter::PDFNameElement*>(pFirst1D->LookupElement("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"Who is this book for?"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pFirst1D->LookupElement("Title"))));
+
+ auto* pFirst2
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pFirst1D->LookupElement("Next"));
+ auto* pFirst2D = pFirst2->LookupObject()->GetDictionary();
+ CPPUNIT_ASSERT(pFirst2D);
+ //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast<vcl::filter::PDFNameElement*>(pFirst2D->LookupElement("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"What\u2019s in this book?"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pFirst2D->LookupElement("Title"))));
+
+ auto* pFirst3
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pFirst2D->LookupElement("Next"));
+ auto* pFirst3D = pFirst3->LookupObject()->GetDictionary();
+ CPPUNIT_ASSERT(pFirst3D);
+ //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast<vcl::filter::PDFNameElement*>(pFirst3D->LookupElement("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"Minimum requirements for using LibreOffice"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pFirst3D->LookupElement("Title"))));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<vcl::filter::PDFElement*>(nullptr),
+ pFirst3D->LookupElement("Next"));
+ CPPUNIT_ASSERT_EQUAL(static_cast<vcl::filter::PDFElement*>(nullptr),
+ pFirstD->LookupElement("Next"));
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageRotate180)
+{
+ // Create an empty document.
+ mxComponent = loadFromDesktop("private:factory/swriter");
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XText> xText = xTextDocument->getText();
+ uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+
+ // Insert the PDF image.
+ uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xGraphicObject(
+ xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY);
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf-image-rotate-180.pdf";
+ xGraphicObject->setPropertyValue("GraphicURL", uno::Any(aURL));
+ uno::Reference<drawing::XShape> xShape(xGraphicObject, uno::UNO_QUERY);
+ xShape->setSize(awt::Size(1000, 1000));
+ uno::Reference<text::XTextContent> xTextContent(xGraphicObject, uno::UNO_QUERY);
+ xText->insertTextContent(xCursor->getStart(), xTextContent, /*bAbsorb=*/false);
+
+ // Save as PDF.
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ // Make sure that the page -> form -> form has a child image.
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pPageObject->getType());
+ // 2: white background and the actual object.
+ CPPUNIT_ASSERT_EQUAL(2, pPageObject->getFormObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject = pPageObject->getFormObject(1);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pFormObject->getType());
+ CPPUNIT_ASSERT_EQUAL(1, pFormObject->getFormObjectCount());
+
+ // Check if the inner form object (original page object in the pdf image) has the correct
+ // rotation.
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pInnerFormObject = pFormObject->getFormObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pInnerFormObject->getType());
+ CPPUNIT_ASSERT_EQUAL(1, pInnerFormObject->getFormObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pImage = pInnerFormObject->getFormObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pImage->getType());
+ basegfx::B2DHomMatrix aMat = pInnerFormObject->getMatrix();
+ basegfx::B2DTuple aScale;
+ basegfx::B2DTuple aTranslate;
+ double fRotate = 0;
+ double fShearX = 0;
+ aMat.decompose(aScale, aTranslate, fRotate, fShearX);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: -1
+ // - Actual : 1
+ // i.e. the 180 degrees rotation didn't happen (via a combination of horizontal + vertical
+ // flip).
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, aScale.getX(), 0.01);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf144222)
+{
+// Assume Windows has the font for U+4E2D
+#ifdef _WIN32
+ aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export");
+ saveAsPDF(u"tdf144222.ods");
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ std::unique_ptr<vcl::pdf::PDFiumTextPage> pTextPage = pPdfPage->getTextPage();
+ CPPUNIT_ASSERT(pTextPage);
+
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ const OUString sChar = u"\u4E2D";
+ basegfx::B2DRectangle aRect1, aRect2;
+ int nCount = 0;
+
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPdfPageObject = pPdfPage->getObject(i);
+ if (pPdfPageObject->getType() == vcl::pdf::PDFPageObjectType::Text)
+ {
+ ++nCount;
+ OUString sText = pPdfPageObject->getText(pTextPage);
+ if (sText == sChar)
+ aRect1 = pPdfPageObject->getBounds();
+ else
+ aRect2 = pPdfPageObject->getBounds();
+ }
+ }
+
+ CPPUNIT_ASSERT_EQUAL(2, nCount);
+ CPPUNIT_ASSERT(!aRect1.isEmpty());
+ CPPUNIT_ASSERT(!aRect2.isEmpty());
+ CPPUNIT_ASSERT(!aRect1.overlaps(aRect2));
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf145873)
+{
+ // Import the bugdoc and export as PDF.
+ aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export");
+ saveAsPDF(u"tdf145873.pptx");
+
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ int nPageObjectCount = pPdfPage->getObjectCount();
+
+ // tdf#145873: Without the fix #1 in place, this test would have failed with
+ // - Expected: 66
+ // - Actual : 3
+ CPPUNIT_ASSERT_EQUAL(66, nPageObjectCount);
+
+ auto pObject = pPdfPage->getObject(4);
+ CPPUNIT_ASSERT_MESSAGE("no object", pObject != nullptr);
+
+ // tdf#145873: Without the fix #2 in place, this test would have failed with
+ // - Expected: 13.23
+ // - Actual : 3.57...
+ // - Delta : 0.1
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(13.23, pObject->getBounds().getWidth(), 0.1);
+ // - Expected: 13.49
+ // - Actual : 3.74...
+ // - Delta : 0.1
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(13.49, pObject->getBounds().getHeight(), 0.1);
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageHyperlink)
+{
+ // Given a Draw file, containing a PDF image, which has a hyperlink in it:
+ aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export");
+
+ // When saving to PDF:
+ saveAsPDF(u"pdf-image-hyperlink.odg");
+
+ // Then make sure that link is preserved:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ // Without the accompanying fix in place, this test would have failed, the hyperlink of the PDF
+ // image was lost.
+ CPPUNIT_ASSERT(pPdfPage->hasLinks());
+
+ // Also test the precision of the form XObject.
+ // Given a full-page form XObject, page height is 27.94 cm (792 points):
+ // When writing the reciprocal of the object height to PDF:
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject;
+ for (int i = 0; i < pPdfPage->getObjectCount(); ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pObject = pPdfPage->getObject(i);
+ if (pObject->getType() == vcl::pdf::PDFPageObjectType::Form)
+ {
+ pFormObject = std::move(pObject);
+ break;
+ }
+ }
+ CPPUNIT_ASSERT(pFormObject);
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pInnerFormObject;
+ for (int i = 0; i < pFormObject->getFormObjectCount(); ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pObject = pFormObject->getFormObject(i);
+ if (pObject->getType() == vcl::pdf::PDFPageObjectType::Form)
+ {
+ pInnerFormObject = std::move(pObject);
+ break;
+ }
+ }
+ CPPUNIT_ASSERT(pInnerFormObject);
+ // Then make sure that enough digits are used, so the point size is unchanged:
+ basegfx::B2DHomMatrix aMatrix = pInnerFormObject->getMatrix();
+ basegfx::B2DTuple aScale;
+ basegfx::B2DTuple aTranslate;
+ double fRotate{};
+ double fShearX{};
+ aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 0.0012626264
+ // - Actual : 0.00126
+ // i.e. the rounded reciprocal was 794 points, not the original 792.
+ // FIXME macOS actual value is 0.0001578282, for unknown reasons.
+#if !defined MACOSX
+ CPPUNIT_ASSERT_EQUAL(0.0012626264, rtl::math::round(aScale.getY(), 10));
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testURIs)
+{
+ struct
+ {
+ OUString in;
+ OString out;
+ bool relativeFsys;
+ } URIs[]
+ = { {
+ "http://example.com/",
+ "http://example.com/",
+ true,
+ },
+ {
+ "file://localfile.odt/",
+ "file://localfile.odt/",
+ true,
+ },
+ {
+ // tdf 143216
+ "http://username:password@example.com",
+ "http://username:password@example.com",
+ true,
+ },
+ {
+ "git://git.example.org/project/example",
+ "git://git.example.org/project/example",
+ true,
+ },
+ {
+ // The odt/pdf gets substituted due to 'ConvertOOoTargetToPDFTarget'
+ "filebypath.odt",
+ "filebypath.pdf",
+ true,
+ },
+ {
+ // The odt/pdf gets substituted due to 'ConvertOOoTargetToPDFTarget'
+ // but this time with ExportLinksRelativeFsys off the path is added
+ "filebypath.odt",
+ OUStringToOString(utl::TempFile::GetTempNameBaseDirectory(), RTL_TEXTENCODING_UTF8)
+ + "filebypath.pdf",
+ false,
+ },
+ {
+ // This also gets made relative due to 'ExportLinksRelativeFsys'
+ utl::TempFile::GetTempNameBaseDirectory() + "fileintempdir.odt",
+ "fileintempdir.pdf",
+ true,
+ } };
+
+ // Create an empty document.
+ // Note: The test harness gets very upset if we try and create multiple
+ // documents, or recreate it; so reuse one instance for all the links
+ mxComponent = loadFromDesktop("private:factory/swriter");
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XText> xText = xTextDocument->getText();
+ uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+ xText->insertString(xCursor, "Test pdf", /*bAbsorb=*/false);
+
+ // Set the name so it can do relative name replacement
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ xModel->attachResource(maTempFile.GetURL(), xModel->getArgs());
+
+ for (unsigned int i = 0; i < (sizeof(URIs) / sizeof(URIs[0])); i++)
+ {
+ // Test the filename rewriting
+ uno::Sequence<beans::PropertyValue> aFilterData(comphelper::InitPropertySequence({
+ { "ExportLinksRelativeFsys", uno::Any(URIs[i].relativeFsys) },
+ { "ConvertOOoTargetToPDFTarget", uno::Any(true) },
+ }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+
+ // Add a link (based on testNestedHyperlink in rtfexport3)
+ xCursor->gotoStart(/*bExpand=*/false);
+ xCursor->gotoEnd(/*bExpand=*/true);
+ uno::Reference<beans::XPropertySet> xCursorProps(xCursor, uno::UNO_QUERY);
+ xCursorProps->setPropertyValue("HyperLinkURL", uno::Any(URIs[i].in));
+
+ // Save as PDF.
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Use the filter rather than the pdfium route, as per the tdf105093 test, it's
+ // easier to parse the annotations
+ vcl::filter::PDFDocument aDocument;
+
+ // Parse the export result.
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+ auto pAnnots = dynamic_cast<vcl::filter::PDFArrayElement*>(aPages[0]->Lookup("Annots"));
+ CPPUNIT_ASSERT(pAnnots);
+
+ // There should be one annotation
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pAnnots->GetElements().size());
+ auto pAnnotReference
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pAnnots->GetElements()[0]);
+ CPPUNIT_ASSERT(pAnnotReference);
+ vcl::filter::PDFObjectElement* pAnnot = pAnnotReference->LookupObject();
+ CPPUNIT_ASSERT(pAnnot);
+ // We're expecting something like /Type /Annot /A << /Type /Action /S /URI /URI (path)
+ CPPUNIT_ASSERT_EQUAL(
+ OString("Annot"),
+ static_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(
+ OString("Link"),
+ static_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Subtype"))->GetValue());
+ auto pAction = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pAnnot->Lookup("A"));
+ CPPUNIT_ASSERT(pAction);
+ auto pURIElem
+ = dynamic_cast<vcl::filter::PDFLiteralStringElement*>(pAction->LookupElement("URI"));
+ CPPUNIT_ASSERT(pURIElem);
+ // Check it matches
+ CPPUNIT_ASSERT_EQUAL(URIs[i].out, pURIElem->GetValue());
+ // tdf#148934 check a11y
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("Test pdf"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pAnnot->Lookup("Contents"))));
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageAnnots)
+{
+ // Given a document with a PDF image that has 2 comments (popup, text) and a hyperlink:
+ aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export");
+
+ // When saving to PDF:
+ saveAsPDF(u"pdf-image-annots.odg");
+
+ // Then make sure only the hyperlink is kept, since Draw itself has its own comments:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 1
+ // - Actual : 3
+ // i.e. not only the hyperlink but also the 2 comments were exported, leading to duplication.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageEncryption)
+{
+ // Given an empty document, with an inserted PDF image:
+ mxComponent = loadFromDesktop("private:factory/swriter");
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XText> xText = xTextDocument->getText();
+ uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+ uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xGraphicObject(
+ xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY);
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "rectangles.pdf";
+ xGraphicObject->setPropertyValue("GraphicURL", uno::Any(aURL));
+ uno::Reference<drawing::XShape> xShape(xGraphicObject, uno::UNO_QUERY);
+ xShape->setSize(awt::Size(1000, 1000));
+ uno::Reference<text::XTextContent> xTextContent(xGraphicObject, uno::UNO_QUERY);
+ xText->insertTextContent(xCursor->getStart(), xTextContent, /*bAbsorb=*/false);
+
+ // When saving as encrypted PDF:
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ uno::Sequence<beans::PropertyValue> aFilterData = {
+ comphelper::makePropertyValue("EncryptFile", true),
+ comphelper::makePropertyValue("DocumentOpenPassword", OUString("secret")),
+ };
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Then make sure that the image is not lost:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport("secret");
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pPageObject->getType());
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 2
+ // - Actual : 0
+ // i.e. instead of the white background and the actual form child, the image was lost due to
+ // missing encryption.
+ CPPUNIT_ASSERT_EQUAL(2, pPageObject->getFormObjectCount());
+}
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testBitmapScaledown)
+{
+ // Given a document with an upscaled and rotated barcode bitmap in it:
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // When saving as PDF:
+ saveAsPDF(u"bitmap-scaledown.odt");
+
+ // Then verify that the bitmap is not downscaled:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ int nPageObjectCount = pPdfPage->getObjectCount();
+ for (int i = 0; i < nPageObjectCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(i);
+ if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image)
+ continue;
+
+ std::unique_ptr<vcl::pdf::PDFiumBitmap> pBitmap = pPageObject->getImageBitmap();
+ CPPUNIT_ASSERT(pBitmap);
+ // In-file sizes: good is 2631x380, bad is 1565x14.
+ int nWidth = pBitmap->getWidth();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 2616
+ // - Actual : 1565
+ // i.e. the bitmap in the pdf result was small enough to be blurry.
+ CPPUNIT_ASSERT_EQUAL(2616, nWidth);
+ }
+}
+} // end anonymous namespace
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/physicalfontcollection.cxx b/vcl/qa/cppunit/physicalfontcollection.cxx
new file mode 100644
index 000000000..0d79c0f8f
--- /dev/null
+++ b/vcl/qa/cppunit/physicalfontcollection.cxx
@@ -0,0 +1,551 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <font/PhysicalFontCollection.hxx>
+#include <font/PhysicalFontFamily.hxx>
+
+#include "fontmocks.hxx"
+
+#include <memory>
+
+constexpr int FONTID = 1;
+
+class VclPhysicalFontCollectionTest : public test::BootstrapFixture
+{
+public:
+ VclPhysicalFontCollectionTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testShouldCreateAndAddFontFamilyToCollection();
+ void testShouldFindFontFamily();
+ void testShouldNotFindFontFamily();
+ void testShouldFindFontFamilyByTokenNames();
+ void testShouldFindNoFamilyWithWorthlessAttributes();
+ void testShouldFindCJKFamily();
+ void testShouldNotFindCJKFamily();
+ void testShouldFindStarsymbolFamily();
+ void testShouldFindOpensymbolFamilyWithMultipleSymbolFamilies();
+ void testShouldFindSymboltypeFamily();
+ void testShouldFindSymbolFamilyByMatchType();
+ void testImpossibleSymbolFamily();
+ void testShouldNotFindSymbolFamily();
+ void testShouldMatchFamilyName();
+ void testShouldMatchBrushScriptFamily();
+ void testShouldNotMatchBrushScriptFamily();
+ void testShouldMatchFixedFamily();
+ void testShouldNotMatchFixedFamily();
+ void testShouldMatchSerifFamily();
+ void testShouldNotMatchSerifFamily();
+ void testShouldMatchSansSerifFamily();
+ void testShouldNotMatchSansSerifFamily();
+ void testShouldMatchDecorativeFamily();
+ void testShouldFindTitlingFamily();
+ void testShouldFindCapitalsFamily();
+ void testShouldFindFamilyName();
+ void testShouldFindOtherStyleFamily();
+ void testShouldNotFindOtherStyleFamily();
+ void testShouldFindSchoolbookFamily();
+
+ CPPUNIT_TEST_SUITE(VclPhysicalFontCollectionTest);
+ CPPUNIT_TEST(testShouldCreateAndAddFontFamilyToCollection);
+ CPPUNIT_TEST(testShouldFindFontFamily);
+ CPPUNIT_TEST(testShouldNotFindFontFamily);
+ CPPUNIT_TEST(testShouldFindFontFamilyByTokenNames);
+ CPPUNIT_TEST(testShouldFindNoFamilyWithWorthlessAttributes);
+ CPPUNIT_TEST(testShouldFindCJKFamily);
+ CPPUNIT_TEST(testShouldNotFindCJKFamily);
+ CPPUNIT_TEST(testShouldFindStarsymbolFamily);
+ CPPUNIT_TEST(testShouldFindOpensymbolFamilyWithMultipleSymbolFamilies);
+ CPPUNIT_TEST(testShouldFindSymboltypeFamily);
+ CPPUNIT_TEST(testShouldFindSymbolFamilyByMatchType);
+ CPPUNIT_TEST(testImpossibleSymbolFamily);
+ CPPUNIT_TEST(testShouldNotFindSymbolFamily);
+ CPPUNIT_TEST(testShouldMatchFamilyName);
+ CPPUNIT_TEST(testShouldMatchBrushScriptFamily);
+ CPPUNIT_TEST(testShouldNotMatchBrushScriptFamily);
+ CPPUNIT_TEST(testShouldMatchFixedFamily);
+ CPPUNIT_TEST(testShouldNotMatchFixedFamily);
+ CPPUNIT_TEST(testShouldMatchSerifFamily);
+ CPPUNIT_TEST(testShouldNotMatchSerifFamily);
+ CPPUNIT_TEST(testShouldMatchSansSerifFamily);
+ CPPUNIT_TEST(testShouldNotMatchSansSerifFamily);
+ CPPUNIT_TEST(testShouldMatchDecorativeFamily);
+ CPPUNIT_TEST(testShouldFindTitlingFamily);
+ CPPUNIT_TEST(testShouldFindCapitalsFamily);
+ CPPUNIT_TEST(testShouldFindFamilyName);
+ CPPUNIT_TEST(testShouldFindOtherStyleFamily);
+ CPPUNIT_TEST(testShouldNotFindOtherStyleFamily);
+ CPPUNIT_TEST(testShouldFindSchoolbookFamily);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclPhysicalFontCollectionTest::testShouldCreateAndAddFontFamilyToCollection()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Empty font collection", static_cast<int>(0),
+ aFontCollection.Count());
+
+ // please note that fonts created this way are NOT normalized and will not be found if you search for them in the collection
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("Test Font Family Name");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Does not have only one font family in collection",
+ static_cast<int>(1), aFontCollection.Count());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Font family name not correct", OUString("Test Font Family Name"),
+ pFontFamily->GetSearchName());
+
+ vcl::font::PhysicalFontFamily* pFontFamily2
+ = aFontCollection.FindOrCreateFontFamily("Test Font Family Name");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Still only one font family in collection", static_cast<int>(1),
+ aFontCollection.Count());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Font family name not correct", OUString("Test Font Family Name"),
+ pFontFamily2->GetSearchName());
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindFontFamily()
+{
+ // note: you must normalize the search family name (first parameter of PhysicalFontFamily constructor)
+ vcl::font::PhysicalFontCollection aFontCollection;
+ aFontCollection.FindOrCreateFontFamily(GetEnglishSearchFontName(u"Test Font Family Name"));
+
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindFontFamily(u"Test Font Family Name");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Font family name not correct",
+ GetEnglishSearchFontName(u"Test Font Family Name"),
+ pFontFamily->GetSearchName());
+}
+
+void VclPhysicalFontCollectionTest::testShouldNotFindFontFamily()
+{
+ // note: you must normalize the search family name (first parameter of PhysicalFontFamily constructor)
+ vcl::font::PhysicalFontCollection aFontCollection;
+ aFontCollection.FindOrCreateFontFamily(GetEnglishSearchFontName(u"Test Font Family Name"));
+
+ CPPUNIT_ASSERT(!aFontCollection.FindFontFamily(u"blah"));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindFontFamilyByTokenNames()
+{
+ // note: you must normalize the search family name (first parameter of PhysicalFontFamily constructor)
+ vcl::font::PhysicalFontCollection aFontCollection;
+ aFontCollection.FindOrCreateFontFamily(GetEnglishSearchFontName(u"Test Font Family Name"));
+
+ OUString sTokenNames(GetEnglishSearchFontName(u"Test Font Family Name;"));
+ sTokenNames += GetEnglishSearchFontName(u"Test 2");
+
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindFontFamilyByTokenNames(u"Test Font Family Name");
+ CPPUNIT_ASSERT_MESSAGE("Did not find the font family", pFontFamily);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Font family name incorrect",
+ GetEnglishSearchFontName(u"Test Font Family Name"),
+ pFontFamily->GetSearchName());
+}
+
+static void AddNormalFontFace(vcl::font::PhysicalFontFamily* const pFontFamily,
+ OUString const& rFamilyName)
+{
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName(rFamilyName);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ pFontFamily->AddFontFace(new TestFontFace(aFontAttr, FONTID));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindNoFamilyWithWorthlessAttributes()
+{
+ // note: you must normalize the search family name (first parameter of PhysicalFontFamily constructor)
+ vcl::font::PhysicalFontCollection aFontCollection;
+ aFontCollection.FindOrCreateFontFamily(GetEnglishSearchFontName(u"Test Font Family Name"));
+
+ CPPUNIT_ASSERT(!aFontCollection.FindFontFamilyByAttributes(ImplFontAttrs::None, WEIGHT_NORMAL,
+ WIDTH_NORMAL, ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindCJKFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+
+ // interestingly, you need to normalize the name still
+ vcl::font::PhysicalFontFamily* pFontFamily = aFontCollection.FindOrCreateFontFamily(
+ GetEnglishSearchFontName(u"시험")); // Korean for "test"
+ AddNormalFontFace(pFontFamily, u"시험");
+
+ vcl::font::PhysicalFontFamily* pCJKFamily = aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::CJK, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NORMAL, "");
+ CPPUNIT_ASSERT_MESSAGE("family not found", pCJKFamily);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("cjk family not found", GetEnglishSearchFontName(u"시험"),
+ pCJKFamily->GetSearchName());
+}
+
+void VclPhysicalFontCollectionTest::testShouldNotFindCJKFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily(GetEnglishSearchFontName(u"No CJK characters"));
+ AddNormalFontFace(pFontFamily, "No CJK characters");
+
+ CPPUNIT_ASSERT_MESSAGE("family found",
+ !aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::CJK, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindStarsymbolFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("starsymbol");
+ AddNormalFontFace(pFontFamily, "starsymbol");
+
+ CPPUNIT_ASSERT_MESSAGE("starsymbol created", pFontFamily);
+
+ vcl::font::PhysicalFontFamily* pStarsymbolFamily = aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Symbol, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NORMAL, "");
+ CPPUNIT_ASSERT_MESSAGE("family not found", pStarsymbolFamily);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("starsymbol family not found", OUString("starsymbol"),
+ pStarsymbolFamily->GetSearchName());
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindOpensymbolFamilyWithMultipleSymbolFamilies()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+
+ vcl::font::PhysicalFontFamily* pOpenSymbolFamily
+ = aFontCollection.FindOrCreateFontFamily("opensymbol");
+ AddNormalFontFace(pOpenSymbolFamily, "opensymbol");
+
+ vcl::font::PhysicalFontFamily* pWingDingsFontFamily
+ = aFontCollection.FindOrCreateFontFamily("wingdings");
+ AddNormalFontFace(pWingDingsFontFamily, "wingdings");
+
+ vcl::font::PhysicalFontFamily* pStarsymbolFamily = aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Symbol, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NORMAL, "");
+ CPPUNIT_ASSERT_MESSAGE("family not found", pStarsymbolFamily);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("opensymbol family not found", OUString("opensymbol"),
+ pStarsymbolFamily->GetSearchName());
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindSymboltypeFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("testsymbol");
+
+ AddNormalFontFace(pFontFamily, "testsymbol");
+
+ vcl::font::PhysicalFontFamily* pSymbolFamily = aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Symbol, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NORMAL, "");
+ CPPUNIT_ASSERT_MESSAGE("family not found", pSymbolFamily);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test symbol family not found", OUString("testsymbol"),
+ pSymbolFamily->GetSearchName());
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindSymbolFamilyByMatchType()
+{
+ // TODO: figure out how to test matchtype with ImplFontAttrs::Full
+
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily = aFontCollection.FindOrCreateFontFamily("symbols");
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName("symbols");
+ aFontAttr.SetSymbolFlag(true);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ pFontFamily->AddFontFace(new TestFontFace(aFontAttr, FONTID));
+
+ vcl::font::PhysicalFontFamily* pSymbolFamily = aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Symbol, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NORMAL, "");
+ CPPUNIT_ASSERT_MESSAGE("family not found", pSymbolFamily);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test symbol family not found", OUString("symbols"),
+ pSymbolFamily->GetSearchName());
+}
+
+void VclPhysicalFontCollectionTest::testImpossibleSymbolFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("testsymbolfamily");
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName("testsymbolfamily");
+ aFontAttr.SetSymbolFlag(true);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ TestFontFace* pFontFace = new TestFontFace(aFontAttr, FONTID);
+ pFontFamily->AddFontFace(pFontFace);
+
+ CPPUNIT_ASSERT_MESSAGE("match for family not possible, but was found anyway",
+ !aFontCollection.FindFontFamilyByAttributes(ImplFontAttrs::Normal,
+ WEIGHT_NORMAL, WIDTH_NORMAL,
+ ITALIC_NORMAL, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldNotFindSymbolFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily = aFontCollection.FindOrCreateFontFamily("symbol");
+ AddNormalFontFace(pFontFamily, "symbol");
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Family found", !aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Normal, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldMatchFamilyName()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+
+ // note that for this test, it is irrelevant what the search name is for PhysicalFontFamily,
+ // the font searches the family name and uses the search parameter of FindFontFamilyByAttributes()
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily(u"Matching family name");
+ AddNormalFontFace(pFontFamily, GetEnglishSearchFontName(u"Matching family name"));
+
+ CPPUNIT_ASSERT_MESSAGE("No family found",
+ aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Normal, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NONE,
+ "Matching family name"));
+}
+
+void VclPhysicalFontCollectionTest::testShouldMatchBrushScriptFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily = aFontCollection.FindOrCreateFontFamily("script");
+ AddNormalFontFace(pFontFamily, "script");
+
+ CPPUNIT_ASSERT_MESSAGE("Brush script family not found",
+ aFontCollection.FindFontFamilyByAttributes(ImplFontAttrs::BrushScript,
+ WEIGHT_NORMAL, WIDTH_NORMAL,
+ ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldNotMatchBrushScriptFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("testfamily");
+ AddNormalFontFace(pFontFamily, "testfamily");
+
+ CPPUNIT_ASSERT_MESSAGE("Brush script family found",
+ !aFontCollection.FindFontFamilyByAttributes(ImplFontAttrs::BrushScript,
+ WEIGHT_NORMAL, WIDTH_NORMAL,
+ ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldMatchFixedFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+
+ // note that for this test, it is irrelevant what the search name is for PhysicalFontFamily,
+ // the font searches the family name and uses the search parameter of FindFontFamilyByAttributes()
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily(GetEnglishSearchFontName(u"Matching family name"));
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName(GetEnglishSearchFontName(u"Matching family name"));
+ aFontAttr.SetFamilyType(FAMILY_MODERN);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ TestFontFace* pFontFace = new TestFontFace(aFontAttr, FONTID);
+ pFontFamily->AddFontFace(pFontFace);
+
+ CPPUNIT_ASSERT_MESSAGE("No fixed family found",
+ aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Fixed, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NONE,
+ GetEnglishSearchFontName(u"Matching family name")));
+}
+
+void VclPhysicalFontCollectionTest::testShouldNotMatchFixedFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+
+ // note that for this test, it is irrelevant what the search name is for PhysicalFontFamily,
+ // the font searches the family name and uses the search parameter of FindFontFamilyByAttributes()
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily(GetEnglishSearchFontName(u"Matching family name"));
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName(GetEnglishSearchFontName(u"Matching family name"));
+ aFontAttr.SetFamilyType(FAMILY_SWISS);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ TestFontFace* pFontFace = new TestFontFace(aFontAttr, FONTID);
+ pFontFamily->AddFontFace(pFontFace);
+
+ CPPUNIT_ASSERT_MESSAGE("Fixed family found",
+ aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Fixed, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NONE,
+ GetEnglishSearchFontName(u"Matching family name")));
+}
+
+void VclPhysicalFontCollectionTest::testShouldMatchSerifFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily = aFontCollection.FindOrCreateFontFamily("serif");
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName("serif");
+ aFontAttr.SetFamilyType(FAMILY_ROMAN);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ TestFontFace* pFontFace = new TestFontFace(aFontAttr, FONTID);
+ pFontFamily->AddFontFace(pFontFace);
+
+ CPPUNIT_ASSERT_MESSAGE("Serif family not found",
+ aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Serif, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldNotMatchSerifFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("sansseriftest");
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName("sansseriftest");
+ aFontAttr.SetFamilyType(FAMILY_SWISS);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ TestFontFace* pFontFace = new TestFontFace(aFontAttr, FONTID);
+ pFontFamily->AddFontFace(pFontFace);
+
+ CPPUNIT_ASSERT_MESSAGE("Serif family found",
+ !aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Serif, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldMatchSansSerifFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("sansserif");
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName("sansserif");
+ aFontAttr.SetFamilyType(FAMILY_SWISS);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ TestFontFace* pFontFace = new TestFontFace(aFontAttr, FONTID);
+ pFontFamily->AddFontFace(pFontFace);
+
+ CPPUNIT_ASSERT_MESSAGE("SansSerif family not found",
+ aFontCollection.FindFontFamilyByAttributes(ImplFontAttrs::SansSerif,
+ WEIGHT_NORMAL, WIDTH_NORMAL,
+ ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldNotMatchSansSerifFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily = aFontCollection.FindOrCreateFontFamily("serif");
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName("serif");
+ aFontAttr.SetFamilyType(FAMILY_ROMAN);
+ aFontAttr.SetWeight(WEIGHT_NORMAL);
+ TestFontFace* pFontFace = new TestFontFace(aFontAttr, FONTID);
+ pFontFamily->AddFontFace(pFontFace);
+
+ CPPUNIT_ASSERT_MESSAGE("SansSerif family found", !aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::SansSerif, WEIGHT_NORMAL,
+ WIDTH_NORMAL, ITALIC_NONE, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldMatchDecorativeFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("decorative");
+
+ FontAttributes aFontAttr;
+ aFontAttr.SetFamilyName("decorative");
+ aFontAttr.SetFamilyType(FAMILY_DECORATIVE);
+ aFontAttr.SetWeight(WEIGHT_MEDIUM);
+ TestFontFace* pFontFace = new TestFontFace(aFontAttr, FONTID);
+ pFontFamily->AddFontFace(pFontFace);
+
+ CPPUNIT_ASSERT_MESSAGE("Decorative family not found",
+ aFontCollection.FindFontFamilyByAttributes(ImplFontAttrs::Decorative,
+ WEIGHT_NORMAL, WIDTH_NORMAL,
+ ITALIC_NORMAL, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindTitlingFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("testtitling");
+ AddNormalFontFace(pFontFamily, "testtitling");
+
+ CPPUNIT_ASSERT_MESSAGE("Titling family not found", aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Titling, WEIGHT_NORMAL,
+ WIDTH_NORMAL, ITALIC_NORMAL, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindCapitalsFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily = aFontCollection.FindOrCreateFontFamily("testcaps");
+ AddNormalFontFace(pFontFamily, "testcaps");
+
+ CPPUNIT_ASSERT_MESSAGE("All-caps family not found", aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Capitals, WEIGHT_NORMAL,
+ WIDTH_NORMAL, ITALIC_NORMAL, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindFamilyName()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily(GetEnglishSearchFontName(u"Test font name"));
+ AddNormalFontFace(pFontFamily, GetEnglishSearchFontName(u"Test font name"));
+
+ CPPUNIT_ASSERT_MESSAGE("Cannot find font name",
+ aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Capitals, WEIGHT_NORMAL, WIDTH_NORMAL, ITALIC_NORMAL,
+ GetEnglishSearchFontName(u"Test font name")));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindOtherStyleFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("testoldstyle");
+ AddNormalFontFace(pFontFamily, "testoldstyle");
+
+ CPPUNIT_ASSERT_MESSAGE("Did not find font name", aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::OtherStyle, WEIGHT_NORMAL,
+ WIDTH_NORMAL, ITALIC_NORMAL, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldNotFindOtherStyleFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily = aFontCollection.FindOrCreateFontFamily("monotype");
+ AddNormalFontFace(pFontFamily, "monotype");
+
+ CPPUNIT_ASSERT_MESSAGE("Found font name", !aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::OtherStyle, WEIGHT_NORMAL,
+ WIDTH_NORMAL, ITALIC_NORMAL, ""));
+}
+
+void VclPhysicalFontCollectionTest::testShouldFindSchoolbookFamily()
+{
+ vcl::font::PhysicalFontCollection aFontCollection;
+ vcl::font::PhysicalFontFamily* pFontFamily
+ = aFontCollection.FindOrCreateFontFamily("testschoolbook");
+ AddNormalFontFace(pFontFamily, "testschoolbook");
+
+ CPPUNIT_ASSERT_MESSAGE("Did not find font name", aFontCollection.FindFontFamilyByAttributes(
+ ImplFontAttrs::Schoolbook, WEIGHT_NORMAL,
+ WIDTH_NORMAL, ITALIC_NORMAL, ""));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclPhysicalFontCollectionTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/physicalfontface.cxx b/vcl/qa/cppunit/physicalfontface.cxx
new file mode 100644
index 000000000..87fdc382b
--- /dev/null
+++ b/vcl/qa/cppunit/physicalfontface.cxx
@@ -0,0 +1,301 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <tools/degree.hxx>
+
+#include <vcl/font.hxx>
+
+#include <font/PhysicalFontFace.hxx>
+#include <fontattributes.hxx>
+
+#include "fontmocks.hxx"
+
+#include <memory>
+
+const sal_IntPtr FONTID = 1;
+
+class VclPhysicalFontFaceTest : public test::BootstrapFixture
+{
+public:
+ VclPhysicalFontFaceTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testShouldCompareAsLesserFontFaceWithShorterWidth();
+ void testShouldCompareAsGreaterFontFaceWithLongerWidth();
+ void testShouldCompareAsLesserFontFaceWithLighterWeight();
+ void testShouldCompareAsGreaterFontFaceWithHeavierWeight();
+ void testShouldCompareAsLesserFontFaceWithLesserItalics();
+ void testShouldCompareAsGreaterFontFaceWithGreaterItalics();
+ void testShouldCompareAsGreaterFontFaceWitHigherAlphabeticalFamilyName();
+ void testShouldCompareAsGreaterFontFaceWitLesserAlphabeticalFamilyName();
+ void testShouldCompareAsGreaterFontFaceWithHigherAlphabeticalStyleName();
+ void testShouldCompareAsGreaterFontFaceWithLesserAlphabeticalStyleName();
+ void testShouldCompareAsSameFontFace();
+ void testMatchStatusValue();
+
+ CPPUNIT_TEST_SUITE(VclPhysicalFontFaceTest);
+ CPPUNIT_TEST(testShouldCompareAsLesserFontFaceWithShorterWidth);
+ CPPUNIT_TEST(testShouldCompareAsGreaterFontFaceWithLongerWidth);
+ CPPUNIT_TEST(testShouldCompareAsLesserFontFaceWithLighterWeight);
+ CPPUNIT_TEST(testShouldCompareAsGreaterFontFaceWithHeavierWeight);
+ CPPUNIT_TEST(testShouldCompareAsLesserFontFaceWithLesserItalics);
+ CPPUNIT_TEST(testShouldCompareAsGreaterFontFaceWithGreaterItalics);
+ CPPUNIT_TEST(testShouldCompareAsGreaterFontFaceWitHigherAlphabeticalFamilyName);
+ CPPUNIT_TEST(testShouldCompareAsGreaterFontFaceWitLesserAlphabeticalFamilyName);
+ CPPUNIT_TEST(testShouldCompareAsGreaterFontFaceWithHigherAlphabeticalStyleName);
+ CPPUNIT_TEST(testShouldCompareAsGreaterFontFaceWithLesserAlphabeticalStyleName);
+ CPPUNIT_TEST(testShouldCompareAsSameFontFace);
+ CPPUNIT_TEST(testMatchStatusValue);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclPhysicalFontFaceTest::testShouldCompareAsLesserFontFaceWithShorterWidth()
+{
+ FontAttributes aFontAttrsShorterWidth;
+ aFontAttrsShorterWidth.SetWidthType(WIDTH_CONDENSED);
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrsShorterWidth, FONTID));
+
+ FontAttributes aFontAttrsLongerWidth;
+ aFontAttrsLongerWidth.SetWidthType(WIDTH_NORMAL);
+ rtl::Reference<TestFontFace> aComparedToFontFace(
+ new TestFontFace(aFontAttrsLongerWidth, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsGreaterFontFaceWithLongerWidth()
+{
+ FontAttributes aFontAttrsLongerWidth;
+ aFontAttrsLongerWidth.SetWidthType(WIDTH_NORMAL);
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrsLongerWidth, FONTID));
+
+ FontAttributes aFontAttrsShorterWidth;
+ aFontAttrsShorterWidth.SetWidthType(WIDTH_CONDENSED);
+ rtl::Reference<TestFontFace> aComparedToFontFace(
+ new TestFontFace(aFontAttrsShorterWidth, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsLesserFontFaceWithLighterWeight()
+{
+ FontAttributes aFontAttrsLighterWeight;
+ aFontAttrsLighterWeight.SetWidthType(WIDTH_NORMAL);
+ aFontAttrsLighterWeight.SetWeight(WEIGHT_THIN);
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrsLighterWeight, FONTID));
+
+ FontAttributes aFontAttrsHeavierWeight;
+ aFontAttrsHeavierWeight.SetWeight(WEIGHT_BOLD);
+ aFontAttrsHeavierWeight.SetWidthType(WIDTH_NORMAL);
+ rtl::Reference<TestFontFace> aComparedToFontFace(
+ new TestFontFace(aFontAttrsHeavierWeight, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsGreaterFontFaceWithHeavierWeight()
+{
+ FontAttributes aFontAttrsHeavierWeight;
+ aFontAttrsHeavierWeight.SetWidthType(WIDTH_NORMAL);
+ aFontAttrsHeavierWeight.SetWeight(WEIGHT_BOLD);
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrsHeavierWeight, FONTID));
+
+ FontAttributes aFontAttrsLighterWeight;
+ aFontAttrsLighterWeight.SetWidthType(WIDTH_NORMAL);
+ aFontAttrsLighterWeight.SetWeight(WEIGHT_THIN);
+ rtl::Reference<TestFontFace> aComparedToFontFace(
+ new TestFontFace(aFontAttrsLighterWeight, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsLesserFontFaceWithLesserItalics()
+{
+ FontAttributes aFontAttrsLesserItalics;
+ aFontAttrsLesserItalics.SetWidthType(WIDTH_NORMAL);
+ aFontAttrsLesserItalics.SetWeight(WEIGHT_THIN);
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrsLesserItalics, FONTID));
+
+ FontAttributes aFontAttrsGreaterItalics;
+ aFontAttrsGreaterItalics.SetWeight(WEIGHT_BOLD);
+ aFontAttrsGreaterItalics.SetWidthType(WIDTH_NORMAL);
+ rtl::Reference<TestFontFace> aComparedToFontFace(
+ new TestFontFace(aFontAttrsGreaterItalics, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsGreaterFontFaceWithGreaterItalics()
+{
+ FontAttributes aFontAttrsGreaterItalics;
+ aFontAttrsGreaterItalics.SetWidthType(WIDTH_NORMAL);
+ aFontAttrsGreaterItalics.SetWeight(WEIGHT_BOLD);
+ rtl::Reference<TestFontFace> aTestedFontFace(
+ new TestFontFace(aFontAttrsGreaterItalics, FONTID));
+
+ FontAttributes aFontAttrsLesserItalics;
+ aFontAttrsLesserItalics.SetWidthType(WIDTH_NORMAL);
+ aFontAttrsLesserItalics.SetWeight(WEIGHT_THIN);
+ rtl::Reference<TestFontFace> aComparedToFontFace(
+ new TestFontFace(aFontAttrsLesserItalics, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsGreaterFontFaceWitHigherAlphabeticalFamilyName()
+{
+ FontAttributes aFontAttrs1;
+ aFontAttrs1.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs1.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs1.SetFamilyName("B family");
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrs1, FONTID));
+
+ FontAttributes aFontAttrs2;
+ aFontAttrs2.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs2.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs2.SetFamilyName("A Family");
+ rtl::Reference<TestFontFace> aComparedToFontFace(new TestFontFace(aFontAttrs2, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsGreaterFontFaceWitLesserAlphabeticalFamilyName()
+{
+ FontAttributes aFontAttrs1;
+ aFontAttrs1.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs1.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs1.SetFamilyName("A family");
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrs1, FONTID));
+
+ FontAttributes aFontAttrs2;
+ aFontAttrs2.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs2.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs2.SetFamilyName("B Family");
+ rtl::Reference<TestFontFace> aComparedToFontFace(new TestFontFace(aFontAttrs2, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsGreaterFontFaceWithHigherAlphabeticalStyleName()
+{
+ FontAttributes aFontAttrs1;
+ aFontAttrs1.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs1.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs1.SetFamilyName("DejaVu Sans");
+ aFontAttrs1.SetStyleName("B Style");
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrs1, FONTID));
+
+ FontAttributes aFontAttrs2;
+ aFontAttrs2.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs2.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs2.SetFamilyName("DejaVu Sans");
+ aFontAttrs2.SetStyleName("A Style");
+ rtl::Reference<TestFontFace> aComparedToFontFace(new TestFontFace(aFontAttrs2, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsGreaterFontFaceWithLesserAlphabeticalStyleName()
+{
+ FontAttributes aFontAttrs1;
+ aFontAttrs1.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs1.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs1.SetFamilyName("DejaVu Sans");
+ aFontAttrs1.SetStyleName("A Style");
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrs1, FONTID));
+
+ FontAttributes aFontAttrs2;
+ aFontAttrs2.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs2.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs2.SetFamilyName("DejaVu Sans");
+ aFontAttrs2.SetStyleName("B Style");
+ rtl::Reference<TestFontFace> aComparedToFontFace(new TestFontFace(aFontAttrs2, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-1),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testShouldCompareAsSameFontFace()
+{
+ FontAttributes aFontAttrs1;
+ aFontAttrs1.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs1.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs1.SetFamilyName("DejaVu Sans");
+ aFontAttrs1.SetStyleName("Style");
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrs1, FONTID));
+
+ FontAttributes aFontAttrs2;
+ aFontAttrs2.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs2.SetWeight(WEIGHT_NORMAL);
+ aFontAttrs2.SetFamilyName("DejaVu Sans");
+ aFontAttrs2.SetStyleName("Style");
+ rtl::Reference<TestFontFace> aComparedToFontFace(new TestFontFace(aFontAttrs2, FONTID));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
+ aTestedFontFace->CompareIgnoreSize(*aComparedToFontFace));
+}
+
+void VclPhysicalFontFaceTest::testMatchStatusValue()
+{
+ FontAttributes aFontAttrs;
+ aFontAttrs.SetFamilyName("DejaVu Sans");
+ aFontAttrs.SetStyleName("Book");
+ aFontAttrs.SetPitch(FontPitch::PITCH_VARIABLE);
+ aFontAttrs.SetWidthType(WIDTH_NORMAL);
+ aFontAttrs.SetWeight(WEIGHT_BOLD);
+ rtl::Reference<TestFontFace> aTestedFontFace(new TestFontFace(aFontAttrs, FONTID));
+
+ std::unique_ptr<OUString> pTargetStyleName(new OUString("Book"));
+ vcl::font::FontMatchStatus aFontMatchStatus = { 0, pTargetStyleName.get() };
+
+ vcl::Font aTestFont("DejaVu Sans", "Book", Size(0, 36));
+
+ vcl::font::FontSelectPattern aFSP(aTestFont, "DejaVu Sans", Size(0, 36), 36, true);
+ aFSP.mbEmbolden = false;
+ aFSP.mnOrientation = Degree10(10);
+ aFSP.SetWeight(WEIGHT_BOLD);
+ aFSP.SetPitch(FontPitch::PITCH_VARIABLE);
+ aFSP.maTargetName = "DejaVu Sans";
+
+ const int EXPECTED_FAMILY = 240'000;
+ const int EXPECTED_STYLE = 120'000;
+ const int EXPECTED_PITCH = 20'000;
+ const int EXPECTED_WIDTHTYPE = 400;
+ const int EXPECTED_WEIGHT = 1'000;
+ const int EXPECTED_ITALIC = 900;
+ const int EXPECTED_ORIENTATION = 80;
+
+ const int EXPECTED_MATCH = EXPECTED_FAMILY + EXPECTED_STYLE + EXPECTED_PITCH
+ + EXPECTED_WIDTHTYPE + EXPECTED_WEIGHT + EXPECTED_ITALIC
+ + EXPECTED_ORIENTATION;
+
+ CPPUNIT_ASSERT(aTestedFontFace->IsBetterMatch(aFSP, aFontMatchStatus));
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_MATCH, aFontMatchStatus.mnFaceMatch);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclPhysicalFontFaceTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/qa/cppunit/physicalfontfacecollection.cxx b/vcl/qa/cppunit/physicalfontfacecollection.cxx
new file mode 100644
index 000000000..358a5b994
--- /dev/null
+++ b/vcl/qa/cppunit/physicalfontfacecollection.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <rtl/ref.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include <vcl/fontcapabilities.hxx>
+#include <vcl/fontcharmap.hxx>
+#include <vcl/virdev.hxx>
+
+#include "fontmocks.hxx"
+
+class VclPhysicalFontFaceCollectionTest : public test::BootstrapFixture
+{
+public:
+ VclPhysicalFontFaceCollectionTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testShouldGetFontId();
+
+ CPPUNIT_TEST_SUITE(VclPhysicalFontFaceCollectionTest);
+ CPPUNIT_TEST(testShouldGetFontId);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclPhysicalFontFaceCollectionTest::testShouldGetFontId()
+{
+ vcl::font::PhysicalFontFaceCollection aCollection;
+ aCollection.Add(new TestFontFace(1988756));
+
+ rtl::Reference<vcl::font::PhysicalFontFace> pActual(new TestFontFace(1988756));
+ rtl::Reference<vcl::font::PhysicalFontFace> pExpected = aCollection.Get(0);
+
+ CPPUNIT_ASSERT_EQUAL(pExpected->GetFontId(), pActual->GetFontId());
+ CPPUNIT_ASSERT_EQUAL(1, aCollection.Count());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclPhysicalFontFaceCollectionTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/physicalfontfamily.cxx b/vcl/qa/cppunit/physicalfontfamily.cxx
new file mode 100644
index 000000000..e3a02fb31
--- /dev/null
+++ b/vcl/qa/cppunit/physicalfontfamily.cxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+
+#include <tools/fontenum.hxx>
+#include <unotools/fontcfg.hxx>
+#include <o3tl/sorted_vector.hxx>
+
+#include <vcl/virdev.hxx>
+
+#include <font/PhysicalFontFamily.hxx>
+
+#include "fontmocks.hxx"
+
+using namespace vcl::font;
+
+class VclPhysicalFontFamilyTest : public test::BootstrapFixture
+{
+public:
+ VclPhysicalFontFamilyTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testCreateFontFamily();
+ void testAddFontFace_Default();
+ void testAddOneFontFace();
+ void testAddTwoFontFaces();
+
+ CPPUNIT_TEST_SUITE(VclPhysicalFontFamilyTest);
+ CPPUNIT_TEST(testCreateFontFamily);
+ CPPUNIT_TEST(testAddFontFace_Default);
+ CPPUNIT_TEST(testAddOneFontFace);
+ CPPUNIT_TEST(testAddTwoFontFaces);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void VclPhysicalFontFamilyTest::testCreateFontFamily()
+{
+ PhysicalFontFamily aFamily("Test font face");
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Family name", OUString(""), aFamily.GetFamilyName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Search name", OUString("Test font face"),
+ aFamily.GetSearchName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Alias names", OUString(""), aFamily.GetAliasNames());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Min quality", -1, aFamily.GetMinQuality());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Type faces", FontTypeFaces::NONE, aFamily.GetTypeFaces());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Match family name", OUString(""), aFamily.GetMatchFamilyName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Match type", ImplFontAttrs::None, aFamily.GetMatchType());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Match weight", WEIGHT_DONTKNOW, aFamily.GetMatchWeight());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Match width", WIDTH_DONTKNOW, aFamily.GetMatchWidth());
+}
+
+void VclPhysicalFontFamilyTest::testAddFontFace_Default()
+{
+ PhysicalFontFamily aFamily("Test font face");
+
+ aFamily.AddFontFace(new TestFontFace(1));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Family name", OUString(""), aFamily.GetFamilyName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Search name", OUString("Test font face"),
+ aFamily.GetSearchName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Alias names", OUString(""), aFamily.GetAliasNames());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Min quality", 0, aFamily.GetMinQuality());
+ FontTypeFaces eTypeFace
+ = FontTypeFaces::Scalable | FontTypeFaces::NoneSymbol | FontTypeFaces::NoneItalic;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Type faces", eTypeFace, aFamily.GetTypeFaces());
+}
+
+void VclPhysicalFontFamilyTest::testAddOneFontFace()
+{
+ PhysicalFontFamily aFamily("Test font face");
+
+ FontAttributes aFontAttrs;
+ aFontAttrs.SetFamilyName("Test font face");
+ aFontAttrs.AddMapName("Alias name");
+ aFontAttrs.SetFamilyType(FontFamily::FAMILY_ROMAN);
+ aFontAttrs.SetPitch(FontPitch::PITCH_VARIABLE);
+ aFontAttrs.SetItalic(FontItalic::ITALIC_NONE);
+ aFontAttrs.SetQuality(10);
+ aFontAttrs.SetWeight(FontWeight::WEIGHT_BOLD);
+ aFontAttrs.SetWidthType(FontWidth::WIDTH_EXPANDED);
+
+ aFamily.AddFontFace(new TestFontFace(aFontAttrs, 1));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Family name", OUString("Test font face"),
+ aFamily.GetFamilyName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Search name", OUString("Test font face"),
+ aFamily.GetSearchName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Alias names", OUString("Alias name"), aFamily.GetAliasNames());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Min quality", 10, aFamily.GetMinQuality());
+ FontTypeFaces eTypeFace = FontTypeFaces::Scalable | FontTypeFaces::NoneSymbol
+ | FontTypeFaces::Bold | FontTypeFaces::NoneItalic;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Type faces", eTypeFace, aFamily.GetTypeFaces());
+}
+
+void VclPhysicalFontFamilyTest::testAddTwoFontFaces()
+{
+ PhysicalFontFamily aFamily("Test font face");
+
+ FontAttributes aFontAttrs;
+ aFontAttrs.SetFamilyName("Test font face");
+ aFontAttrs.AddMapName("Alias name");
+ aFontAttrs.SetFamilyType(FontFamily::FAMILY_ROMAN);
+ aFontAttrs.SetPitch(FontPitch::PITCH_VARIABLE);
+ aFontAttrs.SetItalic(FontItalic::ITALIC_NONE);
+ aFontAttrs.SetQuality(10);
+ aFontAttrs.SetWeight(FontWeight::WEIGHT_THIN);
+ aFontAttrs.SetWidthType(FontWidth::WIDTH_EXPANDED);
+
+ aFamily.AddFontFace(new TestFontFace(aFontAttrs, 1));
+
+ aFontAttrs.SetFamilyName("Test font face");
+ aFontAttrs.AddMapName("Alias name 2");
+ aFontAttrs.SetFamilyType(FontFamily::FAMILY_ROMAN);
+ aFontAttrs.SetPitch(FontPitch::PITCH_VARIABLE);
+ aFontAttrs.SetItalic(FontItalic::ITALIC_NORMAL);
+ aFontAttrs.SetQuality(5);
+ aFontAttrs.SetWeight(FontWeight::WEIGHT_BOLD);
+ aFontAttrs.SetWidthType(FontWidth::WIDTH_CONDENSED);
+
+ aFamily.AddFontFace(new TestFontFace(aFontAttrs, 2));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Family name", OUString("Test font face"),
+ aFamily.GetFamilyName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Search name", OUString("Test font face"),
+ aFamily.GetSearchName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Alias names", OUString("Alias name"), aFamily.GetAliasNames());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Min quality", 5, aFamily.GetMinQuality());
+ FontTypeFaces eTypeFace = FontTypeFaces::Scalable | FontTypeFaces::NoneSymbol
+ | FontTypeFaces::Light | FontTypeFaces::Bold
+ | FontTypeFaces::NoneItalic | FontTypeFaces::Italic;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Type faces", eTypeFace, aFamily.GetTypeFaces());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclPhysicalFontFamilyTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/qa/cppunit/png/PngFilterTest.cxx b/vcl/qa/cppunit/png/PngFilterTest.cxx
new file mode 100644
index 000000000..c167c4c9c
--- /dev/null
+++ b/vcl/qa/cppunit/png/PngFilterTest.cxx
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <test/bootstrapfixture.hxx>
+#include <tools/stream.hxx>
+#include <vcl/filter/PngImageReader.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/graphicfilter.hxx>
+
+using namespace css;
+
+class PngFilterTest : public test::BootstrapFixture
+{
+ OUString maDataUrl;
+
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(maDataUrl) + sFileName;
+ }
+
+public:
+ PngFilterTest()
+ : BootstrapFixture(true, false)
+ , maDataUrl("/vcl/qa/cppunit/png/data/")
+ {
+ }
+
+ void testPng();
+ void testMsGifInPng();
+
+ CPPUNIT_TEST_SUITE(PngFilterTest);
+ CPPUNIT_TEST(testPng);
+ CPPUNIT_TEST(testMsGifInPng);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void PngFilterTest::testPng()
+{
+ for (const OUString& aFileName : { OUString("rect-1bit-pal.png") })
+ {
+ SvFileStream aFileStream(getFullUrl(aFileName), StreamMode::READ);
+
+ vcl::PngImageReader aPngReader(aFileStream);
+ BitmapEx aBitmapEx;
+ aPngReader.read(aBitmapEx);
+
+ Bitmap aBitmap = aBitmapEx.GetBitmap();
+ {
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess->Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess->Height());
+
+ if (pAccess->GetBitCount() == 24 || pAccess->GetBitCount() == 32)
+ {
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(3, 3));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(3, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(0, 3));
+
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x00, 0x00),
+ pAccess->GetPixel(1, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x00, 0x00),
+ pAccess->GetPixel(1, 2));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x00, 0x00),
+ pAccess->GetPixel(2, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x00, 0x00),
+ pAccess->GetPixel(2, 2));
+ }
+ else
+ {
+ CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
+ }
+ }
+ }
+
+ OUString aFilenames[] = {
+ OUString("color-rect-8bit-RGB.png"),
+ OUString("color-rect-8bit-RGB-interlaced.png"),
+ OUString("color-rect-4bit-pal.png"),
+ };
+
+ for (const OUString& aFileName : aFilenames)
+ {
+ SvFileStream aFileStream(getFullUrl(aFileName), StreamMode::READ);
+
+ vcl::PngImageReader aPngReader(aFileStream);
+ BitmapEx aBitmapEx;
+ aPngReader.read(aBitmapEx);
+
+ Bitmap aBitmap = aBitmapEx.GetBitmap();
+ {
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess->Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess->Height());
+ if (pAccess->GetBitCount() == 24 || pAccess->GetBitCount() == 32)
+ {
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(3, 3));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(3, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(0, 3));
+
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0x00, 0x00, 0x00),
+ pAccess->GetPixel(1, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0xFF, 0x00, 0x00),
+ pAccess->GetPixel(1, 2));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0xFF, 0x00),
+ pAccess->GetPixel(2, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0x00, 0x00),
+ pAccess->GetPixel(2, 2));
+ }
+ else
+ {
+ CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
+ }
+ }
+ }
+ for (const OUString& aFileName : { OUString("alpha-rect-8bit-RGBA.png") })
+ {
+ SvFileStream aFileStream(getFullUrl(aFileName), StreamMode::READ);
+
+ vcl::PngImageReader aPngReader(aFileStream);
+ BitmapEx aBitmapEx;
+ aPngReader.read(aBitmapEx);
+
+ Bitmap aBitmap = aBitmapEx.GetBitmap();
+ {
+ Bitmap::ScopedReadAccess pAccess(aBitmap);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess->Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess->Height());
+
+ if (pAccess->GetBitCount() == 24)
+ {
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(3, 3));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(3, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x00),
+ pAccess->GetPixel(0, 3));
+
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0x00, 0x00, 0x00),
+ pAccess->GetPixel(1, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0xFF, 0x00, 0x00),
+ pAccess->GetPixel(1, 2));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0xFF, 0x00),
+ pAccess->GetPixel(2, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0x00, 0x00),
+ pAccess->GetPixel(2, 2));
+
+ AlphaMask aAlpha = aBitmapEx.GetAlpha();
+ {
+ AlphaMask::ScopedReadAccess pAlphaAccess(aAlpha);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(8), pAlphaAccess->GetBitCount());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAlphaAccess->Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAlphaAccess->Height());
+
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x80, 0x00),
+ pAlphaAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x80, 0x00),
+ pAlphaAccess->GetPixel(3, 3));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x80, 0x00),
+ pAlphaAccess->GetPixel(3, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x80, 0x00),
+ pAlphaAccess->GetPixel(0, 3));
+
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x40, 0x00),
+ pAlphaAccess->GetPixel(1, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0xC0, 0x00),
+ pAlphaAccess->GetPixel(1, 2));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0xC0, 0x00),
+ pAlphaAccess->GetPixel(2, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x40, 0x00),
+ pAlphaAccess->GetPixel(2, 2));
+ }
+ }
+ else if (pAccess->GetBitCount() == 32)
+ {
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x80),
+ pAccess->GetPixel(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x80),
+ pAccess->GetPixel(3, 3));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x80),
+ pAccess->GetPixel(3, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0xFF, 0x80),
+ pAccess->GetPixel(0, 3));
+
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0x00, 0x00, 0x40),
+ pAccess->GetPixel(1, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0xFF, 0x00, 0xC0),
+ pAccess->GetPixel(1, 2));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0xFF, 0xC0),
+ pAccess->GetPixel(2, 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0xFF, 0xFF, 0x00, 0x40),
+ pAccess->GetPixel(2, 2));
+ }
+ else
+ {
+ CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
+ }
+ }
+ }
+}
+
+void PngFilterTest::testMsGifInPng()
+{
+ Graphic aGraphic;
+ const OUString aURL(getFullUrl(u"ms-gif.png"));
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ ErrCode aResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, aResult);
+ CPPUNIT_ASSERT(aGraphic.IsGfxLink());
+ // The image is technically a PNG, but it has an animated Gif as a chunk (Microsoft extension).
+ CPPUNIT_ASSERT_EQUAL(GfxLinkType::NativeGif, aGraphic.GetSharedGfxLink()->GetType());
+ CPPUNIT_ASSERT(aGraphic.IsAnimated());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PngFilterTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/png/data/alpha-rect-8bit-RGBA.png b/vcl/qa/cppunit/png/data/alpha-rect-8bit-RGBA.png
new file mode 100644
index 000000000..1e90e1a6c
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/alpha-rect-8bit-RGBA.png
Binary files differ
diff --git a/vcl/qa/cppunit/png/data/color-rect-4bit-pal.png b/vcl/qa/cppunit/png/data/color-rect-4bit-pal.png
new file mode 100644
index 000000000..740eede51
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/color-rect-4bit-pal.png
Binary files differ
diff --git a/vcl/qa/cppunit/png/data/color-rect-8bit-RGB-interlaced.png b/vcl/qa/cppunit/png/data/color-rect-8bit-RGB-interlaced.png
new file mode 100644
index 000000000..17ca9a350
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/color-rect-8bit-RGB-interlaced.png
Binary files differ
diff --git a/vcl/qa/cppunit/png/data/color-rect-8bit-RGB.png b/vcl/qa/cppunit/png/data/color-rect-8bit-RGB.png
new file mode 100644
index 000000000..727859d8a
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/color-rect-8bit-RGB.png
Binary files differ
diff --git a/vcl/qa/cppunit/png/data/ms-gif.png b/vcl/qa/cppunit/png/data/ms-gif.png
new file mode 100644
index 000000000..1f683241f
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/ms-gif.png
Binary files differ
diff --git a/vcl/qa/cppunit/png/data/rect-1bit-pal.png b/vcl/qa/cppunit/png/data/rect-1bit-pal.png
new file mode 100644
index 000000000..cf7ac3e7c
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/rect-1bit-pal.png
Binary files differ
diff --git a/vcl/qa/cppunit/skia/skia.cxx b/vcl/qa/cppunit/skia/skia.cxx
new file mode 100644
index 000000000..f2990d381
--- /dev/null
+++ b/vcl/qa/cppunit/skia/skia.cxx
@@ -0,0 +1,588 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <tools/stream.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include <vcl/graphicfilter.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/skia/SkiaHelper.hxx>
+
+#include <skia/salbmp.hxx>
+#include <skia/utils.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+
+using namespace SkiaHelper;
+
+// This tests backends that use Skia (i.e. intentionally not the svp one, which is the default.)
+// Note that you still may need to actually set for Skia to be used (see vcl/README.vars).
+// If Skia is not enabled, all tests will be silently skipped.
+namespace
+{
+class SkiaTest : public test::BootstrapFixture
+{
+public:
+ SkiaTest()
+ : test::BootstrapFixture(true, false)
+ {
+ }
+
+ void testBitmapErase();
+ void testDrawShaders();
+ void testInterpretAs8Bit();
+ void testAlphaBlendWith();
+ void testBitmapCopyOnWrite();
+ void testMatrixQuality();
+ void testDelayedScale();
+ void testDelayedScaleAlphaImage();
+ void testDrawDelayedScaleImage();
+ void testChecksum();
+ void testTdf137329();
+ void testTdf140848();
+ void testTdf132367();
+
+ CPPUNIT_TEST_SUITE(SkiaTest);
+ CPPUNIT_TEST(testBitmapErase);
+ CPPUNIT_TEST(testDrawShaders);
+ CPPUNIT_TEST(testInterpretAs8Bit);
+ CPPUNIT_TEST(testAlphaBlendWith);
+ CPPUNIT_TEST(testBitmapCopyOnWrite);
+ CPPUNIT_TEST(testMatrixQuality);
+ CPPUNIT_TEST(testDelayedScale);
+ CPPUNIT_TEST(testDelayedScaleAlphaImage);
+ CPPUNIT_TEST(testDrawDelayedScaleImage);
+ CPPUNIT_TEST(testChecksum);
+ CPPUNIT_TEST(testTdf137329);
+ CPPUNIT_TEST(testTdf140848);
+ CPPUNIT_TEST(testTdf132367);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+#if 0
+ template <class BitmapT> // handle both Bitmap and BitmapEx
+ void savePNG(const OUString& sWhere, const BitmapT& rBmp)
+ {
+ SvFileStream aStream(sWhere, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(BitmapEx(rBmp), aStream);
+ }
+ void savePNG(const OUString& sWhere, const ScopedVclPtr<VirtualDevice>& device)
+ {
+ SvFileStream aStream(sWhere, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(device->GetBitmapEx(Point(), device->GetOutputSizePixel()), aStream);
+ }
+#endif
+};
+
+void SkiaTest::testBitmapErase()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ SkiaSalBitmap* skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap);
+ // Uninitialized bitmap.
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasBuffer());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasImage());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasAlphaImage());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
+ // Test that Bitmap.Erase() just sets erase color and doesn't allocate pixels.
+ bitmap.Erase(COL_RED);
+ skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasBuffer());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasImage());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasAlphaImage());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasEraseColor());
+ // Reading a pixel will create pixel data.
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), BitmapReadAccess(bitmap).GetColor(0, 0));
+ skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasBuffer());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasImage());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasAlphaImage());
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
+}
+
+// Test that draw calls that internally result in SkShader calls work properly.
+void SkiaTest::testDrawShaders()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(20, 20));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ bitmap.Erase(COL_RED);
+ SkiaSalBitmap* skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap->PreferSkShader());
+ AlphaMask alpha(Size(10, 10));
+ alpha.Erase(64);
+ SkiaSalBitmap* skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaAlpha->PreferSkShader());
+
+ device->DrawBitmap(Point(5, 5), bitmap);
+ //savePNG("/tmp/a1.png", device);
+ // Check that the area is painted, but nothing else.
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_RED, device->GetPixel(Point(5, 5)));
+ CPPUNIT_ASSERT_EQUAL(COL_RED, device->GetPixel(Point(14, 14)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(15, 15)));
+ device->Erase();
+
+ device->DrawBitmapEx(Point(5, 5), BitmapEx(bitmap, alpha));
+ //savePNG("/tmp/a2.png", device);
+ Color resultRed(COL_RED.GetRed() * 3 / 4 + 64, 64, 64); // 3/4 red, 1/4 white
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(5, 5)));
+ CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(14, 14)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(15, 15)));
+ device->Erase();
+
+ basegfx::B2DHomMatrix matrix;
+ matrix.scale(10, 10);
+ matrix.rotate(M_PI / 4);
+ device->DrawTransformedBitmapEx(matrix, BitmapEx(bitmap, alpha));
+ //savePNG("/tmp/a3.png", device);
+ CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(0, 1)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(1, 0)));
+ CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(0, 10)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(10, 10)));
+ device->Erase();
+
+ // Test with scaling. Use everything 10x larger to reduce the impact of smoothscaling.
+ ScopedVclPtr<VirtualDevice> deviceLarge = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ deviceLarge->SetOutputSizePixel(Size(200, 200));
+ deviceLarge->SetBackground(Wallpaper(COL_WHITE));
+ deviceLarge->Erase();
+ Bitmap bitmapLarge(Size(100, 100), vcl::PixelFormat::N24_BPP);
+ bitmapLarge.Erase(COL_RED);
+ SkiaSalBitmap* skiaBitmapLarge
+ = dynamic_cast<SkiaSalBitmap*>(bitmapLarge.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmapLarge->PreferSkShader());
+ AlphaMask alphaLarge(Size(100, 100));
+ alphaLarge.Erase(64);
+ {
+ BitmapWriteAccess access(bitmapLarge);
+ access.SetFillColor(COL_BLUE);
+ access.FillRect(tools::Rectangle(Point(20, 40), Size(10, 10)));
+ }
+ // Using alpha will still lead to shaders being used.
+ deviceLarge->DrawBitmapEx(Point(50, 50), Size(60, 60), Point(20, 20), Size(30, 30),
+ BitmapEx(bitmapLarge, alphaLarge));
+ //savePNG("/tmp/a4.png", deviceLarge);
+ Color resultBlue(64, 64, COL_BLUE.GetBlue() * 3 / 4 + 64); // 3/4 blue, 1/4 white
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, deviceLarge->GetPixel(Point(40, 40)));
+ CPPUNIT_ASSERT_EQUAL(resultRed, deviceLarge->GetPixel(Point(50, 50)));
+ CPPUNIT_ASSERT_EQUAL(resultRed, deviceLarge->GetPixel(Point(100, 100)));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, deviceLarge->GetPixel(Point(110, 110)));
+ // Don't test colors near the edge between the colors, smoothscaling affects them.
+ const int diff = 3;
+ CPPUNIT_ASSERT_EQUAL(resultRed, deviceLarge->GetPixel(Point(50 + diff, 89 - diff)));
+ CPPUNIT_ASSERT_EQUAL(resultBlue, deviceLarge->GetPixel(Point(50 + diff, 90 + diff)));
+ CPPUNIT_ASSERT_EQUAL(resultBlue, deviceLarge->GetPixel(Point(69 - diff, 100 - diff)));
+ CPPUNIT_ASSERT_EQUAL(resultRed, deviceLarge->GetPixel(Point(70 + diff, 100 - diff)));
+ CPPUNIT_ASSERT_EQUAL(resultBlue, deviceLarge->GetPixel(Point(50 + diff, 100 - diff)));
+ device->Erase();
+}
+
+void SkiaTest::testInterpretAs8Bit()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ // Test with erase color.
+ bitmap.Erase(Color(33, 33, 33));
+ SkiaSalBitmap* skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasEraseColor());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, bitmap.getPixelFormat());
+ bitmap.Convert(BmpConversion::N8BitNoConversion);
+ skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasEraseColor());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, bitmap.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(33), BitmapReadAccess(bitmap).GetPixelIndex(0, 0));
+
+ // Test with image.
+ bitmap = Bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ bitmap.Erase(Color(34, 34, 34));
+ BitmapReadAccess(bitmap).GetColor(0, 0); // Create pixel data, reset erase color.
+ skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ skiaBitmap->GetSkImage();
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, bitmap.getPixelFormat());
+ bitmap.Convert(BmpConversion::N8BitNoConversion);
+ skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, bitmap.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(34), BitmapReadAccess(bitmap).GetPixelIndex(0, 0));
+}
+
+void SkiaTest::testAlphaBlendWith()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ AlphaMask alpha(Size(10, 10));
+ Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ // Test with erase colors set.
+ alpha.Erase(64);
+ SkiaSalBitmap* skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaAlpha->unittestHasEraseColor());
+ bitmap.Erase(Color(64, 64, 64));
+ SkiaSalBitmap* skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasEraseColor());
+ alpha.BlendWith(bitmap);
+ skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaAlpha->unittestHasEraseColor());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
+ AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 0));
+
+ // Test with images set.
+ alpha.Erase(64);
+ AlphaMask::ScopedReadAccess(alpha)->GetColor(0, 0); // Reading a pixel will create pixel data.
+ skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
+ skiaAlpha->GetSkImage();
+ CPPUNIT_ASSERT(!skiaAlpha->unittestHasEraseColor());
+ CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
+ bitmap.Erase(Color(64, 64, 64));
+ Bitmap::ScopedReadAccess(bitmap)->GetColor(0, 0); // Reading a pixel will create pixel data.
+ skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ skiaBitmap->GetSkImage();
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
+ alpha.BlendWith(bitmap);
+ skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
+ AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 0));
+
+ // Test with erase color for alpha and image for other bitmap.
+ alpha.Erase(64);
+ skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaAlpha->unittestHasEraseColor());
+ bitmap.Erase(Color(64, 64, 64));
+ Bitmap::ScopedReadAccess(bitmap)->GetColor(0, 0); // Reading a pixel will create pixel data.
+ skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ skiaBitmap->GetSkImage();
+ CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
+ CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
+ alpha.BlendWith(bitmap);
+ skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
+ CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
+ AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 0));
+}
+
+void SkiaTest::testBitmapCopyOnWrite()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ SkiaSalBitmap bitmap;
+ CPPUNIT_ASSERT(bitmap.Create(Size(10, 10), vcl::PixelFormat::N24_BPP, BitmapPalette()));
+ bitmap.GetSkImage();
+ bitmap.GetAlphaSkImage();
+ CPPUNIT_ASSERT(bitmap.unittestHasBuffer());
+ CPPUNIT_ASSERT(bitmap.unittestHasImage());
+ CPPUNIT_ASSERT(bitmap.unittestHasAlphaImage());
+ SkiaSalBitmap bitmap2;
+ CPPUNIT_ASSERT(bitmap2.Create(bitmap));
+ // Data should be shared.
+ CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetBuffer(), bitmap2.unittestGetBuffer());
+ CPPUNIT_ASSERT(bitmap2.unittestHasImage());
+ CPPUNIT_ASSERT(bitmap2.unittestHasAlphaImage());
+ CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), bitmap2.unittestGetImage());
+ CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), bitmap2.unittestGetAlphaImage());
+ // Reading still should keep the data shared.
+ const SkImage* oldImage = bitmap.unittestGetImage();
+ const SkImage* oldAlphaImage = bitmap.unittestGetAlphaImage();
+ BitmapBuffer* buffer = bitmap.AcquireBuffer(BitmapAccessMode::Read);
+ CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetBuffer(), bitmap2.unittestGetBuffer());
+ bitmap.ReleaseBuffer(buffer, BitmapAccessMode::Read);
+ // Images get possibly updated only after releasing the buffer.
+ CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), bitmap2.unittestGetImage());
+ CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), bitmap2.unittestGetAlphaImage());
+ CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), oldImage);
+ CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), oldAlphaImage);
+ // Writing should unshare.
+ buffer = bitmap.AcquireBuffer(BitmapAccessMode::Write);
+ CPPUNIT_ASSERT(bitmap.unittestGetBuffer() != bitmap2.unittestGetBuffer());
+ bitmap.ReleaseBuffer(buffer, BitmapAccessMode::Write);
+ CPPUNIT_ASSERT(bitmap.unittestGetImage() != bitmap2.unittestGetImage());
+ CPPUNIT_ASSERT(bitmap.unittestGetAlphaImage() != bitmap2.unittestGetAlphaImage());
+ CPPUNIT_ASSERT(bitmap.unittestGetImage() != oldImage);
+ CPPUNIT_ASSERT(bitmap.unittestGetAlphaImage() != oldAlphaImage);
+}
+
+void SkiaTest::testMatrixQuality()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ // Not changing the size (but possibly rotated/flipped) does not need high quality transformations.
+ CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix()));
+ CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(90)));
+ CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(180)));
+ CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(270)));
+ CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(1, -1)));
+ CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(0, -1)));
+ CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(2, 1)));
+ CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(89)));
+}
+
+void SkiaTest::testDelayedScale()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ Bitmap bitmap1(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ SkiaSalBitmap* skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap1.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap1);
+ // Do scaling based on mBuffer.
+ (void)BitmapReadAccess(bitmap1); // allocates mBuffer
+ CPPUNIT_ASSERT(skiaBitmap1->unittestHasBuffer());
+ CPPUNIT_ASSERT(!skiaBitmap1->unittestHasImage());
+ CPPUNIT_ASSERT(bitmap1.Scale(2, 2, BmpScaleFlag::Default));
+ skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap1.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap1);
+ CPPUNIT_ASSERT(skiaBitmap1->unittestHasBuffer());
+ CPPUNIT_ASSERT(!skiaBitmap1->unittestHasImage());
+ CPPUNIT_ASSERT_EQUAL(Size(20, 20), bitmap1.GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL(Size(20, 20), imageSize(skiaBitmap1->GetSkImage()));
+ BitmapBuffer* buffer1 = skiaBitmap1->AcquireBuffer(BitmapAccessMode::Read);
+ CPPUNIT_ASSERT(buffer1);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(20), buffer1->mnWidth);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(20), buffer1->mnHeight);
+ skiaBitmap1->ReleaseBuffer(buffer1, BitmapAccessMode::Read);
+ // Do scaling based on mImage.
+ SkiaSalBitmap skiaBitmap2(skiaBitmap1->GetSkImage());
+ CPPUNIT_ASSERT(!skiaBitmap2.unittestHasBuffer());
+ CPPUNIT_ASSERT(skiaBitmap2.unittestHasImage());
+ CPPUNIT_ASSERT(skiaBitmap2.Scale(2, 3, BmpScaleFlag::Default));
+ CPPUNIT_ASSERT(!skiaBitmap2.unittestHasBuffer());
+ CPPUNIT_ASSERT(skiaBitmap2.unittestHasImage());
+ CPPUNIT_ASSERT_EQUAL(Size(40, 60), skiaBitmap2.GetSize());
+ CPPUNIT_ASSERT_EQUAL(Size(40, 60), imageSize(skiaBitmap2.GetSkImage()));
+ BitmapBuffer* buffer2 = skiaBitmap2.AcquireBuffer(BitmapAccessMode::Read);
+ CPPUNIT_ASSERT(buffer2);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(40), buffer2->mnWidth);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(60), buffer2->mnHeight);
+ skiaBitmap2.ReleaseBuffer(buffer2, BitmapAccessMode::Read);
+}
+
+void SkiaTest::testDelayedScaleAlphaImage()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ auto bitmapTmp = std::make_unique<SkiaSalBitmap>();
+ CPPUNIT_ASSERT(bitmapTmp->Create(Size(10, 10), vcl::PixelFormat::N24_BPP, BitmapPalette()));
+ bitmapTmp->Erase(COL_RED);
+ // Create a bitmap that has only an image, not a pixel buffer.
+ SkiaSalBitmap bitmap(bitmapTmp->GetSkImage());
+ bitmapTmp.release();
+ CPPUNIT_ASSERT(!bitmap.unittestHasBuffer());
+ CPPUNIT_ASSERT(bitmap.unittestHasImage());
+ CPPUNIT_ASSERT(!bitmap.unittestHasAlphaImage());
+ // Set up pending scale.
+ CPPUNIT_ASSERT(bitmap.Scale(2.0, 2.0, BmpScaleFlag::Fast));
+ CPPUNIT_ASSERT(bitmap.unittestHasPendingScale());
+ CPPUNIT_ASSERT(bitmap.InterpretAs8Bit());
+ // Ask for SkImage and make sure it's scaled up.
+ sk_sp<SkImage> image = bitmap.GetSkImage();
+ CPPUNIT_ASSERT_EQUAL(20, image->width());
+ // Ask again, this time it should be cached.
+ sk_sp<SkImage> image2 = bitmap.GetSkImage();
+ CPPUNIT_ASSERT_EQUAL(image.get(), image2.get());
+ // Add another scale.
+ CPPUNIT_ASSERT(bitmap.Scale(3.0, 3.0, BmpScaleFlag::Fast));
+ // Ask for alpha SkImage and make sure it's scaled up.
+ sk_sp<SkImage> alphaImage = bitmap.GetAlphaSkImage();
+ CPPUNIT_ASSERT_EQUAL(60, alphaImage->width());
+ // Ask again, this time it should be cached.
+ sk_sp<SkImage> alphaImage2 = bitmap.GetAlphaSkImage();
+ CPPUNIT_ASSERT_EQUAL(alphaImage.get(), alphaImage2.get());
+ // Ask again for non-alpha image, it should be scaled again.
+ sk_sp<SkImage> image3 = bitmap.GetSkImage();
+ CPPUNIT_ASSERT_EQUAL(60, image3->width());
+ CPPUNIT_ASSERT(image3.get() != image2.get());
+ CPPUNIT_ASSERT(image3.get() != image.get());
+ // Create pixel buffer from the image (it should convert from alpha image because the bitmap is 8bpp
+ // and the alpha image size matches).
+ SkiaSalBitmap bitmapCopy;
+ bitmapCopy.Create(bitmap);
+ CPPUNIT_ASSERT(!bitmap.unittestHasBuffer());
+ BitmapBuffer* buffer1 = bitmap.AcquireBuffer(BitmapAccessMode::Read);
+ CPPUNIT_ASSERT(bitmap.unittestHasBuffer());
+ bitmap.ReleaseBuffer(buffer1, BitmapAccessMode::Read);
+ CPPUNIT_ASSERT_EQUAL(Size(60, 60), bitmap.GetSize());
+ // Scale the copy before the buffer was created (this time it should convert from non-alpha image
+ // because of the different size).
+ CPPUNIT_ASSERT(!bitmapCopy.unittestHasBuffer());
+ CPPUNIT_ASSERT(bitmapCopy.Scale(4.0, 4.0, BmpScaleFlag::Fast));
+ BitmapBuffer* buffer2 = bitmapCopy.AcquireBuffer(BitmapAccessMode::Read);
+ CPPUNIT_ASSERT(bitmapCopy.unittestHasBuffer());
+ bitmapCopy.ReleaseBuffer(buffer2, BitmapAccessMode::Read);
+ CPPUNIT_ASSERT_EQUAL(Size(240, 240), bitmapCopy.GetSize());
+}
+
+void SkiaTest::testDrawDelayedScaleImage()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ if (SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster)
+ return; // This test tests caching that's done only in raster mode.
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(10, 10));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ bitmap.Erase(COL_RED);
+ // Set a pixel to create pixel data.
+ BitmapWriteAccess(bitmap).SetPixel(0, 0, COL_BLUE);
+ SkiaSalBitmap* skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ // Force creating of image.
+ sk_sp<SkImage> image1 = skiaBitmap1->GetSkImage();
+ CPPUNIT_ASSERT(skiaBitmap1->unittestHasImage());
+ CPPUNIT_ASSERT(bitmap.Scale(Size(5, 5)));
+ // Make sure delayed scaling has not changed the image.
+ SkiaSalBitmap* skiaBitmap2 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap2->unittestHasImage());
+ sk_sp<SkImage> image2 = skiaBitmap2->GetSkImage(SkiaHelper::DirectImage::Yes);
+ CPPUNIT_ASSERT_EQUAL(image1, image2);
+ CPPUNIT_ASSERT_EQUAL(Size(5, 5), bitmap.GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), SkiaHelper::imageSize(image2));
+ // Draw the bitmap scaled to size 10x10 and check that the 10x10 image was used (and kept),
+ // even though technically the bitmap is 5x5.
+ device->DrawBitmap(Point(0, 0), Size(10, 10), bitmap);
+ SkiaSalBitmap* skiaBitmap3 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ CPPUNIT_ASSERT(skiaBitmap3->unittestHasImage());
+ sk_sp<SkImage> image3 = skiaBitmap3->GetSkImage(SkiaHelper::DirectImage::Yes);
+ CPPUNIT_ASSERT_EQUAL(image1, image3);
+ CPPUNIT_ASSERT_EQUAL(Size(5, 5), bitmap.GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), SkiaHelper::imageSize(image3));
+}
+
+void SkiaTest::testChecksum()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ bitmap.Erase(COL_RED);
+ BitmapChecksum checksum1 = bitmap.GetChecksum();
+ // Set a pixel to create pixel data, that should change checksum.
+ BitmapWriteAccess(bitmap).SetPixel(0, 0, COL_BLUE);
+ BitmapChecksum checksum2 = bitmap.GetChecksum();
+ CPPUNIT_ASSERT(checksum2 != checksum1);
+ SkiaSalBitmap* skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ // Creating an image should not change the checksum.
+ sk_sp<SkImage> image1 = skiaBitmap1->GetSkImage();
+ BitmapChecksum checksum3 = bitmap.GetChecksum();
+ CPPUNIT_ASSERT_EQUAL(checksum2, checksum3);
+ // Delayed scaling should change checksum even if the scaling has not taken place.
+ bitmap.Scale(Size(20, 20));
+ BitmapChecksum checksum4 = bitmap.GetChecksum();
+ CPPUNIT_ASSERT(checksum4 != checksum3);
+ // Setting back to the original red content should have the original checksum.
+ // (This also makes sure this next step is not affected by the delayed scaling
+ // above possibly taking place now.)
+ bitmap = Bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
+ bitmap.Erase(COL_RED);
+ BitmapChecksum checksum5 = bitmap.GetChecksum();
+ CPPUNIT_ASSERT_EQUAL(checksum1, checksum5);
+ // The optimized changing of images to greyscale should change the checksum.
+ SkiaSalBitmap* skiaBitmap2 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
+ skiaBitmap2->unittestResetToImage();
+ BitmapChecksum checksum6 = skiaBitmap2->GetChecksum();
+ CPPUNIT_ASSERT_EQUAL(checksum5, checksum6);
+ CPPUNIT_ASSERT(skiaBitmap2->ConvertToGreyscale());
+ BitmapChecksum checksum7 = skiaBitmap2->GetChecksum();
+ CPPUNIT_ASSERT(checksum7 != checksum6);
+}
+
+void SkiaTest::testTdf137329()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ // Draw a filled polygon in the entire device, with AA enabled.
+ // All pixels in the device should be black, even those at edges (i.e. not affected by AA).
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(10, 10));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->SetAntialiasing(AntialiasingFlags::Enable);
+ device->Erase();
+ device->SetLineColor();
+ device->SetFillColor(COL_BLACK);
+ device->DrawPolyPolygon(
+ basegfx::B2DPolyPolygon(basegfx::B2DPolygon{ { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 } }));
+ // savePNG("/tmp/tdf137329.png", device);
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 9)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(4, 4)));
+}
+
+void SkiaTest::testTdf140848()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(1300, 400));
+ device->SetBackground(Wallpaper(COL_BLACK));
+ device->SetAntialiasing(AntialiasingFlags::Enable);
+ device->Erase();
+ device->SetLineColor();
+ device->SetFillColor(COL_WHITE);
+ basegfx::B2DPolygon p1 = { { 952.73121259842514519, 102.4599685039370911 },
+ { 952.73121259842514519, 66.55445669291347599 },
+ { 1239.9753070866140661, 66.554456692913390725 },
+ { 1239.9753070866140661, 138.36548031496062094 },
+ { 952.73121259842514519, 138.36548031496070621 } };
+ basegfx::B2DPolygon p2 = { { 1168.1642834645670064, 210.17650393700790801 },
+ { 1168.1642834645670064, 66.554456692913404936 },
+ { 1239.9753070866140661, 66.554456692913390725 },
+ { 1239.9753070866142934, 353.79855118110236845 },
+ { 1168.1642834645670064, 353.79855118110236845 } };
+ device->DrawPolyPolygon(basegfx::B2DPolyPolygon(p1));
+ device->DrawPolyPolygon(basegfx::B2DPolyPolygon(p2));
+ //savePNG("/tmp/tdf140848.png", device);
+ // Rounding errors caused the overlapping part not to be drawn.
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(1200, 100)));
+}
+
+void SkiaTest::testTdf132367()
+{
+ if (!SkiaHelper::isVCLSkiaEnabled())
+ return;
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(2, 2));
+ device->SetBackground(Wallpaper(COL_BLACK));
+ device->Erase();
+ device->DrawPixel(Point(1, 1), COL_WHITE);
+ // This will make the bitmap store data in SkImage.
+ Bitmap bitmap = device->GetBitmap(Point(0, 0), Size(2, 2));
+ // Scaling will only set up delayed scaling of the SkImage.
+ bitmap.Scale(Size(4, 4), BmpScaleFlag::NearestNeighbor);
+ // Now it will need to be converted to pixel buffer, check it's converted properly
+ // from the SkImage.
+ BitmapReadAccess access(bitmap);
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), access.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(4), access.Height());
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access.GetColor(3, 3));
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SkiaTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/svm/data/arc.svm b/vcl/qa/cppunit/svm/data/arc.svm
new file mode 100644
index 000000000..5d443a704
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/arc.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/bitmapexs.svm b/vcl/qa/cppunit/svm/data/bitmapexs.svm
new file mode 100644
index 000000000..f6860bdff
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/bitmapexs.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/bitmaps.svm b/vcl/qa/cppunit/svm/data/bitmaps.svm
new file mode 100644
index 000000000..bf42f1bae
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/bitmaps.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/chord.svm b/vcl/qa/cppunit/svm/data/chord.svm
new file mode 100644
index 000000000..7c7136eed
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/chord.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/clipregion.svm b/vcl/qa/cppunit/svm/data/clipregion.svm
new file mode 100644
index 000000000..bf8170222
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/clipregion.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/comment.svm b/vcl/qa/cppunit/svm/data/comment.svm
new file mode 100644
index 000000000..0e2a0f229
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/comment.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/ellipse.svm b/vcl/qa/cppunit/svm/data/ellipse.svm
new file mode 100644
index 000000000..369e4292c
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/ellipse.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/eps.svm b/vcl/qa/cppunit/svm/data/eps.svm
new file mode 100644
index 000000000..33b923a14
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/eps.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/fillcolor.svm b/vcl/qa/cppunit/svm/data/fillcolor.svm
new file mode 100644
index 000000000..8e1a826c4
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/fillcolor.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/floattransparent.svm b/vcl/qa/cppunit/svm/data/floattransparent.svm
new file mode 100644
index 000000000..802fa7078
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/floattransparent.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/font.svm b/vcl/qa/cppunit/svm/data/font.svm
new file mode 100644
index 000000000..301e9d3c1
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/font.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/gradient.svm b/vcl/qa/cppunit/svm/data/gradient.svm
new file mode 100644
index 000000000..68811e065
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/gradient.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/gradientex.svm b/vcl/qa/cppunit/svm/data/gradientex.svm
new file mode 100644
index 000000000..6a83d078c
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/gradientex.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/hatch.svm b/vcl/qa/cppunit/svm/data/hatch.svm
new file mode 100644
index 000000000..4e6bdf638
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/hatch.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/intersectrectclipregion.svm b/vcl/qa/cppunit/svm/data/intersectrectclipregion.svm
new file mode 100644
index 000000000..23179cbe8
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/intersectrectclipregion.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/intersectregionclipregion.svm b/vcl/qa/cppunit/svm/data/intersectregionclipregion.svm
new file mode 100644
index 000000000..6f8571863
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/intersectregionclipregion.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/layoutmode.svm b/vcl/qa/cppunit/svm/data/layoutmode.svm
new file mode 100644
index 000000000..d12f09d66
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/layoutmode.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/line.svm b/vcl/qa/cppunit/svm/data/line.svm
new file mode 100644
index 000000000..67441ec92
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/line.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/linecolor.svm b/vcl/qa/cppunit/svm/data/linecolor.svm
new file mode 100644
index 000000000..2cba7f734
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/linecolor.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/mapmode.svm b/vcl/qa/cppunit/svm/data/mapmode.svm
new file mode 100644
index 000000000..4f74a336e
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/mapmode.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/masks.svm b/vcl/qa/cppunit/svm/data/masks.svm
new file mode 100644
index 000000000..b9e777930
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/masks.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/moveclipregion.svm b/vcl/qa/cppunit/svm/data/moveclipregion.svm
new file mode 100644
index 000000000..6b5340374
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/moveclipregion.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/overlinecolor.svm b/vcl/qa/cppunit/svm/data/overlinecolor.svm
new file mode 100644
index 000000000..10cd773fb
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/overlinecolor.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/pie.svm b/vcl/qa/cppunit/svm/data/pie.svm
new file mode 100644
index 000000000..1eaf67447
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/pie.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/pixel.svm b/vcl/qa/cppunit/svm/data/pixel.svm
new file mode 100644
index 000000000..dc15ab8f0
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/pixel.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/point.svm b/vcl/qa/cppunit/svm/data/point.svm
new file mode 100644
index 000000000..5b5c3731b
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/point.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/polygon.svm b/vcl/qa/cppunit/svm/data/polygon.svm
new file mode 100644
index 000000000..162ccfd9c
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/polygon.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/polyline.svm b/vcl/qa/cppunit/svm/data/polyline.svm
new file mode 100644
index 000000000..9139da371
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/polyline.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/polypolygon.svm b/vcl/qa/cppunit/svm/data/polypolygon.svm
new file mode 100644
index 000000000..ea01bd14a
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/polypolygon.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/pushpop.svm b/vcl/qa/cppunit/svm/data/pushpop.svm
new file mode 100644
index 000000000..d5ab6e80a
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/pushpop.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/rasterop.svm b/vcl/qa/cppunit/svm/data/rasterop.svm
new file mode 100644
index 000000000..ac9f796c2
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/rasterop.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/rect.svm b/vcl/qa/cppunit/svm/data/rect.svm
new file mode 100644
index 000000000..8c398b572
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/rect.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/refpoint.svm b/vcl/qa/cppunit/svm/data/refpoint.svm
new file mode 100644
index 000000000..e6412f908
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/refpoint.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/roundrect.svm b/vcl/qa/cppunit/svm/data/roundrect.svm
new file mode 100644
index 000000000..aa0ca3e29
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/roundrect.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/strecthtext.svm b/vcl/qa/cppunit/svm/data/strecthtext.svm
new file mode 100644
index 000000000..f6dcb5fba
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/strecthtext.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/text.svm b/vcl/qa/cppunit/svm/data/text.svm
new file mode 100644
index 000000000..37da7f598
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/text.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/textalign.svm b/vcl/qa/cppunit/svm/data/textalign.svm
new file mode 100644
index 000000000..091c49876
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/textalign.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/textarray.svm b/vcl/qa/cppunit/svm/data/textarray.svm
new file mode 100644
index 000000000..7863b03ce
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/textarray.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/textcolor.svm b/vcl/qa/cppunit/svm/data/textcolor.svm
new file mode 100644
index 000000000..f55b3ccd7
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/textcolor.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/textfillecolor.svm b/vcl/qa/cppunit/svm/data/textfillecolor.svm
new file mode 100644
index 000000000..52a4f29f3
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/textfillecolor.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/textlanguage.svm b/vcl/qa/cppunit/svm/data/textlanguage.svm
new file mode 100644
index 000000000..2e930d27e
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/textlanguage.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/textline.svm b/vcl/qa/cppunit/svm/data/textline.svm
new file mode 100644
index 000000000..1d8517823
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/textline.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/textlinecolor.svm b/vcl/qa/cppunit/svm/data/textlinecolor.svm
new file mode 100644
index 000000000..786dfc465
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/textlinecolor.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/textrectangle.svm b/vcl/qa/cppunit/svm/data/textrectangle.svm
new file mode 100644
index 000000000..62c424d6a
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/textrectangle.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/transparent.svm b/vcl/qa/cppunit/svm/data/transparent.svm
new file mode 100644
index 000000000..40864b90a
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/transparent.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/data/wallpaper.svm b/vcl/qa/cppunit/svm/data/wallpaper.svm
new file mode 100644
index 000000000..8fca8c31f
--- /dev/null
+++ b/vcl/qa/cppunit/svm/data/wallpaper.svm
Binary files differ
diff --git a/vcl/qa/cppunit/svm/svmtest.cxx b/vcl/qa/cppunit/svm/svmtest.cxx
new file mode 100644
index 000000000..9356b8f5a
--- /dev/null
+++ b/vcl/qa/cppunit/svm/svmtest.cxx
@@ -0,0 +1,2334 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <osl/endian.h>
+#include <test/bootstrapfixture.hxx>
+#include <test/xmltesttools.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/hatch.hxx>
+#include <vcl/lineinfo.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/pngwrite.hxx>
+#include <tools/fract.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/filter/SvmReader.hxx>
+#include <vcl/filter/SvmWriter.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+
+#include <bitmap/BitmapWriteAccess.hxx>
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include <config_features.h>
+#include <config_fonts.h>
+#include <vcl/skia/SkiaHelper.hxx>
+
+using namespace css;
+
+class SvmTest : public test::BootstrapFixture, public XmlTestTools
+{
+ OUString maDataUrl;
+
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(maDataUrl) + sFileName;
+ }
+
+ void checkRendering(ScopedVclPtrInstance<VirtualDevice> const & pVirtualDev, const GDIMetaFile& rMetaFile);
+
+ // write GDI Metafile to a file in data directory
+ // only use this for new tests to create the svm file
+ void writeToFile(GDIMetaFile& rMetaFile, std::u16string_view rName);
+
+ GDIMetaFile writeAndReadStream(
+ GDIMetaFile& rMetaFile, std::u16string_view rName = std::u16string_view());
+
+ GDIMetaFile readFile(std::u16string_view sName);
+
+ xmlDocUniquePtr dumpMeta(const GDIMetaFile& rMetaFile);
+
+ void checkVirtualDevice(const xmlDocUniquePtr& pDoc);
+ void checkErase(const xmlDocUniquePtr& pDoc);
+
+ void checkPixel(const GDIMetaFile& rMetaFile);
+ void testPixel();
+
+ void checkPoint(const GDIMetaFile& rMetaFile);
+ void testPoint();
+
+ void checkLine(const GDIMetaFile& rMetaFile);
+ void testLine();
+
+ void checkRect(const GDIMetaFile& rMetaFile);
+ void testRect();
+
+ void checkRoundRect(const GDIMetaFile& rMetaFile);
+ void testRoundRect();
+
+ void checkEllipse(const GDIMetaFile& rMetaFile);
+ void testEllipse();
+
+ void checkArc(const GDIMetaFile& rMetaFile);
+ void testArc();
+
+ void checkPie(const GDIMetaFile& rMetaFile);
+ void testPie();
+
+ void checkChord(const GDIMetaFile& rMetaFile);
+ void testChord();
+
+ void checkPolyLine(const GDIMetaFile& rMetaFile);
+ void testPolyLine();
+
+ void checkPolygon(const GDIMetaFile& rMetaFile);
+ void testPolygon();
+
+ void checkPolyPolygon(const GDIMetaFile& rMetaFile);
+ void testPolyPolygon();
+
+ void checkText(const GDIMetaFile& rMetaFile);
+ void testText();
+
+ void checkTextArray(const GDIMetaFile& rMetaFile);
+ void testTextArray();
+
+ void checkstretchText(const GDIMetaFile& rMetaFile);
+ void teststretchText();
+
+ void checkTextRect(const GDIMetaFile& rMetaFile);
+ void testTextRect();
+
+ void checkTextLine(const GDIMetaFile& rMetaFile);
+ void testTextLine();
+
+ void checkBitmaps(const GDIMetaFile& rMetaFile);
+ void testBitmaps();
+
+ void checkBitmapExs(const GDIMetaFile& rMetaFile);
+ void testBitmapExs();
+
+ void checkMasks(const GDIMetaFile& rMetaFile);
+ void testMasks();
+
+ void checkGradient(const GDIMetaFile& rMetaFile);
+ void testGradient();
+
+ void checkGradientEx(const GDIMetaFile& rMetaFile);
+ void testGradientEx();
+
+ void checkHatch(const GDIMetaFile& rMetaFile);
+ void testHatch();
+
+ void checkWallpaper(const GDIMetaFile& rMetaFile);
+ void testWallpaper();
+
+ void checkClipRegion(const GDIMetaFile& rMetaFile);
+ void testClipRegion();
+
+ void checkIntersectRectClipRegion(const GDIMetaFile& rMetaFile);
+ void testIntersectRectClipRegion();
+
+ void checkIntersectRegionClipRegion(const GDIMetaFile& rMetaFile);
+ void testIntersectRegionClipRegion();
+
+ void checkMoveClipRegion(const GDIMetaFile& rMetaFile);
+ void testMoveClipRegion();
+
+ void checkLineColor(const GDIMetaFile& rMetaFile);
+ void testLineColor();
+
+ void checkFillColor(const GDIMetaFile& rMetaFile);
+ void testFillColor();
+
+ void checkTextColor(const GDIMetaFile& rMetaFile);
+ void testTextColor();
+
+ void checkTextFillColor(const GDIMetaFile& rMetaFile);
+ void testTextFillColor();
+
+ void checkTextLineColor(const GDIMetaFile& rMetaFile);
+ void testTextLineColor();
+
+ void checkOverLineColor(const GDIMetaFile& rMetaFile);
+ void testOverLineColor();
+
+ void checkTextAlign(const GDIMetaFile& rMetaFile);
+ void testTextAlign();
+
+ void checkMapMode(const GDIMetaFile& rMetaFile);
+ void testMapMode();
+
+#if HAVE_MORE_FONTS && !defined(_WIN32)
+ void checkFont(const GDIMetaFile& rMetaFile);
+#endif
+ void testFont();
+
+ void checkPushPop(const GDIMetaFile& rMetaFile);
+ void testPushPop();
+
+ void checkRasterOp(const GDIMetaFile& rMetaFile);
+ void testRasterOp();
+
+ void checkTransparent(const GDIMetaFile& rMetaFile);
+ void testTransparent();
+
+ void checkFloatTransparent(const GDIMetaFile& rMetaFile);
+ void testFloatTransparent();
+
+ void checkEPS(const GDIMetaFile& rMetaFile);
+ void testEPS();
+
+ void checkRefPoint(const GDIMetaFile& rMetaFile);
+ void testRefPoint();
+
+ void checkComment(const GDIMetaFile& rMetaFile);
+ void testComment();
+
+ void checkLayoutMode(const GDIMetaFile& rMetaFile);
+ void testLayoutMode();
+
+ void checkTextLanguage(const GDIMetaFile& rMetaFile);
+ void testTextLanguage();
+
+public:
+ SvmTest()
+ : BootstrapFixture(true, false)
+ , maDataUrl("/vcl/qa/cppunit/svm/data/")
+ {}
+
+ CPPUNIT_TEST_SUITE(SvmTest);
+ CPPUNIT_TEST(testPixel);
+ CPPUNIT_TEST(testPoint);
+ CPPUNIT_TEST(testLine);
+ CPPUNIT_TEST(testRect);
+ CPPUNIT_TEST(testRoundRect);
+ CPPUNIT_TEST(testEllipse);
+ CPPUNIT_TEST(testArc);
+ CPPUNIT_TEST(testPie);
+ CPPUNIT_TEST(testChord);
+ CPPUNIT_TEST(testPolyLine);
+ CPPUNIT_TEST(testPolygon);
+ CPPUNIT_TEST(testPolyPolygon);
+ CPPUNIT_TEST(testText);
+ CPPUNIT_TEST(testTextArray);
+ CPPUNIT_TEST(teststretchText);
+ CPPUNIT_TEST(testTextRect);
+ CPPUNIT_TEST(testTextLine);
+ CPPUNIT_TEST(testBitmaps); // BMP, BMPSCALE, BMPSCALEPART
+ CPPUNIT_TEST(testBitmapExs); // BMPEX, BMPEXSCALE, BMPEXSCALEPART
+ CPPUNIT_TEST(testMasks); // MASK, MASKSCALE, MASKSCALEPART
+ CPPUNIT_TEST(testGradient);
+ CPPUNIT_TEST(testGradientEx);
+ CPPUNIT_TEST(testHatch);
+ CPPUNIT_TEST(testWallpaper);
+ CPPUNIT_TEST(testClipRegion);
+ CPPUNIT_TEST(testIntersectRectClipRegion);
+ CPPUNIT_TEST(testIntersectRegionClipRegion);
+ CPPUNIT_TEST(testMoveClipRegion);
+ CPPUNIT_TEST(testLineColor);
+ CPPUNIT_TEST(testFillColor);
+ CPPUNIT_TEST(testTextColor);
+ CPPUNIT_TEST(testTextFillColor);
+ CPPUNIT_TEST(testTextLineColor);
+ CPPUNIT_TEST(testOverLineColor);
+ CPPUNIT_TEST(testTextAlign);
+ CPPUNIT_TEST(testMapMode);
+ CPPUNIT_TEST(testFont);
+ CPPUNIT_TEST(testPushPop);
+ CPPUNIT_TEST(testRasterOp);
+ CPPUNIT_TEST(testTransparent);
+ CPPUNIT_TEST(testFloatTransparent);
+ CPPUNIT_TEST(testEPS);
+ CPPUNIT_TEST(testRefPoint);
+ CPPUNIT_TEST(testComment);
+ CPPUNIT_TEST(testLayoutMode);
+ CPPUNIT_TEST(testTextLanguage);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+static void setupBaseVirtualDevice(VirtualDevice& rDevice, GDIMetaFile& rMeta)
+{
+ rDevice.SetConnectMetaFile(&rMeta);
+ Size aVDSize(10, 10);
+ rDevice.SetOutputSizePixel(aVDSize);
+ rDevice.SetBackground(Wallpaper(COL_LIGHTRED));
+ rDevice.Erase();
+}
+
+void SvmTest::checkRendering(ScopedVclPtrInstance<VirtualDevice> const & pVirtualDev, const GDIMetaFile& rMetaFile)
+{
+ BitmapEx aSourceBitmapEx = pVirtualDev->GetBitmapEx(Point(), Size(10, 10));
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDevResult;
+ pVirtualDevResult->SetOutputSizePixel(Size(10, 10));
+ const_cast<GDIMetaFile&>(rMetaFile).Play(*pVirtualDevResult);
+ BitmapEx aResultBitmapEx = pVirtualDevResult->GetBitmapEx(Point(), Size(10, 10));
+
+ const bool bWriteCompareBitmap = false;
+
+ if (bWriteCompareBitmap)
+ {
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+
+ {
+ SvFileStream aStream(aTempFile.GetURL() + ".source.png", StreamMode::WRITE | StreamMode::TRUNC);
+ vcl::PNGWriter aPNGWriter(aSourceBitmapEx);
+ aPNGWriter.Write(aStream);
+ }
+ {
+ SvFileStream aStream(aTempFile.GetURL() + ".result.png", StreamMode::WRITE | StreamMode::TRUNC);
+ vcl::PNGWriter aPNGWriter(aResultBitmapEx);
+ aPNGWriter.Write(aStream);
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(aSourceBitmapEx.GetChecksum(), aResultBitmapEx.GetChecksum());
+}
+
+static GDIMetaFile readMetafile(const OUString& rUrl)
+{
+ GDIMetaFile aResultMetafile;
+ SvFileStream aFileStream(rUrl, StreamMode::READ);
+ aFileStream.Seek(STREAM_SEEK_TO_BEGIN);
+ SvmReader aReader(aFileStream);
+ aReader.Read(aResultMetafile);
+ return aResultMetafile;
+}
+
+static void writeMetaFile(GDIMetaFile& rInputMetafile, const OUString& rUrl)
+{
+ SvFileStream aFileStream(rUrl, StreamMode::WRITE);
+ aFileStream.Seek(STREAM_SEEK_TO_BEGIN);
+ SvmWriter aWriter(aFileStream);
+ aWriter.Write(rInputMetafile);
+ aFileStream.Close();
+}
+
+void SvmTest::writeToFile(GDIMetaFile& rMetaFile, std::u16string_view rName)
+{
+ if (rName.empty())
+ return;
+ OUString sFilePath = getFullUrl(rName);
+ writeMetaFile(rMetaFile, sFilePath);
+}
+
+GDIMetaFile SvmTest::writeAndReadStream(GDIMetaFile& rMetaFile, std::u16string_view rName)
+{
+ if (!rName.empty())
+ writeToFile(rMetaFile, rName);
+
+ SvMemoryStream aStream;
+ SvmWriter aWriter(aStream);
+ aWriter.Write(rMetaFile);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ GDIMetaFile aResultMetafile;
+ SvmReader aReader(aStream);
+ aResultMetafile.Clear();
+ aReader.Read(aResultMetafile);
+ return aResultMetafile;
+}
+
+GDIMetaFile SvmTest::readFile(std::u16string_view sName)
+{
+ OUString sFilePath = getFullUrl(sName);
+ return readMetafile(sFilePath);
+}
+
+xmlDocUniquePtr SvmTest::dumpMeta(const GDIMetaFile& rMetaFile)
+{
+ MetafileXmlDump dumper;
+ xmlDocUniquePtr pDoc = dumpAndParse(dumper, rMetaFile);
+ CPPUNIT_ASSERT (pDoc);
+
+ checkVirtualDevice(pDoc);
+ checkErase(pDoc);
+
+ return pDoc;
+}
+
+void SvmTest::checkVirtualDevice(const xmlDocUniquePtr& pDoc)
+{
+ assertXPath(pDoc, "/metafile/linecolor[1]", "color", "#000000");
+ assertXPath(pDoc, "/metafile/fillcolor[1]", "color", "#ffffff");
+
+ assertXPathAttrs(pDoc, "/metafile/rect[1]", {
+ {"left", "0"}, {"top", "0"},
+ {"right", "9"}, {"bottom", "9"}
+ });
+
+ assertXPath(pDoc, "/metafile/linecolor[2]", "color", "#000000");
+ assertXPath(pDoc, "/metafile/fillcolor[2]", "color", "#ffffff");
+}
+
+void SvmTest::checkErase(const xmlDocUniquePtr& pDoc)
+{
+ assertXPath(pDoc, "/metafile/linecolor[3]", "color", "#000000");
+ assertXPath(pDoc, "/metafile/fillcolor[3]", "color", "#ff0000");
+
+ assertXPathAttrs(pDoc, "/metafile/rect[2]", {
+ {"left", "0"}, {"top", "0"},
+ {"right", "9"}, {"bottom", "9"}
+ });
+}
+
+void SvmTest::checkPixel(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/pixel[1]", {
+ {"x", "8"}, {"y", "1"}, {"color", "#008000"},
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/pixel[2]", {
+ {"x", "1"}, {"y", "8"}, {"color", "#000080"},
+ });
+}
+
+void SvmTest::testPixel()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->DrawPixel(Point(8, 1), COL_GREEN);
+ pVirtualDev->DrawPixel(Point(1, 8), COL_BLUE);
+
+ checkPixel(writeAndReadStream(aGDIMetaFile));
+ checkPixel(readFile(u"pixel.svm"));
+}
+
+void SvmTest::checkPoint(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/point[1]", {
+ {"x", "4"}, {"y", "4"}
+ });
+}
+
+void SvmTest::testPoint()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->DrawPixel(Point(4, 4));
+
+ checkPoint(writeAndReadStream(aGDIMetaFile));
+ checkPoint(readFile(u"point.svm"));
+}
+
+void SvmTest::checkLine(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/line[1]", {
+ {"startx", "1"}, {"starty", "1"},
+ {"endx", "8"}, {"endy", "8"},
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/line[1]", {
+ {"style", "solid"}, {"width", "0"},
+ {"dashlen", "0"}, {"dashcount", "0"},
+ {"dotlen", "0"}, {"dotcount", "0"},
+ {"distance", "0"},
+ {"join", "round"}, {"cap", "butt"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/line[2]", {
+ {"startx", "1"}, {"starty", "8"},
+ {"endx", "8"}, {"endy", "1"},
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/line[2]", {
+ {"style", "dash"}, {"width", "7"},
+ {"dashlen", "5"}, {"dashcount", "4"},
+ {"dotlen", "3"}, {"dotcount", "2"},
+ {"distance", "1"},
+ {"join", "miter"}, {"cap", "round"}
+ });
+}
+
+void SvmTest::testLine()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->DrawLine(Point(1, 1), Point(8, 8));
+ LineInfo aLineInfo(LineStyle::Dash, 7);
+ aLineInfo.SetDashLen(5);
+ aLineInfo.SetDashCount(4);
+ aLineInfo.SetDotLen(3);
+ aLineInfo.SetDotCount(2);
+ aLineInfo.SetDistance(1);
+ aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Miter);
+ aLineInfo.SetLineCap(css::drawing::LineCap_ROUND);
+ pVirtualDev->DrawLine(Point(1, 8), Point(8, 1), aLineInfo);
+
+ checkLine(writeAndReadStream(aGDIMetaFile));
+ checkLine(readFile(u"line.svm"));
+}
+
+void SvmTest::checkRect(const GDIMetaFile& rMetaFile)
+{
+
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPath(pDoc, "/metafile/linecolor[5]", "color", "#123456");
+ assertXPath(pDoc, "/metafile/fillcolor[5]", "color", "#654321");
+
+ assertXPathAttrs(pDoc, "/metafile/rect[3]", {
+ {"left", "1"}, {"top", "2"},
+ {"right", "4"}, {"bottom", "5"},
+ });
+}
+
+void SvmTest::testRect()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetLineColor(Color(0x123456));
+ pVirtualDev->SetFillColor(Color(0x654321));
+
+ pVirtualDev->DrawRect(tools::Rectangle(Point(1, 2), Size(4, 4)));
+
+ checkRect(writeAndReadStream(aGDIMetaFile));
+ checkRect(readFile(u"rect.svm"));
+}
+
+void SvmTest::checkRoundRect(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPath(pDoc, "/metafile/linecolor[5]", "color", "#123456");
+ assertXPath(pDoc, "/metafile/fillcolor[5]", "color", "#654321");
+
+ assertXPathAttrs(pDoc, "/metafile/roundrect[1]", {
+ {"left", "1"}, {"top", "2"},
+ {"right", "4"}, {"bottom", "5"},
+ {"horizontalround", "1"}, {"verticalround", "2"}
+ });
+}
+
+void SvmTest::testRoundRect()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetLineColor(Color(0x123456));
+ pVirtualDev->SetFillColor(Color(0x654321));
+
+ pVirtualDev->DrawRect(tools::Rectangle(Point(1, 2), Size(4, 4)), 1, 2);
+
+ checkRoundRect(writeAndReadStream(aGDIMetaFile));
+ checkRoundRect(readFile(u"roundrect.svm"));
+}
+
+void SvmTest::checkEllipse(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPath(pDoc, "/metafile/linecolor[5]", "color", "#123456");
+ assertXPath(pDoc, "/metafile/fillcolor[5]", "color", "#654321");
+
+ assertXPathAttrs(pDoc, "/metafile/ellipse[1]", {
+ {"left", "1"}, {"top", "2"},
+ {"right", "4"}, {"bottom", "5"},
+ });
+}
+
+void SvmTest::testEllipse()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetLineColor(Color(0x123456));
+ pVirtualDev->SetFillColor(Color(0x654321));
+
+ pVirtualDev->DrawEllipse(tools::Rectangle(Point(1, 2), Size(4, 4)));
+
+ checkEllipse(writeAndReadStream(aGDIMetaFile));
+ checkEllipse(readFile(u"ellipse.svm"));
+}
+
+void SvmTest::checkArc(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPath(pDoc, "/metafile/linecolor[5]", "color", "#123456");
+ assertXPath(pDoc, "/metafile/fillcolor[5]", "color", "#654321");
+
+ assertXPathAttrs(pDoc, "/metafile/arc[1]", {
+ {"left", "1"}, {"top", "2"},
+ {"right", "4"}, {"bottom", "5"},
+
+ {"startx", "10"}, {"starty", "11"},
+ {"endx", "12"}, {"endy", "13"},
+ });
+}
+
+void SvmTest::testArc()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetLineColor(Color(0x123456));
+ pVirtualDev->SetFillColor(Color(0x654321));
+
+ pVirtualDev->DrawArc(tools::Rectangle(Point(1, 2), Size(4, 4)), Point(10, 11), Point(12, 13));
+
+ checkArc(writeAndReadStream(aGDIMetaFile));
+ checkArc(readFile(u"arc.svm"));
+}
+
+void SvmTest::checkPie(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPath(pDoc, "/metafile/linecolor[5]", "color", "#123456");
+ assertXPath(pDoc, "/metafile/fillcolor[5]", "color", "#654321");
+
+ assertXPathAttrs(pDoc, "/metafile/pie[1]", {
+ {"left", "11"}, {"top", "12"},
+ {"right", "14"}, {"bottom", "15"},
+
+ {"startx", "20"}, {"starty", "21"},
+ {"endx", "22"}, {"endy", "23"},
+ });
+}
+
+void SvmTest::testPie()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetLineColor(Color(0x123456));
+ pVirtualDev->SetFillColor(Color(0x654321));
+
+ pVirtualDev->DrawPie(tools::Rectangle(Point(11, 12), Size(4, 4)), Point(20, 21), Point(22, 23));
+
+ checkPie(writeAndReadStream(aGDIMetaFile));
+ checkPie(readFile(u"pie.svm"));
+}
+
+void SvmTest::checkChord(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPath(pDoc, "/metafile/linecolor[5]", "color", "#123456");
+ assertXPath(pDoc, "/metafile/fillcolor[5]", "color", "#654321");
+
+ assertXPathAttrs(pDoc, "/metafile/chord[1]", {
+ {"left", "21"}, {"top", "22"},
+ {"right", "24"}, {"bottom", "25"},
+
+ {"startx", "30"}, {"starty", "31"},
+ {"endx", "32"}, {"endy", "33"},
+ });
+}
+
+void SvmTest::testChord()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetLineColor(Color(0x123456));
+ pVirtualDev->SetFillColor(Color(0x654321));
+
+ pVirtualDev->DrawChord(tools::Rectangle(Point(21, 22), Size(4, 4)), Point(30, 31), Point(32, 33));
+
+ checkChord(writeAndReadStream(aGDIMetaFile));
+ checkChord(readFile(u"chord.svm"));
+}
+
+void SvmTest::checkPolyLine(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/polyline[1]", {
+ {"style", "solid"}, {"width", "0"},
+ {"dashlen", "0"}, {"dashcount", "0"},
+ {"dotlen", "0"}, {"dotcount", "0"},
+ {"distance", "0"},
+ {"join", "round"}, {"cap", "butt"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/polyline[1]/point[1]", {{"x", "1"}, {"y", "8"}});
+ assertXPathAttrs(pDoc, "/metafile/polyline[1]/point[2]", {{"x", "2"}, {"y", "7"}});
+ assertXPathAttrs(pDoc, "/metafile/polyline[1]/point[3]", {{"x", "3"}, {"y", "6"}});
+
+ assertXPathAttrs(pDoc, "/metafile/polyline[2]", {
+ {"style", "dash"}, {"width", "7"},
+ {"dashlen", "5"}, {"dashcount", "4"},
+ {"dotlen", "3"}, {"dotcount", "2"},
+ {"distance", "1"},
+ {"join", "miter"}, {"cap", "round"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/polyline[2]/point[1]", {{"x", "8"}, {"y", "1"}, {"flags", "normal"}});
+ assertXPathAttrs(pDoc, "/metafile/polyline[2]/point[2]", {{"x", "7"}, {"y", "2"}, {"flags", "control"}});
+ assertXPathAttrs(pDoc, "/metafile/polyline[2]/point[3]", {{"x", "6"}, {"y", "3"}, {"flags", "smooth"}});
+ assertXPathAttrs(pDoc, "/metafile/polyline[2]/point[4]", {{"x", "5"}, {"y", "4"}, {"flags", "symmetric"}});
+}
+
+void SvmTest::testPolyLine()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Polygon aPolygon(3);
+ aPolygon.SetPoint(Point(1, 8), 0);
+ aPolygon.SetPoint(Point(2, 7), 1);
+ aPolygon.SetPoint(Point(3, 6), 2);
+
+ pVirtualDev->DrawPolyLine(aPolygon);
+
+ tools::Polygon aPolygonWithControl(4);
+ aPolygonWithControl.SetPoint(Point(8, 1), 0);
+ aPolygonWithControl.SetPoint(Point(7, 2), 1);
+ aPolygonWithControl.SetPoint(Point(6, 3), 2);
+ aPolygonWithControl.SetPoint(Point(5, 4), 3);
+
+ aPolygonWithControl.SetFlags(0, PolyFlags::Normal);
+ aPolygonWithControl.SetFlags(1, PolyFlags::Control);
+ aPolygonWithControl.SetFlags(2, PolyFlags::Smooth);
+ aPolygonWithControl.SetFlags(3, PolyFlags::Symmetric);
+
+ LineInfo aLineInfo(LineStyle::Dash, 7);
+ aLineInfo.SetDashLen(5);
+ aLineInfo.SetDashCount(4);
+ aLineInfo.SetDotLen(3);
+ aLineInfo.SetDotCount(2);
+ aLineInfo.SetDistance(1);
+ aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Miter);
+ aLineInfo.SetLineCap(css::drawing::LineCap_ROUND);
+
+ pVirtualDev->DrawPolyLine(aPolygonWithControl, aLineInfo);
+
+ checkPolyLine(writeAndReadStream(aGDIMetaFile));
+ checkPolyLine(readFile(u"polyline.svm"));
+}
+
+void SvmTest::checkPolygon(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/polygon[1]/point[1]", {{"x", "1"}, {"y", "8"}});
+ assertXPathAttrs(pDoc, "/metafile/polygon[1]/point[2]", {{"x", "2"}, {"y", "7"}});
+ assertXPathAttrs(pDoc, "/metafile/polygon[1]/point[3]", {{"x", "3"}, {"y", "6"}});
+
+ assertXPathAttrs(pDoc, "/metafile/polygon[2]/point[1]", {{"x", "8"}, {"y", "1"}, {"flags", "normal"}});
+ assertXPathAttrs(pDoc, "/metafile/polygon[2]/point[2]", {{"x", "7"}, {"y", "2"}, {"flags", "control"}});
+ assertXPathAttrs(pDoc, "/metafile/polygon[2]/point[3]", {{"x", "6"}, {"y", "3"}, {"flags", "smooth"}});
+ assertXPathAttrs(pDoc, "/metafile/polygon[2]/point[4]", {{"x", "5"}, {"y", "4"}, {"flags", "symmetric"}});
+}
+
+void SvmTest::testPolygon()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Polygon aPolygon(3);
+ aPolygon.SetPoint(Point(1, 8), 0);
+ aPolygon.SetPoint(Point(2, 7), 1);
+ aPolygon.SetPoint(Point(3, 6), 2);
+
+ pVirtualDev->DrawPolygon(aPolygon);
+
+ tools::Polygon aPolygonWithControl(4);
+ aPolygonWithControl.SetPoint(Point(8, 1), 0);
+ aPolygonWithControl.SetPoint(Point(7, 2), 1);
+ aPolygonWithControl.SetPoint(Point(6, 3), 2);
+ aPolygonWithControl.SetPoint(Point(5, 4), 3);
+
+ aPolygonWithControl.SetFlags(0, PolyFlags::Normal);
+ aPolygonWithControl.SetFlags(1, PolyFlags::Control);
+ aPolygonWithControl.SetFlags(2, PolyFlags::Smooth);
+ aPolygonWithControl.SetFlags(3, PolyFlags::Symmetric);
+
+ pVirtualDev->DrawPolygon(aPolygonWithControl);
+
+ checkPolygon(writeAndReadStream(aGDIMetaFile));
+ checkPolygon(readFile(u"polygon.svm"));
+}
+
+void SvmTest::checkPolyPolygon(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/polypolygon[1]/polygon[1]/point[1]", {{"x", "1"}, {"y", "8"}});
+ assertXPathAttrs(pDoc, "/metafile/polypolygon[1]/polygon[1]/point[2]", {{"x", "2"}, {"y", "7"}});
+ assertXPathAttrs(pDoc, "/metafile/polypolygon[1]/polygon[1]/point[3]", {{"x", "3"}, {"y", "6"}});
+
+ assertXPathAttrs(pDoc, "/metafile/polypolygon[1]/polygon[2]/point[1]", {{"x", "8"}, {"y", "1"}, {"flags", "normal"}});
+ assertXPathAttrs(pDoc, "/metafile/polypolygon[1]/polygon[2]/point[2]", {{"x", "7"}, {"y", "2"}, {"flags", "control"}});
+ assertXPathAttrs(pDoc, "/metafile/polypolygon[1]/polygon[2]/point[3]", {{"x", "6"}, {"y", "3"}, {"flags", "smooth"}});
+ assertXPathAttrs(pDoc, "/metafile/polypolygon[1]/polygon[2]/point[4]", {{"x", "5"}, {"y", "4"}, {"flags", "symmetric"}});
+}
+
+void SvmTest::testPolyPolygon()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Polygon aPolygon(3);
+ aPolygon.SetPoint(Point(1, 8), 0);
+ aPolygon.SetPoint(Point(2, 7), 1);
+ aPolygon.SetPoint(Point(3, 6), 2);
+
+ tools::Polygon aPolygonWithControl(4);
+ aPolygonWithControl.SetPoint(Point(8, 1), 0);
+ aPolygonWithControl.SetPoint(Point(7, 2), 1);
+ aPolygonWithControl.SetPoint(Point(6, 3), 2);
+ aPolygonWithControl.SetPoint(Point(5, 4), 3);
+
+ aPolygonWithControl.SetFlags(0, PolyFlags::Normal);
+ aPolygonWithControl.SetFlags(1, PolyFlags::Control);
+ aPolygonWithControl.SetFlags(2, PolyFlags::Smooth);
+ aPolygonWithControl.SetFlags(3, PolyFlags::Symmetric);
+
+ tools::PolyPolygon aPolyPolygon(2);
+ aPolyPolygon.Insert(aPolygon);
+ aPolyPolygon.Insert(aPolygonWithControl);
+
+ pVirtualDev->DrawPolyPolygon(aPolyPolygon);
+
+ checkPolyPolygon(writeAndReadStream(aGDIMetaFile));
+ checkPolyPolygon(readFile(u"polypolygon.svm"));
+}
+
+void SvmTest::checkText(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/text[1]", {
+ {"x", "4"}, {"y", "6"}, {"index", "1"}, {"length", "2"},
+ });
+
+ assertXPathContent(pDoc, "/metafile/text[1]/textcontent", "xABC");
+}
+
+void SvmTest::testText()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->DrawText(Point(4,6), "xABC", 1, 2);
+
+ checkText(writeAndReadStream(aGDIMetaFile));
+ checkText(readFile(u"text.svm"));
+}
+
+void SvmTest::checkTextArray(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/textarray[1]", {
+ {"x", "4"}, {"y", "6"}, {"index", "1"}, {"length", "4"},
+ });
+ assertXPathContent(pDoc, "/metafile/textarray[1]/dxarray", "15 20 25 ");
+ assertXPathContent(pDoc, "/metafile/textarray[1]/text", "123456");
+}
+
+void SvmTest::testTextArray()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+ sal_Int32 const aDX[] = { 10, 15, 20, 25, 30, 35 };
+ pVirtualDev->DrawTextArray(Point(4,6), "123456", aDX, 1, 4);
+
+ checkTextArray(writeAndReadStream(aGDIMetaFile));
+ checkTextArray(readFile(u"textarray.svm"));
+}
+
+void SvmTest::checkstretchText(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/stretchtext[1]", {
+ {"x", "4"}, {"y", "6"}, {"index", "1"}, {"length", "4"}, {"width", "10"}
+ });
+
+ assertXPathContent(pDoc, "/metafile/stretchtext[1]/textcontent", "123456");
+}
+
+void SvmTest::teststretchText()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+ pVirtualDev->DrawStretchText(Point(4,6), 10, "123456", 1, 4);
+
+ checkstretchText(writeAndReadStream(aGDIMetaFile));
+ checkstretchText(readFile(u"strecthtext.svm"));
+}
+
+void SvmTest::checkTextRect(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/textrect[1]", {
+ {"left", "0"}, {"top", "0"}, {"right", "4"}, {"bottom", "4"}
+ });
+ assertXPathContent(pDoc, "/metafile/textrect[1]/textcontent", "123456");
+ assertXPathContent(pDoc, "/metafile/textrect[1]/style", "Center");
+}
+
+void SvmTest::testTextRect()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+ pVirtualDev->DrawText(tools::Rectangle(Point(0,0), Size(5,5)), "123456", DrawTextFlags::Center);
+
+ checkTextRect(writeAndReadStream(aGDIMetaFile));
+ checkTextRect(readFile(u"textrectangle.svm"));
+}
+
+void SvmTest::checkTextLine(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/textline[1]", {
+ {"x", "4"}, {"y", "6"}, {"width", "10"},
+ {"strikeout", "single"}, {"underline", "single"}, {"overline", "single"}
+ });
+}
+
+void SvmTest::testTextLine()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+ pVirtualDev->DrawTextLine(Point(4,6), 10, STRIKEOUT_SINGLE, LINESTYLE_SINGLE, LINESTYLE_SINGLE);
+
+ checkTextLine(writeAndReadStream(aGDIMetaFile));
+ checkTextLine(readFile(u"textline.svm"));
+}
+
+void SvmTest::checkBitmaps(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ if (SkiaHelper::isVCLSkiaEnabled())
+ return; // TODO SKIA using CRCs is broken (the idea of it)
+
+ assertXPathAttrs(pDoc, "/metafile/bmp[1]", {{"x", "1"}, {"y", "2"}, {"crc",
+#if defined OSL_BIGENDIAN
+ "5e01ddcc"
+#else
+ "b8dee5da"
+#endif
+ }});
+ assertXPathAttrs(pDoc, "/metafile/bmpscale[1]", {
+ {"x", "1"}, {"y", "2"}, {"width", "3"}, {"height", "4"}, {"crc", "281fc589"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/bmpscalepart[1]", {
+ {"destx", "1"}, {"desty", "2"}, {"destwidth", "3"}, {"destheight", "4"},
+ {"srcx", "2"}, {"srcy", "1"}, {"srcwidth", "4"}, {"srcheight", "3"},
+ {"crc",
+#if defined OSL_BIGENDIAN
+ "b8dee5da"
+#else
+ "5e01ddcc"
+#endif
+ }
+ });
+}
+
+void SvmTest::testBitmaps()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ Bitmap aBitmap1(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap1);
+ pAccess->Erase(COL_RED);
+ }
+ Bitmap aBitmap2(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap2);
+ pAccess->Erase(COL_GREEN);
+ }
+ Bitmap aBitmap3(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap3);
+ pAccess->Erase(COL_BLUE);
+ }
+ pVirtualDev->DrawBitmap(Point(1, 2), aBitmap1);
+ pVirtualDev->DrawBitmap(Point(1, 2), Size(3, 4), aBitmap2);
+ pVirtualDev->DrawBitmap(Point(1, 2), Size(3, 4), Point(2, 1), Size(4, 3), aBitmap3);
+
+ {
+ GDIMetaFile aReloadedGDIMetaFile = writeAndReadStream(aGDIMetaFile);
+ checkBitmaps(aReloadedGDIMetaFile);
+ checkRendering(pVirtualDev, aReloadedGDIMetaFile);
+ }
+ {
+ GDIMetaFile aFileGDIMetaFile = readFile(u"bitmaps.svm");
+ checkBitmaps(aFileGDIMetaFile);
+ checkRendering(pVirtualDev, aFileGDIMetaFile);
+ }
+}
+
+void SvmTest::checkBitmapExs(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ if (SkiaHelper::isVCLSkiaEnabled())
+ return; // TODO SKIA using CRCs is broken (the idea of it)
+
+ std::vector<OUString> aExpectedCRC;
+ aExpectedCRC.insert(aExpectedCRC.end(),
+ {
+#if defined OSL_BIGENDIAN
+ "08feb5d3",
+ "281fc589",
+ "b8dee5da",
+ "4df0e464",
+ "186ff868",
+ "33b4a07c", // 4-bit color bitmap - same as 8-bit color bitmap
+ "33b4a07c",
+ "742c3e35",
+#else
+ "d8377d4f",
+ "281fc589",
+ "5e01ddcc",
+ "4df0e464",
+ "4322ee3a",
+ "3c80d829", // 4-bit color bitmap - same as 8-bit color bitmap
+ "3c80d829",
+ "71efc447",
+#endif
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/bmpex[1]", {
+ {"x", "1"}, {"y", "1"}, {"crc", aExpectedCRC[0]}, {"transparenttype", "bitmap"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/bmpexscale[1]", {
+ {"x", "5"}, {"y", "0"}, {"width", "2"}, {"height", "3"},
+ {"crc", aExpectedCRC[1]}, {"transparenttype", "bitmap"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/bmpexscalepart[1]", {
+ {"destx", "7"}, {"desty", "1"}, {"destwidth", "2"}, {"destheight", "2"},
+ {"srcx", "0"}, {"srcy", "0"}, {"srcwidth", "3"}, {"srcheight", "4"},
+ {"crc", aExpectedCRC[2]}, {"transparenttype", "bitmap"}
+ });
+
+#ifndef MACOSX
+ assertXPathAttrs(pDoc, "/metafile/bmpex[2]", {
+ {"x", "6"}, {"y", "6"}, {"crc", aExpectedCRC[3]}, {"transparenttype", "bitmap"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/bmpex[3]", {
+ {"x", "0"}, {"y", "6"}, {"crc", aExpectedCRC[4]}, {"transparenttype", "bitmap"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/bmpex[4]", {
+ {"x", "2"}, {"y", "6"}, {"crc", aExpectedCRC[5]}, {"transparenttype", "bitmap"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/bmpex[5]", {
+ {"x", "0"}, {"y", "8"}, {"crc", aExpectedCRC[6]}, {"transparenttype", "bitmap"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/bmpex[6]", {
+ {"x", "2"}, {"y", "8"}, {"crc", aExpectedCRC[7]}, {"transparenttype", "bitmap"}
+ });
+#endif
+}
+
+void SvmTest::testBitmapExs()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ // DrawBitmapEx
+ {
+ Bitmap aBitmap(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->Erase(COL_YELLOW);
+ }
+
+ pVirtualDev->DrawBitmapEx(Point(1, 1), BitmapEx(aBitmap, COL_WHITE));
+ }
+
+ // DrawBitmapEx - Scale
+ {
+ Bitmap aBitmap(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->Erase(COL_GREEN);
+ }
+ pVirtualDev->DrawBitmapEx(Point(5, 0), Size(2, 3), BitmapEx(aBitmap, COL_WHITE));
+ }
+
+ // DrawBitmapEx - Scale - Part
+ {
+ Bitmap aBitmap(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->Erase(COL_BLUE);
+ }
+ pVirtualDev->DrawBitmapEx(Point(7, 1), Size(2, 2), Point(0, 0), Size(3, 4), BitmapEx(aBitmap, COL_WHITE));
+ }
+
+ // DrawBitmapEx - 50% transparent
+ {
+ Bitmap aBitmap(Size(4, 4), vcl::PixelFormat::N24_BPP);
+ AlphaMask aAlpha(Size(4, 4));
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->Erase(COL_MAGENTA);
+
+ AlphaScopedWriteAccess pAlphaAccess(aAlpha);
+ pAlphaAccess->Erase(Color(128, 128, 128));
+ }
+ pVirtualDev->DrawBitmapEx(Point(6, 6), BitmapEx(aBitmap, aAlpha));
+ }
+
+ // DrawBitmapEx - 1-bit
+ {
+ Bitmap aBitmap(Size(2, 2), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->Erase(COL_MAGENTA);
+ }
+ aBitmap.Convert(BmpConversion::N1BitThreshold);
+ pVirtualDev->DrawBitmapEx(Point(0, 6), BitmapEx(aBitmap, COL_WHITE));
+ }
+
+ // DrawBitmapEx - used to be 4-bit
+ {
+ Bitmap aBitmap(Size(2, 2), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->Erase(COL_MAGENTA);
+ }
+ aBitmap.Convert(BmpConversion::N8BitColors);
+ pVirtualDev->DrawBitmapEx(Point(2, 6), BitmapEx(aBitmap, COL_WHITE));
+ }
+
+ // DrawBitmapEx - 8-bit Color
+ {
+ Bitmap aBitmap(Size(2, 2), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->Erase(COL_MAGENTA);
+ }
+ aBitmap.Convert(BmpConversion::N8BitColors);
+ pVirtualDev->DrawBitmapEx(Point(0, 8), BitmapEx(aBitmap, COL_WHITE));
+ }
+
+ // DrawBitmapEx - 8-bit Grey
+ {
+ Bitmap aBitmap(Size(2, 2), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->Erase(COL_MAGENTA);
+ }
+ aBitmap.Convert(BmpConversion::N8BitGreys);
+ pVirtualDev->DrawBitmapEx(Point(2, 8), BitmapEx(aBitmap, COL_WHITE));
+ }
+
+ {
+ GDIMetaFile aReloadedGDIMetaFile = writeAndReadStream(aGDIMetaFile);
+ checkBitmapExs(aReloadedGDIMetaFile);
+ checkRendering(pVirtualDev, aReloadedGDIMetaFile);
+ }
+ {
+ GDIMetaFile aFileGDIMetaFile = readFile(u"bitmapexs.svm");
+ checkBitmapExs(aFileGDIMetaFile);
+ checkRendering(pVirtualDev, aFileGDIMetaFile);
+ }
+}
+
+void SvmTest::checkMasks(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/mask[1]", {
+ {"x", "1"}, {"y", "2"},
+ {"color", "#000000"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/maskscale[1]", {
+ {"x", "1"}, {"y", "2"}, {"width", "3"}, {"height", "4"},
+ {"color", "#000000"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/maskscalepart[1]", {
+ {"destx", "1"}, {"desty", "2"}, {"destwidth", "3"}, {"destheight", "4"},
+ {"srcx", "2"}, {"srcy", "1"}, {"srcwidth", "4"}, {"srcheight", "3"},
+ {"color", "#ff0000"}
+ });
+}
+
+// TODO: Masks are kind-of special - we don't persist the color attribute (it is
+// always #000000) of the meta-action (which is wrong), but rely on alpha to do
+// the right thing.
+void SvmTest::testMasks()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ Bitmap aBitmap1(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap1);
+ pAccess->Erase(COL_RED);
+ }
+ Bitmap aBitmap2(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap2);
+ pAccess->Erase(COL_GREEN);
+ }
+ Bitmap aBitmap3(Size(4,4), vcl::PixelFormat::N24_BPP);
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap3);
+ pAccess->Erase(COL_BLUE);
+ }
+
+ pVirtualDev->DrawMask(Point(1, 2), aBitmap1, COL_LIGHTRED);
+ pVirtualDev->DrawMask(Point(1, 2), Size(3, 4), aBitmap2, COL_LIGHTRED);
+ pVirtualDev->DrawMask(Point(1, 2), Size(3, 4), Point(2, 1), Size(4, 3), aBitmap3, COL_LIGHTRED, MetaActionType::MASKSCALEPART);
+
+ checkMasks(writeAndReadStream(aGDIMetaFile));
+ checkMasks(readFile(u"masks.svm"));
+}
+
+void SvmTest::checkGradient(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/gradient[1]", {
+ {"style", "Linear"},
+ {"startcolor", "#ffffff"},
+ {"endcolor", "#000000"},
+ {"angle", "0"},
+ {"border", "0"},
+ {"offsetx", "50"},
+ {"offsety", "50"},
+ {"startintensity", "100"},
+ {"endintensity", "100"},
+ {"steps", "0"},
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradient[1]/rectangle", {
+ {"left", "1"},
+ {"top", "2"},
+ {"right", "4"},
+ {"bottom", "6"},
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/gradient[2]", {
+ {"style", "Radial"},
+ {"startcolor", "#ff0000"},
+ {"endcolor", "#00ff00"},
+ {"angle", "55"},
+ {"border", "10"},
+ {"offsetx", "22"},
+ {"offsety", "24"},
+ {"startintensity", "4"},
+ {"endintensity", "14"},
+ {"steps", "64"},
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradient[2]/rectangle", {
+ {"left", "3"},
+ {"top", "4"},
+ {"right", "3"},
+ {"bottom", "5"},
+ });
+}
+
+void SvmTest::testGradient()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Rectangle aRectangle(Point(1, 2), Size(4,5));
+
+ Gradient aGradient(GradientStyle::Linear, COL_WHITE, COL_BLACK);
+ pVirtualDev->DrawGradient(aRectangle, aGradient);
+
+ tools::Rectangle aRectangle2(Point(3, 4), Size(1,2));
+
+ Gradient aGradient2;
+ aGradient2.SetStyle(GradientStyle::Radial);
+ aGradient2.SetStartColor(COL_LIGHTRED);
+ aGradient2.SetEndColor(COL_LIGHTGREEN);
+ aGradient2.SetAngle(Degree10(55));
+ aGradient2.SetBorder(10);
+ aGradient2.SetOfsX(22);
+ aGradient2.SetOfsY(24);
+ aGradient2.SetStartIntensity(4);
+ aGradient2.SetEndIntensity(14);
+ aGradient2.SetSteps(64);
+ pVirtualDev->DrawGradient(aRectangle2, aGradient2);
+
+ checkGradient(writeAndReadStream(aGDIMetaFile));
+ checkGradient(readFile(u"gradient.svm"));
+}
+
+void SvmTest::checkGradientEx(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/gradientex[1]", {
+ {"style", "Linear"},
+ {"startcolor", "#ffffff"},
+ {"endcolor", "#000000"},
+ {"angle", "0"},
+ {"border", "0"},
+ {"offsetx", "50"},
+ {"offsety", "50"},
+ {"startintensity", "100"},
+ {"endintensity", "100"},
+ {"steps", "0"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradientex[1]/polygon/point[1]", {
+ {"x", "1"},
+ {"y", "8"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradientex[1]/polygon/point[2]", {
+ {"x", "2"},
+ {"y", "7"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradientex[1]/polygon/point[3]", {
+ {"x", "3"},
+ {"y", "6"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradientex[2]", {
+ {"style", "Axial"},
+ {"startcolor", "#ff00ff"},
+ {"endcolor", "#008080"},
+ {"angle", "55"},
+ {"border", "10"},
+ {"offsetx", "22"},
+ {"offsety", "24"},
+ {"startintensity", "4"},
+ {"endintensity", "14"},
+ {"steps", "64"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradientex[2]/polygon[1]/point[1]", {
+ {"x", "1"},
+ {"y", "2"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradientex[2]/polygon[1]/point[2]", {
+ {"x", "3"},
+ {"y", "4"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradientex[2]/polygon[2]/point[1]", {
+ {"x", "8"},
+ {"y", "9"}
+ });
+ assertXPathAttrs(pDoc, "/metafile/gradientex[2]/polygon[2]/point[2]", {
+ {"x", "6"},
+ {"y", "7"}
+ });
+}
+
+void SvmTest::testGradientEx()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Polygon aPolygon(3);
+ aPolygon.SetPoint(Point(1, 8), 0);
+ aPolygon.SetPoint(Point(2, 7), 1);
+ aPolygon.SetPoint(Point(3, 6), 2);
+
+ tools::PolyPolygon aPolyPolygon(1);
+ aPolyPolygon.Insert(aPolygon);
+
+ Gradient aGradient(GradientStyle::Linear, COL_WHITE, COL_BLACK);
+ pVirtualDev->DrawGradient(aPolyPolygon, aGradient);
+
+ tools::Polygon aPolygon2(2);
+ aPolygon2.SetPoint(Point(1, 2), 0);
+ aPolygon2.SetPoint(Point(3, 4), 1);
+
+ tools::Polygon aPolygon3(2);
+ aPolygon3.SetPoint(Point(8, 9), 0);
+ aPolygon3.SetPoint(Point(6, 7), 1);
+
+ tools::PolyPolygon aPolyPolygon2(1);
+ aPolyPolygon2.Insert(aPolygon2);
+ aPolyPolygon2.Insert(aPolygon3);
+
+ Gradient aGradient2;
+ aGradient2.SetStyle(GradientStyle::Axial);
+ aGradient2.SetStartColor(COL_LIGHTMAGENTA);
+ aGradient2.SetEndColor(COL_CYAN);
+ aGradient2.SetAngle(Degree10(55));
+ aGradient2.SetBorder(10);
+ aGradient2.SetOfsX(22);
+ aGradient2.SetOfsY(24);
+ aGradient2.SetStartIntensity(4);
+ aGradient2.SetEndIntensity(14);
+ aGradient2.SetSteps(64);
+ pVirtualDev->DrawGradient(aPolyPolygon2, aGradient2);
+
+ checkGradientEx(writeAndReadStream(aGDIMetaFile));
+ checkGradientEx(readFile(u"gradientex.svm"));
+}
+
+void SvmTest::checkHatch(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/hatch[1]/polygon/point[1]", {
+ {"x", "1"}, {"y", "8"},
+ });
+ assertXPathAttrs(pDoc, "/metafile/hatch[1]/polygon/point[2]", {
+ {"x", "2"}, {"y", "7"},
+ });
+ assertXPathAttrs(pDoc, "/metafile/hatch[1]/polygon/point[3]", {
+ {"x", "3"}, {"y", "6"},
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/hatch[1]/hatch", {
+ {"style", "Single"},
+ {"color", "#ffff00"},
+ {"distance", "15"},
+ {"angle", "900"},
+ });
+}
+
+void SvmTest::testHatch()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Polygon aPolygon(3);
+ aPolygon.SetPoint(Point(1, 8), 0);
+ aPolygon.SetPoint(Point(2, 7), 1);
+ aPolygon.SetPoint(Point(3, 6), 2);
+
+ tools::PolyPolygon aPolyPolygon(1);
+ aPolyPolygon.Insert(aPolygon);
+
+ Hatch aHatch(HatchStyle::Single, COL_YELLOW, 15, 900_deg10);
+
+ pVirtualDev->DrawHatch(aPolyPolygon, aHatch);
+
+ checkHatch(writeAndReadStream(aGDIMetaFile));
+ checkHatch(readFile(u"hatch.svm"));
+}
+
+void SvmTest::checkWallpaper(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ // Funny enough - we don't serialize the rectangle of the wallpaper so it's always EMPTY
+ assertXPathAttrs(pDoc, "/metafile/wallpaper[1]",
+ {
+ {"left", "0"},
+ {"top", "0"},
+ {"right", "empty"},
+ {"bottom", "empty"},
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/wallpaper[1]/wallpaper",
+ {
+ {"color", "#00ff00"},
+ {"style", "Tile"},
+ {"fixed", "true"},
+ {"scrollable", "true"},
+ });
+}
+
+void SvmTest::testWallpaper()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ Wallpaper aWallpaper(COL_LIGHTGREEN);
+ pVirtualDev->DrawWallpaper(tools::Rectangle(Point(1, 1), Size(3, 3)), aWallpaper);
+
+ checkWallpaper(writeAndReadStream(aGDIMetaFile));
+ checkWallpaper(readFile(u"wallpaper.svm"));
+}
+
+void SvmTest::checkClipRegion(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[1]", {
+ {"left", "2"},
+ {"top", "2"},
+ {"right", "5"},
+ {"bottom", "5"},
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[2]/polygon[1]/point[1]", {
+ {"x", "1"},
+ {"y", "8"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[2]/polygon[1]/point[2]", {
+ {"x", "2"},
+ {"y", "7"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[2]/polygon[1]/point[3]", {
+ {"x", "3"},
+ {"y", "6"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[3]/polygon[1]/point[1]", {
+ {"x", "1"},
+ {"y", "8"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[3]/polygon[1]/point[2]", {
+ {"x", "2"},
+ {"y", "7"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[3]/polygon[1]/point[3]", {
+ {"x", "3"},
+ {"y", "6"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[3]/polygon[2]/point[1]", {
+ {"x", "4"},
+ {"y", "9"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[3]/polygon[2]/point[2]", {
+ {"x", "5"},
+ {"y", "10"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[3]/polygon[2]/point[3]", {
+ {"x", "6"},
+ {"y", "11"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[4]/polygon[1]/point[1]", {
+ {"x", "0"},
+ {"y", "1"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[4]/polygon[1]/point[2]", {
+ {"x", "2"},
+ {"y", "3"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/clipregion[4]/polygon[1]/point[3]", {
+ {"x", "4"},
+ {"y", "4"}
+ });
+}
+
+void SvmTest::testClipRegion()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ vcl::Region aRegion(tools::Rectangle(Point(2, 2), Size(4, 4)));
+
+ pVirtualDev->SetClipRegion(aRegion);
+
+ tools::Polygon aPolygon(3);
+ aPolygon.SetPoint(Point(1, 8), 0);
+ aPolygon.SetPoint(Point(2, 7), 1);
+ aPolygon.SetPoint(Point(3, 6), 2);
+
+ vcl::Region aRegion2(aPolygon);
+ pVirtualDev->SetClipRegion(aRegion2);
+
+ tools::Polygon aPolygon1(3);
+ aPolygon1.SetPoint(Point(4, 9), 0);
+ aPolygon1.SetPoint(Point(5, 10), 1);
+ aPolygon1.SetPoint(Point(6, 11), 2);
+
+ tools::PolyPolygon aPolyPolygon(2);
+ aPolyPolygon.Insert(aPolygon);
+ aPolyPolygon.Insert(aPolygon1);
+
+ vcl::Region aRegion3(aPolyPolygon);
+ pVirtualDev->SetClipRegion(aRegion3);
+
+ basegfx::B2DPolygon aB2DPolygon;
+ aB2DPolygon.append(basegfx::B2DPoint(0.0, 1.1));
+ aB2DPolygon.append(basegfx::B2DPoint(2.2, 3.3));
+ aB2DPolygon.append(basegfx::B2DPoint(3.7, 3.8));
+
+ basegfx::B2DPolyPolygon aB2DPolyPolygon(aB2DPolygon);
+
+ vcl::Region aRegion4(aB2DPolyPolygon);
+ pVirtualDev->SetClipRegion(aRegion4);
+
+ checkClipRegion(writeAndReadStream(aGDIMetaFile));
+ checkClipRegion(readFile(u"clipregion.svm"));
+}
+
+void SvmTest::checkIntersectRectClipRegion(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/sectregionclipregion[1]", {
+ {"left", "1"},
+ {"top", "2"},
+ {"right", "4"},
+ {"bottom", "9"}
+ });
+}
+
+void SvmTest::testIntersectRectClipRegion()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Rectangle aRectangle(Point(1, 2), Size(4, 8));
+
+ vcl::Region aRegion(aRectangle);
+
+ pVirtualDev->IntersectClipRegion(aRegion);
+ checkIntersectRectClipRegion(writeAndReadStream(aGDIMetaFile));
+ checkIntersectRectClipRegion(readFile(u"intersectrectclipregion.svm"));
+}
+
+void SvmTest::checkIntersectRegionClipRegion(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/sectregionclipregion[1]", {
+ {"left", "1"},
+ {"top", "2"},
+ {"right", "5"},
+ {"bottom", "6"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/sectregionclipregion[2]", {
+ {"left", "1"},
+ {"top", "2"},
+ {"right", "7"},
+ {"bottom", "8"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/sectregionclipregion[3]", {
+ {"left", "0"},
+ {"top", "3"},
+ {"right", "2"},
+ {"bottom", "6"}
+ });
+}
+
+void SvmTest::testIntersectRegionClipRegion()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Polygon aPolygon(3);
+ aPolygon.SetPoint(Point(1, 2), 0);
+ aPolygon.SetPoint(Point(3, 4), 1);
+ aPolygon.SetPoint(Point(5, 6), 2);
+
+ vcl::Region aRegion(aPolygon);
+ pVirtualDev->IntersectClipRegion(aRegion);
+
+ tools::Polygon aPolygon1(2);
+ aPolygon1.SetPoint(Point(5, 6), 0);
+ aPolygon1.SetPoint(Point(7, 8), 1);
+
+ tools::PolyPolygon aPolyPolygon(2);
+ aPolyPolygon.Insert(aPolygon);
+ aPolyPolygon.Insert(aPolygon1);
+
+ vcl::Region aRegion1(aPolyPolygon);
+ pVirtualDev->IntersectClipRegion(aRegion1);
+
+ basegfx::B2DPolygon aB2DPolygon;
+ aB2DPolygon.append(basegfx::B2DPoint(0.0, 3.3));
+ aB2DPolygon.append(basegfx::B2DPoint(1.1, 4.4));
+ aB2DPolygon.append(basegfx::B2DPoint(2.2, 5.5));
+
+ basegfx::B2DPolyPolygon aB2DPolyPolygon(aB2DPolygon);
+
+ vcl::Region aRegion2(aB2DPolyPolygon);
+ pVirtualDev->IntersectClipRegion(aRegion2);
+
+ checkIntersectRegionClipRegion(writeAndReadStream(aGDIMetaFile));
+ checkIntersectRegionClipRegion(readFile(u"intersectregionclipregion.svm"));
+}
+
+void SvmTest::checkMoveClipRegion(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/moveclipregion[1]", {
+ {"horzmove", "1"},
+ {"vertmove", "2"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/moveclipregion[2]", {
+ {"horzmove", "-3"},
+ {"vertmove", "-4"}
+ });
+}
+
+void SvmTest::testMoveClipRegion()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Rectangle aRectangle(Point(1, 2), Size(4, 8));
+
+ vcl::Region aRegion(aRectangle);
+ aRegion.Move(2, 2);
+ pVirtualDev->SetClipRegion(aRegion);
+
+ pVirtualDev->MoveClipRegion(1, 2);
+ pVirtualDev->MoveClipRegion(-3, -4);
+
+ checkMoveClipRegion(writeAndReadStream(aGDIMetaFile));
+ checkMoveClipRegion(readFile(u"moveclipregion.svm"));
+}
+
+void SvmTest::checkLineColor(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/push/linecolor[1]", {
+ {"color", "#654321"},
+ });
+}
+
+void SvmTest::testLineColor()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->Push();
+ pVirtualDev->SetLineColor(Color(0x654321));
+ pVirtualDev->Pop();
+
+ checkLineColor(writeAndReadStream(aGDIMetaFile));
+ checkLineColor(readFile(u"linecolor.svm"));
+}
+
+void SvmTest::checkFillColor(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/push/fillcolor[1]", {
+ {"color", "#456789"},
+ });
+}
+
+void SvmTest::testFillColor()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->Push();
+ pVirtualDev->SetFillColor(Color(0x456789));
+ pVirtualDev->Pop();
+
+ checkFillColor(writeAndReadStream(aGDIMetaFile));
+ checkFillColor(readFile(u"fillcolor.svm"));
+}
+
+void SvmTest::checkTextColor(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/textcolor[1]", {
+ {"color", "#123456"},
+ });
+}
+
+void SvmTest::testTextColor()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetTextColor(Color(0x123456));
+
+ checkTextColor(writeAndReadStream(aGDIMetaFile));
+ checkTextColor(readFile(u"textcolor.svm"));
+}
+
+void SvmTest::checkTextFillColor(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/textfillcolor[1]", {
+ {"color", "#234567"},
+ });
+}
+
+void SvmTest::testTextFillColor()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetTextFillColor(Color(0x234567));
+
+ checkTextFillColor(writeAndReadStream(aGDIMetaFile));
+ checkTextFillColor(readFile(u"textfillecolor.svm"));
+}
+
+void SvmTest::checkTextLineColor(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/textlinecolor[1]", {
+ {"color", "#345678"},
+ });
+}
+
+void SvmTest::testTextLineColor()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetTextLineColor(Color(0x345678));
+
+ checkTextLineColor(writeAndReadStream(aGDIMetaFile));
+ checkTextLineColor(readFile(u"textlinecolor.svm"));
+}
+
+void SvmTest::checkOverLineColor(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/push/overlinecolor[1]", {
+ {"color", "#345678"},
+ });
+}
+
+void SvmTest::testOverLineColor()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->Push();
+ pVirtualDev->SetOverlineColor(Color(0x345678));
+ pVirtualDev->Pop();
+
+ checkOverLineColor(writeAndReadStream(aGDIMetaFile));
+ checkOverLineColor(readFile(u"overlinecolor.svm"));
+}
+
+void SvmTest::checkTextAlign(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/textalign[1]", {
+ {"align", "bottom"},
+ });
+}
+
+void SvmTest::testTextAlign()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetTextAlign(TextAlign::ALIGN_BOTTOM);
+
+ checkTextAlign(writeAndReadStream(aGDIMetaFile));
+ checkTextAlign(readFile(u"textalign.svm"));
+}
+
+void SvmTest::checkMapMode(const GDIMetaFile& rMetafile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetafile);
+
+ assertXPathAttrs(pDoc, "/metafile/mapmode[1]", {
+ {"mapunit", "MapPixel"},
+ {"x", "0"},
+ {"y", "0"},
+ {"scalex", "(1/1)"},
+ {"scaley", "(1/1)"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/mapmode[2]", {
+ {"mapunit", "Map100thInch"},
+ {"x", "0"},
+ {"y", "1"},
+ {"scalex", "(1/2)"},
+ {"scaley", "(2/3)"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/mapmode[3]", {
+ {"mapunit", "MapRelative"},
+ {"x", "0"},
+ {"y", "-1"},
+ {"scalex", "(25/12)"},
+ {"scaley", "(25/16)"}
+ });
+}
+
+void SvmTest::testMapMode()
+{
+ if (!IsDefaultDPI())
+ return;
+ GDIMetaFile aGDIMetafile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetafile);
+
+ MapMode aMapMode;
+
+ pVirtualDev->SetMapMode(aMapMode);
+
+ MapMode aMapMode1(MapUnit::Map100thInch);
+ aMapMode1.SetOrigin(Point(0, 1));
+ aMapMode1.SetScaleX(Fraction(1, 2));
+ aMapMode1.SetScaleY(Fraction(2, 3));
+
+ pVirtualDev->SetMetafileMapMode(aMapMode1, false);
+
+ MapMode aMapMode2;
+ pVirtualDev->SetMetafileMapMode(aMapMode2, true);
+
+ checkMapMode(writeAndReadStream(aGDIMetafile));
+ checkMapMode(readFile(u"mapmode.svm"));
+}
+
+#if HAVE_MORE_FONTS && !defined(_WIN32)
+void SvmTest::checkFont(const GDIMetaFile& rMetafile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetafile);
+ assertXPathAttrs(pDoc, "/metafile/font[1]", {
+ {"color", "#ffffff"},
+ {"fillcolor", "#ffffff"},
+ {"name", "Liberation Sans"},
+ {"stylename", "Regular"},
+ {"width", "12"},
+ {"height", "12"},
+ {"orientation", "50"},
+ {"weight", "thin"},
+ {"vertical", "true"},
+ });
+}
+#endif
+
+void SvmTest::testFont()
+{
+#if HAVE_MORE_FONTS
+// Windows interprets Width differently causing build errors
+#if !defined(_WIN32)
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+ vcl::Font aFont(FontFamily::FAMILY_SCRIPT, Size(15, 15));
+ aFont.SetWeight(FontWeight::WEIGHT_THIN);
+ aFont.SetFamilyName("Liberation Sans");
+ aFont.SetStyleName("Regular");
+ aFont.SetFontHeight(12);
+ aFont.SetAverageFontWidth(12);
+ aFont.SetVertical(true);
+ aFont.SetOrientation(Degree10(50));
+ pVirtualDev->SetFont(aFont);
+ checkFont(writeAndReadStream(aGDIMetaFile));
+ checkFont(readFile(u"font.svm"));
+#endif // _WIN32
+#endif
+}
+
+void SvmTest::checkPushPop(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/push[1]", {{"flags", "PushAll"}});
+ assertXPathAttrs(pDoc, "/metafile/push[1]/linecolor[1]", {{"color", "#800000"}});
+ assertXPathAttrs(pDoc, "/metafile/push[1]/line[1]", {
+ {"startx", "4"}, {"starty", "4"},
+ {"endx", "6"}, {"endy", "6"},
+ });
+ assertXPathAttrs(pDoc, "/metafile/push[1]/push[1]", {{"flags", "PushLineColor, PushFillColor"}});
+ assertXPathAttrs(pDoc, "/metafile/push[1]/push[1]/line[1]", {
+ {"startx", "5"}, {"starty", "5"},
+ {"endx", "7"}, {"endy", "7"},
+ });
+}
+
+void SvmTest::testPushPop()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetLineColor(COL_YELLOW);
+ pVirtualDev->Push();
+ pVirtualDev->SetLineColor(COL_RED);
+ pVirtualDev->DrawLine(Point(4,4), Point(6,6));
+ pVirtualDev->Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
+ pVirtualDev->SetLineColor(COL_LIGHTRED);
+ pVirtualDev->DrawLine(Point(5,5), Point(7,7));
+ pVirtualDev->Pop();
+ pVirtualDev->Pop();
+ pVirtualDev->DrawLine(Point(1,1), Point(8,8));
+
+ checkPushPop(writeAndReadStream(aGDIMetaFile));
+ checkPushPop(readFile(u"pushpop.svm"));
+}
+
+void SvmTest::checkRasterOp(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/rasterop[1]", {
+ {"operation", "xor"},
+ });
+}
+
+void SvmTest::testRasterOp()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetRasterOp(RasterOp::Xor);
+
+ checkRasterOp(writeAndReadStream(aGDIMetaFile));
+ checkRasterOp(readFile(u"rasterop.svm"));
+}
+
+void SvmTest::checkTransparent(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/transparent[1]", {
+ {"transparence", "50"},
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/transparent[1]/polygon/point[1]", {
+ {"x", "1"}, {"y", "8"},
+ });
+ assertXPathAttrs(pDoc, "/metafile/transparent[1]/polygon/point[2]", {
+ {"x", "2"}, {"y", "7"},
+ });
+ assertXPathAttrs(pDoc, "/metafile/transparent[1]/polygon/point[3]", {
+ {"x", "3"}, {"y", "6"},
+ });
+}
+
+void SvmTest::testTransparent()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ tools::Polygon aPolygon(3);
+ aPolygon.SetPoint(Point(1, 8), 0);
+ aPolygon.SetPoint(Point(2, 7), 1);
+ aPolygon.SetPoint(Point(3, 6), 2);
+
+ tools::PolyPolygon aPolyPolygon(1);
+ aPolyPolygon.Insert(aPolygon);
+
+ pVirtualDev->DrawTransparent(aPolygon, 50);
+
+ CPPUNIT_ASSERT(aGDIMetaFile.HasTransparentActions());
+ checkTransparent(writeAndReadStream(aGDIMetaFile));
+ checkTransparent(readFile(u"transparent.svm"));
+}
+
+void SvmTest::checkFloatTransparent(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/floattransparent[1]", {
+ {"x", "1"},
+ {"y", "2"},
+ {"width", "3"},
+ {"height", "4"},
+ {"transparent", "true"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/floattransparent[1]/gradient[1]", {
+ {"style", "Linear"},
+ {"startcolor", "#ffffff"},
+ {"endcolor", "#000000"},
+ {"angle", "0"},
+ {"border", "0"},
+ {"offsetx", "50"},
+ {"offsety", "50"},
+ {"startintensity", "100"},
+ {"endintensity", "100"},
+ {"steps", "0"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/floattransparent[1]/metafile[1]/point[1]", {
+ {"x", "1"},
+ {"y", "8"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/floattransparent[1]/metafile[1]/point[2]", {
+ {"x", "2"},
+ {"y", "7"}
+ });
+}
+
+void SvmTest::testFloatTransparent()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ GDIMetaFile aGDIMetaFile1;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev1;
+ setupBaseVirtualDevice(*pVirtualDev1, aGDIMetaFile1);
+
+ pVirtualDev1->DrawPixel(Point(1, 8));
+ pVirtualDev1->DrawPixel(Point(2, 7));
+
+ Gradient aGradient(GradientStyle::Linear, COL_WHITE, COL_BLACK);
+
+ pVirtualDev->DrawTransparent(aGDIMetaFile1, Point(1, 2), Size(3, 4), aGradient);
+
+ checkFloatTransparent(writeAndReadStream(aGDIMetaFile));
+ checkFloatTransparent(readFile(u"floattransparent.svm"));
+}
+
+void SvmTest::checkEPS(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/eps[1]", {
+ {"x", "1"},
+ {"y", "8"},
+ {"width", "2"},
+ {"height", "7"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/eps[1]/gfxlink[1]", {
+ {"width", "3"},
+ {"height", "6"},
+ {"type", "EpsBuffer"},
+ {"userid", "12345"},
+ {"datasize", "3"},
+ {"data", "616263"},
+ {"native", "false"},
+ {"emf", "false"},
+ {"validmapmode", "true"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/eps[1]/gfxlink[1]/prefmapmode[1]", {
+ {"mapunit", "Map100thInch"},
+ {"x", "0"},
+ {"y", "1"},
+ {"scalex", "(1/2)"},
+ {"scaley", "(2/3)"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/eps[1]/metafile[1]/point[1]", {
+ {"x", "1"},
+ {"y", "8"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/eps[1]/metafile[1]/point[2]", {
+ {"x", "2"},
+ {"y", "7"}
+ });
+}
+
+void SvmTest::testEPS()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ sal_uInt32 nDataSize = 3;
+ std::unique_ptr<sal_uInt8[]> pBuffer (new sal_uInt8[nDataSize]);
+ pBuffer[0] = 'a';
+ pBuffer[1] = 'b';
+ pBuffer[2] = 'c';
+
+ MapMode aMapMode1(MapUnit::Map100thInch);
+ aMapMode1.SetOrigin(Point(0, 1));
+ aMapMode1.SetScaleX(Fraction(1, 2));
+ aMapMode1.SetScaleY(Fraction(2, 3));
+
+ GDIMetaFile aGDIMetaFile1;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev1;
+ setupBaseVirtualDevice(*pVirtualDev1, aGDIMetaFile1);
+
+ pVirtualDev1->DrawPixel(Point(1, 8));
+ pVirtualDev1->DrawPixel(Point(2, 7));
+
+ GfxLink aGfxLink(std::move(pBuffer), nDataSize, GfxLinkType::EpsBuffer);
+ aGfxLink.SetPrefMapMode(aMapMode1);
+ aGfxLink.SetUserId(12345);
+ aGfxLink.SetPrefSize(Size(3, 6));
+ pVirtualDev->DrawEPS(Point(1, 8), Size(2, 7), aGfxLink, &aGDIMetaFile1);
+
+ checkEPS(writeAndReadStream(aGDIMetaFile));
+ checkEPS(readFile(u"eps.svm"));
+}
+
+void SvmTest::checkRefPoint(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/refpoint[1]", {
+ {"x", "0"},
+ {"y", "0"},
+ {"set", "false"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/refpoint[2]", {
+ {"x", "1"},
+ {"y", "2"},
+ {"set", "true"}
+ });
+}
+
+void SvmTest::testRefPoint()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetRefPoint();
+
+ pVirtualDev->SetRefPoint(Point(1,2));
+
+ checkRefPoint(writeAndReadStream(aGDIMetaFile));
+ checkRefPoint(readFile(u"refpoint.svm"));
+}
+
+void SvmTest::checkComment(const GDIMetaFile& rMetafile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetafile);
+
+ assertXPathAttrs(pDoc, "/metafile/comment[1]", {
+ {"value", "0"}
+ });
+
+ assertXPathContent(pDoc, "/metafile/comment[1]/comment[1]", "Test comment");
+
+ assertXPathAttrs(pDoc, "/metafile/comment[2]", {
+ {"datasize", "48"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/comment[2]", {
+ {"data", "540068006500730065002000610072006500200073006f006d0065002000740065007300740020006400610074006100"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/comment[2]", {
+ {"value", "4"}
+ });
+
+ assertXPathContent(pDoc, "/metafile/comment[2]/comment[1]", "This is a test comment");
+}
+
+void SvmTest::testComment()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ aGDIMetaFile.AddAction(new MetaCommentAction("Test comment"));
+
+ using namespace std::literals::string_view_literals;
+ static constexpr auto aString
+ = "T\0h\0e\0s\0e\0 \0a\0r\0e\0 \0s\0o\0m\0e\0 \0t\0e\0s\0t\0 \0d\0a\0t\0a\0"sv;
+ aGDIMetaFile.AddAction(new MetaCommentAction("This is a test comment", \
+ 4, \
+ reinterpret_cast<const sal_uInt8*>(aString.data()), \
+ aString.length() ));
+
+ checkComment(writeAndReadStream(aGDIMetaFile));
+ checkComment(readFile(u"comment.svm"));
+}
+
+void SvmTest::checkLayoutMode(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/layoutmode[1]", {
+ {"textlayout", "#0004"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/layoutmode[2]", {
+ {"textlayout", "#0001"}
+ });
+}
+
+void SvmTest::testLayoutMode()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::TextOriginLeft);
+ pVirtualDev->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::BiDiRtl);
+
+ checkLayoutMode(writeAndReadStream(aGDIMetaFile));
+ checkLayoutMode(readFile(u"layoutmode.svm"));
+}
+
+void SvmTest::checkTextLanguage(const GDIMetaFile& rMetaFile)
+{
+ xmlDocUniquePtr pDoc = dumpMeta(rMetaFile);
+
+ assertXPathAttrs(pDoc, "/metafile/textlanguage[1]", {
+ {"language", "#0408"}
+ });
+
+ assertXPathAttrs(pDoc, "/metafile/textlanguage[2]", {
+ {"language", "#00ff"}
+ });
+}
+
+void SvmTest::testTextLanguage()
+{
+ GDIMetaFile aGDIMetaFile;
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
+ setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
+
+ pVirtualDev->SetDigitLanguage(LANGUAGE_GREEK);
+ pVirtualDev->SetDigitLanguage(LANGUAGE_NONE);
+
+ checkTextLanguage(writeAndReadStream(aGDIMetaFile));
+ checkTextLanguage(readFile(u"textlanguage.svm"));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SvmTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/test_blocklist_evaluate.xml b/vcl/qa/cppunit/test_blocklist_evaluate.xml
new file mode 100644
index 000000000..bd9985e32
--- /dev/null
+++ b/vcl/qa/cppunit/test_blocklist_evaluate.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+
+<!--
+ entry attributes:
+ os - "all", "7", "8", "8_1", "10", "windows", "linux", "osx_10_5", "osx_10_6", "osx_10_7", "osx_10_8", "osx"
+ vendor - "all", "intel", "amd", "nvidia", "microsoft"
+ compare - "less", "less_equal", "greater", "greater_equal", "equal", "not_equal", "between_exclusive", "between_inclusive", "between_inclusive_start"
+ version
+ minVersion
+ maxVersion
+-->
+
+<root>
+ <allowlist>
+ </allowlist>
+ <denylist>
+
+ <entry os="all" vendor="amd" compare="less" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+
+ <entry os="all" vendor="microsoft" compare="equal" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+
+ <entry os="all" vendor="intel" compare="less" version="10.18.14.4264">
+ <device id="all"/>
+ </entry>
+
+ <entry os="osx" vendor="microsoft" compare="equal" version="10.20.30.50">
+ <device id="all"/>
+ </entry>
+
+ <entry os="linux" vendor="microsoft" compare="equal" version="10.20.30.50">
+ <device id="all"/>
+ </entry>
+
+ </denylist>
+</root>
diff --git a/vcl/qa/cppunit/test_blocklist_parse.xml b/vcl/qa/cppunit/test_blocklist_parse.xml
new file mode 100644
index 000000000..9a0f6acc5
--- /dev/null
+++ b/vcl/qa/cppunit/test_blocklist_parse.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+
+<root>
+ <allowlist>
+ <entry os="all" vendor="all" compare="less" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="7" vendor="nvidia" compare="equal" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="8" vendor="microsoft" compare="not_equal" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="8" vendor="0xcafe" compare="not_equal" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="8_1" compare="between_exclusive" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="10" compare="between_inclusive" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="all" compare="between_inclusive_start" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="all">
+ <device id="all"/>
+ </entry>
+ </allowlist>
+ <denylist>
+ <entry os="all" vendor="all" compare="less" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="7" vendor="nvidia" compare="equal" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="8" vendor="microsoft" compare="not_equal" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="8" vendor="0xcafe" compare="not_equal" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="8_1" compare="between_exclusive" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="10" compare="between_inclusive" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="all" compare="between_inclusive_start" version="10.20.30.40">
+ <device id="all"/>
+ </entry>
+ <entry os="all">
+ <device id="all"/>
+ </entry>
+ </denylist>
+</root>
diff --git a/vcl/qa/cppunit/test_blocklist_vulkan.xml b/vcl/qa/cppunit/test_blocklist_vulkan.xml
new file mode 100644
index 000000000..9542ee5f2
--- /dev/null
+++ b/vcl/qa/cppunit/test_blocklist_vulkan.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+
+<!--
+ entry attributes:
+ os - "all", "7", "8", "8_1", "10"
+ vendor - "all", "intel", "amd", "nvidia", "microsoft"
+ compare - "less", "less_equal", "greater", "greater_equal", "equal", "not_equal", "between_exclusive", "between_inclusive", "between_inclusive_start"
+ version
+ minVersion
+ maxVersion
+-->
+
+<root>
+ <allowlist>
+ </allowlist>
+ <denylist>
+
+ <entry os="all" vendor="amd" compare="less" version="1.2.3">
+ <device id="all"/>
+ </entry>
+
+ </denylist>
+</root>
diff --git a/vcl/qa/cppunit/text.cxx b/vcl/qa/cppunit/text.cxx
new file mode 100644
index 000000000..823ffeabf
--- /dev/null
+++ b/vcl/qa/cppunit/text.cxx
@@ -0,0 +1,752 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <osl/file.hxx>
+#include <osl/process.h>
+#include <test/bootstrapfixture.hxx>
+#include <sal/log.hxx>
+#include <tools/stream.hxx>
+
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/errcode.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+
+#include <ImplLayoutArgs.hxx>
+#include <TextLayoutCache.hxx>
+#include <salgdi.hxx>
+
+class VclTextTest : public test::BootstrapFixture
+{
+ // if enabled - check the result images with:
+ // "xdg-open ./workdir/CppunitTest/vcl_text_test.test.core/"
+ static constexpr const bool mbExportBitmap = false;
+
+ void exportDevice(const OUString& filename, const VclPtr<VirtualDevice>& device)
+ {
+ if (mbExportBitmap)
+ {
+ BitmapEx aBitmapEx(device->GetBitmapEx(Point(0, 0), device->GetOutputSizePixel()));
+ OUString cwd;
+ CPPUNIT_ASSERT_EQUAL(osl_Process_E_None, osl_getProcessWorkingDir(&cwd.pData));
+ OUString url;
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None,
+ osl::FileBase::getAbsoluteFileURL(cwd, filename, url));
+ SvFileStream aStream(url, StreamMode::WRITE | StreamMode::TRUNC);
+ CPPUNIT_ASSERT_EQUAL(
+ ERRCODE_NONE, GraphicFilter::GetGraphicFilter().compressAsPNG(aBitmapEx, aStream));
+ }
+ }
+
+public:
+ VclTextTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ void testSimpleText();
+ void testVerticalText();
+ void testTextLayoutCache();
+ void testImplLayoutRuns_AddPos();
+ void testImplLayoutRuns_AddRuns();
+ void testImplLayoutRuns_PosIsInRun();
+ void testImplLayoutRuns_PosIsInAnyRun();
+ void testImplLayoutArgsBiDiStrong();
+ void testImplLayoutArgsBiDiRtl();
+ void testImplLayoutArgsRightAlign();
+ void testImplLayoutArgs_PrepareFallback_precalculatedglyphs();
+
+ CPPUNIT_TEST_SUITE(VclTextTest);
+ CPPUNIT_TEST(testSimpleText);
+ CPPUNIT_TEST(testVerticalText);
+ CPPUNIT_TEST(testTextLayoutCache);
+ CPPUNIT_TEST(testImplLayoutRuns_AddPos);
+ CPPUNIT_TEST(testImplLayoutRuns_AddRuns);
+ CPPUNIT_TEST(testImplLayoutRuns_PosIsInRun);
+ CPPUNIT_TEST(testImplLayoutRuns_PosIsInAnyRun);
+ CPPUNIT_TEST(testImplLayoutArgsBiDiStrong);
+ CPPUNIT_TEST(testImplLayoutArgsBiDiRtl);
+ CPPUNIT_TEST(testImplLayoutArgsRightAlign);
+ CPPUNIT_TEST(testImplLayoutArgs_PrepareFallback_precalculatedglyphs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+// Avoid issues when colorized antialiasing generates slightly tinted rather than truly black
+// pixels:
+static bool isBlack(Color col)
+{
+ return col.GetRed() < 25 && col.GetGreen() < 25 && col.GetBlue() < 25;
+}
+
+// Return pixel width of the base of the given character located above
+// the starting position.
+// In other words, go up in y direction until a black pixel is found,
+// then return the horizontal width of the area of those pixels.
+// For 'L' this gives the width of the base of the character.
+static tools::Long getCharacterBaseWidth(VirtualDevice* device, const Point& start)
+{
+ Bitmap bitmap = device->GetBitmap(Point(), device->GetOutputSizePixel());
+ Bitmap::ScopedReadAccess access(bitmap);
+ tools::Long y = start.Y();
+ while (y >= 0 && !isBlack(access->GetColor(y, start.X())))
+ --y;
+ if (y < 0)
+ return -1;
+ tools::Long xmin = start.X();
+ while (xmin >= 0 && access->GetColor(y, xmin) != COL_WHITE)
+ --xmin;
+ tools::Long xmax = start.X();
+ while (xmax < bitmap.GetSizePixel().Width() && access->GetColor(y, xmax) != COL_WHITE)
+ ++xmax;
+ return xmax - xmin + 1;
+}
+
+// Similar to above but this time from the top, for U+30E8 (it's straight at the top, not at the bottom).
+static tools::Long getCharacterTopWidth(VirtualDevice* device, const Point& start)
+{
+ Bitmap bitmap = device->GetBitmap(Point(), device->GetOutputSizePixel());
+ Bitmap::ScopedReadAccess access(bitmap);
+ tools::Long y = start.Y();
+ while (y < bitmap.GetSizePixel().Height() && !isBlack(access->GetColor(y, start.X())))
+ ++y;
+ if (y >= bitmap.GetSizePixel().Height())
+ return -1;
+ tools::Long xmin = start.X();
+ while (xmin >= 0 && access->GetColor(y, xmin) != COL_WHITE)
+ --xmin;
+ tools::Long xmax = start.X();
+ while (xmax < bitmap.GetSizePixel().Width() && access->GetColor(y, xmax) != COL_WHITE)
+ ++xmax;
+ return xmax - xmin + 1;
+}
+
+// Similar to above, but this time return the pixel height of the left-most
+// line of the character, going right from the starting point.
+// For 'L' this gives the height of the left line.
+static tools::Long getCharacterLeftSideHeight(VirtualDevice* device, const Point& start)
+{
+ Bitmap bitmap = device->GetBitmap(Point(), device->GetOutputSizePixel());
+ Bitmap::ScopedReadAccess access(bitmap);
+ tools::Long x = start.X();
+ while (x < bitmap.GetSizePixel().Width() && !isBlack(access->GetColor(start.Y(), x)))
+ ++x;
+ if (x >= bitmap.GetSizePixel().Width())
+ return -1;
+ tools::Long ymin = start.Y();
+ while (ymin >= 0 && access->GetColor(ymin, x) != COL_WHITE)
+ --ymin;
+ tools::Long ymax = start.Y();
+ while (ymax < bitmap.GetSizePixel().Width() && access->GetColor(ymax, x) != COL_WHITE)
+ ++ymax;
+ return ymax - ymin + 1;
+}
+
+// The same, but from the right side, for U+30E8 (it's straight on the right side, not the left one).
+static tools::Long getCharacterRightSideHeight(VirtualDevice* device, const Point& start)
+{
+ Bitmap bitmap = device->GetBitmap(Point(), device->GetOutputSizePixel());
+ Bitmap::ScopedReadAccess access(bitmap);
+ tools::Long x = start.X();
+ while (x >= 0 && !isBlack(access->GetColor(start.Y(), x)))
+ --x;
+ if (x < 0)
+ return -1;
+ tools::Long ymin = start.Y();
+ while (ymin >= 0 && access->GetColor(ymin, x) != COL_WHITE)
+ --ymin;
+ tools::Long ymax = start.Y();
+ while (ymax < bitmap.GetSizePixel().Width() && access->GetColor(ymax, x) != COL_WHITE)
+ ++ymax;
+ return ymax - ymin + 1;
+}
+
+// Test rendering of the 'L' character (chosen because L is a simple shape).
+// Check things like using a double font size doubling the size of the character, correct rotation, etc.
+// IMPORTANT: If you modify this, check also the testVerticalText().
+void VclTextTest::testSimpleText()
+{
+ OUString text("L");
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(100, 100));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ // Disable AA, to make all pixels be black or white.
+ device->SetAntialiasing(AntialiasingFlags::DisableText);
+
+ // Bail out on all backends that do not work (or I didn't test). Opt-out rather than opt-in
+ // to make sure new backends fail initially.
+ if (device->GetGraphics()->getRenderBackendName() == "qt5"
+ || device->GetGraphics()->getRenderBackendName() == "qt5svp"
+ || device->GetGraphics()->getRenderBackendName() == "gtk3svp"
+ || device->GetGraphics()->getRenderBackendName() == "aqua"
+ || device->GetGraphics()->getRenderBackendName() == "gen"
+ || device->GetGraphics()->getRenderBackendName() == "genpsp")
+ return;
+
+ // Use Dejavu fonts, they are shipped with LO, so they should be ~always available.
+ // Use Sans variant for simpler glyph shapes (no serifs).
+ vcl::Font font("DejaVu Sans", "Book", Size(0, 36));
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(10, 10), text);
+ exportDevice("simple-text-36.png", device);
+ // Height of 'L' with font 36 size should be roughly 28 pixels.
+ // Use the 'doubles' variant of the test, since that one allows
+ // a delta, and allow several pixels of delta to account
+ // for different rendering methods and whatnot.
+ tools::Long height36 = getCharacterLeftSideHeight(device, Point(0, 30));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(28), height36, 4);
+ tools::Long width36 = getCharacterBaseWidth(device, Point(20, 99));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(19), width36, 4);
+
+ font.SetOrientation(2700_deg10);
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(90, 10), text);
+ exportDevice("simple-text-36-270deg.png", device);
+ // Width and height here should be swapped, again allowing for some imprecisions.
+ tools::Long height36Rotated = getCharacterLeftSideHeight(device, Point(0, 20));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36, height36Rotated, 2);
+ tools::Long width36Rotated = getCharacterTopWidth(device, Point(70, 0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height36, width36Rotated, 2);
+
+ font = vcl::Font("DejaVu Sans", "Book", Size(0, 72));
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(10, 10), text);
+ exportDevice("simple-text-72.png", device);
+ // Font size is doubled, so pixel sizes should also roughly double.
+ tools::Long height72 = getCharacterLeftSideHeight(device, Point(0, 30));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height36 * 2, height72, 4);
+ tools::Long width72 = getCharacterBaseWidth(device, Point(20, 99));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36 * 2, width72, 4);
+
+ font.SetOrientation(2700_deg10);
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(90, 10), text);
+ exportDevice("simple-text-72-270deg.png", device);
+ tools::Long height72Rotated = getCharacterLeftSideHeight(device, Point(0, 35));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width72, height72Rotated, 2);
+ tools::Long width72Rotated = getCharacterTopWidth(device, Point(50, 0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height72, width72Rotated, 2);
+
+ // Test width scaled to 200%.
+ font = vcl::Font("DejaVu Sans", "Book", Size(72, 36));
+#ifdef _WIN32
+ // TODO: What is the proper way to draw 200%-wide text? This is needed on Windows
+ // but it breaks Linux.
+ font.SetAverageFontWidth(2 * font.GetOrCalculateAverageFontWidth());
+#endif
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(10, 10), text);
+ exportDevice("simple-text-36-200pct.png", device);
+ tools::Long height36pct200 = getCharacterLeftSideHeight(device, Point(0, 30));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height36, height36pct200, 2);
+ tools::Long width36pct200 = getCharacterBaseWidth(device, Point(20, 99));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36 * 2, width36pct200, 4);
+
+ // Test width scaled to 50%.
+ font = vcl::Font("DejaVu Sans", "Book", Size(18, 36));
+#ifdef _WIN32
+ font.SetAverageFontWidth(0.5 * font.GetOrCalculateAverageFontWidth());
+#endif
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(10, 10), text);
+ exportDevice("simple-text-36-50pct.png", device);
+ tools::Long height36pct50 = getCharacterLeftSideHeight(device, Point(0, 30));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height36, height36pct50, 2);
+ tools::Long width36pct50 = getCharacterBaseWidth(device, Point(15, 99));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36 / 2, width36pct50, 2);
+}
+
+// Like testSimpleText() but for a vertical character, here namely U+30E8 (katakana letter yo),
+// chosen because it's a fairly simple shape (looks like horizontally mirrored E) that should
+// have the right and top lines being straight. Well, and also chosen because I actually
+// do not have much clue about CJK.
+// IMPORTANT: If you modify this, modify also the testSimpleText().
+void VclTextTest::testVerticalText()
+{
+ OUString text(u"\x30e8");
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+ device->SetOutputSizePixel(Size(100, 100));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ // Disable AA, to make all pixels be black or white.
+ device->SetAntialiasing(AntialiasingFlags::DisableText);
+
+ // Bail out on all backends that do not work (or I didn't test). Opt-out rather than opt-in
+ // to make sure new backends fail initially.
+ if (device->GetGraphics()->getRenderBackendName() == "qt5"
+ || device->GetGraphics()->getRenderBackendName() == "qt5svp"
+ || device->GetGraphics()->getRenderBackendName() == "gtk3svp"
+ || device->GetGraphics()->getRenderBackendName() == "aqua"
+ || device->GetGraphics()->getRenderBackendName() == "gen"
+#ifdef MACOSX // vertical fonts are broken on Mac with or without Skia
+ || device->GetGraphics()->getRenderBackendName() == "skia"
+#endif
+ || device->GetGraphics()->getRenderBackendName() == "genpsp")
+ return;
+
+ // We do not ship any CJK fonts, so try to find a common one that is usable for the test.
+ vcl::Font baseFont;
+ vcl::Font font;
+ bool fontFound = false;
+ for (const char* ptrfontName :
+ { "Droid Sans Japanese", "Baekmuk Gulim", "Microsoft JhengHei", "Microsoft YaHei",
+ "MS PGothic", "Hiragino Sans", "Arial Unicode MS" })
+ {
+ OUString fontName = OUString::fromUtf8(ptrfontName);
+ if (!device->IsFontAvailable(fontName))
+ continue;
+ baseFont = vcl::Font(fontName, "Book", Size(0, 36));
+ baseFont.SetLanguage(LANGUAGE_JAPANESE);
+ baseFont.SetVertical(true);
+ baseFont.SetOrientation(2700_deg10);
+ if (device->HasGlyphs(baseFont, text) == -1) // -1 means no glyph is missing
+ {
+ fontFound = true;
+ break;
+ }
+ }
+ if (!fontFound)
+ {
+ SAL_WARN("vcl", "Could not find a font for VclTextTest::testVerticalText, skipping test.");
+ return;
+ }
+
+ font = baseFont;
+ font.SetFontSize(Size(0, 36));
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(90, 10), text);
+ exportDevice("vertical-text-36.png", device);
+ // Height of U+30E8 with font 36 size should be roughly 28 pixels,
+ // but since we don't know which font will be used, allow even more range.
+ tools::Long height36 = getCharacterRightSideHeight(device, Point(99, 22));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(28), height36, 6);
+ tools::Long width36 = getCharacterTopWidth(device, Point(65, 0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(25), width36, 6);
+
+ // Horizontal writing of vertical glyphs. For some reason in this case
+ // the font is not set to be vertical.
+ font.SetOrientation(0_deg10);
+ font.SetVertical(false);
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(10, 10), text);
+ exportDevice("vertical-text-36-0deg.png", device);
+ // Here width and height should be the same, since the glyphs actually
+ // not rotated compared to the vertical writing.
+ tools::Long height36Rotated = getCharacterRightSideHeight(device, Point(99, 35));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height36, height36Rotated, 1);
+ tools::Long width36Rotated = getCharacterTopWidth(device, Point(25, 0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36, width36Rotated, 1);
+
+ font = baseFont;
+ font.SetFontSize(Size(0, 72));
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(90, 10), text);
+ exportDevice("vertical-text-72.png", device);
+ // Font size is doubled, so pixel sizes should also roughly double.
+ tools::Long height72 = getCharacterRightSideHeight(device, Point(99, 35));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height36 * 2, height72, 4);
+ tools::Long width72 = getCharacterTopWidth(device, Point(40, 0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36 * 2, width72, 4);
+
+ font.SetOrientation(0_deg10);
+ font.SetVertical(false);
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(10, 10), text);
+ exportDevice("vertical-text-72-0deg.png", device);
+ tools::Long height72Rotated = getCharacterRightSideHeight(device, Point(99, 60));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height72, height72Rotated, 1);
+ tools::Long width72Rotated = getCharacterTopWidth(device, Point(45, 0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width72, width72Rotated, 1);
+
+ // On Windows scaling of vertical glyphs is broken.
+ if (device->GetGraphics()->getRenderBackendName() == "gdi")
+ return;
+
+ // Test width scaled to 200%.
+ font = baseFont;
+ font.SetFontSize(Size(72, 36));
+#ifdef _WIN32
+ // TODO: What is the proper way to draw 200%-wide text? This is needed on Windows
+ // but it breaks Linux.
+ font.SetAverageFontWidth(2 * font.GetOrCalculateAverageFontWidth());
+#endif
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(90, 10), text);
+ // Double "width" with vertical text makes the height doubled.
+ exportDevice("vertical-text-36-200pct.png", device);
+ tools::Long height36pct200 = getCharacterRightSideHeight(device, Point(99, 35));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height36 * 2, height36pct200, 4);
+ tools::Long width36pct200 = getCharacterTopWidth(device, Point(65, 0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36, width36pct200, 2);
+
+ // Test width scaled to 50%.
+ font = baseFont;
+ font.SetFontSize(Size(18, 36));
+#ifdef _WIN32
+ font.SetAverageFontWidth(0.5 * font.GetOrCalculateAverageFontWidth());
+#endif
+ device->Erase();
+ device->SetFont(font);
+ device->DrawText(Point(90, 10), text);
+ exportDevice("vertical-text-36-50pct.png", device);
+ tools::Long height36pct50 = getCharacterRightSideHeight(device, Point(99, 16));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(height36 / 2, height36pct50, 2);
+ tools::Long width36pct50 = getCharacterTopWidth(device, Point(65, 0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36, width36pct50, 2);
+}
+
+void VclTextTest::testTextLayoutCache()
+{
+ OUString sTestString = u"The quick brown fox\n jumped over the lazy dogالعاشر";
+ vcl::text::TextLayoutCache cache(sTestString.getStr(), sTestString.getLength());
+
+ vcl::text::Run run1 = cache.runs[0];
+ vcl::text::Run run2 = cache.runs[1];
+
+ bool bCorrectRuns = (cache.runs.size() == 2);
+ CPPUNIT_ASSERT_MESSAGE("Wrong number of runs", bCorrectRuns);
+ CPPUNIT_ASSERT_EQUAL(USCRIPT_LATIN, run1.nCode);
+ CPPUNIT_ASSERT_EQUAL(0, run1.nStart);
+ CPPUNIT_ASSERT_EQUAL(45, run1.nEnd);
+ CPPUNIT_ASSERT_EQUAL(USCRIPT_ARABIC, run2.nCode);
+ CPPUNIT_ASSERT_EQUAL(45, run2.nStart);
+ CPPUNIT_ASSERT_EQUAL(51, run2.nEnd);
+}
+
+void VclTextTest::testImplLayoutRuns_AddPos()
+{
+ ImplLayoutRuns aRuns;
+ aRuns.AddPos(1, false);
+ aRuns.AddPos(2, false);
+ aRuns.AddPos(3, false);
+ aRuns.AddPos(4, true); // add RTL marker glyph
+ aRuns.AddPos(5, false);
+ aRuns.AddPos(6, true); // add RTL marker glyph
+ aRuns.AddPos(7, false);
+
+ int nCharPos(0);
+ bool bRightToLeftMarker(false);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(1, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(2, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(3, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(4, nCharPos);
+ CPPUNIT_ASSERT(bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(5, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(6, nCharPos);
+ CPPUNIT_ASSERT(bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(7, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ // no next position, we are running off the end
+ CPPUNIT_ASSERT(!aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+
+ aRuns.ResetPos();
+
+ int nMinRunPos, nEndRunPos;
+ bool bRightToLeft(false);
+
+ CPPUNIT_ASSERT(aRuns.GetRun(&nMinRunPos, &nEndRunPos, &bRightToLeft));
+ CPPUNIT_ASSERT_EQUAL(1, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(4, nEndRunPos);
+ CPPUNIT_ASSERT(!bRightToLeft);
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.GetRun(&nMinRunPos, &nEndRunPos, &bRightToLeft));
+ CPPUNIT_ASSERT_EQUAL(4, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(5, nEndRunPos);
+ CPPUNIT_ASSERT(bRightToLeft);
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.GetRun(&nMinRunPos, &nEndRunPos, &bRightToLeft));
+ CPPUNIT_ASSERT_EQUAL(5, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(6, nEndRunPos);
+ CPPUNIT_ASSERT(!bRightToLeft);
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.GetRun(&nMinRunPos, &nEndRunPos, &bRightToLeft));
+ CPPUNIT_ASSERT_EQUAL(6, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(7, nEndRunPos);
+ CPPUNIT_ASSERT(bRightToLeft);
+
+ // test clear
+ aRuns.Clear();
+ CPPUNIT_ASSERT(aRuns.IsEmpty());
+}
+
+void VclTextTest::testImplLayoutRuns_AddRuns()
+{
+ ImplLayoutRuns aRuns;
+ aRuns.AddRun(1, 4, false);
+ aRuns.AddRun(5, 4, true);
+ aRuns.AddRun(5, 6, false);
+ aRuns.AddRun(6, 7, true);
+
+ int nCharPos(0);
+ bool bRightToLeftMarker(false);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(1, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(2, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(3, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(4, nCharPos);
+ CPPUNIT_ASSERT(bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(5, nCharPos);
+ CPPUNIT_ASSERT(!bRightToLeftMarker);
+
+ CPPUNIT_ASSERT(aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+ CPPUNIT_ASSERT_EQUAL(6, nCharPos);
+ CPPUNIT_ASSERT(bRightToLeftMarker);
+
+ // no next position, we are running off the end
+ CPPUNIT_ASSERT(!aRuns.GetNextPos(&nCharPos, &bRightToLeftMarker));
+
+ aRuns.ResetPos();
+
+ int nMinRunPos, nEndRunPos;
+ bool bRightToLeft(false);
+
+ CPPUNIT_ASSERT(aRuns.GetRun(&nMinRunPos, &nEndRunPos, &bRightToLeft));
+ CPPUNIT_ASSERT_EQUAL(1, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(4, nEndRunPos);
+ CPPUNIT_ASSERT(!bRightToLeft);
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.GetRun(&nMinRunPos, &nEndRunPos, &bRightToLeft));
+ CPPUNIT_ASSERT_EQUAL(4, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(5, nEndRunPos);
+ CPPUNIT_ASSERT(bRightToLeft);
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.GetRun(&nMinRunPos, &nEndRunPos, &bRightToLeft));
+ CPPUNIT_ASSERT_EQUAL(5, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(6, nEndRunPos);
+ CPPUNIT_ASSERT(!bRightToLeft);
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.GetRun(&nMinRunPos, &nEndRunPos, &bRightToLeft));
+ CPPUNIT_ASSERT_EQUAL(6, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(7, nEndRunPos);
+ CPPUNIT_ASSERT(bRightToLeft);
+}
+
+void VclTextTest::testImplLayoutRuns_PosIsInRun()
+{
+ ImplLayoutRuns aRuns;
+ aRuns.AddRun(1, 4, false);
+ aRuns.AddRun(4, 5, true);
+ aRuns.AddRun(5, 6, false);
+ aRuns.AddRun(6, 7, true);
+
+ CPPUNIT_ASSERT(aRuns.PosIsInRun(1));
+ CPPUNIT_ASSERT(aRuns.PosIsInRun(2));
+ CPPUNIT_ASSERT(aRuns.PosIsInRun(3));
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.PosIsInRun(4));
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.PosIsInRun(5));
+
+ aRuns.NextRun();
+ CPPUNIT_ASSERT(aRuns.PosIsInRun(6));
+
+ CPPUNIT_ASSERT(!aRuns.PosIsInRun(7));
+}
+
+void VclTextTest::testImplLayoutRuns_PosIsInAnyRun()
+{
+ ImplLayoutRuns aRuns;
+ aRuns.AddRun(1, 4, false);
+ aRuns.AddRun(4, 5, true);
+ aRuns.AddRun(5, 6, false);
+ aRuns.AddRun(6, 7, true);
+
+ CPPUNIT_ASSERT(aRuns.PosIsInAnyRun(1));
+ CPPUNIT_ASSERT(!aRuns.PosIsInAnyRun(7));
+}
+
+void VclTextTest::testImplLayoutArgsBiDiStrong()
+{
+ OUString sTestString = u"The quick brown fox\n jumped over the lazy dog"
+ "العاشر";
+ vcl::text::ImplLayoutArgs aArgs(sTestString, 0, sTestString.getLength(),
+ SalLayoutFlags::BiDiStrong, LanguageTag(LANGUAGE_NONE),
+ nullptr);
+
+ int nMinRunPos(0);
+ int nEndRunPos(0);
+ bool bRTL(false);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(0, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(19, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(20, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(51, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(20, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(51, nEndRunPos);
+}
+
+void VclTextTest::testImplLayoutArgsBiDiRtl()
+{
+ OUString sTestString = u"The quick brown fox\n jumped over the lazy dog"
+ "العاشر";
+ vcl::text::ImplLayoutArgs aArgs(sTestString, 0, sTestString.getLength(),
+ SalLayoutFlags::BiDiRtl, LanguageTag(LANGUAGE_NONE), nullptr);
+
+ int nMinRunPos(0);
+ int nEndRunPos(0);
+ bool bRTL(false);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(45, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(51, nEndRunPos);
+ CPPUNIT_ASSERT(&bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(21, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(45, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(20, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(21, nEndRunPos);
+ CPPUNIT_ASSERT(bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(0, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(19, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+}
+
+void VclTextTest::testImplLayoutArgsRightAlign()
+{
+ OUString sTestString = u"The quick brown fox\n jumped over the lazy dog"
+ "العاشر";
+ vcl::text::ImplLayoutArgs aArgs(sTestString, 0, sTestString.getLength(),
+ SalLayoutFlags::RightAlign, LanguageTag(LANGUAGE_NONE),
+ nullptr);
+
+ int nMinRunPos(0);
+ int nEndRunPos(0);
+ bool bRTL(false);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(0, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(19, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(20, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(45, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(45, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(51, nEndRunPos);
+ CPPUNIT_ASSERT(bRTL);
+}
+
+void VclTextTest::testImplLayoutArgs_PrepareFallback_precalculatedglyphs()
+{
+ // this font has no Cyrillic characters and thus needs fallback
+ const vcl::Font aFont("KacstBook", Size(0, 36));
+
+ ScopedVclPtrInstance<VirtualDevice> pVirDev;
+ pVirDev->SetFont(aFont);
+
+ const OString sUTF8String(u8"Тхе яуицк\n ыумпед овер");
+ const OUString sTestString(OUString::fromUtf8(sUTF8String));
+ std::unique_ptr<SalLayout> pLayout
+ = pVirDev->ImplLayout(sTestString, 0, sTestString.getLength(), Point(0, 0), 0, {},
+ SalLayoutFlags::GlyphItemsOnly);
+ SalLayoutGlyphs aGlyphs = pLayout->GetGlyphs();
+ SalLayoutGlyphsImpl* pGlyphsImpl = aGlyphs.Impl(1);
+
+ vcl::text::ImplLayoutArgs aArgs(sTestString, 0, sTestString.getLength(),
+ SalLayoutFlags::BiDiRtl, LanguageTag(LANGUAGE_RUSSIAN),
+ nullptr);
+
+ aArgs.PrepareFallback(pGlyphsImpl);
+
+ int nMinRunPos(0);
+ int nEndRunPos(0);
+ bool bRTL(false);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(0, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(3, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(4, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(9, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(11, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(17, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+
+ aArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRTL);
+ CPPUNIT_ASSERT_EQUAL(18, nMinRunPos);
+ CPPUNIT_ASSERT_EQUAL(22, nEndRunPos);
+ CPPUNIT_ASSERT(!bRTL);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclTextTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx
new file mode 100644
index 000000000..15493b953
--- /dev/null
+++ b/vcl/qa/cppunit/timer.cxx
@@ -0,0 +1,567 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+/*
+ * Timers are evil beasts across platforms...
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <osl/thread.hxx>
+#include <chrono>
+
+#include <vcl/timer.hxx>
+#include <vcl/idle.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/scheduler.hxx>
+#include <svdata.hxx>
+#include <salinst.hxx>
+
+// #define TEST_WATCHDOG
+
+// Enables timer tests that appear to provoke windows under load unduly.
+//#define TEST_TIMERPRECISION
+
+namespace {
+
+/// Avoid our timer tests just wedging the build if they fail.
+class WatchDog : public osl::Thread
+{
+ sal_Int32 mnSeconds;
+public:
+ explicit WatchDog(sal_Int32 nSeconds) :
+ Thread(),
+ mnSeconds( nSeconds )
+ {
+ create();
+ }
+ virtual void SAL_CALL run() override
+ {
+ osl::Thread::wait( std::chrono::seconds(mnSeconds) );
+ fprintf(stderr, "ERROR: WatchDog timer thread expired, failing the test!\n");
+ fflush(stderr);
+ CPPUNIT_ASSERT_MESSAGE("watchdog triggered", false);
+ }
+};
+
+}
+
+static WatchDog * aWatchDog = new WatchDog( 120 ); // random high number in secs
+
+class TimerTest : public test::BootstrapFixture
+{
+public:
+ TimerTest() : BootstrapFixture(true, false) {}
+
+ void testIdle();
+ void testIdleMainloop();
+#ifdef TEST_WATCHDOG
+ void testWatchdog();
+#endif
+ void testDurations();
+#ifdef TEST_TIMERPRECISION
+ void testAutoTimer();
+ void testMultiAutoTimers();
+#endif
+ void testAutoTimerStop();
+ void testNestedTimer();
+ void testSlowTimerCallback();
+ void testTriggerIdleFromIdle();
+ void testInvokedReStart();
+ void testPriority();
+ void testRoundRobin();
+
+ CPPUNIT_TEST_SUITE(TimerTest);
+ CPPUNIT_TEST(testIdle);
+ CPPUNIT_TEST(testIdleMainloop);
+#ifdef TEST_WATCHDOG
+ CPPUNIT_TEST(testWatchdog);
+#endif
+ CPPUNIT_TEST(testDurations);
+#ifdef TEST_TIMERPRECISION
+ CPPUNIT_TEST(testAutoTimer);
+ CPPUNIT_TEST(testMultiAutoTimers);
+#endif
+ CPPUNIT_TEST(testAutoTimerStop);
+ CPPUNIT_TEST(testNestedTimer);
+ CPPUNIT_TEST(testSlowTimerCallback);
+ CPPUNIT_TEST(testTriggerIdleFromIdle);
+ CPPUNIT_TEST(testInvokedReStart);
+ CPPUNIT_TEST(testPriority);
+ CPPUNIT_TEST(testRoundRobin);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+#ifdef TEST_WATCHDOG
+void TimerTest::testWatchdog()
+{
+ // out-wait the watchdog.
+ osl::Thread::wait( std::chrono::seconds(12) );
+}
+#endif
+
+namespace {
+
+class IdleBool : public Idle
+{
+ bool &mrBool;
+public:
+ explicit IdleBool( bool &rBool ) :
+ Idle( "IdleBool" ), mrBool( rBool )
+ {
+ SetPriority( TaskPriority::LOWEST );
+ Start();
+ mrBool = false;
+ }
+ virtual void Invoke() override
+ {
+ mrBool = true;
+ Application::EndYield();
+ }
+};
+
+}
+
+void TimerTest::testIdle()
+{
+ bool bTriggered = false;
+ IdleBool aTest( bTriggered );
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_MESSAGE("idle triggered", bTriggered);
+}
+
+void TimerTest::testIdleMainloop()
+{
+ bool bTriggered = false;
+ IdleBool aTest( bTriggered );
+ // coverity[loop_top] - Application::Yield allows the timer to fire and toggle bDone
+ while (!bTriggered)
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // can't test this via Application::Yield since this
+ // also processes all tasks directly via the scheduler.
+ pSVData->maAppData.mnDispatchLevel++;
+ pSVData->mpDefInst->DoYield(true, false);
+ pSVData->maAppData.mnDispatchLevel--;
+ }
+ CPPUNIT_ASSERT_MESSAGE("mainloop idle triggered", bTriggered);
+}
+
+namespace {
+
+class TimerBool : public Timer
+{
+ bool &mrBool;
+public:
+ TimerBool( sal_uLong nMS, bool &rBool ) :
+ Timer( "TimerBool" ), mrBool( rBool )
+ {
+ SetTimeout( nMS );
+ Start();
+ mrBool = false;
+ }
+ virtual void Invoke() override
+ {
+ mrBool = true;
+ Application::EndYield();
+ }
+};
+
+}
+
+void TimerTest::testDurations()
+{
+ static const sal_uLong aDurations[] = { 0, 1, 500, 1000 };
+ for (size_t i = 0; i < SAL_N_ELEMENTS( aDurations ); i++)
+ {
+ bool bDone = false;
+ TimerBool aTimer( aDurations[i], bDone );
+ // coverity[loop_top] - Application::Yield allows the timer to fire and toggle bDone
+ while( !bDone )
+ {
+ Application::Yield();
+ }
+ }
+}
+
+namespace {
+
+class AutoTimerCount : public AutoTimer
+{
+ sal_Int32 &mrCount;
+ const sal_Int32 mnMaxCount;
+
+public:
+ AutoTimerCount( sal_uLong nMS, sal_Int32 &rCount,
+ const sal_Int32 nMaxCount = -1 )
+ : AutoTimer( "AutoTimerCount" )
+ , mrCount( rCount )
+ , mnMaxCount( nMaxCount )
+ {
+ SetTimeout( nMS );
+ Start();
+ mrCount = 0;
+ }
+
+ virtual void Invoke() override
+ {
+ ++mrCount;
+ CPPUNIT_ASSERT( mnMaxCount < 0 || mrCount <= mnMaxCount );
+ if ( mrCount == mnMaxCount )
+ Stop();
+ }
+};
+
+}
+
+#ifdef TEST_TIMERPRECISION
+
+void TimerTest::testAutoTimer()
+{
+ const sal_Int32 nDurationMs = 30;
+ const sal_Int32 nEventsCount = 5;
+ const double exp = (nDurationMs * nEventsCount);
+
+ sal_Int32 nCount = 0;
+ std::ostringstream msg;
+
+ // Repeat when we have random latencies.
+ // This is expected on non-realtime OSes.
+ for (int i = 0; i < 10; ++i)
+ {
+ const auto start = std::chrono::high_resolution_clock::now();
+ nCount = 0;
+ AutoTimerCount aCount(nDurationMs, nCount);
+ while (nCount < nEventsCount) {
+ Application::Yield();
+ }
+
+ const auto end = std::chrono::high_resolution_clock::now();
+ double dur = std::chrono::duration<double, std::milli>(end - start).count();
+
+ msg << std::setprecision(2) << std::fixed
+ << "periodic multi-timer - dur: "
+ << dur << " (" << exp << ") ms." << std::endl;
+
+ // +/- 20% should be reasonable enough a margin.
+ if (dur >= (exp * 0.8) && dur <= (exp * 1.2))
+ {
+ // Success.
+ return;
+ }
+ }
+
+ CPPUNIT_FAIL(msg.str().c_str());
+}
+
+void TimerTest::testMultiAutoTimers()
+{
+ // The behavior of the timers change drastically
+ // when multiple timers are present.
+ // The worst, in my tests, is when two
+ // timers with 1ms period exist with a
+ // third of much longer period.
+
+ const sal_Int32 nDurationMsX = 5;
+ const sal_Int32 nDurationMsY = 10;
+ const sal_Int32 nDurationMs = 40;
+ const sal_Int32 nEventsCount = 5;
+ const double exp = (nDurationMs * nEventsCount);
+ const double expX = (exp / nDurationMsX);
+ const double expY = (exp / nDurationMsY);
+
+ sal_Int32 nCountX = 0;
+ sal_Int32 nCountY = 0;
+ sal_Int32 nCount = 0;
+ std::ostringstream msg;
+
+ // Repeat when we have random latencies.
+ // This is expected on non-realtime OSes.
+ for (int i = 0; i < 10; ++i)
+ {
+ nCountX = 0;
+ nCountY = 0;
+ nCount = 0;
+
+ const auto start = std::chrono::high_resolution_clock::now();
+ AutoTimerCount aCountX(nDurationMsX, nCountX);
+ AutoTimerCount aCountY(nDurationMsY, nCountY);
+
+ AutoTimerCount aCount(nDurationMs, nCount);
+ // coverity[loop_top] - Application::Yield allows the timer to fire and toggle nCount
+ while (nCount < nEventsCount) {
+ Application::Yield();
+ }
+
+ const auto end = std::chrono::high_resolution_clock::now();
+ double dur = std::chrono::duration<double, std::milli>(end - start).count();
+
+ msg << std::setprecision(2) << std::fixed << "periodic multi-timer - dur: "
+ << dur << " (" << exp << ") ms, nCount: " << nCount
+ << " (" << nEventsCount << "), nCountX: " << nCountX
+ << " (" << expX << "), nCountY: " << nCountY
+ << " (" << expY << ")." << std::endl;
+
+ // +/- 20% should be reasonable enough a margin.
+ if (dur >= (exp * 0.8) && dur <= (exp * 1.2) &&
+ nCountX >= (expX * 0.8) && nCountX <= (expX * 1.2) &&
+ nCountY >= (expY * 0.8) && nCountY <= (expY * 1.2))
+ {
+ // Success.
+ return;
+ }
+ }
+
+ CPPUNIT_FAIL(msg.str().c_str());
+}
+#endif // TEST_TIMERPRECISION
+
+void TimerTest::testAutoTimerStop()
+{
+ sal_Int32 nTimerCount = 0;
+ const sal_Int32 nMaxCount = 5;
+ AutoTimerCount aAutoTimer( 0, nTimerCount, nMaxCount );
+ // coverity[loop_top] - Application::Yield allows the timer to fire and increment TimerCount
+ while (nMaxCount != nTimerCount)
+ Application::Yield();
+ CPPUNIT_ASSERT( !aAutoTimer.IsActive() );
+ CPPUNIT_ASSERT( !Application::Reschedule() );
+}
+
+namespace {
+
+class YieldTimer : public Timer
+{
+public:
+ explicit YieldTimer( sal_uLong nMS ) : Timer( "YieldTimer" )
+ {
+ SetTimeout( nMS );
+ Start();
+ }
+ virtual void Invoke() override
+ {
+ for (int i = 0; i < 100; i++)
+ Application::Yield();
+ }
+};
+
+}
+
+void TimerTest::testNestedTimer()
+{
+ sal_Int32 nCount = 0;
+ YieldTimer aCount(5);
+ AutoTimerCount aCountUp( 3, nCount );
+ // coverity[loop_top] - Application::Yield allows the timer to fire and increment nCount
+ while (nCount < 20)
+ Application::Yield();
+}
+
+namespace {
+
+class SlowCallbackTimer : public Timer
+{
+ bool &mbSlow;
+public:
+ SlowCallbackTimer( sal_uLong nMS, bool &bBeenSlow ) :
+ Timer( "SlowCallbackTimer" ), mbSlow( bBeenSlow )
+ {
+ SetTimeout( nMS );
+ Start();
+ mbSlow = false;
+ }
+ virtual void Invoke() override
+ {
+ osl::Thread::wait( std::chrono::seconds(1) );
+ mbSlow = true;
+ }
+};
+
+}
+
+void TimerTest::testSlowTimerCallback()
+{
+ bool bBeenSlow = false;
+ sal_Int32 nCount = 0;
+ AutoTimerCount aHighFreq(1, nCount);
+ SlowCallbackTimer aSlow(250, bBeenSlow);
+ // coverity[loop_top] - Application::Yield allows the timer to fire and toggle bBeenSlow
+ while (!bBeenSlow)
+ Application::Yield();
+ // coverity[loop_top] - Application::Yield allows the timer to fire and increment nCount
+ while (nCount < 200)
+ Application::Yield();
+}
+
+namespace {
+
+class TriggerIdleFromIdle : public Idle
+{
+ bool* mpTriggered;
+ TriggerIdleFromIdle* mpOther;
+public:
+ explicit TriggerIdleFromIdle( bool* pTriggered, TriggerIdleFromIdle* pOther ) :
+ Idle( "TriggerIdleFromIdle" ), mpTriggered(pTriggered), mpOther(pOther)
+ {
+ }
+ virtual void Invoke() override
+ {
+ Start();
+ if (mpOther)
+ mpOther->Start();
+ Application::Yield();
+ if (mpTriggered)
+ *mpTriggered = true;
+ }
+};
+
+}
+
+void TimerTest::testTriggerIdleFromIdle()
+{
+ bool bTriggered1 = false;
+ bool bTriggered2 = false;
+ TriggerIdleFromIdle aTest2( &bTriggered2, nullptr );
+ TriggerIdleFromIdle aTest1( &bTriggered1, &aTest2 );
+ aTest1.Start();
+ Application::Yield();
+ CPPUNIT_ASSERT_MESSAGE("idle not triggered", bTriggered1);
+ CPPUNIT_ASSERT_MESSAGE("idle not triggered", bTriggered2);
+}
+
+namespace {
+
+class IdleInvokedReStart : public Idle
+{
+ sal_Int32 &mrCount;
+public:
+ IdleInvokedReStart( sal_Int32 &rCount )
+ : Idle( "IdleInvokedReStart" ), mrCount( rCount )
+ {
+ Start();
+ }
+ virtual void Invoke() override
+ {
+ mrCount++;
+ if ( mrCount < 2 )
+ Start();
+ }
+};
+
+}
+
+void TimerTest::testInvokedReStart()
+{
+ sal_Int32 nCount = 0;
+ IdleInvokedReStart aIdle( nCount );
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(2), nCount );
+}
+
+namespace {
+
+class IdleSerializer : public Idle
+{
+ sal_uInt32 mnPosition;
+ sal_uInt32 &mrProcessed;
+public:
+ IdleSerializer(const char *pDebugName, TaskPriority ePrio,
+ sal_uInt32 nPosition, sal_uInt32 &rProcessed)
+ : Idle( pDebugName )
+ , mnPosition( nPosition )
+ , mrProcessed( rProcessed )
+ {
+ SetPriority(ePrio);
+ Start();
+ }
+ virtual void Invoke() override
+ {
+ ++mrProcessed;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Ignored prio", mnPosition, mrProcessed );
+ }
+};
+
+}
+
+void TimerTest::testPriority()
+{
+ // scope, so tasks are deleted
+ {
+ // Start: 1st Idle low, 2nd high
+ sal_uInt32 nProcessed = 0;
+ IdleSerializer aLowPrioIdle("IdleSerializer LowPrio",
+ TaskPriority::LOWEST, 2, nProcessed);
+ IdleSerializer aHighPrioIdle("IdleSerializer HighPrio",
+ TaskPriority::HIGHEST, 1, nProcessed);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Not all idles processed", sal_uInt32(2), nProcessed );
+ }
+
+ {
+ // Start: 1st Idle high, 2nd low
+ sal_uInt32 nProcessed = 0;
+ IdleSerializer aHighPrioIdle("IdleSerializer HighPrio",
+ TaskPriority::HIGHEST, 1, nProcessed);
+ IdleSerializer aLowPrioIdle("IdleSerializer LowPrio",
+ TaskPriority::LOWEST, 2, nProcessed);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Not all idles processed", sal_uInt32(2), nProcessed );
+ }
+}
+
+namespace {
+
+class TestAutoIdleRR : public AutoIdle
+{
+ sal_uInt32 &mrCount;
+
+ DECL_LINK( IdleRRHdl, Timer *, void );
+
+public:
+ TestAutoIdleRR( sal_uInt32 &rCount,
+ const char *pDebugName )
+ : AutoIdle( pDebugName )
+ , mrCount( rCount )
+ {
+ CPPUNIT_ASSERT_EQUAL( sal_uInt32(0), mrCount );
+ SetInvokeHandler( LINK( this, TestAutoIdleRR, IdleRRHdl ) );
+ Start();
+ }
+};
+
+}
+
+IMPL_LINK_NOARG(TestAutoIdleRR, IdleRRHdl, Timer *, void)
+{
+ ++mrCount;
+ if ( mrCount == 3 )
+ Stop();
+}
+
+void TimerTest::testRoundRobin()
+{
+ sal_uInt32 nCount1 = 0, nCount2 = 0;
+ TestAutoIdleRR aIdle1( nCount1, "TestAutoIdleRR aIdle1" ),
+ aIdle2( nCount2, "TestAutoIdleRR aIdle2" );
+ while ( Application::Reschedule() )
+ {
+ CPPUNIT_ASSERT( nCount1 == nCount2 || nCount1 - 1 == nCount2 );
+ CPPUNIT_ASSERT( nCount1 <= 3 );
+ CPPUNIT_ASSERT( nCount2 <= 3 );
+ }
+ CPPUNIT_ASSERT_EQUAL( sal_uInt32(3), nCount1 );
+ CPPUNIT_ASSERT_EQUAL( sal_uInt32(3), nCount2 );
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TimerTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/widgetdraw/WidgetDefinitionReaderTest.cxx b/vcl/qa/cppunit/widgetdraw/WidgetDefinitionReaderTest.cxx
new file mode 100644
index 000000000..480ff4110
--- /dev/null
+++ b/vcl/qa/cppunit/widgetdraw/WidgetDefinitionReaderTest.cxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <unotest/bootstrapfixturebase.hxx>
+
+#include <widgetdraw/WidgetDefinitionReader.hxx>
+
+namespace
+{
+constexpr OUStringLiteral gaDataUrl(u"/vcl/qa/cppunit/widgetdraw/data/");
+
+class WidgetDefinitionReaderTest : public test::BootstrapFixtureBase
+{
+private:
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(gaDataUrl) + sFileName;
+ }
+
+public:
+ void testRead();
+ void testReadSettings();
+
+ CPPUNIT_TEST_SUITE(WidgetDefinitionReaderTest);
+ CPPUNIT_TEST(testRead);
+ CPPUNIT_TEST(testReadSettings);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void WidgetDefinitionReaderTest::testReadSettings()
+{
+ {
+ vcl::WidgetDefinition aDefinition;
+ vcl::WidgetDefinitionReader aReader(getFullUrl(u"definitionSettings1.xml"),
+ getFullUrl(u""));
+ CPPUNIT_ASSERT(aReader.read(aDefinition));
+ CPPUNIT_ASSERT_EQUAL(OString(""), aDefinition.mpSettings->msCenteredTabs);
+ }
+
+ {
+ vcl::WidgetDefinition aDefinition;
+ vcl::WidgetDefinitionReader aReader(getFullUrl(u"definitionSettings2.xml"),
+ getFullUrl(u""));
+ CPPUNIT_ASSERT(aReader.read(aDefinition));
+ CPPUNIT_ASSERT_EQUAL(OString("true"), aDefinition.mpSettings->msCenteredTabs);
+ }
+
+ {
+ vcl::WidgetDefinition aDefinition;
+ vcl::WidgetDefinitionReader aReader(getFullUrl(u"definitionSettings3.xml"),
+ getFullUrl(u""));
+ CPPUNIT_ASSERT(aReader.read(aDefinition));
+ CPPUNIT_ASSERT_EQUAL(OString("true"), aDefinition.mpSettings->msNoActiveTabTextRaise);
+ CPPUNIT_ASSERT_EQUAL(OString("false"), aDefinition.mpSettings->msCenteredTabs);
+ CPPUNIT_ASSERT_EQUAL(OString("0"), aDefinition.mpSettings->msListBoxEntryMargin);
+ CPPUNIT_ASSERT_EQUAL(OString("10"), aDefinition.mpSettings->msDefaultFontSize);
+ CPPUNIT_ASSERT_EQUAL(OString("16"), aDefinition.mpSettings->msTitleHeight);
+ CPPUNIT_ASSERT_EQUAL(OString("12"), aDefinition.mpSettings->msFloatTitleHeight);
+ CPPUNIT_ASSERT_EQUAL(OString("15"),
+ aDefinition.mpSettings->msListBoxPreviewDefaultLogicWidth);
+ CPPUNIT_ASSERT_EQUAL(OString("7"),
+ aDefinition.mpSettings->msListBoxPreviewDefaultLogicHeight);
+ }
+}
+
+void WidgetDefinitionReaderTest::testRead()
+{
+ vcl::WidgetDefinition aDefinition;
+
+ vcl::WidgetDefinitionReader aReader(getFullUrl(u"definition1.xml"), getFullUrl(u""));
+ CPPUNIT_ASSERT(aReader.read(aDefinition));
+
+ CPPUNIT_ASSERT_EQUAL(OUString("123456"), aDefinition.mpStyle->maFaceColor.AsRGBHexString());
+ CPPUNIT_ASSERT_EQUAL(OUString("234567"), aDefinition.mpStyle->maCheckedColor.AsRGBHexString());
+ CPPUNIT_ASSERT_EQUAL(OUString("345678"), aDefinition.mpStyle->maLightColor.AsRGBHexString());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("ffffff"),
+ aDefinition.mpStyle->maVisitedLinkColor.AsRGBHexString());
+ CPPUNIT_ASSERT_EQUAL(OUString("ffffff"), aDefinition.mpStyle->maToolTextColor.AsRGBHexString());
+ CPPUNIT_ASSERT_EQUAL(OUString("ffffff"), aDefinition.mpStyle->maFontColor.AsRGBHexString());
+
+ // Pushbutton
+ {
+ ControlState eState
+ = ControlState::DEFAULT | ControlState::ENABLED | ControlState::ROLLOVER;
+ std::vector<std::shared_ptr<vcl::WidgetDefinitionState>> aStates
+ = aDefinition.getDefinition(ControlType::Pushbutton, ControlPart::Entire)
+ ->getStates(ControlType::Pushbutton, ControlPart::Entire, eState,
+ PushButtonValue());
+
+ CPPUNIT_ASSERT_EQUAL(size_t(2), aStates.size());
+
+ CPPUNIT_ASSERT_EQUAL(size_t(2), aStates[0]->mpWidgetDrawActions.size());
+ CPPUNIT_ASSERT_EQUAL(vcl::WidgetDrawActionType::RECTANGLE,
+ aStates[0]->mpWidgetDrawActions[0]->maType);
+ CPPUNIT_ASSERT_EQUAL(vcl::WidgetDrawActionType::LINE,
+ aStates[0]->mpWidgetDrawActions[1]->maType);
+ }
+
+ // Radiobutton
+ {
+ std::vector<std::shared_ptr<vcl::WidgetDefinitionState>> aStates
+ = aDefinition.getDefinition(ControlType::Radiobutton, ControlPart::Entire)
+ ->getStates(ControlType::Radiobutton, ControlPart::Entire, ControlState::NONE,
+ ImplControlValue(ButtonValue::On));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aStates.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(2), aStates[0]->mpWidgetDrawActions.size());
+ }
+
+ {
+ std::vector<std::shared_ptr<vcl::WidgetDefinitionState>> aStates
+ = aDefinition.getDefinition(ControlType::Radiobutton, ControlPart::Entire)
+ ->getStates(ControlType::Radiobutton, ControlPart::Entire, ControlState::NONE,
+ ImplControlValue(ButtonValue::Off));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aStates.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aStates[0]->mpWidgetDrawActions.size());
+ }
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(WidgetDefinitionReaderTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/widgetdraw/data/definition1.xml b/vcl/qa/cppunit/widgetdraw/data/definition1.xml
new file mode 100644
index 000000000..041e8fc24
--- /dev/null
+++ b/vcl/qa/cppunit/widgetdraw/data/definition1.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widgets>
+ <style>
+ <faceColor value="#123456"/>
+ <checkedColor value="#234567"/>
+ <lightColor value="#345678"/>
+ <lightBorderColor value="#FFFFFF"/>
+ <shadowColor value="#FFFFFF"/>
+ <darkShadowColor value="#FFFFFF"/>
+ <buttonTextColor value="#FFFFFF"/>
+ <buttonRolloverTextColor value="#FFFFFF"/>
+ <radioCheckTextColor value="#FFFFFF"/>
+ <groupTextColor value="#FFFFFF"/>
+ <labelTextColor value="#FFFFFF"/>
+ <windowColor value="#FFFFFF"/>
+ <windowTextColor value="#FFFFFF"/>
+ <dialogColor value="#FFFFFF"/>
+ <dialogTextColor value="#FFFFFF"/>
+ <workspaceColor value="#FFFFFF"/>
+ <monoColor value="#FFFFFF"/>
+ <fieldColor value="#FFFFFF"/>
+ <fieldTextColor value="#FFFFFF"/>
+ <fieldRolloverTextColor value="#FFFFFF"/>
+ <activeColor value="#FFFFFF"/>
+ <activeTextColor value="#FFFFFF"/>
+ <activeBorderColor value="#FFFFFF"/>
+ <deactiveColor value="#FFFFFF"/>
+ <deactiveTextColor value="#FFFFFF"/>
+ <deactiveBorderColor value="#FFFFFF"/>
+ <menuColor value="#FFFFFF"/>
+ <menuBarColor value="#FFFFFF"/>
+ <menuBarRolloverColor value="#FFFFFF"/>
+ <menuBorderColor value="#FFFFFF"/>
+ <menuTextColor value="#FFFFFF"/>
+ <menuBarTextColor value="#FFFFFF"/>
+ <menuBarRolloverTextColor value="#FFFFFF"/>
+ <menuBarHighlightTextColor value="#FFFFFF"/>
+ <menuHighlightColor value="#FFFFFF"/>
+ <menuHighlightTextColor value="#FFFFFF"/>
+ <highlightColor value="#FFFFFF"/>
+ <highlightTextColor value="#FFFFFF"/>
+ <activeTabColor value="#FFFFFF"/>
+ <inactiveTabColor value="#FFFFFF"/>
+ <tabTextColor value="#FFFFFF"/>
+ <tabRolloverTextColor value="#FFFFFF"/>
+ <tabHighlightTextColor value="#FFFFFF"/>
+ <disableColor value="#FFFFFF"/>
+ <helpColor value="#FFFFFF"/>
+ <helpTextColor value="#FFFFFF"/>
+ <linkColor value="#FFFFFF"/>
+ <visitedLinkColor value="#FFFFFF"/>
+ <toolTextColor value="#FFFFFF"/>
+ <fontColor value="#FFFFFF"/>
+ </style>
+ <pushbutton>
+ <part value="Entire">
+ <state enabled="any" focused="any" pressed="any" rollover="any" default="any" selected="any" button-value="any">
+ <rect stroke="#808080" fill="#FFFFFF" stroke-width="1.0" rx="5" ry="5" margin="1"/>
+ <line stroke="#808080" fill="#808080" stroke-width="1.0"/>
+ </state>
+ <state enabled="true" focused="any" pressed="any" rollover="true" default="true" selected="any" button-value="any">
+ <rect stroke="#808080" fill="#808080" stroke-width="1.0" rx="5" ry="5" margin="1"/>
+ </state>
+ </part>
+ <part value="Focus">
+ <state enabled="any" focused="any" pressed="any" rollover="any" default="any" selected="any" button-value="any">
+ <rect stroke="#808080" fill="#FFFFFF" stroke-width="1.0" rx="5" ry="5" margin="1"/>
+ </state>
+ </part>
+ </pushbutton>
+ <radiobutton>
+ <part value="Entire">
+ <state enabled="any" focused="any" pressed="any" rollover="any" default="any" selected="any" button-value="false">
+ <rect stroke="#007AFF" fill="#FFFFFF" stroke-width="1" margin="0"/>
+ </state>
+ <state enabled="any" focused="any" pressed="any" rollover="any" default="any" selected="any" button-value="true">
+ <rect stroke="#007AFF" fill="#FFFFFF" stroke-width="1" margin="0"/>
+ <rect stroke="#007AFF" fill="#007AFF" stroke-width="1" margin="3"/>
+ </state>
+ </part>
+ </radiobutton>
+</widgets>
diff --git a/vcl/qa/cppunit/widgetdraw/data/definitionSettings1.xml b/vcl/qa/cppunit/widgetdraw/data/definitionSettings1.xml
new file mode 100644
index 000000000..9ca7f894f
--- /dev/null
+++ b/vcl/qa/cppunit/widgetdraw/data/definitionSettings1.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widgets>
+ <settings>
+ </settings>
+</widgets>
diff --git a/vcl/qa/cppunit/widgetdraw/data/definitionSettings2.xml b/vcl/qa/cppunit/widgetdraw/data/definitionSettings2.xml
new file mode 100644
index 000000000..0d6d6e111
--- /dev/null
+++ b/vcl/qa/cppunit/widgetdraw/data/definitionSettings2.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widgets>
+ <settings>
+ <centeredTabs value="true"/>
+ </settings>
+</widgets>
diff --git a/vcl/qa/cppunit/widgetdraw/data/definitionSettings3.xml b/vcl/qa/cppunit/widgetdraw/data/definitionSettings3.xml
new file mode 100644
index 000000000..9ad88dd54
--- /dev/null
+++ b/vcl/qa/cppunit/widgetdraw/data/definitionSettings3.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widgets>
+ <settings>
+ <noActiveTabTextRaise value="true"/>
+ <centeredTabs value="false"/>
+ <listBoxEntryMargin value="0"/>
+ <defaultFontSize value="10"/>
+ <titleHeight value="16"/>
+ <floatTitleHeight value="12"/>
+ <listBoxPreviewDefaultLogicWidth value="15"/>
+ <listBoxPreviewDefaultLogicHeight value="7"/>
+ </settings>
+</widgets>