summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui
diff options
context:
space:
mode:
authorJo Asplin <jo.asplin@nokia.com>2011-08-31 17:11:06 +0200
committerJo Asplin <jo.asplin@nokia.com>2011-09-01 10:59:49 +0200
commita90f50942e5304e6bf1c8a3e32f1f65c7a38f60b (patch)
tree6ed9a3d0a0a3dd09a78593d89c000f29d3494b89 /tests/auto/gui
parenta863eb1c7bbd5d40a741151f811bd7c62cf51e2d (diff)
Moved gui autotests into new directory structure
Task-number: QTBUG-21133 Change-Id: I83b8f652935cf92151265ca2530a3cf81c31fdef Reviewed-on: http://codereview.qt.nokia.com/3996 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Jo Asplin <jo.asplin@nokia.com>
Diffstat (limited to 'tests/auto/gui')
-rw-r--r--tests/auto/gui/gui.pro9
-rw-r--r--tests/auto/gui/image/image.pro18
-rw-r--r--tests/auto/gui/image/qicoimageformat/.gitignore1
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/invalid/35floppy.icobin0 -> 1078 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/35FLOPPY.ICObin0 -> 1078 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/AddPerfMon.icobin0 -> 1078 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/App.icobin0 -> 318 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.icobin0 -> 25214 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/Qt.icobin0 -> 31371 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/Status_Play.icobin0 -> 2862 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/TIMER01.ICObin0 -> 1078 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/WORLD.icobin0 -> 3310 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/WORLDH.icobin0 -> 3310 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/abcardWindow.icobin0 -> 22486 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/semitransparent.icobin0 -> 25214 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/icons/valid/trolltechlogo_tiny.icobin0 -> 3006 bytes
-rw-r--r--tests/auto/gui/image/qicoimageformat/qicoimageformat.pro28
-rw-r--r--tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp338
-rw-r--r--tests/auto/gui/image/qicon/.gitignore1
-rw-r--r--tests/auto/gui/image/qicon/heart.svg55
-rw-r--r--tests/auto/gui/image/qicon/heart.svgzbin0 -> 1506 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/testtheme/16x16/actions/appointment-new.pngbin0 -> 897 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/testtheme/22x22/actions/appointment-new.pngbin0 -> 1411 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/testtheme/32x32/actions/appointment-new.pngbin0 -> 2399 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/testtheme/index.theme492
-rw-r--r--tests/auto/gui/image/qicon/icons/testtheme/scalable/actions/svg-only.svg425
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/address-book-new.pngbin0 -> 796 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/appointment-new.pngbin0 -> 897 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/address-book-new.pngbin0 -> 924 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/appointment-new.pngbin0 -> 1411 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/address-book-new.pngbin0 -> 1897 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/appointment-new.pngbin0 -> 2399 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/index.theme492
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/address-book-new.svg389
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/appointment-new.svg425
-rw-r--r--tests/auto/gui/image/qicon/image.pngbin0 -> 14743 bytes
-rw-r--r--tests/auto/gui/image/qicon/qicon.pro30
-rw-r--r--tests/auto/gui/image/qicon/rect.pngbin0 -> 175 bytes
-rw-r--r--tests/auto/gui/image/qicon/rect.svg76
-rw-r--r--tests/auto/gui/image/qicon/trash.svg58
-rw-r--r--tests/auto/gui/image/qicon/tst_qicon.cpp781
-rw-r--r--tests/auto/gui/image/qicon/tst_qicon.qrc20
-rw-r--r--tests/auto/gui/image/qimage/.gitignore1
-rw-r--r--tests/auto/gui/image/qimage/images/image.bmpbin0 -> 306 bytes
-rw-r--r--tests/auto/gui/image/qimage/images/image.gifbin0 -> 1089 bytes
-rw-r--r--tests/auto/gui/image/qimage/images/image.icobin0 -> 10134 bytes
-rw-r--r--tests/auto/gui/image/qimage/images/image.jpgbin0 -> 696 bytes
-rw-r--r--tests/auto/gui/image/qimage/images/image.pbm8
-rw-r--r--tests/auto/gui/image/qimage/images/image.pgm10
-rw-r--r--tests/auto/gui/image/qimage/images/image.pngbin0 -> 549 bytes
-rw-r--r--tests/auto/gui/image/qimage/images/image.ppm7
-rw-r--r--tests/auto/gui/image/qimage/images/image.tifbin0 -> 2242 bytes
-rw-r--r--tests/auto/gui/image/qimage/images/image.xbm5
-rw-r--r--tests/auto/gui/image/qimage/images/image.xpm261
-rw-r--r--tests/auto/gui/image/qimage/qimage.pro23
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp2014
-rw-r--r--tests/auto/gui/image/qimageiohandler/.gitignore1
-rw-r--r--tests/auto/gui/image/qimageiohandler/qimageiohandler.pro9
-rw-r--r--tests/auto/gui/image/qimageiohandler/tst_qimageiohandler.cpp96
-rw-r--r--tests/auto/gui/image/qimagereader/.gitignore2
-rw-r--r--tests/auto/gui/image/qimagereader/baseline/35floppy.pngbin0 -> 329 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/baseline/connect.pngbin0 -> 12943 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/baseline/kde_favicon.pngbin0 -> 514 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/baseline/semitransparent.pngbin0 -> 545 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/16bpp.bmpbin0 -> 153654 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/4bpp-rle.bmpbin0 -> 23662 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.jpgbin0 -> 3699 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.pngbin0 -> 230 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/YCbCr_rgb.jpgbin0 -> 2045 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/away.pngbin0 -> 753 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/ball.mngbin0 -> 34394 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/bat1.gifbin0 -> 953 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/bat2.gifbin0 -> 980 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/beavis.jpgbin0 -> 20688 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/black.pngbin0 -> 697 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/black.xpm65
-rw-r--r--tests/auto/gui/image/qimagereader/images/colorful.bmpbin0 -> 65002 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt-colors.xpm26
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt-data.tifbin0 -> 8590 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt-pixel-count.xpm11
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt-pixels.xpm7
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt.bmpbin0 -> 116 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt.gifbin0 -> 2608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt.jpgbin0 -> 18 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt.mngbin0 -> 183 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt.pngbin0 -> 95 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt.svg32
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt.svgzbin0 -> 407 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/corrupt.xbm5
-rw-r--r--tests/auto/gui/image/qimagereader/images/crash-signed-char.bmpbin0 -> 45748 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/earth.gifbin0 -> 51712 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/endless-anim.gifbin0 -> 819 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/fire.mngbin0 -> 44430 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/font.bmpbin0 -> 1026 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/four-frames.gifbin0 -> 427 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/gnus.xbm622
-rw-r--r--tests/auto/gui/image/qimagereader/images/grayscale-ref.tifbin0 -> 256182 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/grayscale.tifbin0 -> 64162 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/image.pbm8
-rw-r--r--tests/auto/gui/image/qimagereader/images/image.pgm10
-rw-r--r--tests/auto/gui/image/qimagereader/images/image.pngbin0 -> 549 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/image.ppm7
-rw-r--r--tests/auto/gui/image/qimagereader/images/image_100dpi.tifbin0 -> 2242 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/kollada-noextbin0 -> 13907 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/kollada.pngbin0 -> 13907 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/marble.xpm470
-rw-r--r--tests/auto/gui/image/qimagereader/images/namedcolors.xpm18
-rw-r--r--tests/auto/gui/image/qimagereader/images/negativeheight.bmpbin0 -> 24630 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/noclearcode.bmpbin0 -> 326 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/noclearcode.gifbin0 -> 130 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/nontransparent.xpm788
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt-gif-anim.gifbin0 -> 1661 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt-gif-noanim.gifbin0 -> 1642 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt.gifbin0 -> 26504 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt1.gifbin0 -> 7216 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt2.gifbin0 -> 5559 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt3.gifbin0 -> 4702 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt4.gifbin0 -> 4310 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt5.gifbin0 -> 4234 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt6.gifbin0 -> 4732 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt7.gifbin0 -> 5265 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qt8.gifbin0 -> 6144 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/qtbug13653-no_eoi.jpgbin0 -> 8250 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/rect.svg462
-rw-r--r--tests/auto/gui/image/qimagereader/images/rect.svgzbin0 -> 5082 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/rgba_adobedeflate_littleendian.tifbin0 -> 4784 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/rgba_lzw_littleendian.tifbin0 -> 26690 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/rgba_nocompression_bigendian.tifbin0 -> 160384 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/rgba_nocompression_littleendian.tifbin0 -> 160388 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/rgba_packbits_littleendian.tifbin0 -> 161370 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/rgba_zipdeflate_littleendian.tifbin0 -> 14728 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/runners.ppmbin0 -> 960016 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/teapot.ppm31
-rw-r--r--tests/auto/gui/image/qimagereader/images/test.ppm2
-rw-r--r--tests/auto/gui/image/qimagereader/images/test.xpm260
-rw-r--r--tests/auto/gui/image/qimagereader/images/test32bfv4.bmpbin0 -> 232874 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/test32v5.bmpbin0 -> 174858 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_1.tiffbin0 -> 7740 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_2.tiffbin0 -> 9570 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_3.tiffbin0 -> 11392 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_4.tiffbin0 -> 11392 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_5.tiffbin0 -> 11392 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_6.tiffbin0 -> 11392 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_7.tiffbin0 -> 11392 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_8.tiffbin0 -> 11392 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_1.tiffbin0 -> 2382 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_2.tiffbin0 -> 1608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_3.tiffbin0 -> 1608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_4.tiffbin0 -> 1608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_5.tiffbin0 -> 1608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_6.tiffbin0 -> 1608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_7.tiffbin0 -> 1608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_8.tiffbin0 -> 1608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/original_indexed.tiffbin0 -> 5922 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/original_mono.tiffbin0 -> 786 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/original_rgb.tiffbin0 -> 12608 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_1.tiffbin0 -> 15560 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_2.tiffbin0 -> 17972 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_3.tiffbin0 -> 17324 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_4.tiffbin0 -> 17324 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_5.tiffbin0 -> 17648 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_6.tiffbin0 -> 17324 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_7.tiffbin0 -> 17324 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_8.tiffbin0 -> 17324 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/transparent.xpm788
-rw-r--r--tests/auto/gui/image/qimagereader/images/trolltech.gifbin0 -> 42629 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tst7.bmpbin0 -> 582 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tst7.pngbin0 -> 167 bytes
-rwxr-xr-xtests/auto/gui/image/qimagereader/images/txts.pngbin0 -> 5413 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/qimagereader.pro36
-rw-r--r--tests/auto/gui/image/qimagereader/qimagereader.qrc71
-rw-r--r--tests/auto/gui/image/qimagereader/tst_qimagereader.cpp2026
-rw-r--r--tests/auto/gui/image/qimagewriter/.gitignore1
-rw-r--r--tests/auto/gui/image/qimagewriter/images/YCbCr_cmyk.jpgbin0 -> 3699 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/YCbCr_rgb.jpgbin0 -> 2045 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/beavis.jpgbin0 -> 20688 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/colorful.bmpbin0 -> 65002 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/earth.gifbin0 -> 51712 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/font.bmpbin0 -> 1026 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/gnus.xbm622
-rw-r--r--tests/auto/gui/image/qimagewriter/images/kollada.pngbin0 -> 13907 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/marble.xpm329
-rw-r--r--tests/auto/gui/image/qimagewriter/images/ship63.pbmbin0 -> 111 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/teapot.ppm31
-rw-r--r--tests/auto/gui/image/qimagewriter/images/teapot.tiffbin0 -> 262274 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/images/trolltech.gifbin0 -> 42629 bytes
-rw-r--r--tests/auto/gui/image/qimagewriter/qimagewriter.pro25
-rw-r--r--tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp628
-rw-r--r--tests/auto/gui/image/qmovie/.gitignore1
-rw-r--r--tests/auto/gui/image/qmovie/animations/comicsecard.gifbin0 -> 12112 bytes
-rw-r--r--tests/auto/gui/image/qmovie/animations/corrupt.gifbin0 -> 847 bytes
-rw-r--r--tests/auto/gui/image/qmovie/animations/dutch.mngbin0 -> 18534 bytes
-rw-r--r--tests/auto/gui/image/qmovie/animations/trolltech.gifbin0 -> 70228 bytes
-rw-r--r--tests/auto/gui/image/qmovie/qmovie.pro28
-rw-r--r--tests/auto/gui/image/qmovie/resources.qrc5
-rw-r--r--tests/auto/gui/image/qmovie/tst_qmovie.cpp225
-rw-r--r--tests/auto/gui/image/qpicture/.gitignore1
-rw-r--r--tests/auto/gui/image/qpicture/qpicture.pro6
-rw-r--r--tests/auto/gui/image/qpicture/tst_qpicture.cpp289
-rw-r--r--tests/auto/gui/image/qpixmap/.gitignore1
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img1.pngbin0 -> 26622 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img2.pngbin0 -> 149 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img1.pngbin0 -> 26532 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img2.pngbin0 -> 160 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp.icobin0 -> 285478 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_16x16.pngbin0 -> 754 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_256x256.pngbin0 -> 16269 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_32x32.pngbin0 -> 1745 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_48x48.pngbin0 -> 2618 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp.icobin0 -> 7406 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_16x16.pngbin0 -> 1454 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_32x32.pngbin0 -> 1721 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_48x48.pngbin0 -> 1967 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/designer.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_50_50_100_100.pngbin0 -> 4385 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_x_y_w_h.pngbin0 -> 4104 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_50_50_100_100.pngbin0 -> 4243 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_x_y_w_h.pngbin0 -> 4116 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_-128_dy_-128_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_-128_dy_0_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_50_50_100_100.pngbin0 -> 4367 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_x_y_w_h.pngbin0 -> 4157 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_-128_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_0_50_50_100_100.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_0_null.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_0_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_10_50_50_100_100.pngbin0 -> 4271 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_10_x_y_w_h.pngbin0 -> 4188 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_128_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_0_dy_1_null.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_10_dy_0_50_50_100_100.pngbin0 -> 4248 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_10_dy_0_x_y_w_h.pngbin0 -> 4196 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_10_dy_10_50_50_100_100.pngbin0 -> 4243 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_10_dy_10_x_y_w_h.pngbin0 -> 4220 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_128_dy_0_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_128_dy_128_64_64_128_128.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_128_dy_128_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/images/dx_1_dy_0_null.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_argb32.pngbin0 -> 4189 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.gifbin0 -> 3317 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.pngbin0 -> 2431 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gifbin0 -> 4075 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.gifbin0 -> 2086 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.pngbin0 -> 1405 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gifbin0 -> 4138 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.jpgbin0 -> 11810 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/gui/image/qpixmap/qpixmap.pro33
-rw-r--r--tests/auto/gui/image/qpixmap/qpixmap.qrc29
-rw-r--r--tests/auto/gui/image/qpixmap/tst_qpixmap.cpp1787
-rw-r--r--tests/auto/gui/image/qpixmapcache/.gitignore1
-rw-r--r--tests/auto/gui/image/qpixmapcache/qpixmapcache.pro6
-rw-r--r--tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp521
-rw-r--r--tests/auto/gui/image/qpixmapfilter/noise.pngbin0 -> 7517 bytes
-rw-r--r--tests/auto/gui/image/qpixmapfilter/qpixmapfilter.pro13
-rw-r--r--tests/auto/gui/image/qpixmapfilter/tst_qpixmapfilter.cpp450
-rw-r--r--tests/auto/gui/image/qvolatileimage/qvolatileimage.pro10
-rw-r--r--tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp403
-rw-r--r--tests/auto/gui/kernel/kernel.pro17
-rw-r--r--tests/auto/gui/kernel/qclipboard/.gitignore5
-rw-r--r--tests/auto/gui/kernel/qclipboard/copier/copier.pro10
-rw-r--r--tests/auto/gui/kernel/qclipboard/copier/main.cpp54
-rw-r--r--tests/auto/gui/kernel/qclipboard/paster/main.cpp54
-rw-r--r--tests/auto/gui/kernel/qclipboard/paster/paster.pro11
-rw-r--r--tests/auto/gui/kernel/qclipboard/qclipboard.pro4
-rw-r--r--tests/auto/gui/kernel/qclipboard/test/test.pro32
-rw-r--r--tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp422
-rw-r--r--tests/auto/gui/kernel/qdrag/.gitignore1
-rw-r--r--tests/auto/gui/kernel/qdrag/qdrag.pro9
-rw-r--r--tests/auto/gui/kernel/qdrag/tst_qdrag.cpp94
-rw-r--r--tests/auto/gui/kernel/qevent/.gitignore1
-rw-r--r--tests/auto/gui/kernel/qevent/qevent.pro4
-rw-r--r--tests/auto/gui/kernel/qevent/tst_qevent.cpp92
-rw-r--r--tests/auto/gui/kernel/qfileopenevent/qfileopenevent.pro3
-rw-r--r--tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp72
-rw-r--r--tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro10
-rw-r--r--tests/auto/gui/kernel/qfileopenevent/test/test.pro7
-rw-r--r--tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp362
-rw-r--r--tests/auto/gui/kernel/qguivariant/.gitignore1
-rw-r--r--tests/auto/gui/kernel/qguivariant/qguivariant.pro5
-rw-r--r--tests/auto/gui/kernel/qguivariant/tst_qguivariant.cpp72
-rw-r--r--tests/auto/gui/kernel/qkeysequence/.gitignore1
-rw-r--r--tests/auto/gui/kernel/qkeysequence/keys_de.qmbin0 -> 721 bytes
-rw-r--r--tests/auto/gui/kernel/qkeysequence/keys_de.ts61
-rw-r--r--tests/auto/gui/kernel/qkeysequence/qkeysequence.pro8
-rw-r--r--tests/auto/gui/kernel/qkeysequence/qkeysequence.qrc6
-rw-r--r--tests/auto/gui/kernel/qkeysequence/qt_de.qmbin0 -> 186240 bytes
-rw-r--r--tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp636
-rw-r--r--tests/auto/gui/kernel/qmouseevent/.gitignore1
-rw-r--r--tests/auto/gui/kernel/qmouseevent/qmouseevent.pro3
-rw-r--r--tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp231
-rw-r--r--tests/auto/gui/kernel/qmouseevent_modal/.gitignore1
-rw-r--r--tests/auto/gui/kernel/qmouseevent_modal/qmouseevent_modal.pro6
-rw-r--r--tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp231
-rw-r--r--tests/auto/gui/kernel/qpalette/.gitignore1
-rw-r--r--tests/auto/gui/kernel/qpalette/qpalette.pro6
-rw-r--r--tests/auto/gui/kernel/qpalette/tst_qpalette.cpp132
-rw-r--r--tests/auto/gui/kernel/qshortcut/.gitignore1
-rw-r--r--tests/auto/gui/kernel/qshortcut/qshortcut.pro11
-rw-r--r--tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp1272
-rw-r--r--tests/auto/gui/kernel/qtouchevent/qtouchevent.pro3
-rw-r--r--tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp1398
-rw-r--r--tests/auto/gui/math3d/math3d.pro6
-rw-r--r--tests/auto/gui/math3d/qmatrixnxn/qmatrixnxn.pro2
-rw-r--r--tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp3385
-rw-r--r--tests/auto/gui/math3d/qquaternion/qquaternion.pro2
-rw-r--r--tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp888
-rw-r--r--tests/auto/gui/math3d/qvectornd/qvectornd.pro2
-rw-r--r--tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp2142
-rw-r--r--tests/auto/gui/painting/painting.pro21
-rw-r--r--tests/auto/gui/painting/qbrush/.gitignore1
-rw-r--r--tests/auto/gui/painting/qbrush/qbrush.pro3
-rw-r--r--tests/auto/gui/painting/qbrush/tst_qbrush.cpp423
-rw-r--r--tests/auto/gui/painting/qcolor/.gitignore1
-rw-r--r--tests/auto/gui/painting/qcolor/qcolor.pro5
-rw-r--r--tests/auto/gui/painting/qcolor/tst_qcolor.cpp1538
-rw-r--r--tests/auto/gui/painting/qpaintengine/.gitignore1
-rw-r--r--tests/auto/gui/painting/qpaintengine/qpaintengine.pro9
-rw-r--r--tests/auto/gui/painting/qpaintengine/tst_qpaintengine.cpp99
-rw-r--r--tests/auto/gui/painting/qpainter/.gitignore2
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.pngbin0 -> 243 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.pngbin0 -> 245 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.pngbin0 -> 195 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.pngbin0 -> 461 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.pngbin0 -> 470 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.pngbin0 -> 195 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.pngbin0 -> 1294 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.pngbin0 -> 619 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.pngbin0 -> 195 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/dst.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.pngbin0 -> 214 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.pngbin0 -> 247 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.pngbin0 -> 258 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.pngbin0 -> 253 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.pngbin0 -> 237 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.pngbin0 -> 260 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.pngbin0 -> 258 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.pngbin0 -> 173 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.pngbin0 -> 203 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.pngbin0 -> 217 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.pngbin0 -> 207 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.pngbin0 -> 196 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.pngbin0 -> 213 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.pngbin0 -> 218 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.pngbin0 -> 176 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.pngbin0 -> 175 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.pngbin0 -> 177 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.pngbin0 -> 176 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.pngbin0 -> 176 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.pngbin0 -> 176 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.pngbin0 -> 217 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.pngbin0 -> 242 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.pngbin0 -> 249 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.pngbin0 -> 244 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.pngbin0 -> 234 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.pngbin0 -> 254 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.pngbin0 -> 251 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.pngbin0 -> 211 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.pngbin0 -> 208 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.pngbin0 -> 215 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.pngbin0 -> 187 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.pngbin0 -> 213 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.pngbin0 -> 204 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.pngbin0 -> 198 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.pngbin0 -> 177 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.pngbin0 -> 198 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.pngbin0 -> 195 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.pngbin0 -> 185 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.pngbin0 -> 188 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.pngbin0 -> 198 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.pngbin0 -> 185 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.pngbin0 -> 168 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.pngbin0 -> 167 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.pngbin0 -> 167 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.pngbin0 -> 167 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.pngbin0 -> 167 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.pngbin0 -> 167 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.pngbin0 -> 167 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.pngbin0 -> 155 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.pngbin0 -> 224 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.pngbin0 -> 229 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.pngbin0 -> 224 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.pngbin0 -> 198 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.pngbin0 -> 229 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.pngbin0 -> 227 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.pngbin0 -> 239 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.pngbin0 -> 237 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.pngbin0 -> 243 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.pngbin0 -> 226 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.pngbin0 -> 235 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.pngbin0 -> 230 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.pngbin0 -> 232 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.pngbin0 -> 184 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.pngbin0 -> 217 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.pngbin0 -> 213 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.pngbin0 -> 222 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.pngbin0 -> 194 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.pngbin0 -> 219 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.pngbin0 -> 215 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.pngbin0 -> 212 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.pngbin0 -> 186 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.pngbin0 -> 212 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.pngbin0 -> 216 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.pngbin0 -> 194 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.pngbin0 -> 207 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.pngbin0 -> 214 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.pngbin0 -> 208 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.pngbin0 -> 169 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.pngbin0 -> 255 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.pngbin0 -> 260 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.pngbin0 -> 251 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.pngbin0 -> 251 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.pngbin0 -> 261 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.pngbin0 -> 264 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.pngbin0 -> 228 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/src1.xbm12
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/src2-mask.xbm16
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/src2.xbm16
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop/src3.xbm12
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/dst.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1.xbm6
-rw-r--r--tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src2.xbm5
-rw-r--r--tests/auto/gui/painting/qpainter/qpainter.pro20
-rw-r--r--tests/auto/gui/painting/qpainter/task217400.pngbin0 -> 526 bytes
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp4697
-rw-r--r--tests/auto/gui/painting/qpainter/utils/createImages/createImages.pro11
-rw-r--r--tests/auto/gui/painting/qpainter/utils/createImages/main.cpp194
-rw-r--r--tests/auto/gui/painting/qpainterpath/.gitignore2
-rw-r--r--tests/auto/gui/painting/qpainterpath/qpainterpath.pro5
-rw-r--r--tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp1332
-rw-r--r--tests/auto/gui/painting/qpainterpathstroker/.gitignore1
-rw-r--r--tests/auto/gui/painting/qpainterpathstroker/qpainterpathstroker.pro5
-rw-r--r--tests/auto/gui/painting/qpainterpathstroker/tst_qpainterpathstroker.cpp75
-rw-r--r--tests/auto/gui/painting/qpathclipper/.gitignore1
-rw-r--r--tests/auto/gui/painting/qpathclipper/pathcompare.h126
-rw-r--r--tests/auto/gui/painting/qpathclipper/paths.cpp734
-rw-r--r--tests/auto/gui/painting/qpathclipper/paths.h95
-rw-r--r--tests/auto/gui/painting/qpathclipper/qpathclipper.pro11
-rw-r--r--tests/auto/gui/painting/qpathclipper/tst_qpathclipper.cpp1334
-rw-r--r--tests/auto/gui/painting/qpen/.gitignore1
-rw-r--r--tests/auto/gui/painting/qpen/qpen.pro5
-rw-r--r--tests/auto/gui/painting/qpen/tst_qpen.cpp226
-rw-r--r--tests/auto/gui/painting/qpolygon/.gitignore1
-rw-r--r--tests/auto/gui/painting/qpolygon/qpolygon.pro7
-rw-r--r--tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp105
-rw-r--r--tests/auto/gui/painting/qprinter/.gitignore4
-rw-r--r--tests/auto/gui/painting/qprinter/qprinter.pro5
-rw-r--r--tests/auto/gui/painting/qprinter/tst_qprinter.cpp1044
-rw-r--r--tests/auto/gui/painting/qprinterinfo/.gitignore1
-rw-r--r--tests/auto/gui/painting/qprinterinfo/qprinterinfo.pro7
-rw-r--r--tests/auto/gui/painting/qprinterinfo/tst_qprinterinfo.cpp401
-rw-r--r--tests/auto/gui/painting/qregion/.gitignore1
-rw-r--r--tests/auto/gui/painting/qregion/qregion.pro8
-rw-r--r--tests/auto/gui/painting/qregion/tst_qregion.cpp1012
-rw-r--r--tests/auto/gui/painting/qtransform/.gitignore1
-rw-r--r--tests/auto/gui/painting/qtransform/qtransform.pro7
-rw-r--r--tests/auto/gui/painting/qtransform/tst_qtransform.cpp807
-rw-r--r--tests/auto/gui/painting/qwmatrix/.gitignore1
-rw-r--r--tests/auto/gui/painting/qwmatrix/qwmatrix.pro6
-rw-r--r--tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp436
-rw-r--r--tests/auto/gui/text/qabstracttextdocumentlayout/.gitignore1
-rw-r--r--tests/auto/gui/text/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro9
-rw-r--r--tests/auto/gui/text/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp159
-rw-r--r--tests/auto/gui/text/qcssparser/.gitignore1
-rw-r--r--tests/auto/gui/text/qcssparser/qcssparser.pro17
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/comments/input1
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/comments/output4
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/comments2/input1
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/comments2/output12
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/comments3/input1
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/comments3/output4
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/comments4/input1
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/comments4/output3
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/input1
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/output5
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/simple/input1
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/simple/output9
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/unicode/input1
-rw-r--r--tests/auto/gui/text/qcssparser/testdata/scanner/unicode/output3
-rw-r--r--tests/auto/gui/text/qcssparser/tst_qcssparser.cpp1718
-rw-r--r--tests/auto/gui/text/qfont/.gitignore1
-rw-r--r--tests/auto/gui/text/qfont/qfont.pro5
-rw-r--r--tests/auto/gui/text/qfont/tst_qfont.cpp629
-rw-r--r--tests/auto/gui/text/qfontdatabase/.gitignore1
-rw-r--r--tests/auto/gui/text/qfontdatabase/FreeMono.ttfbin0 -> 267400 bytes
-rw-r--r--tests/auto/gui/text/qfontdatabase/qfontdatabase.pro10
-rw-r--r--tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp294
-rw-r--r--tests/auto/gui/text/qfontmetrics/.gitignore1
-rw-r--r--tests/auto/gui/text/qfontmetrics/qfontmetrics.pro4
-rw-r--r--tests/auto/gui/text/qfontmetrics/testfont.qrc5
-rw-r--r--tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp323
-rw-r--r--tests/auto/gui/text/qfontmetrics/ucs4font.ttfbin0 -> 3076 bytes
-rw-r--r--tests/auto/gui/text/qglyphrun/qglyphrun.pro11
-rw-r--r--tests/auto/gui/text/qglyphrun/test.ttfbin0 -> 3712 bytes
-rw-r--r--tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp679
-rw-r--r--tests/auto/gui/text/qrawfont/qrawfont.pro14
-rw-r--r--tests/auto/gui/text/qrawfont/testfont.ttfbin0 -> 63212 bytes
-rw-r--r--tests/auto/gui/text/qrawfont/testfont_bold_italic.ttfbin0 -> 49760 bytes
-rw-r--r--tests/auto/gui/text/qrawfont/tst_qrawfont.cpp897
-rw-r--r--tests/auto/gui/text/qstatictext/qstatictext.pro5
-rw-r--r--tests/auto/gui/text/qstatictext/tst_qstatictext.cpp870
-rw-r--r--tests/auto/gui/text/qsyntaxhighlighter/.gitignore1
-rw-r--r--tests/auto/gui/text/qsyntaxhighlighter/qsyntaxhighlighter.pro4
-rw-r--r--tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp549
-rw-r--r--tests/auto/gui/text/qtextblock/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextblock/qtextblock.pro9
-rw-r--r--tests/auto/gui/text/qtextblock/tst_qtextblock.cpp197
-rw-r--r--tests/auto/gui/text/qtextcursor/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextcursor/qtextcursor.pro5
-rw-r--r--tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp1862
-rw-r--r--tests/auto/gui/text/qtextdocument/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextdocument/common.h93
-rw-r--r--tests/auto/gui/text/qtextdocument/qtextdocument.pro6
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp2788
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/qtextdocumentfragment.pro8
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp4030
-rw-r--r--tests/auto/gui/text/qtextdocumentlayout/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextdocumentlayout/qtextdocumentlayout.pro5
-rw-r--r--tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp276
-rw-r--r--tests/auto/gui/text/qtextformat/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextformat/qtextformat.pro9
-rw-r--r--tests/auto/gui/text/qtextformat/tst_qtextformat.cpp374
-rw-r--r--tests/auto/gui/text/qtextlayout/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextlayout/qtextlayout.pro12
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp1506
-rw-r--r--tests/auto/gui/text/qtextlist/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextlist/qtextlist.pro9
-rw-r--r--tests/auto/gui/text/qtextlist/tst_qtextlist.cpp453
-rw-r--r--tests/auto/gui/text/qtextobject/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextobject/qtextobject.pro9
-rw-r--r--tests/auto/gui/text/qtextobject/tst_qtextobject.cpp128
-rw-r--r--tests/auto/gui/text/qtextodfwriter/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextodfwriter/qtextodfwriter.pro6
-rw-r--r--tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp426
-rw-r--r--tests/auto/gui/text/qtextpiecetable/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextpiecetable/qtextpiecetable.pro9
-rw-r--r--tests/auto/gui/text/qtextpiecetable/tst_qtextpiecetable.cpp1155
-rw-r--r--tests/auto/gui/text/qtextscriptengine/.gitignore1
-rw-r--r--tests/auto/gui/text/qtextscriptengine/generate/generate.pro14
-rw-r--r--tests/auto/gui/text/qtextscriptengine/generate/main.cpp129
-rw-r--r--tests/auto/gui/text/qtextscriptengine/qtextscriptengine.pro7
-rw-r--r--tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp1304
-rw-r--r--tests/auto/gui/text/qtexttable/.gitignore1
-rw-r--r--tests/auto/gui/text/qtexttable/qtexttable.pro6
-rw-r--r--tests/auto/gui/text/qtexttable/tst_qtexttable.cpp1004
-rw-r--r--tests/auto/gui/text/qzip/.gitignore1
-rw-r--r--tests/auto/gui/text/qzip/qzip.pro12
-rw-r--r--tests/auto/gui/text/qzip/testdata/symlink.zipbin0 -> 289 bytes
-rw-r--r--tests/auto/gui/text/qzip/testdata/test.zipbin0 -> 286 bytes
-rw-r--r--tests/auto/gui/text/qzip/tst_qzip.cpp167
-rw-r--r--tests/auto/gui/text/text.pro32
-rw-r--r--tests/auto/gui/util/qdesktopservices/.gitignore1
-rw-r--r--tests/auto/gui/util/qdesktopservices/qdesktopservices.pro30
-rw-r--r--tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp388
-rw-r--r--tests/auto/gui/util/util.pro4
635 files changed, 66894 insertions, 0 deletions
diff --git a/tests/auto/gui/gui.pro b/tests/auto/gui/gui.pro
new file mode 100644
index 0000000000..d54198467d
--- /dev/null
+++ b/tests/auto/gui/gui.pro
@@ -0,0 +1,9 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ image \
+ kernel \
+ math3d \
+ painting \
+ text \
+ util \
+
diff --git a/tests/auto/gui/image/image.pro b/tests/auto/gui/image/image.pro
new file mode 100644
index 0000000000..fe089f5e75
--- /dev/null
+++ b/tests/auto/gui/image/image.pro
@@ -0,0 +1,18 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qimagereader \
+ qicoimageformat \
+ qpixmap \
+ qpixmapcache \
+ qimage \
+ qpixmapfilter \
+ qimageiohandler \
+ qimagewriter \
+ qmovie \
+ qvolatileimage \
+ qicon \
+ qpicture \
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qpixmapcache \
+
diff --git a/tests/auto/gui/image/qicoimageformat/.gitignore b/tests/auto/gui/image/qicoimageformat/.gitignore
new file mode 100644
index 0000000000..9f673c5635
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/.gitignore
@@ -0,0 +1 @@
+tst_qicoimageformat
diff --git a/tests/auto/gui/image/qicoimageformat/icons/invalid/35floppy.ico b/tests/auto/gui/image/qicoimageformat/icons/invalid/35floppy.ico
new file mode 100644
index 0000000000..96087612fb
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/invalid/35floppy.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/35FLOPPY.ICO b/tests/auto/gui/image/qicoimageformat/icons/valid/35FLOPPY.ICO
new file mode 100644
index 0000000000..e9551d6390
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/35FLOPPY.ICO
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/AddPerfMon.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/AddPerfMon.ico
new file mode 100644
index 0000000000..3368d3634a
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/AddPerfMon.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/App.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/App.ico
new file mode 100644
index 0000000000..03b80a68f8
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/App.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico
new file mode 100644
index 0000000000..8da119efdd
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/Qt.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/Qt.ico
new file mode 100644
index 0000000000..fef1dee146
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/Qt.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/Status_Play.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/Status_Play.ico
new file mode 100644
index 0000000000..d05782cce9
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/Status_Play.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/TIMER01.ICO b/tests/auto/gui/image/qicoimageformat/icons/valid/TIMER01.ICO
new file mode 100644
index 0000000000..5563beec8c
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/TIMER01.ICO
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/WORLD.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/WORLD.ico
new file mode 100644
index 0000000000..7a8ab39f56
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/WORLD.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/WORLDH.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/WORLDH.ico
new file mode 100644
index 0000000000..c2b48f8d99
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/WORLDH.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/abcardWindow.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/abcardWindow.ico
new file mode 100644
index 0000000000..e78a15c42b
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/abcardWindow.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/semitransparent.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/semitransparent.ico
new file mode 100644
index 0000000000..893ceb254c
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/semitransparent.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/icons/valid/trolltechlogo_tiny.ico b/tests/auto/gui/image/qicoimageformat/icons/valid/trolltechlogo_tiny.ico
new file mode 100644
index 0000000000..3e02a53e58
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/icons/valid/trolltechlogo_tiny.ico
Binary files differ
diff --git a/tests/auto/gui/image/qicoimageformat/qicoimageformat.pro b/tests/auto/gui/image/qicoimageformat/qicoimageformat.pro
new file mode 100644
index 0000000000..c150c9af9f
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/qicoimageformat.pro
@@ -0,0 +1,28 @@
+load(qttest_p4)
+SOURCES+= tst_qicoimageformat.cpp
+
+wince*: {
+ DEFINES += SRCDIR=\\\".\\\"
+ addFiles.files = icons
+ addFiles.path = .
+ CONFIG(debug, debug|release):{
+ addPlugins.files = $$QT_BUILD_TREE/plugins/imageformats/qico4d.dll
+ } else {
+ addPlugins.files = $$QT_BUILD_TREE/plugins/imageformats/qico4.dll
+ }
+ addPlugins.path = imageformats
+ DEPLOYMENT += addFiles addPlugins
+} else:symbian {
+ addFiles.files = icons
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+ qt_not_deployed {
+ addPlugins.files = qico.dll
+ addPlugins.path = imageformats
+ DEPLOYMENT += addPlugins
+ }
+ TARGET.UID3 = 0xE0340004
+ DEFINES += SYMBIAN_SRCDIR_UID=$$lower($$replace(TARGET.UID3,"0x",""))
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
diff --git a/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp b/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp
new file mode 100644
index 0000000000..3aace12fdb
--- /dev/null
+++ b/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp
@@ -0,0 +1,338 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtCore>
+
+#if defined(Q_OS_SYMBIAN)
+# define STRINGIFY(x) #x
+# define TOSTRING(x) STRINGIFY(x)
+# define SRCDIR "C:/Private/" TOSTRING(SYMBIAN_SRCDIR_UID) "/"
+#endif
+
+class tst_QIcoImageFormat : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QIcoImageFormat();
+ virtual ~tst_QIcoImageFormat();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void format();
+ void canRead_data();
+ void canRead();
+ void SequentialFile_data();
+ void SequentialFile();
+ void imageCount_data();
+ void imageCount();
+ void jumpToNextImage_data();
+ void jumpToNextImage();
+ void loopCount_data();
+ void loopCount();
+ void nextImageDelay_data();
+ void nextImageDelay();
+ void pngCompression_data();
+ void pngCompression();
+
+private:
+ QString m_IconPath;
+};
+
+
+tst_QIcoImageFormat::tst_QIcoImageFormat()
+{
+ m_IconPath = QLatin1String(SRCDIR) + "/icons";
+ qDebug() << m_IconPath;
+}
+
+tst_QIcoImageFormat::~tst_QIcoImageFormat()
+{
+
+}
+
+void tst_QIcoImageFormat::init()
+{
+
+}
+
+void tst_QIcoImageFormat::cleanup()
+{
+
+}
+
+void tst_QIcoImageFormat::initTestCase()
+{
+
+}
+
+void tst_QIcoImageFormat::cleanupTestCase()
+{
+
+}
+
+void tst_QIcoImageFormat::format()
+{
+ QImageReader reader(m_IconPath + "/valid/35FLOPPY.ICO", "ico");
+ QByteArray fmt = reader.format();
+ QCOMPARE(const_cast<const char*>(fmt.data()), "ico" );
+}
+
+void tst_QIcoImageFormat::canRead_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("isValid");
+
+ QTest::newRow("floppy (16px,32px - 16 colors)") << "valid/35FLOPPY.ICO" << 1;
+ QTest::newRow("16px,32px,48px - 256,16M colors") << "valid/abcardWindow.ico" << 1;
+ QTest::newRow("16px - 16 colors") << "valid/App.ico" << 1;
+ QTest::newRow("16px,32px,48px - 16,256,16M colors") << "valid/Obj_N2_Internal_Mem.ico" << 1;
+ QTest::newRow("16px - 16,256,16M colors") << "valid/Status_Play.ico" << 1;
+ QTest::newRow("16px,32px - 16 colors") << "valid/TIMER01.ICO" << 1;
+ QTest::newRow("16px16c, 32px32c, 32px256c") << "valid/WORLD.ico" << 1;
+ QTest::newRow("16px16c, 32px32c, 32px256c") << "valid/WORLDH.ico" << 1;
+ QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0;
+ QTest::newRow("103x16px, 24BPP") << "valid/trolltechlogo_tiny.ico" << 1;
+ QTest::newRow("includes 32BPP w/alpha") << "valid/semitransparent.ico" << 1;
+ QTest::newRow("PNG compression") << "valid/Qt.ico" << 1;
+}
+
+void tst_QIcoImageFormat::canRead()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, isValid);
+
+ QImageReader reader(m_IconPath + "/" + fileName);
+ QCOMPARE(reader.canRead(), (isValid == 0 ? false : true));
+}
+
+class QSequentialFile : public QFile
+{
+public:
+ QSequentialFile(const QString &name) : QFile(name) {}
+
+ virtual ~QSequentialFile() {}
+
+ virtual bool isSequential() const {
+ return true;
+ }
+
+};
+
+void tst_QIcoImageFormat::SequentialFile_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("isValid");
+
+ QTest::newRow("floppy (16,32 pixels - 16 colors)") << "valid/35FLOPPY.ICO" << 1;
+
+ QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0;
+
+
+}
+
+void tst_QIcoImageFormat::SequentialFile()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, isValid);
+
+ QSequentialFile *file = new QSequentialFile(m_IconPath + "/" + fileName);
+ QVERIFY(file);
+ QVERIFY(file->open(QFile::ReadOnly));
+ QImageReader reader(file);
+
+ // Perform the check twice. If canRead() does not restore the sequential device back to its original state,
+ // it will fail on the second try.
+ QCOMPARE(reader.canRead(), (isValid == 0 ? false : true));
+ QCOMPARE(reader.canRead(), (isValid == 0 ? false : true));
+ file->close();
+}
+
+
+void tst_QIcoImageFormat::imageCount_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("floppy (16px,32px - 16 colors)") << "valid/35FLOPPY.ICO" << 2;
+ QTest::newRow("16px,32px,48px - 256,16M colors") << "valid/abcardWindow.ico" << 6;
+ QTest::newRow("16px - 16 colors") << "valid/App.ico" << 1;
+ QTest::newRow("16px,32px,48px - 16,256,16M colors") << "valid/Obj_N2_Internal_Mem.ico" << 9;
+ QTest::newRow("16px - 16,256,16M colors") << "valid/Status_Play.ico" << 3;
+ QTest::newRow("16px,32px - 16 colors") << "valid/TIMER01.ICO" << 2;
+ QTest::newRow("16px16c, 32px32c, 32px256c") << "valid/WORLD.ico" << 3;
+ QTest::newRow("16px16c, 32px32c, 32px256c") << "valid/WORLDH.ico" << 3;
+ QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0;
+ QTest::newRow("includes 32BPP w/alpha") << "valid/semitransparent.ico" << 9;
+ QTest::newRow("PNG compression") << "valid/Qt.ico" << 4;
+
+}
+
+void tst_QIcoImageFormat::imageCount()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, count);
+
+ QImageReader reader(m_IconPath + "/" + fileName);
+ QCOMPARE(reader.imageCount(), count);
+
+}
+
+void tst_QIcoImageFormat::jumpToNextImage_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("floppy (16px,32px - 16 colors)") << "valid/35FLOPPY.ICO" << 2;
+ QTest::newRow("16px,32px,48px - 256,16M colors") << "valid/abcardWindow.ico" << 6;
+ QTest::newRow("16px - 16 colors") << "valid/App.ico" << 1;
+ QTest::newRow("16px,32px,48px - 16,256,16M colors") << "valid/Obj_N2_Internal_Mem.ico" << 9;
+ QTest::newRow("16px - 16,256,16M colors") << "valid/Status_Play.ico" << 3;
+ QTest::newRow("16px,32px - 16 colors") << "valid/TIMER01.ICO" << 2;
+ QTest::newRow("16px16c, 32px32c, 32px256c") << "valid/WORLD.ico" << 3;
+ QTest::newRow("16px16c, 32px32c, 32px256c") << "valid/WORLDH.ico" << 3;
+ QTest::newRow("includes 32BPP w/alpha") << "valid/semitransparent.ico" << 9;
+ QTest::newRow("PNG compression") << "valid/Qt.ico" << 4;
+}
+
+void tst_QIcoImageFormat::jumpToNextImage()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, count);
+
+ QImageReader reader(m_IconPath + "/" + fileName);
+ bool bJumped = reader.jumpToImage(0);
+ while (bJumped) {
+ count--;
+ bJumped = reader.jumpToNextImage();
+ }
+ QCOMPARE(count, 0);
+}
+
+void tst_QIcoImageFormat::loopCount_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("floppy (16px,32px - 16 colors)") << "valid/35FLOPPY.ICO" << 0;
+ QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0;
+}
+
+void tst_QIcoImageFormat::loopCount()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, count);
+
+ QImageReader reader(m_IconPath + "/" + fileName);
+ QCOMPARE(reader.loopCount(), count);
+}
+
+void tst_QIcoImageFormat::nextImageDelay_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("floppy (16px,32px - 16 colors)") << "valid/35FLOPPY.ICO" << 2;
+ QTest::newRow("16px,32px,48px - 256,16M colors") << "valid/abcardWindow.ico" << 6;
+ QTest::newRow("16px - 16 colors") << "valid/App.ico" << 1;
+ QTest::newRow("16px,32px,48px - 16,256,16M colors") << "valid/Obj_N2_Internal_Mem.ico" << 9;
+ QTest::newRow("16px - 16,256,16M colors") << "valid/Status_Play.ico" << 3;
+ QTest::newRow("16px,32px - 16 colors") << "valid/TIMER01.ICO" << 2;
+ QTest::newRow("16px16c, 32px32c, 32px256c") << "valid/WORLD.ico" << 3;
+ QTest::newRow("16px16c, 32px32c, 32px256c") << "valid/WORLDH.ico" << 3;
+ QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << -1;
+ QTest::newRow("includes 32BPP w/alpha") << "valid/semitransparent.ico" << 9;
+ QTest::newRow("PNG compression") << "valid/Qt.ico" << 4;
+}
+
+void tst_QIcoImageFormat::nextImageDelay()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, count);
+
+ QImageReader reader(m_IconPath + "/" + fileName);
+ if (count == -1) {
+ QCOMPARE(reader.nextImageDelay(), 0);
+ } else {
+ int i;
+ for (i = 0; i < count; i++) {
+ QVERIFY(reader.jumpToImage(i));
+ QCOMPARE(reader.nextImageDelay(), 0);
+ }
+ }
+}
+
+void tst_QIcoImageFormat::pngCompression_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("index");
+ QTest::addColumn<int>("width");
+ QTest::addColumn<int>("height");
+
+ QTest::newRow("PNG compression") << "valid/Qt.ico" << 4 << 256 << 256;
+}
+
+void tst_QIcoImageFormat::pngCompression()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, index);
+ QFETCH(int, width);
+ QFETCH(int, height);
+
+ QImageReader reader(m_IconPath + "/" + fileName);
+
+ QImage image;
+ reader.jumpToImage(index);
+ reader.read(&image);
+
+ QCOMPARE(image.width(), width);
+ QCOMPARE(image.height(), height);
+}
+
+QTEST_MAIN(tst_QIcoImageFormat)
+#include "tst_qicoimageformat.moc"
+
diff --git a/tests/auto/gui/image/qicon/.gitignore b/tests/auto/gui/image/qicon/.gitignore
new file mode 100644
index 0000000000..c101ef9d28
--- /dev/null
+++ b/tests/auto/gui/image/qicon/.gitignore
@@ -0,0 +1 @@
+tst_qicon
diff --git a/tests/auto/gui/image/qicon/heart.svg b/tests/auto/gui/image/qicon/heart.svg
new file mode 100644
index 0000000000..8c982cd93c
--- /dev/null
+++ b/tests/auto/gui/image/qicon/heart.svg
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) --><svg viewBox="100 200 550 500" height="841.88976pt" id="svg1" inkscape:version="0.40+cvs" sodipodi:docbase="C:\Documents and Settings\Jon Phillips\My Documents\projects\clipart-project\submissions" sodipodi:docname="heart-left-highlight.svg" sodipodi:version="0.32" width="595.27559pt" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg">
+<metadata>
+<rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<cc:Work rdf:about="">
+<dc:title>Heart Left-Highlight</dc:title>
+<dc:description>This is a normal valentines day heart.</dc:description>
+<dc:subject>
+<rdf:Bag>
+<rdf:li>holiday</rdf:li>
+<rdf:li>valentines</rdf:li>
+<rdf:li></rdf:li>
+<rdf:li>valentine</rdf:li>
+<rdf:li>hash(0x8a091c0)</rdf:li>
+<rdf:li>hash(0x8a0916c)</rdf:li>
+<rdf:li>signs_and_symbols</rdf:li>
+<rdf:li>hash(0x8a091f0)</rdf:li>
+<rdf:li>day</rdf:li>
+</rdf:Bag>
+</dc:subject>
+<dc:publisher>
+<cc:Agent rdf:about="http://www.openclipart.org">
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:publisher>
+<dc:creator>
+<cc:Agent>
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:creator>
+<dc:rights>
+<cc:Agent>
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:rights>
+<dc:date></dc:date>
+<dc:format>image/svg+xml</dc:format>
+<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+<cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+<dc:language>en</dc:language>
+</cc:Work>
+<cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+</cc:License>
+</rdf:RDF>
+</metadata>
+<defs id="defs3"/>
+<sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="layer1" inkscape:cx="549.40674" inkscape:cy="596.00159" inkscape:document-units="px" inkscape:guide-bbox="true" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="615" inkscape:window-width="866" inkscape:window-x="88" inkscape:window-y="116" inkscape:zoom="0.35000000" pagecolor="#ffffff" showguides="true"/>
+<g id="layer1" inkscape:groupmode="layer" inkscape:label="Layer 1">
+<path d="M 263.41570,235.14588 C 197.17570,235.14588 143.41575,288.90587 143.41575,355.14588 C 143.41575,489.90139 279.34890,525.23318 371.97820,658.45392 C 459.55244,526.05056 600.54070,485.59932 600.54070,355.14588 C 600.54070,288.90588 546.78080,235.14587 480.54070,235.14588 C 432.49280,235.14588 391.13910,263.51631 371.97820,304.33338 C 352.81740,263.51630 311.46370,235.14587 263.41570,235.14588 z " id="path7" sodipodi:nodetypes="ccccccc" style="fill:#e60000;fill-opacity:1.0000000;stroke:#000000;stroke-width:18.700001;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"/>
+<path d="M 265.00000,253.59375 C 207.04033,253.59375 160.00000,300.63407 160.00000,358.59375 C 160.00000,476.50415 278.91857,507.43251 359.96875,624.00000 C 366.52868,614.08205 220.00000,478.47309 220.00000,378.59375 C 220.00000,320.63407 267.04033,273.59375 325.00000,273.59375 C 325.50453,273.59375 325.99718,273.64912 326.50000,273.65625 C 309.22436,261.07286 288.00557,253.59374 265.00000,253.59375 z " id="path220" sodipodi:nodetypes="ccccccc" style="fill:#e6e6e6;fill-opacity:0.64556962;stroke:none;stroke-width:18.700001;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"/>
+</g>
+</svg>
diff --git a/tests/auto/gui/image/qicon/heart.svgz b/tests/auto/gui/image/qicon/heart.svgz
new file mode 100644
index 0000000000..0f0913ffa7
--- /dev/null
+++ b/tests/auto/gui/image/qicon/heart.svgz
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/testtheme/16x16/actions/appointment-new.png b/tests/auto/gui/image/qicon/icons/testtheme/16x16/actions/appointment-new.png
new file mode 100644
index 0000000000..18b7c6781e
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/testtheme/16x16/actions/appointment-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/testtheme/22x22/actions/appointment-new.png b/tests/auto/gui/image/qicon/icons/testtheme/22x22/actions/appointment-new.png
new file mode 100644
index 0000000000..d676ffd463
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/testtheme/22x22/actions/appointment-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/testtheme/32x32/actions/appointment-new.png b/tests/auto/gui/image/qicon/icons/testtheme/32x32/actions/appointment-new.png
new file mode 100644
index 0000000000..85daef3b0b
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/testtheme/32x32/actions/appointment-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/testtheme/index.theme b/tests/auto/gui/image/qicon/icons/testtheme/index.theme
new file mode 100644
index 0000000000..e18736ab43
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/testtheme/index.theme
@@ -0,0 +1,492 @@
+[Icon Theme]
+_Name=Test
+_Comment=Test Theme
+Inherits=crystalsvg, themeparent
+Example=x-directory-normal
+
+# KDE Specific Stuff
+DisplayDepth=32
+LinkOverlay=link_overlay
+LockOverlay=lock_overlay
+ZipOverlay=zip_overlay
+DesktopDefault=48
+DesktopSizes=16,22,32,48,64,72,96,128
+ToolbarDefault=22
+ToolbarSizes=16,22,32,48
+MainToolbarDefault=22
+MainToolbarSizes=16,22,32,48
+SmallDefault=16
+SmallSizes=16
+PanelDefault=32
+PanelSizes=16,22,32,48,64,72,96,128
+
+# Directory list
+Directories=16x16/actions,16x16/apps,16x16/categories,16x16/devices,16x16/emblems,16x16/emotes,16x16/mimetypes,16x16/places,16x16/status,22x22/actions,22x22/apps,22x22/categories,22x22/devices,22x22/emblems,22x22/emotes,22x22/mimetypes,22x22/places,22x22/status,24x24/actions,24x24/apps,24x24/categories,24x24/devices,24x24/emblems,24x24/emotes,24x24/mimetypes,24x24/places,24x24/status,32x32/actions,32x32/apps,32x32/categories,32x32/devices,32x32/emblems,32x32/emotes,32x32/mimetypes,32x32/places,32x32/status,48x48/actions,48x48/apps,48x48/categories,48x48/devices,48x48/emblems,48x48/emotes,48x48/mimetypes,48x48/places,48x48/status,64x64/actions,64x64/apps,64x64/categories,64x64/devices,64x64/emblems,64x64/emotes,64x64/mimetypes,64x64/places,64x64/status,72x72/actions,72x72/apps,72x72/categories,72x72/devices,72x72/emblems,72x72/emotes,72x72/mimetypes,72x72/places,72x72/status,96x96/actions,96x96/apps,96x96/categories,96x96/devices,96x96/emblems,96x96/emotes,96x96/mimetypes,96x96/places,96x96/status,128x128/actions,128x128/apps,128x128/categories,128x128/devices,128x128/emblems,128x128/emotes,128x128/mimetypes,128x128/places,128x128/status,scalable/actions,scalable/apps,scalable/categories,scalable/devices,scalable/emblems,scalable/emotes,scalable/mimetypes,scalable/places,scalable/status
+
+[16x16/actions]
+Size=16
+Context=Actions
+Type=Fixed
+
+[16x16/apps]
+Size=16
+Context=Applications
+Type=Fixed
+
+[16x16/categories]
+Size=16
+Context=Categories
+Type=Fixed
+
+[16x16/devices]
+Size=16
+Context=Devices
+Type=Fixed
+
+[16x16/emblems]
+Size=16
+Context=Emblems
+Type=Fixed
+
+[16x16/emotes]
+Size=16
+Context=Emotes
+Type=Fixed
+
+[16x16/mimetypes]
+Size=16
+Context=MimeTypes
+Type=Fixed
+
+[16x16/places]
+Size=16
+Context=Places
+Type=Fixed
+
+[16x16/status]
+Size=16
+Context=Status
+Type=Fixed
+
+[22x22/actions]
+Size=22
+Context=Actions
+Type=Fixed
+
+[22x22/apps]
+Size=22
+Context=Applications
+Type=Fixed
+
+[22x22/categories]
+Size=22
+Context=Categories
+Type=Fixed
+
+[22x22/devices]
+Size=22
+Context=Devices
+Type=Fixed
+
+[22x22/emblems]
+Size=22
+Context=Emblems
+Type=Fixed
+
+[22x22/emotes]
+Size=22
+Context=Emotes
+Type=Fixed
+
+[22x22/mimetypes]
+Size=22
+Context=MimeTypes
+Type=Fixed
+
+[22x22/places]
+Size=22
+Context=Places
+Type=Fixed
+
+[22x22/status]
+Size=22
+Context=Status
+Type=Fixed
+
+[24x24/actions]
+Size=24
+Context=Actions
+Type=Fixed
+
+[24x24/apps]
+Size=24
+Context=Applications
+Type=Fixed
+
+[24x24/categories]
+Size=24
+Context=Categories
+Type=Fixed
+
+[24x24/devices]
+Size=24
+Context=Devices
+Type=Fixed
+
+[24x24/emblems]
+Size=24
+Context=Emblems
+Type=Fixed
+
+[24x24/emotes]
+Size=24
+Context=Emotes
+Type=Fixed
+
+[24x24/mimetypes]
+Size=24
+Context=MimeTypes
+Type=Fixed
+
+[24x24/places]
+Size=24
+Context=Places
+Type=Fixed
+
+[24x24/status]
+Size=24
+Context=Status
+Type=Fixed
+
+[32x32/actions]
+Size=32
+Context=Actions
+Type=Fixed
+
+[32x32/apps]
+Size=32
+Context=Applications
+Type=Fixed
+
+[32x32/categories]
+Size=32
+Context=Categories
+Type=Fixed
+
+[32x32/devices]
+Size=32
+Context=Devices
+Type=Fixed
+
+[32x32/emblems]
+Size=32
+Context=Emblems
+Type=Fixed
+
+[32x32/emotes]
+Size=32
+Context=Emotes
+Type=Fixed
+
+[32x32/mimetypes]
+Size=32
+Context=MimeTypes
+Type=Fixed
+
+[32x32/places]
+Size=32
+Context=Places
+Type=Fixed
+
+[32x32/status]
+Size=32
+Context=Status
+Type=Fixed
+
+[48x48/actions]
+Size=48
+Context=Actions
+Type=Fixed
+
+[48x48/apps]
+Size=48
+Context=Applications
+Type=Fixed
+
+[48x48/categories]
+Size=48
+Context=Categories
+Type=Fixed
+
+[48x48/devices]
+Size=48
+Context=Devices
+Type=Fixed
+
+[48x48/emblems]
+Size=48
+Context=Emblems
+Type=Fixed
+
+[48x48/emotes]
+Size=48
+Context=Emotes
+Type=Fixed
+
+[48x48/mimetypes]
+Size=48
+Context=MimeTypes
+Type=Fixed
+
+[48x48/places]
+Size=48
+Context=Places
+Type=Fixed
+
+[48x48/status]
+Size=48
+Context=Status
+Type=Fixed
+
+[64x64/actions]
+Size=64
+Context=Actions
+Type=Fixed
+
+[64x64/apps]
+Size=64
+Context=Applications
+Type=Fixed
+
+[64x64/categories]
+Size=64
+Context=Categories
+Type=Fixed
+
+[64x64/devices]
+Size=64
+Context=Devices
+Type=Fixed
+
+[64x64/emblems]
+Size=64
+Context=Emblems
+Type=Fixed
+
+[64x64/emotes]
+Size=64
+Context=Emotes
+Type=Fixed
+
+[64x64/mimetypes]
+Size=64
+Context=MimeTypes
+Type=Fixed
+
+[64x64/places]
+Size=64
+Context=Places
+Type=Fixed
+
+[64x64/status]
+Size=64
+Context=Status
+Type=Fixed
+
+[72x72/actions]
+Size=72
+Context=Actions
+Type=Fixed
+
+[72x72/apps]
+Size=72
+Context=Applications
+Type=Fixed
+
+[72x72/categories]
+Size=72
+Context=Categories
+Type=Fixed
+
+[72x72/devices]
+Size=72
+Context=Devices
+Type=Fixed
+
+[72x72/emblems]
+Size=72
+Context=Emblems
+Type=Fixed
+
+[72x72/emotes]
+Size=72
+Context=Emotes
+Type=Fixed
+
+[72x72/mimetypes]
+Size=72
+Context=MimeTypes
+Type=Fixed
+
+[72x72/places]
+Size=72
+Context=Places
+Type=Fixed
+
+[72x72/status]
+Size=72
+Context=Status
+Type=Fixed
+
+[96x96/actions]
+Size=96
+Context=Actions
+Type=Fixed
+
+[96x96/apps]
+Size=96
+Context=Applications
+Type=Fixed
+
+[96x96/categories]
+Size=96
+Context=Categories
+Type=Fixed
+
+[96x96/devices]
+Size=96
+Context=Devices
+Type=Fixed
+
+[96x96/emblems]
+Size=96
+Context=Emblems
+Type=Fixed
+
+[96x96/emotes]
+Size=96
+Context=Emotes
+Type=Fixed
+
+[96x96/mimetypes]
+Size=96
+Context=MimeTypes
+Type=Fixed
+
+[96x96/places]
+Size=96
+Context=Places
+Type=Fixed
+
+[96x96/status]
+Size=96
+Context=Status
+Type=Fixed
+
+[128x128/actions]
+Size=128
+Context=Actions
+Type=Fixed
+
+[128x128/apps]
+Size=128
+Context=Applications
+Type=Fixed
+
+[128x128/categories]
+Size=128
+Context=Categories
+Type=Fixed
+
+[128x128/devices]
+Size=128
+Context=Devices
+Type=Fixed
+
+[128x128/emblems]
+Size=128
+Context=Emblems
+Type=Fixed
+
+[128x128/emotes]
+Size=128
+Context=Emotes
+Type=Fixed
+
+[128x128/mimetypes]
+Size=128
+Context=MimeTypes
+Type=Fixed
+
+[128x128/places]
+Size=128
+Context=Places
+Type=Fixed
+
+[128x128/status]
+Size=128
+Context=Status
+Type=Fixed
+
+[scalable/actions]
+Size=48
+Context=Actions
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/apps]
+Size=48
+Context=Applications
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/categories]
+Size=48
+Context=Categories
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/devices]
+Size=48
+Context=Devices
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/emblems]
+Size=48
+Context=Emblems
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/emotes]
+Size=48
+Context=Emotes
+Type=Scalable
+Minsize=32
+MaxSize=256
+
+[scalable/mimetypes]
+Size=48
+Context=MimeTypes
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/places]
+Size=48
+Context=Places
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/status]
+Size=48
+Context=Status
+Type=Scalable
+MinSize=32
+MaxSize=256
diff --git a/tests/auto/gui/image/qicon/icons/testtheme/scalable/actions/svg-only.svg b/tests/auto/gui/image/qicon/icons/testtheme/scalable/actions/svg-only.svg
new file mode 100644
index 0000000000..4cb14f82f0
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/testtheme/scalable/actions/svg-only.svg
@@ -0,0 +1,425 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ width="48px"
+ height="48px"
+ id="svg11300"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/actions"
+ sodipodi:docname="appointment-new.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 24 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="48 : 24 : 1"
+ inkscape:persp3d-origin="24 : 16 : 1"
+ id="perspective59" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5204">
+ <stop
+ style="stop-color:#c4a000;stop-opacity:1;"
+ offset="0"
+ id="stop5206" />
+ <stop
+ style="stop-color:#c4a000;stop-opacity:0;"
+ offset="1"
+ id="stop5208" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5196">
+ <stop
+ style="stop-color:#c4a000;stop-opacity:1;"
+ offset="0"
+ id="stop5198" />
+ <stop
+ style="stop-color:#c4a000;stop-opacity:0;"
+ offset="1"
+ id="stop5200" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient12512">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop12513" />
+ <stop
+ style="stop-color:#fff520;stop-opacity:0.89108908;"
+ offset="0.50000000"
+ id="stop12517" />
+ <stop
+ style="stop-color:#fff300;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop12514" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient12512"
+ id="radialGradient278"
+ gradientUnits="userSpaceOnUse"
+ cx="55.000000"
+ cy="125.00000"
+ fx="55.000000"
+ fy="125.00000"
+ r="14.375000" />
+ <linearGradient
+ id="linearGradient10653">
+ <stop
+ style="stop-color:#f3f4ff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop10655" />
+ <stop
+ style="stop-color:#9193af;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop10657" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient42174">
+ <stop
+ style="stop-color:#a0a0a0;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop42176" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop42178" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2145">
+ <stop
+ style="stop-color:#fffffd;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2147" />
+ <stop
+ style="stop-color:#cbcbc9;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop2149" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37935">
+ <stop
+ id="stop37937"
+ offset="0.0000000"
+ style="stop-color:#9497b3;stop-opacity:1.0000000;" />
+ <stop
+ id="stop37939"
+ offset="1.0000000"
+ style="stop-color:#4c4059;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2152">
+ <stop
+ id="stop2154"
+ offset="0.0000000"
+ style="stop-color:#9aa29a;stop-opacity:1.0000000;" />
+ <stop
+ id="stop2156"
+ offset="1.0000000"
+ style="stop-color:#b5beb5;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3816">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3818" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3820" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3816"
+ id="radialGradient3822"
+ cx="31.112698"
+ cy="19.008621"
+ fx="31.112698"
+ fy="19.008621"
+ r="8.6620579"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2152"
+ id="linearGradient4307"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(3.123841,0.000000,0.000000,0.969691,-31.88758,-19.59492)"
+ x1="8.9156475"
+ y1="37.197018"
+ x2="9.8855033"
+ y2="52.090678" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10653"
+ id="radialGradient4309"
+ gradientUnits="userSpaceOnUse"
+ cx="11.329200"
+ cy="10.583970"
+ fx="11.329200"
+ fy="10.583970"
+ r="15.532059" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2145"
+ id="radialGradient4311"
+ gradientUnits="userSpaceOnUse"
+ cx="11.901996"
+ cy="10.045444"
+ fx="11.901996"
+ fy="10.045444"
+ r="29.292715" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient42174"
+ id="linearGradient4313"
+ gradientUnits="userSpaceOnUse"
+ x1="6.3422160"
+ y1="7.7893324"
+ x2="22.218424"
+ y2="25.884274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5196"
+ id="radialGradient5202"
+ cx="23.375"
+ cy="10.972863"
+ fx="23.375"
+ fy="10.972863"
+ r="3.3478092"
+ gradientTransform="matrix(3.630420,1.654030e-15,-1.608743e-15,3.742066,-61.48607,-29.18618)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5204"
+ id="linearGradient5210"
+ x1="19.667364"
+ y1="4.2570662"
+ x2="20.329933"
+ y2="5.2845874"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37935"
+ id="radialGradient5212"
+ gradientUnits="userSpaceOnUse"
+ cx="8.7468252"
+ cy="6.8283234"
+ fx="8.7468252"
+ fy="6.8283234"
+ r="29.889715" />
+ </defs>
+ <sodipodi:namedview
+ stroke="#c4a000"
+ fill="#babdb6"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="11.313708"
+ inkscape:cx="13.2248"
+ inkscape:cy="25.106052"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="833"
+ inkscape:window-height="772"
+ inkscape:window-x="305"
+ inkscape:window-y="76" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+ <dc:title>New Appointment</dc:title>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>appointment</rdf:li>
+ <rdf:li>new</rdf:li>
+ <rdf:li>meeting</rdf:li>
+ <rdf:li>rvsp</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <path
+ d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z"
+ sodipodi:ry="8.6620579"
+ sodipodi:rx="8.6620579"
+ sodipodi:cy="19.008621"
+ sodipodi:cx="31.112698"
+ id="path4318"
+ style="opacity:1;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ sodipodi:type="arc"
+ transform="matrix(2.563158,0.000000,0.000000,1.219602,-55.98414,14.04144)" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path14341"
+ d="M 18.587591,1.403729 L 4.226755,18.096665 L 5.4854717,19.339844 L 18.587591,1.403729 z "
+ style="color:#000000;fill:url(#linearGradient4307);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path18921"
+ d="M 18.467176,1.3138035 L 5.6605716,19.072612 L 7.4900985,20.687913 L 18.467176,1.3138035 z "
+ style="fill:#fefefe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ transform="matrix(1.431529,0.000000,0.000000,1.431529,0.569459,-1.654618)"
+ d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z"
+ sodipodi:ry="14.910714"
+ sodipodi:rx="14.910714"
+ sodipodi:cy="16.910715"
+ sodipodi:cx="16.25"
+ id="path27786"
+ style="fill:url(#radialGradient5212);fill-opacity:1;fill-rule:evenodd;stroke:#605773;stroke-width:0.69855404;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(1.163838,0.000000,0.000000,1.163838,4.824801,2.777556)"
+ d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z"
+ sodipodi:ry="14.910714"
+ sodipodi:rx="14.910714"
+ sodipodi:cy="16.910715"
+ sodipodi:cx="16.25"
+ id="path35549"
+ style="fill:url(#radialGradient4311);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4313);stroke-width:0.71139598;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;color:#000000;fill:url(#radialGradient5202);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5210);stroke-width:0.56498736;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4120"
+ sodipodi:cx="23.375"
+ sodipodi:cy="11.875"
+ sodipodi:rx="8.5"
+ sodipodi:ry="8.5"
+ d="M 16.679382,6.6387137 A 8.5,8.5 0 0 1 23.332691,3.3751053 L 23.375,11.875 z"
+ transform="matrix(1.769951,0.000000,0.000000,1.769951,-17.02424,1.610741)"
+ sodipodi:start="3.8052902"
+ sodipodi:end="4.7074114" />
+ <path
+ transform="matrix(2.073295,0.000000,0.000000,2.073295,-7.310224,-13.13682)"
+ d="M 16.40625 17.28125 A 1.21875 1.21875 0 1 1 13.96875,17.28125 A 1.21875 1.21875 0 1 1 16.40625 17.28125 z"
+ sodipodi:ry="1.21875"
+ sodipodi:rx="1.21875"
+ sodipodi:cy="17.28125"
+ sodipodi:cx="15.1875"
+ id="path34778"
+ style="fill:#f3f3f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.48232403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:type="arc" />
+ <path
+ id="path35559"
+ d="M 22.176614,20.718014 L 13.155702,13.140282"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ id="path35561"
+ d="M 19.408614,29.776506 L 22.368655,25.283228"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc" />
+ <path
+ transform="matrix(2.749493,0.000000,0.000000,2.749493,-22.30073,-12.40939)"
+ d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z"
+ sodipodi:ry="0.61871845"
+ sodipodi:rx="0.61871845"
+ sodipodi:cy="7.6932044"
+ sodipodi:cx="16.705399"
+ id="path35563"
+ style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(2.749493,0.000000,0.000000,2.749493,-22.30073,14.80922)"
+ d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z"
+ sodipodi:ry="0.61871845"
+ sodipodi:rx="0.61871845"
+ sodipodi:cy="7.6932044"
+ sodipodi:cx="16.705399"
+ id="path35565"
+ style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(2.749493,0.000000,0.000000,2.749493,-35.91004,1.199890)"
+ d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z"
+ sodipodi:ry="0.61871845"
+ sodipodi:rx="0.61871845"
+ sodipodi:cy="7.6932044"
+ sodipodi:cx="16.705399"
+ id="path35567"
+ style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(2.749493,0.000000,0.000000,2.749493,-8.691448,1.199890)"
+ d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z"
+ sodipodi:ry="0.61871845"
+ sodipodi:rx="0.61871845"
+ sodipodi:cy="7.6932044"
+ sodipodi:cx="16.705399"
+ id="path35569"
+ style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient4309);stroke-width:0.73656511;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ id="path10651"
+ sodipodi:cx="16.25"
+ sodipodi:cy="16.910715"
+ sodipodi:rx="14.910714"
+ sodipodi:ry="14.910714"
+ d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z"
+ transform="matrix(1.357654,0.000000,0.000000,1.357654,1.769896,-0.493735)" />
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:url(#radialGradient278);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block"
+ id="path12511"
+ sodipodi:cx="55"
+ sodipodi:cy="125"
+ sodipodi:rx="14.375"
+ sodipodi:ry="14.375"
+ d="M 69.375 125 A 14.375 14.375 0 1 1 40.625,125 A 14.375 14.375 0 1 1 69.375 125 z"
+ transform="matrix(0.611127,0.000000,0.000000,0.611127,5.544052,-66.92818)"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/stock_new-16.png"
+ inkscape:export-xdpi="33.852203"
+ inkscape:export-ydpi="33.852203" />
+ </g>
+</svg>
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/address-book-new.png b/tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/address-book-new.png
new file mode 100644
index 0000000000..2098cfdf36
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/address-book-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/appointment-new.png b/tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/appointment-new.png
new file mode 100644
index 0000000000..18b7c6781e
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/appointment-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/address-book-new.png b/tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/address-book-new.png
new file mode 100644
index 0000000000..fad446cd92
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/address-book-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/appointment-new.png b/tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/appointment-new.png
new file mode 100644
index 0000000000..d676ffd463
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/appointment-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/address-book-new.png b/tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/address-book-new.png
new file mode 100644
index 0000000000..420139d307
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/address-book-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/appointment-new.png b/tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/appointment-new.png
new file mode 100644
index 0000000000..85daef3b0b
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/appointment-new.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/index.theme b/tests/auto/gui/image/qicon/icons/themeparent/index.theme
new file mode 100644
index 0000000000..e536a0bf2f
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/index.theme
@@ -0,0 +1,492 @@
+[Icon Theme]
+_Name=Test
+_Comment=Test Theme
+Inherits=gnome,crystalsvg
+Example=x-directory-normal
+
+# KDE Specific Stuff
+DisplayDepth=32
+LinkOverlay=link_overlay
+LockOverlay=lock_overlay
+ZipOverlay=zip_overlay
+DesktopDefault=48
+DesktopSizes=16,22,32,48,64,72,96,128
+ToolbarDefault=22
+ToolbarSizes=16,22,32,48
+MainToolbarDefault=22
+MainToolbarSizes=16,22,32,48
+SmallDefault=16
+SmallSizes=16
+PanelDefault=32
+PanelSizes=16,22,32,48,64,72,96,128
+
+# Directory list
+Directories=16x16/actions,16x16/apps,16x16/categories,16x16/devices,16x16/emblems,16x16/emotes,16x16/mimetypes,16x16/places,16x16/status,22x22/actions,22x22/apps,22x22/categories,22x22/devices,22x22/emblems,22x22/emotes,22x22/mimetypes,22x22/places,22x22/status,24x24/actions,24x24/apps,24x24/categories,24x24/devices,24x24/emblems,24x24/emotes,24x24/mimetypes,24x24/places,24x24/status,32x32/actions,32x32/apps,32x32/categories,32x32/devices,32x32/emblems,32x32/emotes,32x32/mimetypes,32x32/places,32x32/status,48x48/actions,48x48/apps,48x48/categories,48x48/devices,48x48/emblems,48x48/emotes,48x48/mimetypes,48x48/places,48x48/status,64x64/actions,64x64/apps,64x64/categories,64x64/devices,64x64/emblems,64x64/emotes,64x64/mimetypes,64x64/places,64x64/status,72x72/actions,72x72/apps,72x72/categories,72x72/devices,72x72/emblems,72x72/emotes,72x72/mimetypes,72x72/places,72x72/status,96x96/actions,96x96/apps,96x96/categories,96x96/devices,96x96/emblems,96x96/emotes,96x96/mimetypes,96x96/places,96x96/status,128x128/actions,128x128/apps,128x128/categories,128x128/devices,128x128/emblems,128x128/emotes,128x128/mimetypes,128x128/places,128x128/status,scalable/actions,scalable/apps,scalable/categories,scalable/devices,scalable/emblems,scalable/emotes,scalable/mimetypes,scalable/places,scalable/status
+
+[16x16/actions]
+Size=16
+Context=Actions
+Type=Fixed
+
+[16x16/apps]
+Size=16
+Context=Applications
+Type=Fixed
+
+[16x16/categories]
+Size=16
+Context=Categories
+Type=Fixed
+
+[16x16/devices]
+Size=16
+Context=Devices
+Type=Fixed
+
+[16x16/emblems]
+Size=16
+Context=Emblems
+Type=Fixed
+
+[16x16/emotes]
+Size=16
+Context=Emotes
+Type=Fixed
+
+[16x16/mimetypes]
+Size=16
+Context=MimeTypes
+Type=Fixed
+
+[16x16/places]
+Size=16
+Context=Places
+Type=Fixed
+
+[16x16/status]
+Size=16
+Context=Status
+Type=Fixed
+
+[22x22/actions]
+Size=22
+Context=Actions
+Type=Fixed
+
+[22x22/apps]
+Size=22
+Context=Applications
+Type=Fixed
+
+[22x22/categories]
+Size=22
+Context=Categories
+Type=Fixed
+
+[22x22/devices]
+Size=22
+Context=Devices
+Type=Fixed
+
+[22x22/emblems]
+Size=22
+Context=Emblems
+Type=Fixed
+
+[22x22/emotes]
+Size=22
+Context=Emotes
+Type=Fixed
+
+[22x22/mimetypes]
+Size=22
+Context=MimeTypes
+Type=Fixed
+
+[22x22/places]
+Size=22
+Context=Places
+Type=Fixed
+
+[22x22/status]
+Size=22
+Context=Status
+Type=Fixed
+
+[24x24/actions]
+Size=24
+Context=Actions
+Type=Fixed
+
+[24x24/apps]
+Size=24
+Context=Applications
+Type=Fixed
+
+[24x24/categories]
+Size=24
+Context=Categories
+Type=Fixed
+
+[24x24/devices]
+Size=24
+Context=Devices
+Type=Fixed
+
+[24x24/emblems]
+Size=24
+Context=Emblems
+Type=Fixed
+
+[24x24/emotes]
+Size=24
+Context=Emotes
+Type=Fixed
+
+[24x24/mimetypes]
+Size=24
+Context=MimeTypes
+Type=Fixed
+
+[24x24/places]
+Size=24
+Context=Places
+Type=Fixed
+
+[24x24/status]
+Size=24
+Context=Status
+Type=Fixed
+
+[32x32/actions]
+Size=32
+Context=Actions
+Type=Fixed
+
+[32x32/apps]
+Size=32
+Context=Applications
+Type=Fixed
+
+[32x32/categories]
+Size=32
+Context=Categories
+Type=Fixed
+
+[32x32/devices]
+Size=32
+Context=Devices
+Type=Fixed
+
+[32x32/emblems]
+Size=32
+Context=Emblems
+Type=Fixed
+
+[32x32/emotes]
+Size=32
+Context=Emotes
+Type=Fixed
+
+[32x32/mimetypes]
+Size=32
+Context=MimeTypes
+Type=Fixed
+
+[32x32/places]
+Size=32
+Context=Places
+Type=Fixed
+
+[32x32/status]
+Size=32
+Context=Status
+Type=Fixed
+
+[48x48/actions]
+Size=48
+Context=Actions
+Type=Fixed
+
+[48x48/apps]
+Size=48
+Context=Applications
+Type=Fixed
+
+[48x48/categories]
+Size=48
+Context=Categories
+Type=Fixed
+
+[48x48/devices]
+Size=48
+Context=Devices
+Type=Fixed
+
+[48x48/emblems]
+Size=48
+Context=Emblems
+Type=Fixed
+
+[48x48/emotes]
+Size=48
+Context=Emotes
+Type=Fixed
+
+[48x48/mimetypes]
+Size=48
+Context=MimeTypes
+Type=Fixed
+
+[48x48/places]
+Size=48
+Context=Places
+Type=Fixed
+
+[48x48/status]
+Size=48
+Context=Status
+Type=Fixed
+
+[64x64/actions]
+Size=64
+Context=Actions
+Type=Fixed
+
+[64x64/apps]
+Size=64
+Context=Applications
+Type=Fixed
+
+[64x64/categories]
+Size=64
+Context=Categories
+Type=Fixed
+
+[64x64/devices]
+Size=64
+Context=Devices
+Type=Fixed
+
+[64x64/emblems]
+Size=64
+Context=Emblems
+Type=Fixed
+
+[64x64/emotes]
+Size=64
+Context=Emotes
+Type=Fixed
+
+[64x64/mimetypes]
+Size=64
+Context=MimeTypes
+Type=Fixed
+
+[64x64/places]
+Size=64
+Context=Places
+Type=Fixed
+
+[64x64/status]
+Size=64
+Context=Status
+Type=Fixed
+
+[72x72/actions]
+Size=72
+Context=Actions
+Type=Fixed
+
+[72x72/apps]
+Size=72
+Context=Applications
+Type=Fixed
+
+[72x72/categories]
+Size=72
+Context=Categories
+Type=Fixed
+
+[72x72/devices]
+Size=72
+Context=Devices
+Type=Fixed
+
+[72x72/emblems]
+Size=72
+Context=Emblems
+Type=Fixed
+
+[72x72/emotes]
+Size=72
+Context=Emotes
+Type=Fixed
+
+[72x72/mimetypes]
+Size=72
+Context=MimeTypes
+Type=Fixed
+
+[72x72/places]
+Size=72
+Context=Places
+Type=Fixed
+
+[72x72/status]
+Size=72
+Context=Status
+Type=Fixed
+
+[96x96/actions]
+Size=96
+Context=Actions
+Type=Fixed
+
+[96x96/apps]
+Size=96
+Context=Applications
+Type=Fixed
+
+[96x96/categories]
+Size=96
+Context=Categories
+Type=Fixed
+
+[96x96/devices]
+Size=96
+Context=Devices
+Type=Fixed
+
+[96x96/emblems]
+Size=96
+Context=Emblems
+Type=Fixed
+
+[96x96/emotes]
+Size=96
+Context=Emotes
+Type=Fixed
+
+[96x96/mimetypes]
+Size=96
+Context=MimeTypes
+Type=Fixed
+
+[96x96/places]
+Size=96
+Context=Places
+Type=Fixed
+
+[96x96/status]
+Size=96
+Context=Status
+Type=Fixed
+
+[128x128/actions]
+Size=128
+Context=Actions
+Type=Fixed
+
+[128x128/apps]
+Size=128
+Context=Applications
+Type=Fixed
+
+[128x128/categories]
+Size=128
+Context=Categories
+Type=Fixed
+
+[128x128/devices]
+Size=128
+Context=Devices
+Type=Fixed
+
+[128x128/emblems]
+Size=128
+Context=Emblems
+Type=Fixed
+
+[128x128/emotes]
+Size=128
+Context=Emotes
+Type=Fixed
+
+[128x128/mimetypes]
+Size=128
+Context=MimeTypes
+Type=Fixed
+
+[128x128/places]
+Size=128
+Context=Places
+Type=Fixed
+
+[128x128/status]
+Size=128
+Context=Status
+Type=Fixed
+
+[scalable/actions]
+Size=48
+Context=Actions
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/apps]
+Size=48
+Context=Applications
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/categories]
+Size=48
+Context=Categories
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/devices]
+Size=48
+Context=Devices
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/emblems]
+Size=48
+Context=Emblems
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/emotes]
+Size=48
+Context=Emotes
+Type=Scalable
+Minsize=32
+MaxSize=256
+
+[scalable/mimetypes]
+Size=48
+Context=MimeTypes
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/places]
+Size=48
+Context=Places
+Type=Scalable
+MinSize=32
+MaxSize=256
+
+[scalable/status]
+Size=48
+Context=Status
+Type=Scalable
+MinSize=32
+MaxSize=256
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/address-book-new.svg b/tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/address-book-new.svg
new file mode 100644
index 0000000000..600a82c1b0
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/address-book-new.svg
@@ -0,0 +1,389 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48px"
+ height="48px"
+ id="svg1256"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
+ sodipodi:docname="address-book-new.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 24 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="48 : 24 : 1"
+ inkscape:persp3d-origin="24 : 16 : 1"
+ id="perspective58" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5060">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop5062" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5064" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5048">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop5050" />
+ <stop
+ id="stop5056"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5052" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient12512">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop12513" />
+ <stop
+ style="stop-color:#fff520;stop-opacity:0.89108908;"
+ offset="0.50000000"
+ id="stop12517" />
+ <stop
+ style="stop-color:#fff300;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop12514" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient12512"
+ id="radialGradient278"
+ gradientUnits="userSpaceOnUse"
+ cx="55.000000"
+ cy="125.00000"
+ fx="55.000000"
+ fy="125.00000"
+ r="14.375000" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2116">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop2118" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop2120" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2094">
+ <stop
+ style="stop-color:#d6e3f0;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2096" />
+ <stop
+ style="stop-color:#95b1cf;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop2098" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2803">
+ <stop
+ id="stop2805"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop2807"
+ offset="1.0000000"
+ style="stop-color:#cbcbcb;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2795">
+ <stop
+ id="stop2797"
+ offset="0.0000000"
+ style="stop-color:#000000;stop-opacity:0.068627454;" />
+ <stop
+ id="stop2799"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="4.9530048"
+ x2="41.219128"
+ y1="4.9530050"
+ x1="35.433035"
+ gradientTransform="matrix(0.254000,0.000000,1.822151e-16,3.759813,0.788629,0.148567)"
+ id="linearGradient2801"
+ xlink:href="#linearGradient2795"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="84.287079"
+ x2="10.219901"
+ y1="93.338043"
+ x1="10.496115"
+ gradientTransform="matrix(2.262742,0.000000,0.000000,0.441942,1.000000,-0.875000)"
+ id="linearGradient2813"
+ xlink:href="#linearGradient2803"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2094"
+ id="linearGradient2100"
+ gradientTransform="matrix(0.957750,0.000000,0.000000,1.027989,1.000000,-0.571911)"
+ x1="6.5871811"
+ y1="22.132999"
+ x2="14.511404"
+ y2="22.132999"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2116"
+ id="linearGradient2112"
+ gradientTransform="matrix(1.025428,0.000000,0.000000,0.957303,0.000000,-0.806758)"
+ x1="73.361984"
+ y1="26.652197"
+ x2="-2.7582901"
+ y2="21.270376"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient5013"
+ gradientUnits="userSpaceOnUse"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5048"
+ id="linearGradient5016"
+ gradientUnits="userSpaceOnUse"
+ x1="302.85715"
+ y1="366.64789"
+ x2="302.85715"
+ y2="609.50507"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient5020"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5048"
+ id="linearGradient5027"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+ x1="302.85715"
+ y1="366.64789"
+ x2="302.85715"
+ y2="609.50507" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient5029"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient5031"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.27843137"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="-111.52422"
+ inkscape:cy="10.167608"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:window-width="872"
+ inkscape:window-height="688"
+ inkscape:window-x="562"
+ inkscape:window-y="160"
+ fill="#ef2929"
+ stroke="#cc0000"
+ inkscape:showpageshadow="false" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Addess Book - New</dc:title>
+ <dc:date />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>address</rdf:li>
+ <rdf:li>contact</rdf:li>
+ <rdf:li>book</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <path
+ style="opacity:1;color:#000000;fill:#edd400;fill-opacity:1;fill-rule:evenodd;stroke:#c4a000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 33.096456,4.6520202 L 40.521077,4.6520202 C 41.228184,4.6520202 41.758513,4.8287969 41.93529,5.71268 L 42.819174,12.606972 C 42.907562,13.667632 42.443523,14.021185 41.493349,14.021185 L 32.919679,14.021185 L 33.096456,4.6520202 z "
+ id="path21630"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path21632"
+ d="M 34.10295,5.638875 L 40.463507,5.638875 C 40.771656,5.638875 40.940266,5.669037 40.986054,5.960473 L 41.777489,12.344449 C 41.847258,12.775421 41.959897,13.019804 41.637211,13.034341 L 33.963412,13.034341 L 34.10295,5.638875 z "
+ style="opacity:0.48538011;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000006;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path21634"
+ d="M 35.596456,12.40202 L 43.021077,12.40202 C 43.728184,12.40202 44.258513,12.578797 44.43529,13.46268 L 45.319174,20.356972 C 45.407562,21.417632 44.943523,21.771185 43.993349,21.771185 L 35.419679,21.771185 L 35.596456,12.40202 z "
+ style="opacity:1;color:#000000;fill:#9db029;fill-opacity:1;fill-rule:evenodd;stroke:#727e0a;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ style="opacity:0.48538011;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000006;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 36.60295,13.388875 L 42.963507,13.388875 C 43.271656,13.388875 43.440266,13.419037 43.486054,13.710473 L 44.277489,20.094449 C 44.347258,20.525421 44.459897,20.769804 44.137211,20.784341 L 36.463412,20.784341 L 36.60295,13.388875 z "
+ id="path21636"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:1;color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:#cc0000;stroke-width:0.99999988;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 36.06451,20.776498 L 44.50992,20.776498 C 45.314245,20.776498 45.917487,20.995896 46.118569,22.092882 L 47.123975,30.649381 C 47.224515,31.965765 46.696677,32.40456 45.615866,32.40456 L 35.863428,32.40456 L 36.06451,20.776498 z "
+ id="path21638"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path21640"
+ d="M 37.209384,21.763574 L 44.444435,21.763574 C 44.79495,21.763574 44.986742,21.801928 45.038825,22.172513 L 45.939072,30.290267 C 46.018433,30.838284 46.146559,31.149038 45.779508,31.167522 L 37.050661,31.167522 L 37.209384,21.763574 z "
+ style="opacity:0.48538011;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000072;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <g
+ id="g5022"
+ transform="matrix(2.165152e-2,0,0,4.307902e-2,43.08625,34.04509)">
+ <rect
+ y="-150.69685"
+ x="-1559.2523"
+ height="478.35718"
+ width="1339.6335"
+ id="rect4173"
+ style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path5058"
+ d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+ id="path5018"
+ sodipodi:nodetypes="cccc" />
+ </g>
+ <path
+ style="color:#000000;fill:#5b6b94;fill-opacity:1;fill-rule:nonzero;stroke:#364878;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 6.3643222,5.5185897 C 6.4551049,3.6036003 7.3719758,2.5542814 9.0788784,2.549044 L 38.405776,2.4590577 C 38.652361,2.4583011 38.974317,2.6592071 38.999012,2.9089888 L 42.257491,35.867228 L 40.942189,35.923862 L 41.571429,42.369516 C 41.632441,42.994499 41.390059,43.52882 40.5,43.533035 L 9.7893046,43.678474 C 7.25676,43.690468 4.6538454,41.59976 4.7759337,39.024403 L 6.3643222,5.5185897 z "
+ id="rect1408"
+ sodipodi:nodetypes="csssccsssss" />
+ <path
+ id="path2489"
+ d="M 40.125,34.875 L 10.9375,35 C 9.3809819,35.177868 8.125,36.39612 8.125,38 C 8.125,39.60388 9.3809819,40.822132 10.9375,41 L 40.125,41.125 L 40.125,41.0625 C 38.469378,40.984348 37.125,39.674851 37.125,38 C 37.125,36.325149 38.469378,35.015652 40.125,34.9375 L 40.125,34.875 z "
+ style="color:#000000;fill:url(#linearGradient2813);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="ccccccssc"
+ id="path2784"
+ d="M 9.6875,2.8125 C 7.9805897,2.8125 7.050103,3.8215062 6.96875,5.6738658 L 5.3125,37.825772 C 5.22054,40.904199 7.1393732,42.654485 9.125,43.15625 C 4.875,41.525579 5.4375,34.164455 10.75,34.195222 L 41.648286,34.195222 L 38.335786,3.2432432 C 38.310025,3.0025304 37.987878,2.8125 37.742036,2.8125 L 9.6875,2.8125 z "
+ style="color:#000000;fill:url(#linearGradient2100);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ y="3.968539"
+ x="9.7886267"
+ height="29.604792"
+ width="2"
+ id="rect2793"
+ style="opacity:0.48044691;color:#000000;fill:url(#linearGradient2801);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.60818715;visibility:visible;display:inline;overflow:visible"
+ transform="matrix(1.000000,0.000000,-3.582731e-2,0.999358,0.000000,0.000000)" />
+ <path
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2112);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 9.8751008,3.3336831 C 8.1912014,3.3336831 7.5384236,4.0658459 7.4581673,5.887831 L 6.1592633,35.777198 C 7.0925916,34.170451 8.5988591,33.594437 11.011665,33.594437 L 40.963081,33.594437 L 38.137179,3.7573631 C 38.114727,3.5203092 37.793961,3.3336831 37.551434,3.3336831 L 9.8751008,3.3336831 z "
+ id="path2104"
+ sodipodi:nodetypes="cccscssc" />
+ <path
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000477%;writing-mode:lr-tb;text-anchor:start;fill:#ad7fa8;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ d="M 21.12553,18.381288 C 21.050283,19.50227 21.269376,20.384155 21.782812,21.026947 C 22.296751,21.661909 23.039741,21.979388 24.011788,21.979387 C 24.97597,21.979388 25.754005,21.65799 26.345892,21.01519 C 26.945589,20.372398 27.282799,19.49443 27.357529,18.381288 C 27.431173,17.283839 27.207372,16.413709 26.686123,15.770905 C 26.165371,15.120279 25.426826,14.794959 24.470482,14.79495 C 23.521952,14.794959 22.743917,15.11636 22.136378,15.759145 C 21.536656,16.401952 21.199707,17.275998 21.12553,18.381288 M 27.29793,21.897075 C 26.787062,22.500679 26.216183,22.947501 25.58529,23.237544 C 24.962734,23.519747 24.247754,23.66085 23.44035,23.660849 C 22.092032,23.66085 21.027197,23.174832 20.245835,22.202797 C 19.472826,21.222925 19.138938,19.949092 19.244172,18.381288 C 19.349395,16.813498 19.858197,15.539665 20.770584,14.559781 C 21.682954,13.579917 22.809375,13.089981 24.149854,13.089969 C 24.957257,13.089981 25.656689,13.238924 26.24815,13.536791 C 26.840107,13.826846 27.347352,14.269749 27.76988,14.865501 L 27.873267,13.325141 L 29.554732,13.325141 L 28.973868,21.979387 C 30.129917,21.806931 31.058551,21.285637 31.759769,20.415508 C 32.469312,19.537544 32.870659,18.404812 32.963808,17.017304 C 33.020082,16.178542 32.947536,15.390722 32.746168,14.653848 C 32.552597,13.916994 32.226018,13.235002 31.766435,12.607873 C 31.020085,11.580979 30.077151,10.79708 28.937625,10.256176 C 27.806428,9.707462 26.551007,9.433097 25.171361,9.433081 C 24.207151,9.433097 23.27347,9.56244 22.370314,9.821111 C 21.467662,10.071974 20.623234,10.448244 19.837027,10.949925 C 18.552629,11.749517 17.517932,12.79994 16.732929,14.101199 C 15.956279,15.394643 15.517185,16.797819 15.415642,18.310738 C 15.331983,19.557142 15.476998,20.725151 15.85069,21.814765 C 16.232213,22.904387 16.822316,23.864664 17.621,24.695594 C 18.389368,25.51085 19.300238,26.130129 20.353615,26.553435 C 21.406448,26.984578 22.54823,27.20015 23.778962,27.200153 C 24.790178,27.20015 25.793384,27.027692 26.788584,26.682781 C 27.791068,26.345701 28.72125,25.859684 29.579139,25.224728 L 30.549801,26.529919 C 29.518874,27.2903 28.409917,27.870384 27.222932,28.270174 C 26.043227,28.677799 24.857618,28.881612 23.666104,28.881616 C 22.215881,28.881612 20.865341,28.622926 19.614483,28.105557 C 18.36308,27.596019 17.268571,26.851316 16.330955,25.871444 C 15.393328,24.89157 14.705054,23.758838 14.266133,22.47324 C 13.827731,21.179813 13.658252,19.792311 13.757696,18.310738 C 13.853452,16.88405 14.211263,15.523986 14.831129,14.230542 C 15.450993,12.937121 16.287663,11.800469 17.34115,10.820582 C 18.419191,9.825045 19.638236,9.0646655 20.998287,8.5394366 C 22.358842,8.0064001 23.779908,7.7398759 25.261489,7.7398585 C 26.923341,7.7398759 28.440813,8.080872 29.813913,8.7628469 C 31.194815,9.444854 32.325282,10.41297 33.205316,11.667193 C 33.741656,12.435425 34.132443,13.270279 34.377679,14.171752 C 34.630708,15.073243 34.724877,16.006082 34.660187,16.970271 C 34.521787,19.031929 33.789414,20.658519 32.463064,21.850041 C 31.136671,23.04157 29.374449,23.66085 27.17639,23.707883 L 27.29793,21.897075"
+ id="text21625" />
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:url(#radialGradient278);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block"
+ id="path12511"
+ sodipodi:cx="55"
+ sodipodi:cy="125"
+ sodipodi:rx="14.375"
+ sodipodi:ry="14.375"
+ d="M 69.375 125 A 14.375 14.375 0 1 1 40.625,125 A 14.375 14.375 0 1 1 69.375 125 z"
+ transform="matrix(0.611127,0.000000,0.000000,0.611127,-24.94992,-67.63529)"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/stock_new-16.png"
+ inkscape:export-xdpi="33.852203"
+ inkscape:export-ydpi="33.852203" />
+ </g>
+</svg>
diff --git a/tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/appointment-new.svg b/tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/appointment-new.svg
new file mode 100644
index 0000000000..4cb14f82f0
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/appointment-new.svg
@@ -0,0 +1,425 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ width="48px"
+ height="48px"
+ id="svg11300"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/actions"
+ sodipodi:docname="appointment-new.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 24 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="48 : 24 : 1"
+ inkscape:persp3d-origin="24 : 16 : 1"
+ id="perspective59" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5204">
+ <stop
+ style="stop-color:#c4a000;stop-opacity:1;"
+ offset="0"
+ id="stop5206" />
+ <stop
+ style="stop-color:#c4a000;stop-opacity:0;"
+ offset="1"
+ id="stop5208" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5196">
+ <stop
+ style="stop-color:#c4a000;stop-opacity:1;"
+ offset="0"
+ id="stop5198" />
+ <stop
+ style="stop-color:#c4a000;stop-opacity:0;"
+ offset="1"
+ id="stop5200" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient12512">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop12513" />
+ <stop
+ style="stop-color:#fff520;stop-opacity:0.89108908;"
+ offset="0.50000000"
+ id="stop12517" />
+ <stop
+ style="stop-color:#fff300;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop12514" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient12512"
+ id="radialGradient278"
+ gradientUnits="userSpaceOnUse"
+ cx="55.000000"
+ cy="125.00000"
+ fx="55.000000"
+ fy="125.00000"
+ r="14.375000" />
+ <linearGradient
+ id="linearGradient10653">
+ <stop
+ style="stop-color:#f3f4ff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop10655" />
+ <stop
+ style="stop-color:#9193af;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop10657" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient42174">
+ <stop
+ style="stop-color:#a0a0a0;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop42176" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop42178" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2145">
+ <stop
+ style="stop-color:#fffffd;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2147" />
+ <stop
+ style="stop-color:#cbcbc9;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop2149" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37935">
+ <stop
+ id="stop37937"
+ offset="0.0000000"
+ style="stop-color:#9497b3;stop-opacity:1.0000000;" />
+ <stop
+ id="stop37939"
+ offset="1.0000000"
+ style="stop-color:#4c4059;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2152">
+ <stop
+ id="stop2154"
+ offset="0.0000000"
+ style="stop-color:#9aa29a;stop-opacity:1.0000000;" />
+ <stop
+ id="stop2156"
+ offset="1.0000000"
+ style="stop-color:#b5beb5;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3816">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3818" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3820" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3816"
+ id="radialGradient3822"
+ cx="31.112698"
+ cy="19.008621"
+ fx="31.112698"
+ fy="19.008621"
+ r="8.6620579"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2152"
+ id="linearGradient4307"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(3.123841,0.000000,0.000000,0.969691,-31.88758,-19.59492)"
+ x1="8.9156475"
+ y1="37.197018"
+ x2="9.8855033"
+ y2="52.090678" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10653"
+ id="radialGradient4309"
+ gradientUnits="userSpaceOnUse"
+ cx="11.329200"
+ cy="10.583970"
+ fx="11.329200"
+ fy="10.583970"
+ r="15.532059" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2145"
+ id="radialGradient4311"
+ gradientUnits="userSpaceOnUse"
+ cx="11.901996"
+ cy="10.045444"
+ fx="11.901996"
+ fy="10.045444"
+ r="29.292715" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient42174"
+ id="linearGradient4313"
+ gradientUnits="userSpaceOnUse"
+ x1="6.3422160"
+ y1="7.7893324"
+ x2="22.218424"
+ y2="25.884274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5196"
+ id="radialGradient5202"
+ cx="23.375"
+ cy="10.972863"
+ fx="23.375"
+ fy="10.972863"
+ r="3.3478092"
+ gradientTransform="matrix(3.630420,1.654030e-15,-1.608743e-15,3.742066,-61.48607,-29.18618)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5204"
+ id="linearGradient5210"
+ x1="19.667364"
+ y1="4.2570662"
+ x2="20.329933"
+ y2="5.2845874"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37935"
+ id="radialGradient5212"
+ gradientUnits="userSpaceOnUse"
+ cx="8.7468252"
+ cy="6.8283234"
+ fx="8.7468252"
+ fy="6.8283234"
+ r="29.889715" />
+ </defs>
+ <sodipodi:namedview
+ stroke="#c4a000"
+ fill="#babdb6"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="11.313708"
+ inkscape:cx="13.2248"
+ inkscape:cy="25.106052"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="833"
+ inkscape:window-height="772"
+ inkscape:window-x="305"
+ inkscape:window-y="76" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+ <dc:title>New Appointment</dc:title>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>appointment</rdf:li>
+ <rdf:li>new</rdf:li>
+ <rdf:li>meeting</rdf:li>
+ <rdf:li>rvsp</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <path
+ d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z"
+ sodipodi:ry="8.6620579"
+ sodipodi:rx="8.6620579"
+ sodipodi:cy="19.008621"
+ sodipodi:cx="31.112698"
+ id="path4318"
+ style="opacity:1;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ sodipodi:type="arc"
+ transform="matrix(2.563158,0.000000,0.000000,1.219602,-55.98414,14.04144)" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path14341"
+ d="M 18.587591,1.403729 L 4.226755,18.096665 L 5.4854717,19.339844 L 18.587591,1.403729 z "
+ style="color:#000000;fill:url(#linearGradient4307);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path18921"
+ d="M 18.467176,1.3138035 L 5.6605716,19.072612 L 7.4900985,20.687913 L 18.467176,1.3138035 z "
+ style="fill:#fefefe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ transform="matrix(1.431529,0.000000,0.000000,1.431529,0.569459,-1.654618)"
+ d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z"
+ sodipodi:ry="14.910714"
+ sodipodi:rx="14.910714"
+ sodipodi:cy="16.910715"
+ sodipodi:cx="16.25"
+ id="path27786"
+ style="fill:url(#radialGradient5212);fill-opacity:1;fill-rule:evenodd;stroke:#605773;stroke-width:0.69855404;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(1.163838,0.000000,0.000000,1.163838,4.824801,2.777556)"
+ d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z"
+ sodipodi:ry="14.910714"
+ sodipodi:rx="14.910714"
+ sodipodi:cy="16.910715"
+ sodipodi:cx="16.25"
+ id="path35549"
+ style="fill:url(#radialGradient4311);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4313);stroke-width:0.71139598;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;color:#000000;fill:url(#radialGradient5202);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5210);stroke-width:0.56498736;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4120"
+ sodipodi:cx="23.375"
+ sodipodi:cy="11.875"
+ sodipodi:rx="8.5"
+ sodipodi:ry="8.5"
+ d="M 16.679382,6.6387137 A 8.5,8.5 0 0 1 23.332691,3.3751053 L 23.375,11.875 z"
+ transform="matrix(1.769951,0.000000,0.000000,1.769951,-17.02424,1.610741)"
+ sodipodi:start="3.8052902"
+ sodipodi:end="4.7074114" />
+ <path
+ transform="matrix(2.073295,0.000000,0.000000,2.073295,-7.310224,-13.13682)"
+ d="M 16.40625 17.28125 A 1.21875 1.21875 0 1 1 13.96875,17.28125 A 1.21875 1.21875 0 1 1 16.40625 17.28125 z"
+ sodipodi:ry="1.21875"
+ sodipodi:rx="1.21875"
+ sodipodi:cy="17.28125"
+ sodipodi:cx="15.1875"
+ id="path34778"
+ style="fill:#f3f3f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.48232403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:type="arc" />
+ <path
+ id="path35559"
+ d="M 22.176614,20.718014 L 13.155702,13.140282"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ id="path35561"
+ d="M 19.408614,29.776506 L 22.368655,25.283228"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc" />
+ <path
+ transform="matrix(2.749493,0.000000,0.000000,2.749493,-22.30073,-12.40939)"
+ d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z"
+ sodipodi:ry="0.61871845"
+ sodipodi:rx="0.61871845"
+ sodipodi:cy="7.6932044"
+ sodipodi:cx="16.705399"
+ id="path35563"
+ style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(2.749493,0.000000,0.000000,2.749493,-22.30073,14.80922)"
+ d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z"
+ sodipodi:ry="0.61871845"
+ sodipodi:rx="0.61871845"
+ sodipodi:cy="7.6932044"
+ sodipodi:cx="16.705399"
+ id="path35565"
+ style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(2.749493,0.000000,0.000000,2.749493,-35.91004,1.199890)"
+ d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z"
+ sodipodi:ry="0.61871845"
+ sodipodi:rx="0.61871845"
+ sodipodi:cy="7.6932044"
+ sodipodi:cx="16.705399"
+ id="path35567"
+ style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(2.749493,0.000000,0.000000,2.749493,-8.691448,1.199890)"
+ d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z"
+ sodipodi:ry="0.61871845"
+ sodipodi:rx="0.61871845"
+ sodipodi:cy="7.6932044"
+ sodipodi:cx="16.705399"
+ id="path35569"
+ style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient4309);stroke-width:0.73656511;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ id="path10651"
+ sodipodi:cx="16.25"
+ sodipodi:cy="16.910715"
+ sodipodi:rx="14.910714"
+ sodipodi:ry="14.910714"
+ d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z"
+ transform="matrix(1.357654,0.000000,0.000000,1.357654,1.769896,-0.493735)" />
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:url(#radialGradient278);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block"
+ id="path12511"
+ sodipodi:cx="55"
+ sodipodi:cy="125"
+ sodipodi:rx="14.375"
+ sodipodi:ry="14.375"
+ d="M 69.375 125 A 14.375 14.375 0 1 1 40.625,125 A 14.375 14.375 0 1 1 69.375 125 z"
+ transform="matrix(0.611127,0.000000,0.000000,0.611127,5.544052,-66.92818)"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/stock_new-16.png"
+ inkscape:export-xdpi="33.852203"
+ inkscape:export-ydpi="33.852203" />
+ </g>
+</svg>
diff --git a/tests/auto/gui/image/qicon/image.png b/tests/auto/gui/image/qicon/image.png
new file mode 100644
index 0000000000..8d703640c1
--- /dev/null
+++ b/tests/auto/gui/image/qicon/image.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/qicon.pro b/tests/auto/gui/image/qicon/qicon.pro
new file mode 100644
index 0000000000..cc87fae539
--- /dev/null
+++ b/tests/auto/gui/image/qicon/qicon.pro
@@ -0,0 +1,30 @@
+load(qttest_p4)
+
+QT += widgets
+SOURCES += tst_qicon.cpp
+RESOURCES = tst_qicon.qrc
+
+wince* {
+ QT += xml svg
+ addFiles.files += $$_PRO_FILE_PWD_/*.png
+ addFiles.files += $$_PRO_FILE_PWD_/*.svg
+ addFiles.files += $$_PRO_FILE_PWD_/*.svgz
+ addFiles.files += $$_PRO_FILE_PWD_/tst_qicon.cpp
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+
+ DEPLOYMENT_PLUGIN += qsvg
+ DEFINES += SRCDIR=\\\".\\\"
+} else:symbian {
+ QT += xml svg
+ addFiles.files = *.png tst_qicon.cpp *.svg *.svgz
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+ qt_not_deployed {
+ plugins.files = qsvgicon.dll
+ plugins.path = iconengines
+ DEPLOYMENT += plugins
+ }
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
diff --git a/tests/auto/gui/image/qicon/rect.png b/tests/auto/gui/image/qicon/rect.png
new file mode 100644
index 0000000000..b5d3ecbddf
--- /dev/null
+++ b/tests/auto/gui/image/qicon/rect.png
Binary files differ
diff --git a/tests/auto/gui/image/qicon/rect.svg b/tests/auto/gui/image/qicon/rect.svg
new file mode 100644
index 0000000000..8eb24727be
--- /dev/null
+++ b/tests/auto/gui/image/qicon/rect.svg
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="40px"
+ height="5px"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="test.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="1005"
+ inkscape:window-width="1280"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="13.6"
+ inkscape:cx="20"
+ inkscape:cy="2.5"
+ inkscape:window-x="-4"
+ inkscape:window-y="-4"
+ inkscape:current-layer="svg2" />
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 2.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="40 : 2.5 : 1"
+ inkscape:persp3d-origin="20 : 1.6666667 : 1"
+ id="perspective9" />
+ </defs>
+ <g
+ id="layer1">
+ <rect
+ width="40px"
+ height="5px"
+ x="0px"
+ y="0px"
+ id="rect2393"
+ style="fill:#ff0000" />
+ </g>
+ <rect
+ style="fill:#000000"
+ id="rect2382"
+ width="2"
+ height="2"
+ x="19"
+ y="1.5" />
+</svg>
diff --git a/tests/auto/gui/image/qicon/trash.svg b/tests/auto/gui/image/qicon/trash.svg
new file mode 100644
index 0000000000..c44e4c75a2
--- /dev/null
+++ b/tests/auto/gui/image/qicon/trash.svg
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 10, SVG Export Plug-In . SVG Version: 3.0.0 Build 76) --><svg enable-background="new 0 0 347 348" height="348" i:pageBounds="0 792 612 0" i:rulerOrigin="0 0" i:viewOrigin="131 567" overflow="visible" space="preserve" viewBox="-20 -20 387 388" width="347" xmlns="http://www.w3.org/2000/svg" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" xmlns:graph="http://ns.adobe.com/Graphs/1.0/" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" xmlns:x="http://ns.adobe.com/Extensibility/1.0/" xmlns:xlink="http://www.w3.org/1999/xlink">
+<metadata>
+<rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<cc:Work rdf:about="">
+<dc:title>Keep Tidy Inside</dc:title>
+<dc:description></dc:description>
+<dc:subject>
+<rdf:Bag>
+<rdf:li></rdf:li>
+<rdf:li>symbol</rdf:li>
+<rdf:li>bin</rdf:li>
+<rdf:li>signs_and_symbols</rdf:li>
+<rdf:li>clean</rdf:li>
+<rdf:li>rubish</rdf:li>
+<rdf:li>trash</rdf:li>
+<rdf:li>inside</rdf:li>
+<rdf:li>garbage</rdf:li>
+<rdf:li>sign</rdf:li>
+</rdf:Bag>
+</dc:subject>
+<dc:publisher>
+<cc:Agent rdf:about="http://www.openclipart.org">
+<dc:title>Martin Owens</dc:title>
+</cc:Agent>
+</dc:publisher>
+<dc:creator>
+<cc:Agent>
+<dc:title>Martin Owens</dc:title>
+</cc:Agent>
+</dc:creator>
+<dc:rights>
+<cc:Agent>
+<dc:title>Martin Owens</dc:title>
+</cc:Agent>
+</dc:rights>
+<dc:date></dc:date>
+<dc:format>image/svg+xml</dc:format>
+<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+<cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+<dc:language>en</dc:language>
+</cc:Work>
+<cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+</cc:License>
+</rdf:RDF>
+</metadata>
+<g i:dimmedPercent="50" i:knockout="Off" i:layer="yes" i:rgbTrio="#4F008000FFFF" id="Layer_1">
+<path d="M347,174c0,96.098-77.679,174-173.5,174C77.679,348,0,270.098,0,174 C0,77.902,77.679,0,173.5,0C269.321,0,347,77.902,347,174z" fill="#10A040" i:knockout="Off"/>
+<path d="M238,53c0,13.807-11.864,25-26.5,25S185,66.807,185,53s11.864-25,26.5-25 S238,39.193,238,53z" fill="#FFFFFF" i:knockout="Off"/>
+<path d="M66,175c1.055,6.355,19.333,126.417,19.333,126.417h68.333 c0,0,14.105-122.524,14.333-126.417c6.224-0.622,6.667-13-2-13c-12.164,0-89.205-0.059-98,0S61.167,174.487,66,175z" fill="#FFFFFF" i:knockout="Off"/>
+<path d="M78,141c17.292-5.325,24.179-23.532,27-31c14.513,6.596,40.333,12.265,59,8 c3.683,19.419-28.043,19.31-23,37C132.577,145.705,89.404,167.292,78,141z" fill="#FFFFFF" i:knockout="Off"/>
+<path d="M103,82l139-1c-0.6,3.421,33.633,57.497,29,67c-4.089,0.418-67,5-67,5 c6.109-9.379-13-43-13-43L103,82z" fill="#FFFFFF" i:knockout="Off"/>
+<path d="M270,156l-66-3c0,0-23.565,143.355-24,145s1.855,2.536,3,1s51-82,51-82 s19.754,80.701,20,82s3.721,1.209,4,0S270,156,270,156z" fill="#FFFFFF" i:knockout="Off"/>
+</g>
+</svg>
diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp
new file mode 100644
index 0000000000..4c430f9435
--- /dev/null
+++ b/tests/auto/gui/image/qicon/tst_qicon.cpp
@@ -0,0 +1,781 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QImageReader>
+#include <qicon.h>
+
+#if defined(Q_OS_SYMBIAN)
+#define SRCDIR "."
+#endif
+#include <qiconengine.h>
+
+Q_DECLARE_METATYPE(QSize)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QIcon : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QIcon();
+
+private slots:
+ void init();
+ void cleanup();
+
+ void actualSize_data(); // test with 1 pixmap
+ void actualSize();
+ void actualSize2_data(); // test with 2 pixmaps with different aspect ratio
+ void actualSize2();
+ void svgActualSize();
+ void isNull();
+ void swap();
+ void bestMatch();
+ void cacheKey();
+ void detach();
+ void svg();
+ void addFile();
+ void availableSizes();
+ void name();
+ void streamAvailableSizes_data();
+ void streamAvailableSizes();
+ void fromTheme();
+
+ void task184901_badCache();
+ void task223279_inconsistentAddFile();
+ void task239461_custom_iconengine_crash();
+
+private:
+ bool haveImageFormat(QByteArray const&);
+
+ QString oldCurrentDir;
+
+ const static QIcon staticIcon;
+};
+
+// Creating an icon statically should not cause a crash.
+// But we do not officially support this. See QTBUG-8666
+const QIcon tst_QIcon::staticIcon = QIcon::fromTheme("edit-find");
+
+void tst_QIcon::init()
+{
+ QString srcdir(QLatin1String(SRCDIR));
+ if (!srcdir.isEmpty()) {
+ oldCurrentDir = QDir::current().absolutePath();
+ QDir::setCurrent(srcdir);
+ }
+}
+
+void tst_QIcon::cleanup()
+{
+ if (!oldCurrentDir.isEmpty()) {
+ QDir::setCurrent(oldCurrentDir);
+ }
+}
+
+bool tst_QIcon::haveImageFormat(QByteArray const& desiredFormat)
+{
+ return QImageReader::supportedImageFormats().contains(desiredFormat);
+}
+
+tst_QIcon::tst_QIcon()
+{
+}
+
+void tst_QIcon::actualSize_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QSize>("argument");
+ QTest::addColumn<QSize>("result");
+
+ // square image
+ QTest::newRow("resource0") << ":/image.png" << QSize(128, 128) << QSize(128, 128);
+ QTest::newRow("resource1") << ":/image.png" << QSize( 64, 64) << QSize( 64, 64);
+ QTest::newRow("resource2") << ":/image.png" << QSize( 32, 64) << QSize( 32, 32);
+ QTest::newRow("resource3") << ":/image.png" << QSize( 16, 64) << QSize( 16, 16);
+ QTest::newRow("resource4") << ":/image.png" << QSize( 16, 128) << QSize( 16, 16);
+ QTest::newRow("resource5") << ":/image.png" << QSize( 128, 16) << QSize( 16, 16);
+ QTest::newRow("resource6") << ":/image.png" << QSize( 150, 150) << QSize( 128, 128);
+ // rect image
+ QTest::newRow("resource7") << ":/rect.png" << QSize( 20, 40) << QSize( 20, 40);
+ QTest::newRow("resource8") << ":/rect.png" << QSize( 10, 20) << QSize( 10, 20);
+ QTest::newRow("resource9") << ":/rect.png" << QSize( 15, 50) << QSize( 15, 30);
+ QTest::newRow("resource10") << ":/rect.png" << QSize( 25, 50) << QSize( 20, 40);
+
+ const QString prefix = QLatin1String(SRCDIR) + QLatin1String("/");
+ QTest::newRow("external0") << prefix + "image.png" << QSize(128, 128) << QSize(128, 128);
+ QTest::newRow("external1") << prefix + "image.png" << QSize( 64, 64) << QSize( 64, 64);
+ QTest::newRow("external2") << prefix + "image.png" << QSize( 32, 64) << QSize( 32, 32);
+ QTest::newRow("external3") << prefix + "image.png" << QSize( 16, 64) << QSize( 16, 16);
+ QTest::newRow("external4") << prefix + "image.png" << QSize( 16, 128) << QSize( 16, 16);
+ QTest::newRow("external5") << prefix + "image.png" << QSize( 128, 16) << QSize( 16, 16);
+ QTest::newRow("external6") << prefix + "image.png" << QSize( 150, 150) << QSize( 128, 128);
+ // rect image
+ QTest::newRow("external7") << ":/rect.png" << QSize( 20, 40) << QSize( 20, 40);
+ QTest::newRow("external8") << ":/rect.png" << QSize( 10, 20) << QSize( 10, 20);
+ QTest::newRow("external9") << ":/rect.png" << QSize( 15, 50) << QSize( 15, 30);
+ QTest::newRow("external10") << ":/rect.png" << QSize( 25, 50) << QSize( 20, 40);
+}
+
+void tst_QIcon::actualSize()
+{
+ QFETCH(QString, source);
+ QFETCH(QSize, argument);
+ QFETCH(QSize, result);
+
+ {
+ QPixmap pixmap(source);
+ QIcon icon(pixmap);
+ QCOMPARE(icon.actualSize(argument), result);
+ QCOMPARE(icon.pixmap(argument).size(), result);
+ }
+
+ {
+ QIcon icon(source);
+ QCOMPARE(icon.actualSize(argument), result);
+ QCOMPARE(icon.pixmap(argument).size(), result);
+ }
+}
+
+void tst_QIcon::actualSize2_data()
+{
+ QTest::addColumn<QSize>("argument");
+ QTest::addColumn<QSize>("result");
+
+ // two images - 128x128 and 20x40. Let the games begin
+ QTest::newRow("trivial1") << QSize( 128, 128) << QSize( 128, 128);
+ QTest::newRow("trivial2") << QSize( 20, 40) << QSize( 20, 40);
+
+ // QIcon chooses the one with the smallest area to choose the pixmap
+ QTest::newRow("best1") << QSize( 100, 100) << QSize( 100, 100);
+ QTest::newRow("best2") << QSize( 20, 20) << QSize( 10, 20);
+ QTest::newRow("best3") << QSize( 15, 30) << QSize( 15, 30);
+ QTest::newRow("best4") << QSize( 5, 5) << QSize( 2, 5);
+ QTest::newRow("best5") << QSize( 10, 15) << QSize( 7, 15);
+}
+
+void tst_QIcon::actualSize2()
+{
+ QIcon icon;
+ const QString prefix = QLatin1String(SRCDIR) + QLatin1String("/");
+
+ icon.addPixmap(QPixmap(prefix + "image.png"));
+ icon.addPixmap(QPixmap(prefix + "rect.png"));
+
+ QFETCH(QSize, argument);
+ QFETCH(QSize, result);
+
+ QCOMPARE(icon.actualSize(argument), result);
+ QCOMPARE(icon.pixmap(argument).size(), result);
+}
+
+void tst_QIcon::svgActualSize()
+{
+ if (!haveImageFormat("svg")) {
+ QSKIP("SVG support is not available", SkipAll);
+ }
+
+ const QString prefix = QLatin1String(SRCDIR) + QLatin1String("/");
+ QIcon icon(prefix + "rect.svg");
+ QCOMPARE(icon.actualSize(QSize(16, 16)), QSize(16, 2));
+ QCOMPARE(icon.pixmap(QSize(16, 16)).size(), QSize(16, 2));
+
+ QPixmap p(16, 16);
+ p.fill(Qt::cyan);
+ icon.addPixmap(p);
+
+ QCOMPARE(icon.actualSize(QSize(16, 16)), QSize(16, 16));
+ QCOMPARE(icon.pixmap(QSize(16, 16)).size(), QSize(16, 16));
+
+ QCOMPARE(icon.actualSize(QSize(16, 14)), QSize(16, 2));
+ QCOMPARE(icon.pixmap(QSize(16, 14)).size(), QSize(16, 2));
+}
+
+void tst_QIcon::isNull() {
+ // test default constructor
+ QIcon defaultConstructor;
+ QVERIFY(defaultConstructor.isNull());
+
+ // test copy constructor
+ QVERIFY(QIcon(defaultConstructor).isNull());
+
+ // test pixmap constructor
+ QPixmap nullPixmap;
+ QVERIFY(QIcon(nullPixmap).isNull());
+
+ // test string constructor with empty string
+ QIcon iconEmptyString = QIcon(QString());
+ QVERIFY(iconEmptyString.isNull());
+ QVERIFY(!iconEmptyString.actualSize(QSize(32, 32)).isValid());;
+
+ // test string constructor with non-existing file
+ QIcon iconNoFile = QIcon("imagedoesnotexist");
+ QVERIFY(!iconNoFile.isNull());
+ QVERIFY(!iconNoFile.actualSize(QSize(32, 32)).isValid());
+
+ // test string constructor with non-existing file with suffix
+ QIcon iconNoFileSuffix = QIcon("imagedoesnotexist.png");
+ QVERIFY(!iconNoFileSuffix.isNull());
+ QVERIFY(!iconNoFileSuffix.actualSize(QSize(32, 32)).isValid());
+
+ const QString prefix = QLatin1String(SRCDIR) + QLatin1String("/");
+ // test string constructor with existing file but unsupported format
+ QIcon iconUnsupportedFormat = QIcon(prefix + "tst_qicon.cpp");
+ QVERIFY(!iconUnsupportedFormat.isNull());
+ QVERIFY(!iconUnsupportedFormat.actualSize(QSize(32, 32)).isValid());
+
+ // test string constructor with existing file and supported format
+ QIcon iconSupportedFormat = QIcon(prefix + "image.png");
+ QVERIFY(!iconSupportedFormat.isNull());
+ QVERIFY(iconSupportedFormat.actualSize(QSize(32, 32)).isValid());
+}
+
+void tst_QIcon::swap()
+{
+ QPixmap p1(1, 1), p2(2, 2);
+ p1.fill(Qt::black);
+ p2.fill(Qt::black);
+
+ QIcon i1(p1), i2(p2);
+ const qint64 i1k = i1.cacheKey();
+ const qint64 i2k = i2.cacheKey();
+ QVERIFY(i1k != i2k);
+ i1.swap(i2);
+ QCOMPARE(i1.cacheKey(), i2k);
+ QCOMPARE(i2.cacheKey(), i1k);
+}
+
+void tst_QIcon::bestMatch()
+{
+ QPixmap p1(1, 1);
+ QPixmap p2(2, 2);
+ QPixmap p3(3, 3);
+ QPixmap p4(4, 4);
+ QPixmap p5(5, 5);
+ QPixmap p6(6, 6);
+ QPixmap p7(7, 7);
+ QPixmap p8(8, 8);
+
+ p1.fill(Qt::black);
+ p2.fill(Qt::black);
+ p3.fill(Qt::black);
+ p4.fill(Qt::black);
+ p5.fill(Qt::black);
+ p6.fill(Qt::black);
+ p7.fill(Qt::black);
+ p8.fill(Qt::black);
+
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ QIcon::State state = (j == 0) ? QIcon::On : QIcon::Off;
+ QIcon::State oppositeState = (state == QIcon::On) ? QIcon::Off
+ : QIcon::On;
+ QIcon::Mode mode;
+ QIcon::Mode oppositeMode;
+
+ QIcon icon;
+
+ switch (i) {
+ case 0:
+ default:
+ mode = QIcon::Normal;
+ oppositeMode = QIcon::Active;
+ break;
+ case 1:
+ mode = QIcon::Active;
+ oppositeMode = QIcon::Normal;
+ break;
+ case 2:
+ mode = QIcon::Disabled;
+ oppositeMode = QIcon::Selected;
+ break;
+ case 3:
+ mode = QIcon::Selected;
+ oppositeMode = QIcon::Disabled;
+ }
+
+ /*
+ The test mirrors the code in
+ QPixmapIconEngine::bestMatch(), to make sure that
+ nobody breaks QPixmapIconEngine by mistake. Before
+ you change this test or the code that it tests,
+ please talk to the maintainer if possible.
+ */
+ if (mode == QIcon::Disabled || mode == QIcon::Selected) {
+ icon.addPixmap(p1, oppositeMode, oppositeState);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p1.size());
+
+ icon.addPixmap(p2, oppositeMode, state);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p2.size());
+
+ icon.addPixmap(p3, QIcon::Active, oppositeState);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p3.size());
+
+ icon.addPixmap(p4, QIcon::Normal, oppositeState);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p4.size());
+
+ icon.addPixmap(p5, mode, oppositeState);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p5.size());
+
+ icon.addPixmap(p6, QIcon::Active, state);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p6.size());
+
+ icon.addPixmap(p7, QIcon::Normal, state);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p7.size());
+
+ icon.addPixmap(p8, mode, state);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p8.size());
+ } else {
+ icon.addPixmap(p1, QIcon::Selected, oppositeState);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p1.size());
+
+ icon.addPixmap(p2, QIcon::Disabled, oppositeState);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p2.size());
+
+ icon.addPixmap(p3, QIcon::Selected, state);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p3.size());
+
+ icon.addPixmap(p4, QIcon::Disabled, state);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p4.size());
+
+ icon.addPixmap(p5, oppositeMode, oppositeState);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p5.size());
+
+ icon.addPixmap(p6, mode, oppositeState);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p6.size());
+
+ icon.addPixmap(p7, oppositeMode, state);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p7.size());
+
+ icon.addPixmap(p8, mode, state);
+ QVERIFY(icon.pixmap(100, mode, state).size() == p8.size());
+ }
+ }
+ }
+}
+
+void tst_QIcon::cacheKey()
+{
+ QIcon icon1("image.png");
+ qint64 icon1_key = icon1.cacheKey();
+ QIcon icon2 = icon1;
+
+ QVERIFY(icon2.cacheKey() == icon1.cacheKey());
+ icon2.detach();
+ QVERIFY(icon2.cacheKey() != icon1.cacheKey());
+ QVERIFY(icon1.cacheKey() == icon1_key);
+}
+
+void tst_QIcon::detach()
+{
+ QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0xffff0000);
+ QIcon icon1(QPixmap::fromImage(img));
+ QIcon icon2 = icon1;
+ icon2.addFile("image.png", QSize(64, 64));
+
+ QImage img1 = icon1.pixmap(64, 64).toImage();
+ QImage img2 = icon2.pixmap(64, 64).toImage();
+ QVERIFY(img1 != img2);
+
+ img1 = icon1.pixmap(32, 32).toImage();
+ img2 = icon2.pixmap(32, 32).toImage();
+ QVERIFY(img1 == img2);
+}
+
+void tst_QIcon::svg()
+{
+ if (!haveImageFormat("svg")) {
+ QSKIP("SVG support is not available", SkipAll);
+ }
+ QIcon icon1("heart.svg");
+
+ QVERIFY(!icon1.pixmap(32).isNull());
+ QImage img1 = icon1.pixmap(32).toImage();
+ QVERIFY(!icon1.pixmap(32, QIcon::Disabled).isNull());
+ QImage img2 = icon1.pixmap(32, QIcon::Disabled).toImage();
+
+ icon1.addFile("trash.svg", QSize(), QIcon::Disabled);
+ QVERIFY(!icon1.pixmap(32, QIcon::Disabled).isNull());
+ QImage img3 = icon1.pixmap(32, QIcon::Disabled).toImage();
+ QVERIFY(img3 != img2);
+ QVERIFY(img3 != img1);
+
+ QPixmap pm("image.png");
+ icon1.addPixmap(pm, QIcon::Normal, QIcon::On);
+ QVERIFY(!icon1.pixmap(128, QIcon::Normal, QIcon::On).isNull());
+ QImage img4 = icon1.pixmap(128, QIcon::Normal, QIcon::On).toImage();
+ QVERIFY(img4 != img3);
+ QVERIFY(img4 != img2);
+ QVERIFY(img4 != img1);
+
+ QIcon icon2;
+ icon2.addFile("heart.svg");
+ QVERIFY(icon2.pixmap(57).toImage() == icon1.pixmap(57).toImage());
+
+ QIcon icon3("trash.svg");
+ icon3.addFile("heart.svg");
+ QVERIFY(icon3.pixmap(57).toImage() == icon1.pixmap(57).toImage());
+
+ QIcon icon4("heart.svg");
+ icon4.addFile("image.png", QSize(), QIcon::Active);
+ QVERIFY(!icon4.pixmap(32).isNull());
+ QVERIFY(!icon4.pixmap(32, QIcon::Active).isNull());
+ QVERIFY(icon4.pixmap(32).toImage() == img1);
+ QIcon pmIcon(pm);
+ QVERIFY(icon4.pixmap(pm.size(), QIcon::Active).toImage() == pmIcon.pixmap(pm.size(), QIcon::Active).toImage());
+
+#ifndef QT_NO_COMPRESS
+ QIcon icon5("heart.svgz");
+ QVERIFY(!icon5.pixmap(32).isNull());
+#endif
+}
+
+void tst_QIcon::addFile()
+{
+ QIcon icon;
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png"), QSize(), QIcon::Selected);
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-32.png"), QSize(), QIcon::Selected);
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-128.png"), QSize(), QIcon::Selected);
+
+#ifndef Q_OS_WINCE
+ QVERIFY(icon.pixmap(16, QIcon::Normal).toImage() ==
+ QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png")).toImage());
+ QVERIFY(icon.pixmap(32, QIcon::Normal).toImage() ==
+ QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-32.png")).toImage());
+ QVERIFY(icon.pixmap(128, QIcon::Normal).toImage() ==
+ QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-128.png")).toImage());
+ QVERIFY(icon.pixmap(16, QIcon::Selected).toImage() ==
+ QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png")).toImage());
+ QVERIFY(icon.pixmap(32, QIcon::Selected).toImage() ==
+ QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-32.png")).toImage());
+ QVERIFY(icon.pixmap(128, QIcon::Selected).toImage() ==
+ QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-128.png")).toImage());
+#else
+ // WinCE only includes the 16x16 images for size reasons
+ QVERIFY(icon.pixmap(16, QIcon::Normal).toImage() ==
+ QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png")).toImage());
+ QVERIFY(icon.pixmap(16, QIcon::Selected).toImage() ==
+ QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png")).toImage());
+#endif
+}
+
+static bool sizeLess(const QSize &a, const QSize &b)
+{
+ return a.width() < b.width();
+}
+
+void tst_QIcon::availableSizes()
+{
+ {
+ QIcon icon;
+ icon.addFile("image.png", QSize(32,32));
+ icon.addFile("image.png", QSize(64,64));
+ icon.addFile("image.png", QSize(128,128));
+ icon.addFile("image.png", QSize(256,256), QIcon::Disabled);
+ icon.addFile("image.png", QSize(16,16), QIcon::Normal, QIcon::On);
+
+ QList<QSize> availableSizes = icon.availableSizes();
+ QCOMPARE(availableSizes.size(), 3);
+ qSort(availableSizes.begin(), availableSizes.end(), sizeLess);
+ QCOMPARE(availableSizes.at(0), QSize(32,32));
+ QCOMPARE(availableSizes.at(1), QSize(64,64));
+ QCOMPARE(availableSizes.at(2), QSize(128,128));
+
+ availableSizes = icon.availableSizes(QIcon::Disabled);
+ QCOMPARE(availableSizes.size(), 1);
+ QCOMPARE(availableSizes.at(0), QSize(256,256));
+
+ availableSizes = icon.availableSizes(QIcon::Normal, QIcon::On);
+ QCOMPARE(availableSizes.size(), 1);
+ QCOMPARE(availableSizes.at(0), QSize(16,16));
+ }
+
+ if (haveImageFormat("svg")) {
+ // checks that there are no availableSizes for scalable images.
+ QIcon icon("heart.svg");
+ QList<QSize> availableSizes = icon.availableSizes();
+ QVERIFY(availableSizes.isEmpty());
+ }
+
+ if (haveImageFormat("svg")) {
+ // even if an a scalable image contain added pixmaps,
+ // availableSizes still should be empty.
+ QIcon icon("heart.svg");
+ icon.addFile("image.png", QSize(32,32));
+ QList<QSize> availableSizes = icon.availableSizes();
+ QVERIFY(availableSizes.isEmpty());
+ }
+
+ {
+ // we try to load an icon from resources
+ QIcon icon(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"));
+ QList<QSize> availableSizes = icon.availableSizes();
+ QCOMPARE(availableSizes.size(), 1);
+ QCOMPARE(availableSizes.at(0), QSize(16, 16));
+ }
+
+ {
+ // load an icon from binary data.
+ QPixmap pix;
+ QFile file(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"));
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ uchar *data = file.map(0, file.size());
+ QVERIFY(data != 0);
+ pix.loadFromData(data, file.size());
+ QIcon icon(pix);
+
+ QList<QSize> availableSizes = icon.availableSizes();
+ QCOMPARE(availableSizes.size(), 1);
+ QCOMPARE(availableSizes.at(0), QSize(16,16));
+ }
+
+ {
+ // there shouldn't be available sizes for invalid images!
+ QVERIFY(QIcon(QLatin1String("")).availableSizes().isEmpty());
+ QVERIFY(QIcon(QLatin1String("non-existing.png")).availableSizes().isEmpty());
+ }
+}
+
+void tst_QIcon::name()
+{
+ {
+ // No name if icon does not come from a theme
+ QIcon icon(":/image.png");
+ QString name = icon.name();
+ QVERIFY(name.isEmpty());
+ }
+
+ {
+ // Getting the name of an icon coming from a theme should work
+ QString searchPath = QLatin1String(":/icons");
+ QIcon::setThemeSearchPaths(QStringList() << searchPath);
+ QString themeName("testtheme");
+ QIcon::setThemeName(themeName);
+
+ QIcon icon = QIcon::fromTheme("appointment-new");
+ QString name = icon.name();
+ QCOMPARE(name, QLatin1String("appointment-new"));
+ }
+}
+
+void tst_QIcon::streamAvailableSizes_data()
+{
+ QTest::addColumn<QIcon>("icon");
+
+ QIcon icon;
+ icon.addFile(":/image.png", QSize(32,32));
+ QTest::newRow( "32x32" ) << icon;
+ icon.addFile(":/image.png", QSize(64,64));
+ QTest::newRow( "64x64" ) << icon;
+ icon.addFile(":/image.png", QSize(128,128));
+ QTest::newRow( "128x128" ) << icon;
+ icon.addFile(":/image.png", QSize(256,256));
+ QTest::newRow( "256x256" ) << icon;
+}
+
+void tst_QIcon::streamAvailableSizes()
+{
+ QFETCH(QIcon, icon);
+
+ QByteArray ba;
+ // write to QByteArray
+ {
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream stream(&buffer);
+ stream << icon;
+ }
+
+ // read from QByteArray
+ {
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::ReadOnly);
+ QDataStream stream(&buffer);
+ QIcon i;
+ stream >> i;
+ QCOMPARE(i.isNull(), icon.isNull());
+ QCOMPARE(i.availableSizes(), icon.availableSizes());
+ }
+}
+
+
+static inline bool operator<(const QSize &lhs, const QSize &rhs)
+{
+ if (lhs.width() < rhs.width())
+ return true;
+ else if (lhs.width() == lhs.width())
+ return lhs.height() < lhs.height();
+ return false;
+}
+
+void tst_QIcon::task184901_badCache()
+{
+ QPixmap pm("image.png");
+ QIcon icon(pm);
+
+ //the disabled icon must have an effect (grayed)
+ QVERIFY(icon.pixmap(32, QIcon::Normal).toImage() != icon.pixmap(32, QIcon::Disabled).toImage());
+
+ icon.addPixmap(pm, QIcon::Disabled);
+ //the disabled icon must now be the same as the normal one.
+ QVERIFY( icon.pixmap(32, QIcon::Normal).toImage() == icon.pixmap(32, QIcon::Disabled).toImage() );
+}
+
+void tst_QIcon::fromTheme()
+{
+ QString searchPath = QLatin1String(":/icons");
+ QIcon::setThemeSearchPaths(QStringList() << searchPath);
+ QVERIFY(QIcon::themeSearchPaths().size() == 1);
+ QCOMPARE(searchPath, QIcon::themeSearchPaths()[0]);
+
+ QString themeName("testtheme");
+ QIcon::setThemeName(themeName);
+ QCOMPARE(QIcon::themeName(), themeName);
+
+ // Test normal icon
+ QIcon appointmentIcon = QIcon::fromTheme("appointment-new");
+ QVERIFY(!appointmentIcon.isNull());
+ QVERIFY(!appointmentIcon.availableSizes(QIcon::Normal, QIcon::Off).isEmpty());
+ QVERIFY(appointmentIcon.availableSizes().contains(QSize(16, 16)));
+ QVERIFY(appointmentIcon.availableSizes().contains(QSize(32, 32)));
+ QVERIFY(appointmentIcon.availableSizes().contains(QSize(22, 22)));
+
+ // Test icon from parent theme
+ QIcon abIcon = QIcon::fromTheme("address-book-new");
+ QVERIFY(!abIcon.isNull());
+ QVERIFY(QIcon::hasThemeIcon("address-book-new"));
+ QVERIFY(!abIcon.availableSizes().isEmpty());
+
+ // Test non existing icon
+ QIcon noIcon = QIcon::fromTheme("broken-icon");
+ QVERIFY(noIcon.isNull());
+ QVERIFY(!QIcon::hasThemeIcon("broken-icon"));
+
+ // Test non existing icon with fallback
+ noIcon = QIcon::fromTheme("broken-icon", abIcon);
+ QVERIFY(noIcon.cacheKey() == abIcon.cacheKey());
+
+ // Test svg-only icon
+ noIcon = QIcon::fromTheme("svg-icon", abIcon);
+ QVERIFY(!noIcon.availableSizes().isEmpty());
+
+ QByteArray ba;
+ // write to QByteArray
+ {
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream stream(&buffer);
+ stream << abIcon;
+ }
+
+ // read from QByteArray
+ {
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::ReadOnly);
+ QDataStream stream(&buffer);
+ QIcon i;
+ stream >> i;
+ QCOMPARE(i.isNull(), abIcon.isNull());
+ QCOMPARE(i.availableSizes(), abIcon.availableSizes());
+ }
+
+ // Make sure setting the theme name clears the state
+ QIcon::setThemeName("");
+ abIcon = QIcon::fromTheme("address-book-new");
+ QVERIFY(abIcon.isNull());
+}
+
+
+void tst_QIcon::task223279_inconsistentAddFile()
+{
+ QIcon icon1;
+ icon1.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"));
+ icon1.addFile(QLatin1String("IconThatDoesntExist"), QSize(32, 32));
+ QPixmap pm1 = icon1.pixmap(32, 32);
+
+ QIcon icon2;
+ icon2.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"));
+ icon2.addFile(QLatin1String("IconThatDoesntExist"));
+ QPixmap pm2 = icon1.pixmap(32, 32);
+
+ QCOMPARE(pm1.isNull(), false);
+ QCOMPARE(pm1.size(), QSize(16,16));
+ QCOMPARE(pm1.isNull(), pm2.isNull());
+ QCOMPARE(pm1.size(), pm2.size());
+}
+
+
+// During detach, v2 engines are cloned, while v1 engines are only
+// passed on, so v1 engines need to be referenced counted. This test
+// verifies that the engine is destroyed once and only once.
+
+class IconEngine : public QIconEngine
+{
+public:
+ ~IconEngine() { destructorCalled++; }
+ virtual void paint(QPainter *, const QRect &, QIcon::Mode, QIcon::State) { }
+ static int destructorCalled;
+};
+int IconEngine::destructorCalled = 0;
+
+void tst_QIcon::task239461_custom_iconengine_crash()
+{
+ QIconEngine *engine = new IconEngine();
+ {
+ QIcon icon(engine);
+ QIcon icon2 = icon;
+
+ QPixmap pixmap(32, 32);
+ icon.addPixmap(pixmap);
+ }
+ QCOMPARE(IconEngine::destructorCalled, 1);
+}
+
+
+QTEST_MAIN(tst_QIcon)
+#include "tst_qicon.moc"
diff --git a/tests/auto/gui/image/qicon/tst_qicon.qrc b/tests/auto/gui/image/qicon/tst_qicon.qrc
new file mode 100644
index 0000000000..7925a33c84
--- /dev/null
+++ b/tests/auto/gui/image/qicon/tst_qicon.qrc
@@ -0,0 +1,20 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/">
+<file>image.png</file>
+<file>rect.png</file>
+<file>./icons/testtheme/16x16/actions/appointment-new.png</file>
+<file>./icons/testtheme/22x22/actions/appointment-new.png</file>
+<file>./icons/testtheme/32x32/actions/appointment-new.png</file>
+<file>./icons/testtheme/index.theme</file>
+<file>./icons/testtheme/scalable/actions/svg-only.svg</file>
+<file>./icons/themeparent/16x16/actions/address-book-new.png</file>
+<file>./icons/themeparent/16x16/actions/appointment-new.png</file>
+<file>./icons/themeparent/22x22/actions/address-book-new.png</file>
+<file>./icons/themeparent/22x22/actions/appointment-new.png</file>
+<file>./icons/themeparent/32x32/actions/address-book-new.png</file>
+<file>./icons/themeparent/32x32/actions/appointment-new.png</file>
+<file>./icons/themeparent/index.theme</file>
+<file>./icons/themeparent/scalable/actions/address-book-new.svg</file>
+<file>./icons/themeparent/scalable/actions/appointment-new.svg</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/gui/image/qimage/.gitignore b/tests/auto/gui/image/qimage/.gitignore
new file mode 100644
index 0000000000..d8afbffa72
--- /dev/null
+++ b/tests/auto/gui/image/qimage/.gitignore
@@ -0,0 +1 @@
+tst_qimage
diff --git a/tests/auto/gui/image/qimage/images/image.bmp b/tests/auto/gui/image/qimage/images/image.bmp
new file mode 100644
index 0000000000..39640e43e9
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimage/images/image.gif b/tests/auto/gui/image/qimage/images/image.gif
new file mode 100644
index 0000000000..2c5a7f87e9
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimage/images/image.ico b/tests/auto/gui/image/qimage/images/image.ico
new file mode 100644
index 0000000000..7312d20f87
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.ico
Binary files differ
diff --git a/tests/auto/gui/image/qimage/images/image.jpg b/tests/auto/gui/image/qimage/images/image.jpg
new file mode 100644
index 0000000000..7611322b1b
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimage/images/image.pbm b/tests/auto/gui/image/qimage/images/image.pbm
new file mode 100644
index 0000000000..67e5efa3e9
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.pbm
@@ -0,0 +1,8 @@
+P1
+16 6
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
diff --git a/tests/auto/gui/image/qimage/images/image.pgm b/tests/auto/gui/image/qimage/images/image.pgm
new file mode 100644
index 0000000000..443bf40964
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.pgm
@@ -0,0 +1,10 @@
+P2
+24 7
+15
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
+0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
+0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
+0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
+0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
diff --git a/tests/auto/gui/image/qimage/images/image.png b/tests/auto/gui/image/qimage/images/image.png
new file mode 100644
index 0000000000..7d4890a7ff
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.png
Binary files differ
diff --git a/tests/auto/gui/image/qimage/images/image.ppm b/tests/auto/gui/image/qimage/images/image.ppm
new file mode 100644
index 0000000000..2a5640e189
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.ppm
@@ -0,0 +1,7 @@
+P3
+4 4
+15
+ 0 0 0 0 0 0 0 0 0 15 0 15
+ 0 0 0 0 15 7 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 15 7 0 0 0
+15 0 15 0 0 0 0 0 0 0 0 0 \ No newline at end of file
diff --git a/tests/auto/gui/image/qimage/images/image.tif b/tests/auto/gui/image/qimage/images/image.tif
new file mode 100644
index 0000000000..ee0637cf25
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimage/images/image.xbm b/tests/auto/gui/image/qimage/images/image.xbm
new file mode 100644
index 0000000000..d0e0fcf2c1
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.xbm
@@ -0,0 +1,5 @@
+#define Cloverleaf_width 9
+#define Cloverleaf_height 9
+static unsigned char Cloverleaf_bits[] = {
+ 0xc6, 0x00, 0x29, 0x01, 0x29, 0x01, 0xfe, 0x00, 0x28, 0x00, 0xfe, 0x00,
+ 0x29, 0x01, 0x29, 0x01, 0xc6, 0x00, };
diff --git a/tests/auto/gui/image/qimage/images/image.xpm b/tests/auto/gui/image/qimage/images/image.xpm
new file mode 100644
index 0000000000..264ba401e6
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/image.xpm
@@ -0,0 +1,261 @@
+/* XPM */
+static char * foo_xpm[] = {
+"256 256 2 1",
+" c None",
+". c #E22626",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................",
+"................................................................................................................................................................................................................................................................"};
diff --git a/tests/auto/gui/image/qimage/qimage.pro b/tests/auto/gui/image/qimage/qimage.pro
new file mode 100644
index 0000000000..b517bc1237
--- /dev/null
+++ b/tests/auto/gui/image/qimage/qimage.pro
@@ -0,0 +1,23 @@
+load(qttest_p4)
+SOURCES += tst_qimage.cpp
+
+QT += core-private gui-private
+
+wince*: {
+ addImages.files = images/*
+ addImages.path = images
+ DEPLOYMENT += addImages
+ DEFINES += SRCDIR=\\\".\\\"
+} else:symbian {
+ TARGET.EPOCHEAPSIZE = 0x200000 0x800000
+ addImages.files = images/*
+ addImages.path = images
+ DEPLOYMENT += addImages
+ qt_not_deployed {
+ imagePlugins.files = qjpeg.dll qgif.dll qmng.dll qtiff.dll qico.dll
+ imagePlugins.path = imageformats
+ DEPLOYMENT += imagePlugins
+ }
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
new file mode 100644
index 0000000000..dce2957ae4
--- /dev/null
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -0,0 +1,2014 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qimage.h>
+#include <qimagereader.h>
+#include <qlist.h>
+#include <qmatrix.h>
+#include <stdio.h>
+
+#include <qpainter.h>
+#include <private/qdrawhelper_p.h>
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+#if defined(Q_OS_SYMBIAN)
+# define SRCDIR ""
+#endif
+
+Q_DECLARE_METATYPE(QImage::Format)
+Q_DECLARE_METATYPE(Qt::GlobalColor)
+
+class tst_QImage : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QImage();
+
+private slots:
+ void swap();
+ void create();
+ void createInvalidXPM();
+ void createFromUChar();
+ void formatHandlersInput_data();
+ void formatHandlersInput();
+
+ void setAlphaChannel_data();
+ void setAlphaChannel();
+
+ void alphaChannel();
+
+ void convertToFormat_data();
+ void convertToFormat();
+
+ void convertToFormatRgb888ToRGB32();
+
+ void createAlphaMask_data();
+ void createAlphaMask();
+#ifndef QT_NO_IMAGE_HEURISTIC_MASK
+ void createHeuristicMask();
+#endif
+
+ void dotsPerMeterZero();
+
+ void convertToFormatPreserveDotsPrMeter();
+#ifndef QT_NO_IMAGE_TEXT
+ void convertToFormatPreserveText();
+#endif
+
+ void rotate_data();
+ void rotate();
+
+ void copy();
+
+ void setPixel_data();
+ void setPixel();
+
+ void setColorCount();
+ void setColor();
+
+ void rasterClipping();
+
+ void pointOverloads();
+ void destructor();
+ void cacheKey();
+
+ void smoothScale();
+ void smoothScale2();
+ void smoothScale3();
+
+ void smoothScaleBig();
+ void smoothScaleAlpha();
+
+ void transformed_data();
+ void transformed();
+ void transformed2();
+
+ void scaled();
+
+ void paintEngine();
+ void setAlphaChannelWhilePainting();
+
+ void smoothScaledSubImage();
+
+ void nullSize_data();
+ void nullSize();
+
+ void premultipliedAlphaConsistency();
+
+ void compareIndexed();
+
+ void fillColor_data();
+ void fillColor();
+
+ void fillColorWithAlpha();
+
+ void rgbSwapped_data();
+ void rgbSwapped();
+
+ void deepCopyWhenPaintingActive();
+ void scaled_QTBUG19157();
+};
+
+tst_QImage::tst_QImage()
+
+{
+}
+
+void tst_QImage::swap()
+{
+ QImage i1( 16, 16, QImage::Format_RGB32 ), i2( 32, 32, QImage::Format_RGB32 );
+ i1.fill( Qt::white );
+ i2.fill( Qt::black );
+ const qint64 i1k = i1.cacheKey();
+ const qint64 i2k = i2.cacheKey();
+ i1.swap(i2);
+ QCOMPARE(i1.cacheKey(), i2k);
+ QCOMPARE(i1.size(), QSize(32,32));
+ QCOMPARE(i2.cacheKey(), i1k);
+ QCOMPARE(i2.size(), QSize(16,16));
+}
+
+// Test if QImage (or any functions called from QImage) throws an
+// exception when creating an extremely large image.
+// QImage::create() should return "false" in this case.
+void tst_QImage::create()
+{
+ bool cr = true;
+#if !defined(Q_WS_QWS) && !defined(Q_OS_WINCE)
+ QT_TRY {
+#endif
+ //QImage image(7000000, 7000000, 8, 256, QImage::IgnoreEndian);
+ QImage image(7000000, 7000000, QImage::Format_Indexed8);
+ image.setColorCount(256);
+ cr = !image.isNull();
+#if !defined(Q_WS_QWS) && !defined(Q_OS_WINCE)
+ } QT_CATCH (...) {
+ }
+#endif
+ QVERIFY( !cr );
+}
+
+void tst_QImage::createInvalidXPM()
+{
+ QTest::ignoreMessage(QtWarningMsg, "QImage::QImage(), XPM is not supported");
+ const char *xpm[] = {""};
+ QImage invalidXPM(xpm);
+ QVERIFY(invalidXPM.isNull());
+}
+
+void tst_QImage::createFromUChar()
+{
+ uchar data[] = {
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ 0xFF,
+#endif
+ 1,1,1, 0xFF, 2,2,2, 0xFF, 3,3,3, 0xFF, 4,4,4,
+#if Q_BYTE_ORDER != Q_BIG_ENDIAN
+ 0xFF,
+#endif
+ };
+
+ // When the data is const, nothing you do to the image will change the source data.
+ QImage i1((const uchar*)data, 2, 2, 8, QImage::Format_RGB32);
+ QCOMPARE(i1.pixel(0,0), 0xFF010101U);
+ QCOMPARE(i1.pixel(1,0), 0xFF020202U);
+ QCOMPARE(i1.pixel(0,1), 0xFF030303U);
+ QCOMPARE(i1.pixel(1,1), 0xFF040404U);
+ {
+ QImage i(i1);
+ i.setPixel(0,0,5);
+ }
+ QCOMPARE(i1.pixel(0,0), 0xFF010101U);
+ QCOMPARE(*(QRgb*)data, 0xFF010101U);
+ *((QRgb*)i1.bits()) = 7U;
+ QCOMPARE(i1.pixel(0,0), 7U);
+ QCOMPARE(*(QRgb*)data, 0xFF010101U);
+
+ // Changing copies should not change the original image or data.
+ {
+ QImage i(i1);
+ i.setPixel(0,0,5);
+ QCOMPARE(*(QRgb*)data, 0xFF010101U);
+ i1.setPixel(0,0,9);
+ QCOMPARE(i1.pixel(0,0), 0xFF000009U);
+ QCOMPARE(i.pixel(0,0), 0xFF000005U);
+ }
+ QCOMPARE(i1.pixel(0,0), 0xFF000009U);
+
+ // When the data is non-const, nothing you do to copies of the image will change the source data,
+ // but changing the image (here via bits()) will change the source data.
+ QImage i2((uchar*)data, 2, 2, 8, QImage::Format_RGB32);
+ QCOMPARE(i2.pixel(0,0), 0xFF010101U);
+ QCOMPARE(i2.pixel(1,0), 0xFF020202U);
+ QCOMPARE(i2.pixel(0,1), 0xFF030303U);
+ QCOMPARE(i2.pixel(1,1), 0xFF040404U);
+ {
+ QImage i(i2);
+ i.setPixel(0,0,5);
+ }
+ QCOMPARE(i2.pixel(0,0), 0xFF010101U);
+ QCOMPARE(*(QRgb*)data, 0xFF010101U);
+ *((QRgb*)i2.bits()) = 7U;
+ QCOMPARE(i2.pixel(0,0), 7U);
+ QCOMPARE(*(QRgb*)data, 7U);
+
+ // Changing the data will change the image in either case.
+ QImage i3((uchar*)data, 2, 2, 8, QImage::Format_RGB32);
+ QImage i4((const uchar*)data, 2, 2, 8, QImage::Format_RGB32);
+ *(QRgb*)data = 6U;
+ QCOMPARE(i3.pixel(0,0), 6U);
+ QCOMPARE(i4.pixel(0,0), 6U);
+}
+
+void tst_QImage::formatHandlersInput_data()
+{
+ QTest::addColumn<QString>("testFormat");
+ QTest::addColumn<QString>("testFile");
+ #ifdef Q_OS_SYMBIAN
+ const QString prefix = QLatin1String(SRCDIR) + "images/";
+ #else
+ const QString prefix = QLatin1String(SRCDIR) + "/images/";
+ #endif
+
+ // add a new line here when a file is added
+ QTest::newRow("ICO") << "ICO" << prefix + "image.ico";
+ QTest::newRow("PNG") << "PNG" << prefix + "image.png";
+ QTest::newRow("GIF") << "GIF" << prefix + "image.gif";
+ QTest::newRow("BMP") << "BMP" << prefix + "image.bmp";
+ QTest::newRow("JPEG") << "JPEG" << prefix + "image.jpg";
+ QTest::newRow("PBM") << "PBM" << prefix + "image.pbm";
+ QTest::newRow("PGM") << "PGM" << prefix + "image.pgm";
+ QTest::newRow("PPM") << "PPM" << prefix + "image.ppm";
+ QTest::newRow("XBM") << "XBM" << prefix + "image.xbm";
+ QTest::newRow("XPM") << "XPM" << prefix + "image.xpm";
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("TIFF") << "TIFF" << prefix + "image.tif";
+#endif
+}
+
+void tst_QImage::formatHandlersInput()
+{
+ QFETCH(QString, testFormat);
+ QFETCH(QString, testFile);
+ QList<QByteArray> formats = QImageReader::supportedImageFormats();
+ // qDebug("Image input formats : %s", formats.join(" | ").latin1());
+
+ bool formatSupported = false;
+ for (QList<QByteArray>::Iterator it = formats.begin(); it != formats.end(); ++it) {
+ if (*it == testFormat.toLower()) {
+ formatSupported = true;
+ break;
+ }
+ }
+ if (formatSupported) {
+// qDebug(QImage::imageFormat(testFile));
+ QCOMPARE(testFormat.toLatin1().toLower(), QImageReader::imageFormat(testFile));
+ } else {
+ QString msg = "Format not supported : ";
+ QSKIP(QString(msg + testFormat).toLatin1(), SkipSingle);
+ }
+}
+
+void tst_QImage::setAlphaChannel_data()
+{
+ QTest::addColumn<int>("red");
+ QTest::addColumn<int>("green");
+ QTest::addColumn<int>("blue");
+ QTest::addColumn<int>("alpha");
+ QTest::addColumn<bool>("gray");
+
+ QTest::newRow("red at 0%, gray") << 255 << 0 << 0 << 0 << true;
+ QTest::newRow("red at 25%, gray") << 255 << 0 << 0 << 63 << true;
+ QTest::newRow("red at 50%, gray") << 255 << 0 << 0 << 127 << true;
+ QTest::newRow("red at 100%, gray") << 255 << 0 << 0 << 191 << true;
+ QTest::newRow("red at 0%, 32bit") << 255 << 0 << 0 << 0 << false;
+ QTest::newRow("red at 25%, 32bit") << 255 << 0 << 0 << 63 << false;
+ QTest::newRow("red at 50%, 32bit") << 255 << 0 << 0 << 127 << false;
+ QTest::newRow("red at 100%, 32bit") << 255 << 0 << 0 << 191 << false;
+
+ QTest::newRow("green at 0%, gray") << 0 << 255 << 0 << 0 << true;
+ QTest::newRow("green at 25%, gray") << 0 << 255 << 0 << 63 << true;
+ QTest::newRow("green at 50%, gray") << 0 << 255 << 0 << 127 << true;
+ QTest::newRow("green at 100%, gray") << 0 << 255 << 0 << 191 << true;
+ QTest::newRow("green at 0%, 32bit") << 0 << 255 << 0 << 0 << false;
+ QTest::newRow("green at 25%, 32bit") << 0 << 255 << 0 << 63 << false;
+ QTest::newRow("green at 50%, 32bit") << 0 << 255 << 0 << 127 << false;
+ QTest::newRow("green at 100%, 32bit") << 0 << 255 << 0 << 191 << false;
+
+ QTest::newRow("blue at 0%, gray") << 0 << 0 << 255 << 0 << true;
+ QTest::newRow("blue at 25%, gray") << 0 << 0 << 255 << 63 << true;
+ QTest::newRow("blue at 50%, gray") << 0 << 0 << 255 << 127 << true;
+ QTest::newRow("blue at 100%, gray") << 0 << 0 << 255 << 191 << true;
+ QTest::newRow("blue at 0%, 32bit") << 0 << 0 << 255 << 0 << false;
+ QTest::newRow("blue at 25%, 32bit") << 0 << 0 << 255 << 63 << false;
+ QTest::newRow("blue at 50%, 32bit") << 0 << 0 << 255 << 127 << false;
+ QTest::newRow("blue at 100%, 32bit") << 0 << 0 << 255 << 191 << false;
+}
+
+void tst_QImage::setAlphaChannel()
+{
+ QFETCH(int, red);
+ QFETCH(int, green);
+ QFETCH(int, blue);
+ QFETCH(int, alpha);
+ QFETCH(bool, gray);
+
+ int width = 100;
+ int height = 100;
+
+ QImage image(width, height, QImage::Format_RGB32);
+ image.fill(qRgb(red, green, blue));
+
+ // Create the alpha channel
+ QImage alphaChannel;
+ if (gray) {
+ alphaChannel = QImage(width, height, QImage::Format_Indexed8);
+ alphaChannel.setColorCount(256);
+ for (int i=0; i<256; ++i)
+ alphaChannel.setColor(i, qRgb(i, i, i));
+ alphaChannel.fill(alpha);
+ } else {
+ alphaChannel = QImage(width, height, QImage::Format_ARGB32);
+ alphaChannel.fill(qRgb(alpha, alpha, alpha));
+ }
+
+ image.setAlphaChannel(alphaChannel);
+ image = image.convertToFormat(QImage::Format_ARGB32);
+ QVERIFY(image.format() == QImage::Format_ARGB32);
+
+ // alpha of 0 becomes black at a=0 due to premultiplication
+ QRgb pixel = alpha == 0 ? 0 : qRgba(red, green, blue, alpha);
+ bool allPixelsOK = true;
+ for (int y=0; y<height; ++y) {
+ for (int x=0; x<width; ++x) {
+ allPixelsOK &= image.pixel(x, y) == pixel;
+ }
+ }
+ QVERIFY(allPixelsOK);
+
+ QImage outAlpha = image.alphaChannel();
+ QCOMPARE(outAlpha.size(), image.size());
+
+ bool allAlphaOk = true;
+ for (int y=0; y<height; ++y) {
+ for (int x=0; x<width; ++x) {
+ allAlphaOk &= outAlpha.pixelIndex(x, y) == alpha;
+ }
+ }
+ QVERIFY(allAlphaOk);
+
+}
+
+void tst_QImage::alphaChannel()
+{
+ QImage img(10, 10, QImage::Format_Mono);
+ img.setColor(0, Qt::transparent);
+ img.setColor(1, Qt::black);
+ img.fill(0);
+
+ QPainter p(&img);
+ p.fillRect(2, 2, 6, 6, Qt::black);
+ p.end();
+
+ QCOMPARE(img.alphaChannel(), img.convertToFormat(QImage::Format_ARGB32).alphaChannel());
+}
+
+void tst_QImage::convertToFormat_data()
+{
+ QTest::addColumn<int>("inFormat");
+ QTest::addColumn<uint>("inPixel");
+ QTest::addColumn<int>("resFormat");
+ QTest::addColumn<uint>("resPixel");
+
+ QTest::newRow("red rgb32 -> argb32") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_ARGB32) << 0xffff0000;
+ QTest::newRow("green rgb32 -> argb32") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_ARGB32) << 0xff00ff00;
+ QTest::newRow("blue rgb32 -> argb32") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_ARGB32) << 0xff0000ff;
+
+ QTest::newRow("red rgb32 -> rgb16") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_RGB16) << 0xffff0000;
+ QTest::newRow("green rgb32 -> rgb16") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_RGB16) << 0xff00ff00;
+ QTest::newRow("blue rgb32 -> rgb16") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_RGB16) << 0xff0000ff;
+ QTest::newRow("funky rgb32 -> rgb16") << int(QImage::Format_RGB32) << 0xfff0c080
+ << int(QImage::Format_RGB16) << 0xfff7c384;
+
+ QTest::newRow("red rgb32 -> argb32_pm") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_ARGB32_Premultiplied) << 0xffff0000;
+ QTest::newRow("green rgb32 -> argb32_pm") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_ARGB32_Premultiplied) <<0xff00ff00;
+ QTest::newRow("blue rgb32 -> argb32_pm") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_ARGB32_Premultiplied) << 0xff0000ff;
+
+ QTest::newRow("semired argb32 -> pm") << int(QImage::Format_ARGB32) << 0x7fff0000u
+ << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u;
+ QTest::newRow("semigreen argb32 -> pm") << int(QImage::Format_ARGB32) << 0x7f00ff00u
+ << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u;
+ QTest::newRow("semiblue argb32 -> pm") << int(QImage::Format_ARGB32) << 0x7f0000ffu
+ << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu;
+ QTest::newRow("semiwhite argb32 -> pm") << int(QImage::Format_ARGB32) << 0x7fffffffu
+ << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu;
+ QTest::newRow("semiblack argb32 -> pm") << int(QImage::Format_ARGB32) << 0x7f000000u
+ << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u;
+
+ QTest::newRow("semired pm -> argb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u
+ << int(QImage::Format_ARGB32) << 0x7fff0000u;
+ QTest::newRow("semigreen pm -> argb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u
+ << int(QImage::Format_ARGB32) << 0x7f00ff00u;
+ QTest::newRow("semiblue pm -> argb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu
+ << int(QImage::Format_ARGB32) << 0x7f0000ffu;
+ QTest::newRow("semiwhite pm -> argb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu
+ << int(QImage::Format_ARGB32) << 0x7fffffffu;
+ QTest::newRow("semiblack pm -> argb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u
+ << int(QImage::Format_ARGB32) << 0x7f000000u;
+
+ QTest::newRow("semired pm -> rgb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u
+ << int(QImage::Format_RGB32) << 0xffff0000u;
+ QTest::newRow("semigreen pm -> rgb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u
+ << int(QImage::Format_RGB32) << 0xff00ff00u;
+ QTest::newRow("semiblue pm -> rgb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu
+ << int(QImage::Format_RGB32) << 0xff0000ffu;
+ QTest::newRow("semiwhite pm -> rgb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu
+ << int(QImage::Format_RGB32) << 0xffffffffu;
+ QTest::newRow("semiblack pm -> rgb32") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u
+ << int(QImage::Format_RGB32) << 0xff000000u;
+
+ QTest::newRow("semired argb32 -> rgb32") << int(QImage::Format_ARGB32) << 0x7fff0000u
+ << int(QImage::Format_RGB32) << 0xffff0000u;
+ QTest::newRow("semigreen argb32 -> rgb32") << int(QImage::Format_ARGB32) << 0x7f00ff00u
+ << int(QImage::Format_RGB32) << 0xff00ff00u;
+ QTest::newRow("semiblue argb32 -> rgb32") << int(QImage::Format_ARGB32) << 0x7f0000ffu
+ << int(QImage::Format_RGB32) << 0xff0000ffu;
+ QTest::newRow("semiwhite argb -> rgb32") << int(QImage::Format_ARGB32) << 0x7fffffffu
+ << int(QImage::Format_RGB32) << 0xffffffffu;
+ QTest::newRow("semiblack argb -> rgb32") << int(QImage::Format_ARGB32) << 0x7f000000u
+ << int(QImage::Format_RGB32) << 0xff000000u;
+
+ QTest::newRow("black mono -> rgb32") << int(QImage::Format_Mono) << 0x00000000u
+ << int(QImage::Format_RGB32) << 0xff000000u;
+
+ QTest::newRow("white mono -> rgb32") << int(QImage::Format_Mono) << 0x00000001u
+ << int(QImage::Format_RGB32) << 0xffffffffu;
+ QTest::newRow("red rgb16 -> argb32") << int(QImage::Format_RGB16) << 0xffff0000
+ << int(QImage::Format_ARGB32) << 0xffff0000;
+ QTest::newRow("green rgb16 -> argb32") << int(QImage::Format_RGB16) << 0xff00ff00
+ << int(QImage::Format_ARGB32) << 0xff00ff00;
+ QTest::newRow("blue rgb16 -> argb32") << int(QImage::Format_RGB16) << 0xff0000ff
+ << int(QImage::Format_ARGB32) << 0xff0000ff;
+ QTest::newRow("red rgb16 -> rgb16") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_RGB16) << 0xffff0000;
+ QTest::newRow("green rgb16 -> rgb16") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_RGB16) << 0xff00ff00;
+ QTest::newRow("blue rgb16 -> rgb16") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_RGB16) << 0xff0000ff;
+ QTest::newRow("semired argb32 -> rgb16") << int(QImage::Format_ARGB32) << 0x7fff0000u
+ << int(QImage::Format_RGB16) << 0xffff0000;
+ QTest::newRow("semigreen argb32 -> rgb16") << int(QImage::Format_ARGB32) << 0x7f00ff00u
+ << int(QImage::Format_RGB16) << 0xff00ff00;
+ QTest::newRow("semiblue argb32 -> rgb16") << int(QImage::Format_ARGB32) << 0x7f0000ffu
+ << int(QImage::Format_RGB16) << 0xff0000ff;
+ QTest::newRow("semired pm -> rgb16") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u
+ << int(QImage::Format_RGB16) << 0xffff0000u;
+
+ QTest::newRow("semigreen pm -> rgb16") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u
+ << int(QImage::Format_RGB16) << 0xff00ff00u;
+ QTest::newRow("semiblue pm -> rgb16") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu
+ << int(QImage::Format_RGB16) << 0xff0000ffu;
+ QTest::newRow("semiwhite pm -> rgb16") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu
+ << int(QImage::Format_RGB16) << 0xffffffffu;
+ QTest::newRow("semiblack pm -> rgb16") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u
+ << int(QImage::Format_RGB16) << 0xff000000u;
+
+ QTest::newRow("mono -> mono lsb") << int(QImage::Format_Mono) << 1u
+ << int(QImage::Format_MonoLSB) << 0xffffffffu;
+ QTest::newRow("mono lsb -> mono") << int(QImage::Format_MonoLSB) << 1u
+ << int(QImage::Format_Mono) << 0xffffffffu;
+
+ QTest::newRow("red rgb32 -> rgb666") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_RGB666) << 0xffff0000;
+ QTest::newRow("green rgb32 -> rgb666") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_RGB666) << 0xff00ff00;
+ QTest::newRow("blue rgb32 -> rgb666") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_RGB666) << 0xff0000ff;
+
+ QTest::newRow("red rgb16 -> rgb666") << int(QImage::Format_RGB16) << 0xffff0000
+ << int(QImage::Format_RGB666) << 0xffff0000;
+ QTest::newRow("green rgb16 -> rgb666") << int(QImage::Format_RGB16) << 0xff00ff00
+ << int(QImage::Format_RGB666) << 0xff00ff00;
+ QTest::newRow("blue rgb16 -> rgb666") << int(QImage::Format_RGB16) << 0xff0000ff
+ << int(QImage::Format_RGB666) << 0xff0000ff;
+
+ QTest::newRow("red rgb32 -> rgb15") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_RGB555) << 0xffff0000;
+ QTest::newRow("green rgb32 -> rgb15") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_RGB555) << 0xff00ff00;
+ QTest::newRow("blue rgb32 -> rgb15") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_RGB555) << 0xff0000ff;
+ QTest::newRow("funky rgb32 -> rgb15") << int(QImage::Format_RGB32) << 0xfff0c080
+ << int(QImage::Format_RGB555) << 0xfff7c684;
+
+ QTest::newRow("red rgb16 -> rgb15") << int(QImage::Format_RGB16) << 0xffff0000
+ << int(QImage::Format_RGB555) << 0xffff0000;
+ QTest::newRow("green rgb16 -> rgb15") << int(QImage::Format_RGB16) << 0xff00ff00
+ << int(QImage::Format_RGB555) << 0xff00ff00;
+ QTest::newRow("blue rgb16 -> rgb15") << int(QImage::Format_RGB16) << 0xff0000ff
+ << int(QImage::Format_RGB555) << 0xff0000ff;
+ QTest::newRow("funky rgb16 -> rgb15") << int(QImage::Format_RGB16) << 0xfff0c080
+ << int(QImage::Format_RGB555) << 0xfff7c684;
+
+ QTest::newRow("red rgb32 -> argb8565") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0xffff0000;
+ QTest::newRow("green rgb32 -> argb8565") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0xff00ff00;
+ QTest::newRow("blue rgb32 -> argb8565") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0xff0000ff;
+
+ QTest::newRow("red rgb16 -> argb8565") << int(QImage::Format_RGB16) << 0xffff0000
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0xffff0000;
+ QTest::newRow("green rgb16 -> argb8565") << int(QImage::Format_RGB16) << 0xff00ff00
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0xff00ff00;
+ QTest::newRow("blue rgb16 -> argb8565") << int(QImage::Format_RGB16) << 0xff0000ff
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0xff0000ff;
+
+ QTest::newRow("red argb8565 -> argb32") << int(QImage::Format_ARGB8565_Premultiplied) << 0xffff0000
+ << int(QImage::Format_ARGB32) << 0xffff0000;
+ QTest::newRow("green argb8565 -> argb32") << int(QImage::Format_ARGB8565_Premultiplied) << 0xff00ff00
+ << int(QImage::Format_ARGB32) << 0xff00ff00;
+ QTest::newRow("blue argb8565 -> argb32") << int(QImage::Format_ARGB8565_Premultiplied) << 0xff0000ff
+ << int(QImage::Format_ARGB32) << 0xff0000ff;
+
+ QTest::newRow("semired argb32 -> argb8565") << int(QImage::Format_ARGB32) << 0x7fff0000u
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0x7f7b0000u;
+ QTest::newRow("semigreen argb32 -> argb8565") << int(QImage::Format_ARGB32) << 0x7f00ff00u
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0x7f007d00u;
+ QTest::newRow("semiblue argb32 -> argb8565") << int(QImage::Format_ARGB32) << 0x7f0000ffu
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0x7f00007bu;
+
+ QTest::newRow("semired pm -> argb8565") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0x7f7b0000u;
+ QTest::newRow("semigreen pm -> argb8565") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0x7f007d00u;
+ QTest::newRow("semiblue pm -> argb8565") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0x7f00007bu;
+ QTest::newRow("semiwhite pm -> argb8565") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0x7f7b7d7bu;
+ QTest::newRow("semiblack pm -> argb8565") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u
+ << int(QImage::Format_ARGB8565_Premultiplied) << 0x7f000000u;
+
+ QTest::newRow("red rgb666 -> argb32") << int(QImage::Format_RGB666) << 0xffff0000
+ << int(QImage::Format_ARGB32) << 0xffff0000;
+ QTest::newRow("green rgb666 -> argb32") << int(QImage::Format_RGB666) << 0xff00ff00
+ << int(QImage::Format_ARGB32) << 0xff00ff00;
+ QTest::newRow("blue rgb666 -> argb32") << int(QImage::Format_RGB666) << 0xff0000ff
+ << int(QImage::Format_ARGB32) << 0xff0000ff;
+
+ QTest::newRow("semired argb32 -> rgb666") << int(QImage::Format_ARGB32) << 0x7fff0000u
+ << int(QImage::Format_RGB666) << 0xffff0000;
+ QTest::newRow("semigreen argb32 -> rgb666") << int(QImage::Format_ARGB32) << 0x7f00ff00u
+ << int(QImage::Format_RGB666) << 0xff00ff00;
+ QTest::newRow("semiblue argb32 -> rgb666") << int(QImage::Format_ARGB32) << 0x7f0000ffu
+ << int(QImage::Format_RGB666) << 0xff0000ff;
+
+ QTest::newRow("semired pm -> rgb666") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u
+ << int(QImage::Format_RGB666) << 0xffff0000u;
+ QTest::newRow("semigreen pm -> rgb666") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u
+ << int(QImage::Format_RGB666) << 0xff00ff00u;
+ QTest::newRow("semiblue pm -> rgb666") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu
+ << int(QImage::Format_RGB666) << 0xff0000ffu;
+ QTest::newRow("semiwhite pm -> rgb666") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu
+ << int(QImage::Format_RGB666) << 0xffffffffu;
+ QTest::newRow("semiblack pm -> rgb666") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u
+ << int(QImage::Format_RGB666) << 0xff000000u;
+
+ QTest::newRow("red rgb15 -> argb32") << int(QImage::Format_RGB555) << 0xffff0000
+ << int(QImage::Format_ARGB32) << 0xffff0000;
+ QTest::newRow("green rgb15 -> argb32") << int(QImage::Format_RGB555) << 0xff00ff00
+ << int(QImage::Format_ARGB32) << 0xff00ff00;
+ QTest::newRow("blue rgb15 -> argb32") << int(QImage::Format_RGB555) << 0xff0000ff
+ << int(QImage::Format_ARGB32) << 0xff0000ff;
+
+ QTest::newRow("semired argb32 -> rgb15") << int(QImage::Format_ARGB32) << 0x7fff0000u
+ << int(QImage::Format_RGB555) << 0xffff0000;
+ QTest::newRow("semigreen argb32 -> rgb15") << int(QImage::Format_ARGB32) << 0x7f00ff00u
+ << int(QImage::Format_RGB555) << 0xff00ff00;
+ QTest::newRow("semiblue argb32 -> rgb15") << int(QImage::Format_ARGB32) << 0x7f0000ffu
+ << int(QImage::Format_RGB555) << 0xff0000ff;
+
+ QTest::newRow("semired pm -> rgb15") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u
+ << int(QImage::Format_RGB555) << 0xffff0000u;
+ QTest::newRow("semigreen pm -> rgb15") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u
+ << int(QImage::Format_RGB555) << 0xff00ff00u;
+ QTest::newRow("semiblue pm -> rgb15") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu
+ << int(QImage::Format_RGB555) << 0xff0000ffu;
+ QTest::newRow("semiwhite pm -> rgb15") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu
+ << int(QImage::Format_RGB555) << 0xffffffffu;
+ QTest::newRow("semiblack pm -> rgb15") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u
+ << int(QImage::Format_RGB555) << 0xff000000u;
+
+
+ QTest::newRow("red rgb32 -> argb8555") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0xffff0000;
+ QTest::newRow("green rgb32 -> argb8555") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0xff00ff00;
+ QTest::newRow("blue rgb32 -> argb8555") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0xff0000ff;
+
+ QTest::newRow("red rgb16 -> argb8555") << int(QImage::Format_RGB16) << 0xffff0000
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0xffff0000;
+ QTest::newRow("green rgb16 -> argb8555") << int(QImage::Format_RGB16) << 0xff00ff00
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0xff00ff00;
+ QTest::newRow("blue rgb16 -> argb8555") << int(QImage::Format_RGB16) << 0xff0000ff
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0xff0000ff;
+
+ QTest::newRow("red argb8555 -> argb32") << int(QImage::Format_ARGB8555_Premultiplied) << 0xffff0000
+ << int(QImage::Format_ARGB32) << 0xffff0000;
+ QTest::newRow("green argb8555 -> argb32") << int(QImage::Format_ARGB8555_Premultiplied) << 0xff00ff00
+ << int(QImage::Format_ARGB32) << 0xff00ff00;
+ QTest::newRow("blue argb8555 -> argb32") << int(QImage::Format_ARGB8555_Premultiplied) << 0xff0000ff
+ << int(QImage::Format_ARGB32) << 0xff0000ff;
+
+ QTest::newRow("semired argb32 -> argb8555") << int(QImage::Format_ARGB32) << 0x7fff0000u
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0x7f7b0000u;
+ QTest::newRow("semigreen argb32 -> argb8555") << int(QImage::Format_ARGB32) << 0x7f00ff00u
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0x7f007b00u;
+ QTest::newRow("semiblue argb32 -> argb8555") << int(QImage::Format_ARGB32) << 0x7f0000ffu
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0x7f00007bu;
+
+ QTest::newRow("semired pm -> argb8555") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0x7f7b0000u;
+ QTest::newRow("semigreen pm -> argb8555") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0x7f007b00u;
+ QTest::newRow("semiblue pm -> argb8555") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0x7f00007bu;
+ QTest::newRow("semiwhite pm -> argb8555") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0x7f7b7b7bu;
+ QTest::newRow("semiblack pm -> argb8555") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u
+ << int(QImage::Format_ARGB8555_Premultiplied) << 0x7f000000u;
+
+ QTest::newRow("red rgb32 -> rgb888") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_RGB888) << 0xffff0000;
+ QTest::newRow("green rgb32 -> rgb888") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_RGB888) << 0xff00ff00;
+ QTest::newRow("blue rgb32 -> rgb888") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_RGB888) << 0xff0000ff;
+
+ QTest::newRow("red rgb16 -> rgb888") << int(QImage::Format_RGB16) << 0xffff0000
+ << int(QImage::Format_RGB888) << 0xffff0000;
+ QTest::newRow("green rgb16 -> rgb888") << int(QImage::Format_RGB16) << 0xff00ff00
+ << int(QImage::Format_RGB888) << 0xff00ff00;
+ QTest::newRow("blue rgb16 -> rgb888") << int(QImage::Format_RGB16) << 0xff0000ff
+ << int(QImage::Format_RGB888) << 0xff0000ff;
+
+ QTest::newRow("red rgb888 -> argb32") << int(QImage::Format_RGB888) << 0xffff0000
+ << int(QImage::Format_ARGB32) << 0xffff0000;
+ QTest::newRow("green rgb888 -> argb32") << int(QImage::Format_RGB888) << 0xff00ff00
+ << int(QImage::Format_ARGB32) << 0xff00ff00;
+ QTest::newRow("blue rgb888 -> argb32") << int(QImage::Format_RGB888) << 0xff0000ff
+ << int(QImage::Format_ARGB32) << 0xff0000ff;
+
+ QTest::newRow("semired argb32 -> rgb888") << int(QImage::Format_ARGB32) << 0x7fff0000u
+ << int(QImage::Format_RGB888) << 0xffff0000;
+ QTest::newRow("semigreen argb32 -> rgb888") << int(QImage::Format_ARGB32) << 0x7f00ff00u
+ << int(QImage::Format_RGB888) << 0xff00ff00;
+ QTest::newRow("semiblue argb32 -> rgb888") << int(QImage::Format_ARGB32) << 0x7f0000ffu
+ << int(QImage::Format_RGB888) << 0xff0000ff;
+
+ QTest::newRow("semired pm -> rgb888") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f0000u
+ << int(QImage::Format_RGB888) << 0xffff0000u;
+ QTest::newRow("semigreen pm -> rgb888") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f007f00u
+ << int(QImage::Format_RGB888) << 0xff00ff00u;
+ QTest::newRow("semiblue pm -> rgb888") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f00007fu
+ << int(QImage::Format_RGB888) << 0xff0000ffu;
+ QTest::newRow("semiwhite pm -> rgb888") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f7f7f7fu
+ << int(QImage::Format_RGB888) << 0xffffffffu;
+ QTest::newRow("semiblack pm -> rgb888") << int(QImage::Format_ARGB32_Premultiplied) << 0x7f000000u
+ << int(QImage::Format_RGB888) << 0xff000000u;
+}
+
+
+void tst_QImage::convertToFormat()
+{
+ QFETCH(int, inFormat);
+ QFETCH(uint, inPixel);
+ QFETCH(int, resFormat);
+ QFETCH(uint, resPixel);
+
+ QImage src(32, 32, QImage::Format(inFormat));
+
+ if (inFormat == QImage::Format_Mono) {
+ src.setColor(0, qRgba(0,0,0,0xff));
+ src.setColor(1, qRgba(255,255,255,0xff));
+ }
+
+ for (int y=0; y<src.height(); ++y)
+ for (int x=0; x<src.width(); ++x)
+ src.setPixel(x, y, inPixel);
+
+ QImage result = src.convertToFormat(QImage::Format(resFormat));
+
+ QCOMPARE(src.width(), result.width());
+ QCOMPARE(src.height(), result.height());
+
+ bool same = true;
+ for (int y=0; y<result.height(); ++y) {
+ for (int x=0; x<result.width(); ++x) {
+ QRgb pixel = result.pixel(x, y);
+ same &= (pixel == resPixel);
+ if (!same) {
+ printf("expect=%08x, result=%08x\n", resPixel, pixel);
+ y = 100000;
+ break;
+ }
+
+ }
+ }
+ QVERIFY(same);
+
+ // repeat tests converting from an image with nonstandard stride
+
+ int dp = (src.depth() < 8 || result.depth() < 8) ? 8 : 1;
+ QImage src2(src.bits() + (dp*src.depth())/8,
+ src.width() - dp*2,
+ src.height(), src.bytesPerLine(),
+ src.format());
+ if (src.depth() < 8)
+ src2.setColorTable(src.colorTable());
+
+ const QImage result2 = src2.convertToFormat(QImage::Format(resFormat));
+
+ QCOMPARE(src2.width(), result2.width());
+ QCOMPARE(src2.height(), result2.height());
+
+ QImage expected2(result.bits() + (dp*result.depth())/8,
+ result.width() - dp*2,
+ result.height(), result.bytesPerLine(),
+ result.format());
+ if (result.depth() < 8)
+ expected2.setColorTable(result.colorTable());
+
+ result2.save("result2.xpm", "XPM");
+ expected2.save("expected2.xpm", "XPM");
+
+ QCOMPARE(result2, expected2);
+ QFile::remove(QLatin1String("result2.xpm"));
+ QFile::remove(QLatin1String("expected2.xpm"));
+}
+
+void tst_QImage::convertToFormatRgb888ToRGB32()
+{
+ // 545 so width % 4 != 0. This ensure there is padding at the end of the scanlines
+ const int height = 545;
+ const int width = 545;
+ QImage source(width, height, QImage::Format_RGB888);
+ for (int y = 0; y < height; ++y) {
+ uchar *srcPixels = source.scanLine(y);
+ for (int x = 0; x < width * 3; ++x)
+ srcPixels[x] = x;
+ }
+
+ QImage rgb32Image = source.convertToFormat(QImage::Format_RGB888);
+ QCOMPARE(rgb32Image.format(), QImage::Format_RGB888);
+ for (int x = 0; x < width; ++x) {
+ for (int y = 0; y < height; ++y)
+ QCOMPARE(rgb32Image.pixel(x, y), source.pixel(x, y));
+ }
+}
+
+void tst_QImage::createAlphaMask_data()
+{
+ QTest::addColumn<int>("x");
+ QTest::addColumn<int>("y");
+ QTest::addColumn<int>("alpha1");
+ QTest::addColumn<int>("alpha2");
+
+ int alphas[] = { 0, 127, 255 };
+
+ for (unsigned a1 = 0; a1 < sizeof(alphas) / sizeof(int); ++a1) {
+ for (unsigned a2 = 0; a2 < sizeof(alphas) / sizeof(int); ++a2) {
+ if (a1 == a2)
+ continue;
+ for (int x=10; x<18; x+=3) {
+ for (int y=100; y<108; y+=3) {
+ QTest::newRow(qPrintable(QString::fromLatin1("x=%1, y=%2, a1=%3, a2=%4").arg(x).arg(y).arg(alphas[a1]).arg(alphas[a2])))
+ << x << y << alphas[a1] << alphas[a2];
+ }
+ }
+ }
+ }
+}
+
+void tst_QImage::createAlphaMask()
+{
+ QFETCH(int, x);
+ QFETCH(int, y);
+ QFETCH(int, alpha1);
+ QFETCH(int, alpha2);
+
+ QSize size(255, 255);
+ int pixelsInLines = size.width() + size.height() - 1;
+ int pixelsOutofLines = size.width() * size.height() - pixelsInLines;
+
+ // Generate an white image with two lines, horizontal at y and vertical at x.
+ // Lines have alpha of alpha2, rest has alpha of alpha1
+ QImage image(size, QImage::Format_ARGB32);
+ for (int cy=0; cy<image.height(); ++cy) {
+ for (int cx=0; cx<image.width(); ++cx) {
+ int alpha = (y == cy || x == cx) ? alpha2 : alpha1;
+ image.setPixel(cx, cy, qRgba(255, 255, 255, alpha));
+ }
+ }
+
+ QImage mask = image.createAlphaMask(Qt::OrderedAlphaDither);
+
+ // Sanity check...
+ QCOMPARE(mask.width(), image.width());
+ QCOMPARE(mask.height(), image.height());
+
+ // Sum up the number of pixels set for both lines and other area
+ int sumAlpha1 = 0;
+ int sumAlpha2 = 0;
+ for (int cy=0; cy<image.height(); ++cy) {
+ for (int cx=0; cx<image.width(); ++cx) {
+ int *alpha = (y == cy || x == cx) ? &sumAlpha2 : &sumAlpha1;
+ *alpha += mask.pixelIndex(cx, cy);
+ }
+ }
+
+ // Compare the set bits to whats expected for that alpha.
+ const int threshold = 5;
+ QVERIFY(qAbs(sumAlpha1 * 255 / pixelsOutofLines - alpha1) < threshold);
+ QVERIFY(qAbs(sumAlpha2 * 255 / pixelsInLines - alpha2) < threshold);
+}
+
+void tst_QImage::dotsPerMeterZero()
+{
+ QImage img(100, 100, QImage::Format_RGB32);
+ QVERIFY(!img.isNull());
+
+ int defaultDpmX = img.dotsPerMeterX();
+ int defaultDpmY = img.dotsPerMeterY();
+ QVERIFY(defaultDpmX != 0);
+ QVERIFY(defaultDpmY != 0);
+
+ img.setDotsPerMeterX(0);
+ img.setDotsPerMeterY(0);
+
+ QCOMPARE(img.dotsPerMeterX(), defaultDpmX);
+ QCOMPARE(img.dotsPerMeterY(), defaultDpmY);
+}
+
+void tst_QImage::rotate_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<int>("degrees");
+
+ QVector<int> degrees;
+ degrees << 0 << 90 << 180 << 270;
+
+ foreach (int d, degrees) {
+ QString title = QString("%1 %2").arg(d);
+ QTest::newRow(qPrintable(title.arg("Format_RGB32")))
+ << QImage::Format_RGB32 << d;
+ QTest::newRow(qPrintable(title.arg("Format_ARGB32")))
+ << QImage::Format_ARGB32 << d;
+ QTest::newRow(qPrintable(title.arg("Format_ARGB32_Premultiplied")))
+ << QImage::Format_ARGB32_Premultiplied << d;
+ QTest::newRow(qPrintable(title.arg("Format_RGB16")))
+ << QImage::Format_RGB16 << d;
+ QTest::newRow(qPrintable(title.arg("Format_ARGB8565_Premultiplied")))
+ << QImage::Format_ARGB8565_Premultiplied << d;
+ QTest::newRow(qPrintable(title.arg("Format_RGB666")))
+ << QImage::Format_RGB666 << d;
+ QTest::newRow(qPrintable(title.arg("Format_RGB555")))
+ << QImage::Format_RGB555 << d;
+ QTest::newRow(qPrintable(title.arg("Format_ARGB8555_Premultiplied")))
+ << QImage::Format_ARGB8555_Premultiplied << d;
+ QTest::newRow(qPrintable(title.arg("Format_RGB888")))
+ << QImage::Format_RGB888 << d;
+ QTest::newRow(qPrintable(title.arg("Format_Indexed8")))
+ << QImage::Format_Indexed8 << d;
+ }
+}
+
+void tst_QImage::rotate()
+{
+ QFETCH(QImage::Format, format);
+ QFETCH(int, degrees);
+
+ // test if rotate90 is lossless
+ int w = 54;
+ int h = 13;
+ QImage original(w, h, format);
+ original.fill(qRgb(255,255,255));
+
+ if (format == QImage::Format_Indexed8) {
+ original.setColorCount(256);
+ for (int i = 0; i < 255; ++i)
+ original.setColor(i, qRgb(0, i, i));
+ }
+
+ if (original.colorTable().isEmpty()) {
+ for (int x = 0; x < w; ++x) {
+ original.setPixel(x,0, qRgb(x,0,128));
+ original.setPixel(x,h - 1, qRgb(0,255 - x,128));
+ }
+ for (int y = 0; y < h; ++y) {
+ original.setPixel(0, y, qRgb(y,0,255));
+ original.setPixel(w - 1, y, qRgb(0,255 - y,255));
+ }
+ } else {
+ const int n = original.colorTable().size();
+ for (int x = 0; x < w; ++x) {
+ original.setPixel(x, 0, x % n);
+ original.setPixel(x, h - 1, n - (x % n) - 1);
+ }
+ for (int y = 0; y < h; ++y) {
+ original.setPixel(0, y, y % n);
+ original.setPixel(w - 1, y, n - (y % n) - 1);
+ }
+ }
+
+ // original.save("rotated90_original.png", "png");
+
+ // Initialize the matrix manually (do not use rotate) to avoid rounding errors
+ QMatrix matRotate90;
+ matRotate90.rotate(degrees);
+ QImage dest = original;
+ // And rotate it 4 times, then the image should be identical to the original
+ for (int i = 0; i < 4 ; ++i) {
+ dest = dest.transformed(matRotate90);
+ }
+
+ // Make sure they are similar in format before we compare them.
+ dest = dest.convertToFormat(format);
+
+ // dest.save("rotated90_result.png","png");
+ QCOMPARE(original, dest);
+
+ // Test with QMatrix::rotate 90 also, since we trust that now
+ matRotate90.rotate(degrees);
+ dest = original;
+ // And rotate it 4 times, then the image should be identical to the original
+ for (int i = 0; i < 4 ; ++i) {
+ dest = dest.transformed(matRotate90);
+ }
+
+ // Make sure they are similar in format before we compare them.
+ dest = dest.convertToFormat(format);
+
+ QCOMPARE(original, dest);
+}
+
+void tst_QImage::copy()
+{
+ // Task 99250
+ {
+ QImage img(16,16,QImage::Format_ARGB32);
+ img.copy(QRect(1000,1,1,1));
+ }
+}
+
+void tst_QImage::setPixel_data()
+{
+ QTest::addColumn<int>("format");
+ QTest::addColumn<uint>("value");
+ QTest::addColumn<uint>("expected");
+
+ QTest::newRow("ARGB32 red") << int(QImage::Format_ARGB32)
+ << 0xffff0000 << 0xffff0000;
+ QTest::newRow("ARGB32 green") << int(QImage::Format_ARGB32)
+ << 0xff00ff00 << 0xff00ff00;
+ QTest::newRow("ARGB32 blue") << int(QImage::Format_ARGB32)
+ << 0xff0000ff << 0xff0000ff;
+ QTest::newRow("RGB16 red") << int(QImage::Format_RGB16)
+ << 0xffff0000 << 0xf800u;
+ QTest::newRow("RGB16 green") << int(QImage::Format_RGB16)
+ << 0xff00ff00 << 0x07e0u;
+ QTest::newRow("RGB16 blue") << int(QImage::Format_RGB16)
+ << 0xff0000ff << 0x001fu;
+ QTest::newRow("ARGB8565_Premultiplied red") << int(QImage::Format_ARGB8565_Premultiplied)
+ << 0xffff0000 << 0xffff0000;
+ QTest::newRow("ARGB8565_Premultiplied green") << int(QImage::Format_ARGB8565_Premultiplied)
+ << 0xff00ff00 << 0xff00ff00;
+ QTest::newRow("ARGB8565_Premultiplied blue") << int(QImage::Format_ARGB8565_Premultiplied)
+ << 0xff0000ff << 0xff0000ff;
+ QTest::newRow("RGB666 red") << int(QImage::Format_RGB666)
+ << 0xffff0000 << 0xffff0000;
+ QTest::newRow("RGB666 green") << int(QImage::Format_RGB666)
+ << 0xff00ff00 << 0xff00ff00;;
+ QTest::newRow("RGB666 blue") << int(QImage::Format_RGB666)
+ << 0xff0000ff << 0xff0000ff;
+ QTest::newRow("RGB555 red") << int(QImage::Format_RGB555)
+ << 0xffff0000 << 0x7c00u;
+ QTest::newRow("RGB555 green") << int(QImage::Format_RGB555)
+ << 0xff00ff00 << 0x03e0u;
+ QTest::newRow("RGB555 blue") << int(QImage::Format_RGB555)
+ << 0xff0000ff << 0x001fu;
+ QTest::newRow("ARGB8555_Premultiplied red") << int(QImage::Format_ARGB8555_Premultiplied)
+ << 0xffff0000 << 0xffff0000;
+ QTest::newRow("ARGB8555_Premultiplied green") << int(QImage::Format_ARGB8555_Premultiplied)
+ << 0xff00ff00 << 0xff00ff00;
+ QTest::newRow("ARGB8555_Premultiplied blue") << int(QImage::Format_ARGB8555_Premultiplied)
+ << 0xff0000ff << 0xff0000ff;
+ QTest::newRow("RGB888 red") << int(QImage::Format_RGB888)
+ << 0xffff0000 << 0xffff0000;
+ QTest::newRow("RGB888 green") << int(QImage::Format_RGB888)
+ << 0xff00ff00 << 0xff00ff00;
+ QTest::newRow("RGB888 blue") << int(QImage::Format_RGB888)
+ << 0xff0000ff << 0xff0000ff;
+}
+
+void tst_QImage::setPixel()
+{
+ QFETCH(int, format);
+ QFETCH(uint, value);
+ QFETCH(uint, expected);
+
+ const int w = 13;
+ const int h = 15;
+
+ QImage img(w, h, QImage::Format(format));
+
+ // fill image
+ for (int y = 0; y < h; ++y)
+ for (int x = 0; x < w; ++x)
+ img.setPixel(x, y, value);
+
+ // check pixel values
+ switch (format) {
+ case int(QImage::Format_RGB32):
+ case int(QImage::Format_ARGB32):
+ case int(QImage::Format_ARGB32_Premultiplied):
+ {
+ for (int y = 0; y < h; ++y) {
+ const quint32 *row = (const quint32*)(img.scanLine(y));
+ for (int x = 0; x < w; ++x) {
+ quint32 result = row[x];
+ if (result != expected)
+ printf("[x,y]: %d,%d, expected=%08x, result=%08x\n",
+ x, y, expected, result);
+ QCOMPARE(uint(result), expected);
+ }
+ }
+ break;
+ }
+ case int(QImage::Format_RGB555):
+ case int(QImage::Format_RGB16):
+ {
+ for (int y = 0; y < h; ++y) {
+ const quint16 *row = (const quint16*)(img.scanLine(y));
+ for (int x = 0; x < w; ++x) {
+ quint16 result = row[x];
+ if (result != expected)
+ printf("[x,y]: %d,%d, expected=%04x, result=%04x\n",
+ x, y, expected, result);
+ QCOMPARE(uint(result), expected);
+ }
+ }
+ break;
+ }
+ case int(QImage::Format_RGB666):
+ {
+ for (int y = 0; y < h; ++y) {
+ const qrgb666 *row = (const qrgb666*)(img.scanLine(y));
+ for (int x = 0; x < w; ++x) {
+ quint32 result = row[x];
+ if (result != expected)
+ printf("[x,y]: %d,%d, expected=%04x, result=%04x\n",
+ x, y, expected, result);
+ QCOMPARE(result, expected);
+ }
+ }
+ break;
+ }
+ case int(QImage::Format_ARGB8565_Premultiplied):
+ {
+ for (int y = 0; y < h; ++y) {
+ const qargb8565 *row = (const qargb8565*)(img.scanLine(y));
+ for (int x = 0; x < w; ++x) {
+ quint32 result = row[x];
+ if (result != expected)
+ printf("[x,y]: %d,%d, expected=%04x, result=%04x\n",
+ x, y, expected, result);
+ QCOMPARE(result, expected);
+ }
+ }
+ break;
+ }
+ case int(QImage::Format_ARGB8555_Premultiplied):
+ {
+ for (int y = 0; y < h; ++y) {
+ const qargb8555 *row = (const qargb8555*)(img.scanLine(y));
+ for (int x = 0; x < w; ++x) {
+ quint32 result = row[x];
+ if (result != expected)
+ printf("[x,y]: %d,%d, expected=%04x, result=%04x\n",
+ x, y, expected, result);
+ QCOMPARE(result, expected);
+ }
+ }
+ break;
+ }
+ case int(QImage::Format_RGB888):
+ {
+ for (int y = 0; y < h; ++y) {
+ const qrgb888 *row = (const qrgb888*)(img.scanLine(y));
+ for (int x = 0; x < w; ++x) {
+ qrgb888 result = row[x];
+ if (result != expected)
+ printf("[x,y]: %d,%d, expected=%04x, result=%04x\n",
+ x, y, expected, quint32(result));
+ QCOMPARE(uint(result), expected);
+ }
+ }
+ break;
+ }
+ default:
+ qFatal("Test not implemented for format %d", format);
+ }
+}
+
+void tst_QImage::convertToFormatPreserveDotsPrMeter()
+{
+ QImage img(100, 100, QImage::Format_ARGB32_Premultiplied);
+
+ int dpmx = 123;
+ int dpmy = 234;
+ img.setDotsPerMeterX(dpmx);
+ img.setDotsPerMeterY(dpmy);
+ img.fill(0x12345678);
+
+ img = img.convertToFormat(QImage::Format_RGB32);
+
+ QCOMPARE(img.dotsPerMeterX(), dpmx);
+ QCOMPARE(img.dotsPerMeterY(), dpmy);
+}
+
+#ifndef QT_NO_IMAGE_TEXT
+void tst_QImage::convertToFormatPreserveText()
+{
+ QImage img(100, 100, QImage::Format_ARGB32_Premultiplied);
+
+ img.setText("foo", "bar");
+ img.setText("foo2", "bar2");
+ img.fill(0x12345678);
+
+ QStringList listResult;
+ listResult << "foo" << "foo2";
+ QString result = "foo: bar\n\nfoo2: bar2";
+
+ QImage imgResult1 = img.convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(imgResult1.text(), result);
+ QCOMPARE(imgResult1.textKeys(), listResult);
+
+ QVector<QRgb> colorTable(4);
+ for (int i = 0; i < 4; ++i)
+ colorTable[i] = QRgb(42);
+ QImage imgResult2 = img.convertToFormat(QImage::Format_MonoLSB,
+ colorTable);
+ QCOMPARE(imgResult2.text(), result);
+ QCOMPARE(imgResult2.textKeys(), listResult);
+}
+#endif // QT_NO_IMAGE_TEXT
+
+void tst_QImage::setColorCount()
+{
+ QImage img(0, 0, QImage::Format_Indexed8);
+ QTest::ignoreMessage(QtWarningMsg, "QImage::setColorCount: null image");
+ img.setColorCount(256);
+ QCOMPARE(img.colorCount(), 0);
+}
+
+void tst_QImage::setColor()
+{
+ QImage img(0, 0, QImage::Format_Indexed8);
+ img.setColor(0, qRgba(18, 219, 108, 128));
+ QCOMPARE(img.colorCount(), 0);
+
+ QImage img2(1, 1, QImage::Format_Indexed8);
+ img2.setColor(0, qRgba(18, 219, 108, 128));
+ QCOMPARE(img2.colorCount(), 1);
+}
+
+/* Just some sanity checking that we don't draw outside the buffer of
+ * the image. Hopefully this will create crashes or at least some
+ * random test fails when broken.
+ */
+void tst_QImage::rasterClipping()
+{
+ QImage image(10, 10, QImage::Format_RGB32);
+ image.fill(0xffffffff);
+
+ QPainter p(&image);
+
+ p.drawLine(-1000, 5, 5, 5);
+ p.drawLine(-1000, 5, 1000, 5);
+ p.drawLine(5, 5, 1000, 5);
+
+ p.drawLine(5, -1000, 5, 5);
+ p.drawLine(5, -1000, 5, 1000);
+ p.drawLine(5, 5, 5, 1000);
+
+ p.setBrush(Qt::red);
+
+ p.drawEllipse(3, 3, 4, 4);
+ p.drawEllipse(-100, -100, 210, 210);
+
+ p.drawEllipse(-1000, 0, 2010, 2010);
+ p.drawEllipse(0, -1000, 2010, 2010);
+ p.drawEllipse(-2010, -1000, 2010, 2010);
+ p.drawEllipse(-1000, -2010, 2010, 2010);
+ QVERIFY(true);
+}
+
+// Tests the new QPoint overloads in QImage in Qt 4.2
+void tst_QImage::pointOverloads()
+{
+ QImage image(100, 100, QImage::Format_RGB32);
+ image.fill(0xff00ff00);
+
+ // IsValid
+ QVERIFY(image.valid(QPoint(0, 0)));
+ QVERIFY(image.valid(QPoint(99, 0)));
+ QVERIFY(image.valid(QPoint(0, 99)));
+ QVERIFY(image.valid(QPoint(99, 99)));
+
+ QVERIFY(!image.valid(QPoint(50, -1))); // outside on the top
+ QVERIFY(!image.valid(QPoint(50, 100))); // outside on the bottom
+ QVERIFY(!image.valid(QPoint(-1, 50))); // outside on the left
+ QVERIFY(!image.valid(QPoint(100, 50))); // outside on the right
+
+ // Test the pixel setter
+ image.setPixel(QPoint(10, 10), 0xff0000ff);
+ QCOMPARE(image.pixel(10, 10), 0xff0000ff);
+
+ // pixel getter
+ QCOMPARE(image.pixel(QPoint(10, 10)), 0xff0000ff);
+
+ // pixelIndex()
+ QImage indexed = image.convertToFormat(QImage::Format_Indexed8);
+ QCOMPARE(indexed.pixelIndex(10, 10), indexed.pixelIndex(QPoint(10, 10)));
+}
+
+void tst_QImage::destructor()
+{
+ QPolygon poly(6);
+ poly.setPoint(0,-1455, 1435);
+
+ QImage image(100, 100, QImage::Format_RGB32);
+ QPainter ptPix(&image);
+ ptPix.setPen(Qt::black);
+ ptPix.setBrush(Qt::black);
+ ptPix.drawPolygon(poly, Qt::WindingFill);
+ ptPix.end();
+
+}
+
+
+/* XPM */
+static const char *monoPixmap[] = {
+/* width height ncolors chars_per_pixel */
+"4 4 2 1",
+"x c #000000",
+". c #ffffff",
+/* pixels */
+"xxxx",
+"x..x",
+"x..x",
+"xxxx"
+};
+
+
+#ifndef QT_NO_IMAGE_HEURISTIC_MASK
+void tst_QImage::createHeuristicMask()
+{
+ QImage img(monoPixmap);
+ img = img.convertToFormat(QImage::Format_MonoLSB);
+ QImage mask = img.createHeuristicMask();
+ QImage newMask = mask.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ // line 2
+ QVERIFY(newMask.pixel(0,1) != newMask.pixel(1,1));
+ QVERIFY(newMask.pixel(1,1) == newMask.pixel(2,1));
+ QVERIFY(newMask.pixel(2,1) != newMask.pixel(3,1));
+
+ // line 3
+ QVERIFY(newMask.pixel(0,2) != newMask.pixel(1,2));
+ QVERIFY(newMask.pixel(1,2) == newMask.pixel(2,2));
+ QVERIFY(newMask.pixel(2,2) != newMask.pixel(3,2));
+}
+#endif
+
+void tst_QImage::cacheKey()
+{
+ QImage image1(2, 2, QImage::Format_RGB32);
+ qint64 image1_key = image1.cacheKey();
+ QImage image2 = image1;
+
+ QVERIFY(image2.cacheKey() == image1.cacheKey());
+ image2.detach();
+ QVERIFY(image2.cacheKey() != image1.cacheKey());
+ QVERIFY(image1.cacheKey() == image1_key);
+}
+
+void tst_QImage::smoothScale()
+{
+ unsigned int data[2] = { qRgba(0, 0, 0, 0), qRgba(128, 128, 128, 128) };
+
+ QImage imgX((unsigned char *)data, 2, 1, QImage::Format_ARGB32_Premultiplied);
+ QImage imgY((unsigned char *)data, 1, 2, QImage::Format_ARGB32_Premultiplied);
+
+ QImage scaledX = imgX.scaled(QSize(4, 1), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ QImage scaledY = imgY.scaled(QSize(1, 4), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+
+ uint *scaled[2] = {
+ (unsigned int *)scaledX.bits(),
+ (unsigned int *)scaledY.bits()
+ };
+
+ int expected[4] = { 0, 32, 96, 128 };
+ for (int image = 0; image < 2; ++image) {
+ for (int index = 0; index < 4; ++index) {
+ for (int component = 0; component < 4; ++component) {
+ int pixel = scaled[image][index];
+ int val = (pixel >> (component * 8)) & 0xff;
+
+ QCOMPARE(val, expected[index]);
+ }
+ }
+ }
+}
+
+// test area sampling
+void tst_QImage::smoothScale2()
+{
+ int sizes[] = { 2, 4, 8, 10, 16, 20, 32, 40, 64, 100, 101, 128, 0 };
+ QImage::Format formats[] = { QImage::Format_ARGB32, QImage::Format_RGB32, QImage::Format_Invalid };
+ for (int i = 0; sizes[i] != 0; ++i) {
+ for (int j = 0; formats[j] != QImage::Format_Invalid; ++j) {
+ int size = sizes[i];
+
+ QRgb expected = formats[j] == QImage::Format_ARGB32 ? qRgba(63, 127, 255, 255) : qRgb(63, 127, 255);
+
+ QImage img(size, size, formats[j]);
+ img.fill(expected);
+
+ // scale x down, y down
+ QImage scaled = img.scaled(QSize(1, 1), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ QRgb pixel = scaled.pixel(0, 0);
+ QCOMPARE(qAlpha(pixel), qAlpha(expected));
+ QCOMPARE(qRed(pixel), qRed(expected));
+ QCOMPARE(qGreen(pixel), qGreen(expected));
+ QCOMPARE(qBlue(pixel), qBlue(expected));
+
+ // scale x down, y up
+ scaled = img.scaled(QSize(1, size * 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ for (int y = 0; y < scaled.height(); ++y) {
+ pixel = scaled.pixel(0, y);
+ QCOMPARE(qAlpha(pixel), qAlpha(expected));
+ QCOMPARE(qRed(pixel), qRed(expected));
+ QCOMPARE(qGreen(pixel), qGreen(expected));
+ QCOMPARE(qBlue(pixel), qBlue(expected));
+ }
+
+ // scale x up, y down
+ scaled = img.scaled(QSize(size * 2, 1), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ for (int x = 0; x < scaled.width(); ++x) {
+ pixel = scaled.pixel(x, 0);
+ QCOMPARE(qAlpha(pixel), qAlpha(expected));
+ QCOMPARE(qRed(pixel), qRed(expected));
+ QCOMPARE(qGreen(pixel), qGreen(expected));
+ QCOMPARE(qBlue(pixel), qBlue(expected));
+ }
+
+ // scale x up, y up
+ scaled = img.scaled(QSize(size * 2, size * 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ for (int y = 0; y < scaled.height(); ++y) {
+ for (int x = 0; x < scaled.width(); ++x) {
+ pixel = scaled.pixel(x, y);
+ QCOMPARE(qAlpha(pixel), qAlpha(expected));
+ QCOMPARE(qRed(pixel), qRed(expected));
+ QCOMPARE(qGreen(pixel), qGreen(expected));
+ QCOMPARE(qBlue(pixel), qBlue(expected));
+ }
+ }
+ }
+ }
+}
+
+static inline int rand8()
+{
+ return int(256. * (qrand() / (RAND_MAX + 1.0)));
+}
+
+// compares img.scale against the bilinear filtering used by QPainter
+void tst_QImage::smoothScale3()
+{
+ QImage img(128, 128, QImage::Format_RGB32);
+ for (int y = 0; y < img.height(); ++y) {
+ for (int x = 0; x < img.width(); ++x) {
+ const int red = rand8();
+ const int green = rand8();
+ const int blue = rand8();
+ const int alpha = 255;
+
+ img.setPixel(x, y, qRgba(red, green, blue, alpha));
+ }
+ }
+
+ qreal scales[2] = { .5, 2 };
+
+ for (int i = 0; i < 2; ++i) {
+ QImage a = img.scaled(img.size() * scales[i], Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ QImage b(a.size(), a.format());
+ b.fill(0x0);
+
+ QPainter p(&b);
+ p.setRenderHint(QPainter::SmoothPixmapTransform);
+ p.scale(scales[i], scales[i]);
+ p.drawImage(0, 0, img);
+ p.end();
+ int err = 0;
+
+ for (int y = 0; y < a.height(); ++y) {
+ for (int x = 0; x < a.width(); ++x) {
+ QRgb ca = a.pixel(x, y);
+ QRgb cb = b.pixel(x, y);
+
+ // tolerate a little bit of rounding errors
+ bool r = true;
+ r &= qAbs(qRed(ca) - qRed(cb)) <= 18;
+ r &= qAbs(qGreen(ca) - qGreen(cb)) <= 18;
+ r &= qAbs(qBlue(ca) - qBlue(cb)) <= 18;
+ if (!r)
+ err++;
+ }
+ }
+ QCOMPARE(err, 0);
+ }
+}
+
+void tst_QImage::smoothScaleBig()
+{
+#if defined(Q_OS_WINCE)
+ int bigValue = 2000;
+#elif defined(Q_OS_SYMBIAN)
+ int bigValue = 2000;
+#else
+ int bigValue = 200000;
+#endif
+ QImage tall(4, bigValue, QImage::Format_ARGB32);
+ tall.fill(0x0);
+
+ QImage wide(bigValue, 4, QImage::Format_ARGB32);
+ wide.fill(0x0);
+
+ QImage tallScaled = tall.scaled(4, tall.height() / 4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ QImage wideScaled = wide.scaled(wide.width() / 4, 4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+
+ QCOMPARE(tallScaled.pixel(0, 0), QRgb(0x0));
+ QCOMPARE(wideScaled.pixel(0, 0), QRgb(0x0));
+}
+
+void tst_QImage::smoothScaleAlpha()
+{
+ QImage src(128, 128, QImage::Format_ARGB32_Premultiplied);
+ src.fill(0x0);
+
+ QPainter srcPainter(&src);
+ srcPainter.setPen(Qt::NoPen);
+ srcPainter.setBrush(Qt::white);
+ srcPainter.drawEllipse(QRect(QPoint(), src.size()));
+ srcPainter.end();
+
+ QImage dst(32, 32, QImage::Format_ARGB32_Premultiplied);
+ dst.fill(0xffffffff);
+ QImage expected = dst;
+
+ QPainter dstPainter(&dst);
+ dstPainter.drawImage(0, 0, src.scaled(dst.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ dstPainter.end();
+
+ QCOMPARE(dst, expected);
+}
+
+static int count(const QImage &img, int x, int y, int dx, int dy, QRgb pixel)
+{
+ int i = 0;
+ while (x >= 0 && x < img.width() && y >= 0 && y < img.height()) {
+ i += (img.pixel(x, y) == pixel);
+ x += dx;
+ y += dy;
+ }
+ return i;
+}
+
+const int transformed_image_width = 128;
+const int transformed_image_height = 128;
+
+void tst_QImage::transformed_data()
+{
+ QTest::addColumn<QTransform>("transform");
+
+ {
+ QTransform transform;
+ transform.translate(10.4, 10.4);
+ QTest::newRow("Translate") << transform;
+ }
+ {
+ QTransform transform;
+ transform.scale(1.5, 1.5);
+ QTest::newRow("Scale") << transform;
+ }
+ {
+ QTransform transform;
+ transform.rotate(30);
+ QTest::newRow("Rotate 30") << transform;
+ }
+ {
+ QTransform transform;
+ transform.rotate(90);
+ QTest::newRow("Rotate 90") << transform;
+ }
+ {
+ QTransform transform;
+ transform.rotate(180);
+ QTest::newRow("Rotate 180") << transform;
+ }
+ {
+ QTransform transform;
+ transform.rotate(270);
+ QTest::newRow("Rotate 270") << transform;
+ }
+ {
+ QTransform transform;
+ transform.translate(transformed_image_width/2, transformed_image_height/2);
+ transform.rotate(155, Qt::XAxis);
+ transform.translate(-transformed_image_width/2, -transformed_image_height/2);
+ QTest::newRow("Perspective 1") << transform;
+ }
+ {
+ QTransform transform;
+ transform.rotate(155, Qt::XAxis);
+ transform.translate(-transformed_image_width/2, -transformed_image_height/2);
+ QTest::newRow("Perspective 2") << transform;
+ }
+}
+
+void tst_QImage::transformed()
+{
+ QFETCH(QTransform, transform);
+
+ QImage img(transformed_image_width, transformed_image_height, QImage::Format_ARGB32_Premultiplied);
+ QPainter p(&img);
+ p.fillRect(0, 0, img.width(), img.height(), Qt::red);
+ p.drawRect(0, 0, img.width()-1, img.height()-1);
+ p.end();
+
+ QImage transformed = img.transformed(transform, Qt::SmoothTransformation);
+
+ // all borders should have touched pixels
+
+ QVERIFY(count(transformed, 0, 0, 1, 0, 0x0) < transformed.width());
+ QVERIFY(count(transformed, 0, 0, 0, 1, 0x0) < transformed.height());
+
+ QVERIFY(count(transformed, 0, img.height() - 1, 1, 0, 0x0) < transformed.width());
+ QVERIFY(count(transformed, img.width() - 1, 0, 0, 1, 0x0) < transformed.height());
+
+ QImage transformedPadded(transformed.width() + 2, transformed.height() + 2, img.format());
+ transformedPadded.fill(0x0);
+
+ p.begin(&transformedPadded);
+ p.setRenderHint(QPainter::SmoothPixmapTransform);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setTransform(transformed.trueMatrix(transform, img.width(), img.height()) * QTransform().translate(1, 1));
+ p.drawImage(0, 0, img);
+ p.end();
+
+ // no borders should have touched pixels since we have a one-pixel padding
+
+ QCOMPARE(count(transformedPadded, 0, 0, 1, 0, 0x0), transformedPadded.width());
+ QCOMPARE(count(transformedPadded, 0, 0, 0, 1, 0x0), transformedPadded.height());
+
+ QCOMPARE(count(transformedPadded, 0, transformedPadded.height() - 1, 1, 0, 0x0), transformedPadded.width());
+ QCOMPARE(count(transformedPadded, transformedPadded.width() - 1, 0, 0, 1, 0x0), transformedPadded.height());
+}
+
+void tst_QImage::transformed2()
+{
+ QImage img(3, 3, QImage::Format_Mono);
+ QPainter p(&img);
+ p.fillRect(0, 0, 3, 3, Qt::white);
+ p.fillRect(0, 0, 3, 3, Qt::Dense4Pattern);
+ p.end();
+
+ QTransform transform;
+ transform.scale(3, 3);
+
+ QImage expected(9, 9, QImage::Format_Mono);
+ p.begin(&expected);
+ p.fillRect(0, 0, 9, 9, Qt::white);
+ p.setBrush(Qt::black);
+ p.setPen(Qt::NoPen);
+ p.drawRect(3, 0, 3, 3);
+ p.drawRect(0, 3, 3, 3);
+ p.drawRect(6, 3, 3, 3);
+ p.drawRect(3, 6, 3, 3);
+ p.end();
+
+ {
+ QImage actual = img.transformed(transform);
+
+ QCOMPARE(actual.format(), expected.format());
+ QCOMPARE(actual.size(), expected.size());
+ QCOMPARE(actual, expected);
+ }
+
+ {
+ transform.rotate(-90);
+ QImage actual = img.transformed(transform);
+
+ QCOMPARE(actual.convertToFormat(QImage::Format_ARGB32_Premultiplied),
+ expected.convertToFormat(QImage::Format_ARGB32_Premultiplied));
+ }
+}
+
+void tst_QImage::scaled()
+{
+ QImage img(102, 3, QImage::Format_Mono);
+ QPainter p(&img);
+ p.fillRect(0, 0, img.width(), img.height(), Qt::white);
+ p.end();
+
+ QImage scaled = img.scaled(1994, 10);
+
+ QImage expected(1994, 10, QImage::Format_Mono);
+ p.begin(&expected);
+ p.fillRect(0, 0, expected.width(), expected.height(), Qt::white);
+ p.end();
+
+ QCOMPARE(scaled, expected);
+}
+
+void tst_QImage::paintEngine()
+{
+ QImage img;
+
+ QPaintEngine *engine;
+ {
+ QImage temp(100, 100, QImage::Format_RGB32);
+ temp.fill(0xff000000);
+
+ QPainter p(&temp);
+ p.fillRect(80,80,10,10,Qt::blue);
+ p.end();
+
+ img = temp;
+
+ engine = temp.paintEngine();
+ }
+
+ {
+ QPainter p(&img);
+
+ p.fillRect(80,10,10,10,Qt::yellow);
+ p.end();
+ }
+
+ QImage expected(100, 100, QImage::Format_RGB32);
+ expected.fill(0xff000000);
+
+ QPainter p(&expected);
+ p.fillRect(80,80,10,10,Qt::blue);
+ p.fillRect(80,10,10,10,Qt::yellow);
+ p.end();
+
+ QCOMPARE(engine, img.paintEngine());
+ QCOMPARE(img, expected);
+}
+
+void tst_QImage::setAlphaChannelWhilePainting()
+{
+ QImage image(100, 100, QImage::Format_ARGB32);
+ image.fill(Qt::black);
+ QPainter p(&image);
+
+ image.setAlphaChannel(image.createMaskFromColor(QColor(Qt::black).rgb(), Qt::MaskInColor));
+}
+
+
+// See task 240047 for details
+void tst_QImage::smoothScaledSubImage()
+{
+ QImage original(128, 128, QImage::Format_RGB32);
+ QPainter p(&original);
+ p.fillRect(0, 0, 64, 128, Qt::black);
+ p.fillRect(64, 0, 64, 128, Qt::white);
+ p.end();
+
+ QImage subimage(((const QImage &) original).bits(), 32, 32, original.bytesPerLine(), QImage::Format_RGB32); // only in the black part of the source...
+
+ QImage scaled = subimage.scaled(8, 8, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+
+ for (int y=0; y<scaled.height(); ++y)
+ for (int x=0; x<scaled.width(); ++x)
+ QCOMPARE(scaled.pixel(x, y), 0xff000000);
+}
+
+void tst_QImage::nullSize_data()
+{
+ QTest::addColumn<QImage>("image");
+ QTest::newRow("null image") << QImage();
+ QTest::newRow("zero-size image") << QImage(0, 0, QImage::Format_RGB32);
+}
+
+void tst_QImage::nullSize()
+{
+ QFETCH(QImage, image);
+ QCOMPARE(image.isNull(), true);
+ QCOMPARE(image.width(), image.size().width());
+ QCOMPARE(image.height(), image.size().height());
+}
+
+void tst_QImage::premultipliedAlphaConsistency()
+{
+ QImage img(256, 1, QImage::Format_ARGB32);
+ for (int x = 0; x < 256; ++x)
+ img.setPixel(x, 0, (x << 24) | 0xffffff);
+
+ QImage converted = img.convertToFormat(QImage::Format_ARGB8565_Premultiplied);
+ QImage pm32 = converted.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ for (int i = 0; i < pm32.width(); ++i) {
+ QRgb pixel = pm32.pixel(i, 0);
+ QVERIFY(qRed(pixel) <= qAlpha(pixel));
+ QVERIFY(qGreen(pixel) <= qAlpha(pixel));
+ QVERIFY(qBlue(pixel) <= qAlpha(pixel));
+ }
+}
+
+void tst_QImage::compareIndexed()
+{
+ QImage img(256, 1, QImage::Format_Indexed8);
+
+ QVector<QRgb> colorTable(256);
+ for (int i = 0; i < 256; ++i)
+ colorTable[i] = qRgb(i, i, i);
+ img.setColorTable(colorTable);
+
+ for (int i = 0; i < 256; ++i) {
+ img.setPixel(i, 0, i);
+ }
+
+ QImage imgInverted(256, 1, QImage::Format_Indexed8);
+ QVector<QRgb> invertedColorTable(256);
+ for (int i = 0; i < 256; ++i)
+ invertedColorTable[255-i] = qRgb(i, i, i);
+ imgInverted.setColorTable(invertedColorTable);
+
+ for (int i = 0; i < 256; ++i) {
+ imgInverted.setPixel(i, 0, (255-i));
+ }
+
+ QCOMPARE(img, imgInverted);
+}
+
+void tst_QImage::fillColor_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<Qt::GlobalColor>("color");
+ QTest::addColumn<uint>("pixelValue");
+
+ QTest::newRow("Mono, color0") << QImage::Format_Mono << Qt::color0 << 0u;
+ QTest::newRow("Mono, color1") << QImage::Format_Mono << Qt::color1 << 1u;
+
+ QTest::newRow("MonoLSB, color0") << QImage::Format_MonoLSB << Qt::color0 << 0u;
+ QTest::newRow("MonoLSB, color1") << QImage::Format_MonoLSB << Qt::color1 << 1u;
+
+ const char *names[] = {
+ "Indexed8",
+ "RGB32",
+ "ARGB32",
+ "ARGB32pm",
+ "RGB16",
+ "ARGB8565pm",
+ "RGB666",
+ "ARGB6666pm",
+ "RGB555",
+ "ARGB8555pm",
+ "RGB888",
+ "RGB444",
+ "ARGB4444pm",
+ 0
+ };
+
+ QImage::Format formats[] = {
+ QImage::Format_Indexed8,
+ QImage::Format_RGB32,
+ QImage::Format_ARGB32,
+ QImage::Format_ARGB32_Premultiplied,
+ QImage::Format_RGB16,
+ QImage::Format_ARGB8565_Premultiplied,
+ QImage::Format_RGB666,
+ QImage::Format_ARGB6666_Premultiplied,
+ QImage::Format_RGB555,
+ QImage::Format_ARGB8555_Premultiplied,
+ QImage::Format_RGB888,
+ QImage::Format_RGB444,
+ QImage::Format_ARGB4444_Premultiplied
+ };
+
+ for (int i=0; names[i] != 0; ++i) {
+ QByteArray name;
+ name.append(names[i]).append(", ");
+
+ QTest::newRow(QByteArray(name).append("black").constData()) << formats[i] << Qt::black << 0xff000000;
+ QTest::newRow(QByteArray(name).append("white").constData()) << formats[i] << Qt::white << 0xffffffff;
+ QTest::newRow(QByteArray(name).append("red").constData()) << formats[i] << Qt::red << 0xffff0000;
+ QTest::newRow(QByteArray(name).append("green").constData()) << formats[i] << Qt::green << 0xff00ff00;
+ QTest::newRow(QByteArray(name).append("blue").constData()) << formats[i] << Qt::blue << 0xff0000ff;
+ }
+
+ QTest::newRow("RGB16, transparent") << QImage::Format_RGB16 << Qt::transparent << 0xff000000;
+ QTest::newRow("RGB32, transparent") << QImage::Format_RGB32 << Qt::transparent << 0xff000000;
+ QTest::newRow("ARGB32, transparent") << QImage::Format_ARGB32 << Qt::transparent << 0x00000000u;
+ QTest::newRow("ARGB32pm, transparent") << QImage::Format_ARGB32_Premultiplied << Qt::transparent << 0x00000000u;
+}
+
+void tst_QImage::fillColor()
+{
+ QFETCH(QImage::Format, format);
+ QFETCH(Qt::GlobalColor, color);
+ QFETCH(uint, pixelValue);
+
+ QImage image(1, 1, format);
+
+ if (image.depth() == 8) {
+ QVector<QRgb> table;
+ table << 0xff000000;
+ table << 0xffffffff;
+ table << 0xffff0000;
+ table << 0xff00ff00;
+ table << 0xff0000ff;
+ image.setColorTable(table);
+ }
+
+ image.fill(color);
+ if (image.depth() == 1) {
+ QCOMPARE(image.pixelIndex(0, 0), (int) pixelValue);
+ } else {
+ QCOMPARE(image.pixel(0, 0), pixelValue);
+ }
+
+ image.fill(QColor(color));
+ if (image.depth() == 1) {
+ QCOMPARE(image.pixelIndex(0, 0), (int) pixelValue);
+ } else {
+ QCOMPARE(image.pixel(0, 0), pixelValue);
+ }
+}
+
+void tst_QImage::fillColorWithAlpha()
+{
+ QImage argb32(1, 1, QImage::Format_ARGB32);
+ argb32.fill(QColor(255, 0, 0, 127));
+ QCOMPARE(argb32.pixel(0, 0), qRgba(255, 0, 0, 127));
+
+ QImage argb32pm(1, 1, QImage::Format_ARGB32_Premultiplied);
+ argb32pm.fill(QColor(255, 0, 0, 127));
+ QCOMPARE(argb32pm.pixel(0, 0), 0x7f7f0000u);
+}
+
+void tst_QImage::rgbSwapped_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+
+ QTest::newRow("Format_Indexed8") << QImage::Format_Indexed8;
+ QTest::newRow("Format_RGB32") << QImage::Format_RGB32;
+ QTest::newRow("Format_ARGB32") << QImage::Format_ARGB32;
+ QTest::newRow("Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("Format_RGB16") << QImage::Format_RGB16;
+ QTest::newRow("Format_ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied;
+ QTest::newRow("Format_ARGB6666_Premultiplied") << QImage::Format_ARGB6666_Premultiplied;
+ QTest::newRow("Format_ARGB4444_Premultiplied") << QImage::Format_ARGB4444_Premultiplied;
+ QTest::newRow("Format_RGB666") << QImage::Format_RGB666;
+ QTest::newRow("Format_RGB555") << QImage::Format_RGB555;
+ QTest::newRow("Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied;
+ QTest::newRow("Format_RGB888") << QImage::Format_RGB888;
+ QTest::newRow("Format_RGB444") << QImage::Format_RGB444;
+}
+
+void tst_QImage::rgbSwapped()
+{
+ QFETCH(QImage::Format, format);
+
+ QImage image(100, 1, format);
+ image.fill(0);
+
+ QVector<QColor> testColor(image.width());
+
+ for (int i = 0; i < image.width(); ++i)
+ testColor[i] = QColor(i, 10 + i, 20 + i * 2, 30 + i);
+
+ if (format != QImage::Format_Indexed8) {
+ QPainter p(&image);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ for (int i = 0; i < image.width(); ++i)
+ p.fillRect(QRect(i, 0, 1, 1), testColor[i].rgb());
+ } else {
+ image.setColorCount(image.width());
+ for (int i = 0; i < image.width(); ++i) {
+ image.setColor(0, testColor[i].rgba());
+ image.setPixel(i, 0, i);
+ }
+ }
+
+ QImage imageSwapped = image.rgbSwapped();
+
+ for (int i = 0; i < image.width(); ++i) {
+ QColor referenceColor = QColor(image.pixel(i, 0));
+ QColor swappedColor = QColor(imageSwapped.pixel(i, 0));
+
+ QCOMPARE(swappedColor.alpha(), referenceColor.alpha());
+ QCOMPARE(swappedColor.red(), referenceColor.blue());
+ QCOMPARE(swappedColor.green(), referenceColor.green());
+ QCOMPARE(swappedColor.blue(), referenceColor.red());
+ }
+
+ QImage imageSwappedTwice = imageSwapped.rgbSwapped();
+
+ QCOMPARE(image, imageSwappedTwice);
+
+ QCOMPARE(memcmp(image.constBits(), imageSwappedTwice.constBits(), image.byteCount()), 0);
+}
+
+void tst_QImage::deepCopyWhenPaintingActive()
+{
+ QImage image(64, 64, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+
+ QPainter painter(&image);
+ QImage copy = image;
+
+ painter.setBrush(Qt::black);
+ painter.drawEllipse(image.rect());
+
+ QVERIFY(copy != image);
+}
+
+void tst_QImage::scaled_QTBUG19157()
+{
+ QImage foo(5000, 1, QImage::Format_RGB32);
+ foo = foo.scaled(1024, 1024, Qt::KeepAspectRatio);
+ QVERIFY(!foo.isNull());
+}
+
+QTEST_MAIN(tst_QImage)
+#include "tst_qimage.moc"
diff --git a/tests/auto/gui/image/qimageiohandler/.gitignore b/tests/auto/gui/image/qimageiohandler/.gitignore
new file mode 100644
index 0000000000..6ea7bdb667
--- /dev/null
+++ b/tests/auto/gui/image/qimageiohandler/.gitignore
@@ -0,0 +1 @@
+tst_qimageiohandler
diff --git a/tests/auto/gui/image/qimageiohandler/qimageiohandler.pro b/tests/auto/gui/image/qimageiohandler/qimageiohandler.pro
new file mode 100644
index 0000000000..46e5cfb2cf
--- /dev/null
+++ b/tests/auto/gui/image/qimageiohandler/qimageiohandler.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qimageiohandler.h
+############################################################
+
+load(qttest_p4)
+
+SOURCES += tst_qimageiohandler.cpp
+
+
diff --git a/tests/auto/gui/image/qimageiohandler/tst_qimageiohandler.cpp b/tests/auto/gui/image/qimageiohandler/tst_qimageiohandler.cpp
new file mode 100644
index 0000000000..dd132302f8
--- /dev/null
+++ b/tests/auto/gui/image/qimageiohandler/tst_qimageiohandler.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qimageiohandler.h>
+#include <qfile.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QImageIOHandler : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QImageIOHandler();
+ virtual ~tst_QImageIOHandler();
+
+private slots:
+ void getSetCheck();
+};
+
+class MyImageIOHandler : public QImageIOHandler
+{
+public:
+ MyImageIOHandler() : QImageIOHandler() { }
+ bool canRead() const { return true; }
+ bool read(QImage *) { return true; }
+};
+
+tst_QImageIOHandler::tst_QImageIOHandler()
+{
+}
+
+tst_QImageIOHandler::~tst_QImageIOHandler()
+{
+}
+
+// Testing get/set functions
+void tst_QImageIOHandler::getSetCheck()
+{
+ MyImageIOHandler obj1;
+ // QIODevice * QImageIOHandler::device()
+ // void QImageIOHandler::setDevice(QIODevice *)
+ QFile *var1 = new QFile;
+ obj1.setDevice(var1);
+ QCOMPARE(obj1.device(), (QIODevice *)var1);
+ obj1.setDevice((QIODevice *)0);
+ QCOMPARE(obj1.device(), (QIODevice *)0);
+ delete var1;
+}
+
+QTEST_MAIN(tst_QImageIOHandler)
+#include "tst_qimageiohandler.moc"
diff --git a/tests/auto/gui/image/qimagereader/.gitignore b/tests/auto/gui/image/qimagereader/.gitignore
new file mode 100644
index 0000000000..fdf03f239d
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/.gitignore
@@ -0,0 +1,2 @@
+tst_qimagereader
+junk
diff --git a/tests/auto/gui/image/qimagereader/baseline/35floppy.png b/tests/auto/gui/image/qimagereader/baseline/35floppy.png
new file mode 100644
index 0000000000..56b9b44c47
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/baseline/35floppy.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/baseline/connect.png b/tests/auto/gui/image/qimagereader/baseline/connect.png
new file mode 100644
index 0000000000..9544bb9c76
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/baseline/connect.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/baseline/kde_favicon.png b/tests/auto/gui/image/qimagereader/baseline/kde_favicon.png
new file mode 100644
index 0000000000..e19287b49d
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/baseline/kde_favicon.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/baseline/semitransparent.png b/tests/auto/gui/image/qimagereader/baseline/semitransparent.png
new file mode 100644
index 0000000000..a3ad780699
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/baseline/semitransparent.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/16bpp.bmp b/tests/auto/gui/image/qimagereader/images/16bpp.bmp
new file mode 100644
index 0000000000..74ce63edd4
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/16bpp.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/4bpp-rle.bmp b/tests/auto/gui/image/qimagereader/images/4bpp-rle.bmp
new file mode 100644
index 0000000000..ae71e678fd
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/4bpp-rle.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.jpg b/tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.jpg
new file mode 100644
index 0000000000..b8aa9ea609
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.png b/tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.png
new file mode 100644
index 0000000000..a24db1b13f
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/YCbCr_rgb.jpg b/tests/auto/gui/image/qimagereader/images/YCbCr_rgb.jpg
new file mode 100644
index 0000000000..8771224cb5
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/YCbCr_rgb.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/away.png b/tests/auto/gui/image/qimagereader/images/away.png
new file mode 100644
index 0000000000..0e21a37883
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/away.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/ball.mng b/tests/auto/gui/image/qimagereader/images/ball.mng
new file mode 100644
index 0000000000..81544780fd
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/ball.mng
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/bat1.gif b/tests/auto/gui/image/qimagereader/images/bat1.gif
new file mode 100644
index 0000000000..cb6f4f7a8e
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/bat1.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/bat2.gif b/tests/auto/gui/image/qimagereader/images/bat2.gif
new file mode 100644
index 0000000000..fbbda4ef76
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/bat2.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/beavis.jpg b/tests/auto/gui/image/qimagereader/images/beavis.jpg
new file mode 100644
index 0000000000..d55504779b
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/beavis.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/black.png b/tests/auto/gui/image/qimagereader/images/black.png
new file mode 100644
index 0000000000..6c94085ed5
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/black.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/black.xpm b/tests/auto/gui/image/qimagereader/images/black.xpm
new file mode 100644
index 0000000000..d7925bf211
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/black.xpm
@@ -0,0 +1,65 @@
+/* XPM */
+static char * ddd_xpm[] = {
+/* $Id: ddd.xpm,v 1.5 1999/08/19 11:30:07 andreas Exp $
+ * DDD Logo. Copyright (C) 1997 TU Braunschweig, Germany.
+ * For details on DDD, see `http://www.gnu.org/software/ddd/'.
+ * width height ncolors chars_per_pixel */
+" 48 48 8 1",
+/* Colors */
+" c None m None g None g4 None s Background ",
+". c black m black g black g4 black s Legs ",
+"X c grey m white g grey g4 grey s Body ",
+"- c grey m white g grey g4 grey s Border ",
+"o c #000040 m black g grey25 g4 grey25 s Handle1 ",
+"O c blue4 m black g grey25 g4 grey25 s Handle2 ",
+"+ c white m white g white g4 white s Light ",
+"* c DarkGreen m black g grey25 g4 grey25 s Eye ",
+/* Pixels */
+" . . ",
+" . .. ",
+" . . ",
+" .. . ",
+" .. .. .. ",
+" .. . . . ",
+" . . . . .. ",
+" . .X. . ",
+" . *.X.* .. ",
+" .. .. .XXX. .. ... ",
+" . .X...XXX...X. . ",
+" .. ..XXX.XXX.XXX. .. ",
+" .....XXXX...XXXX. . ",
+" .. ..XXXXXXXXX.. .. ",
+" ...XXXXXXX..... ",
+" ......... ",
+" .XXXXXXX. ",
+" .....XXX..... ",
+" .XXXXXoOOOOOOX. ... ",
+" .. ..XXXoOOO-----OOO..... ",
+" .........XXoO-----..----O .. ",
+" .. ..X..oO--.........--O .. ",
+" . ..XXXoO--..++.......--O .. ",
+" .. .XXXXO-XXX+++XXXXXXXXX-O . ",
+" .. .....oO-XX+++XXXXXXXXXXX-O .. ",
+" .. .XXXoO--XX++XXXXXXXXXXXX-O .. ",
+" .. ..XXXoO-..+++............-O .. ",
+" . .. .XXoO--..++.............-OO .. ",
+" . ... ...oO--..................-O ",
+".. . .XXoO-XXXXXXXXXXXXXXXXXXX-O ",
+" .. .XXoO-XXXXXXXXXXXXXXXXXXX-O ",
+" .. .XoO-XXXXXXXXXXXXXXXXXXX-O. ",
+" . ...oO-.................-O .. ",
+" . .XXoO-.................-O .. ",
+" . ..XoO-.................-O .. ",
+" . ...oO-XXXXXXXXXXXXXXX-OOO . ",
+" .. .XoOO-XXXXXXXXXXXXX-OOOOO . ",
+" .. ..XoOO---.......---OOOOOO . ",
+" .. ....oOO---...----OOOOOOOO ",
+" . .XX..oOO-----OOOOOOOOOOO ",
+" . .....OOOOOOOOooOOOOOOOOO ",
+" . .XXooooooOo oOOOOOOOOO ",
+" . .XXX. ooOOOOOOO ",
+" .. ... ooOOOOOO ",
+" . ooOOOOOO ",
+" ooOOOOOO ",
+" ooOOOOOO ",
+" ooOOOOOO "};
diff --git a/tests/auto/gui/image/qimagereader/images/colorful.bmp b/tests/auto/gui/image/qimagereader/images/colorful.bmp
new file mode 100644
index 0000000000..8ea6f4acd7
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/colorful.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt-colors.xpm b/tests/auto/gui/image/qimagereader/images/corrupt-colors.xpm
new file mode 100644
index 0000000000..f8d80edbbc
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt-colors.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static const char *marble_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 240 240 223 2",
+/* colors */
+".. c #959595",
+".# c #c5c5c5",
+".a c #adadad",
+".b c #dedede",
+".c c #b7b7b7",
+".d c #d2d2d2",
+".e c #bebebe",
+".f c #c9c9c9",
+".g c #b8b8b8",
+".h c #d6d6d6",
+".i c #9e9e9e",
+".j c #eaeaea",
+".k c #b2b2b2",
+".l c #cecece",
+".m c #a5a5a5",
+".n c #e4e4e4",
+".o c #c4c4c4",
+".p c #d9d9d9",
+".q c #b1b1b1",
+/* pixels */
+"aYbla9aN.N#x",
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt-data.tif b/tests/auto/gui/image/qimagereader/images/corrupt-data.tif
new file mode 100644
index 0000000000..d63c688b27
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt-data.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt-pixel-count.xpm b/tests/auto/gui/image/qimagereader/images/corrupt-pixel-count.xpm
new file mode 100644
index 0000000000..3a736ff262
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt-pixel-count.xpm
@@ -0,0 +1,11 @@
+/* XPM */
+static const char *marble_xpm[] = {
+/* width height num_colors chars_per_pixel */
+"2 2 2 -2",
+/* colors */
+"a c #adadad",
+"b c #dedede",
+/* pixels */
+"ab",
+"ba"
+};
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt-pixels.xpm b/tests/auto/gui/image/qimagereader/images/corrupt-pixels.xpm
new file mode 100644
index 0000000000..21031ee604
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt-pixels.xpm
@@ -0,0 +1,7 @@
+/* XPM */
+static char * test_xpm[] = {
+"256 256 1 1",
+" c grey",
+" ",
+" ",
+" "};
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt.bmp b/tests/auto/gui/image/qimagereader/images/corrupt.bmp
new file mode 100644
index 0000000000..824190bdeb
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt.gif b/tests/auto/gui/image/qimagereader/images/corrupt.gif
new file mode 100644
index 0000000000..07259454c9
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt.jpg b/tests/auto/gui/image/qimagereader/images/corrupt.jpg
new file mode 100644
index 0000000000..1959662922
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt.mng b/tests/auto/gui/image/qimagereader/images/corrupt.mng
new file mode 100644
index 0000000000..17fd43a5ca
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt.mng
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt.png b/tests/auto/gui/image/qimagereader/images/corrupt.png
new file mode 100644
index 0000000000..9d8911c64e
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt.svg b/tests/auto/gui/image/qimagereader/images/corrupt.svg
new file mode 100644
index 0000000000..8747df008f
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt.svg
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="40px"
+ height="5px"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="test.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="1005"
+ \ No newline at end of file
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt.svgz b/tests/auto/gui/image/qimagereader/images/corrupt.svgz
new file mode 100644
index 0000000000..67fdceee0b
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt.svgz
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/corrupt.xbm b/tests/auto/gui/image/qimagereader/images/corrupt.xbm
new file mode 100644
index 0000000000..8510634e6d
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/corrupt.xbm
@@ -0,0 +1,5 @@
+#define noname_width 271
+#define noname_height 273
+static char noname_bits[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f};
diff --git a/tests/auto/gui/image/qimagereader/images/crash-signed-char.bmp b/tests/auto/gui/image/qimagereader/images/crash-signed-char.bmp
new file mode 100644
index 0000000000..b35cda6c35
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/crash-signed-char.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/earth.gif b/tests/auto/gui/image/qimagereader/images/earth.gif
new file mode 100644
index 0000000000..2c229eb110
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/earth.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/endless-anim.gif b/tests/auto/gui/image/qimagereader/images/endless-anim.gif
new file mode 100644
index 0000000000..00df8da786
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/endless-anim.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/fire.mng b/tests/auto/gui/image/qimagereader/images/fire.mng
new file mode 100644
index 0000000000..c6695c8369
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/fire.mng
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/font.bmp b/tests/auto/gui/image/qimagereader/images/font.bmp
new file mode 100644
index 0000000000..28b8c66924
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/font.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/four-frames.gif b/tests/auto/gui/image/qimagereader/images/four-frames.gif
new file mode 100644
index 0000000000..6aff2e0af2
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/four-frames.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/gnus.xbm b/tests/auto/gui/image/qimagereader/images/gnus.xbm
new file mode 100644
index 0000000000..58d1ac845a
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/gnus.xbm
@@ -0,0 +1,622 @@
+#define noname_width 271
+#define noname_height 273
+static char noname_bits[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfa,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x49,0xe0,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x97,0xaa,0x8a,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x57,0x2a,0x41,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa9,0x52,0x16,0xfe,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4a,0x49,0x05,
+ 0xf9,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x95,0xaa,0x58,0xf4,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xa5,0x54,0x26,0xe1,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x54,0x49,0x49,0xe4,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x2a,0xa5,
+ 0x2a,0xd1,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0xd5,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0x52,0x95,0x54,0xc4,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,
+ 0x24,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x57,0x29,0xa9,0x92,0x11,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x57,0xd5,0xfa,0xff,0xff,0xab,0xea,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x4a,0x55,0x2a,0x41,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x25,0x29,0xe5,0xff,0xff,0x95,0xa4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa7,0xa4,
+ 0x24,0xa5,0x14,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4a,0xa5,0xd4,0xff,
+ 0x3f,0x52,0xa9,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x29,0x55,0x55,0x55,0x41,0x7e,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xa9,0x54,0xea,0xff,0xdf,0x2a,0x55,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x4a,0x49,0x12,0x7e,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x55,0xa5,0x92,0xff,0x23,0xa5,0x4a,0xd6,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa5,0xa4,0x94,0xaa,0x42,
+ 0x7d,0xff,0xff,0xff,0xff,0xff,0xff,0x9f,0x4a,0x2a,0xa9,0xff,0xad,0x92,0x24,
+ 0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2a,
+ 0x95,0x52,0x52,0x29,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x52,0x49,0x55,
+ 0xfe,0x91,0x54,0x55,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x49,0x29,0x55,0x25,0x85,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0x95,0xaa,0x92,0x7e,0x55,0x55,0xa9,0x4a,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2a,0x50,0x95,0xaa,0x24,0x7e,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x57,0x2a,0x95,0x54,0x79,0x95,0x92,0x92,0x94,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xb9,0x62,0x29,0x49,
+ 0x85,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x49,0x49,0x95,0xba,0xa4,0x54,
+ 0xaa,0x52,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,
+ 0x1a,0xf8,0xa7,0xaa,0x22,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x52,
+ 0x2a,0x75,0x55,0xa5,0x24,0xa5,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xbf,0x5a,0xfd,0x57,0x92,0x94,0x7e,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x4a,0x4a,0x55,0x49,0x89,0x92,0x94,0xaa,0x94,0xf4,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x1a,0xfc,0x2f,0x55,0x05,0x7c,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x55,0xa9,0x4a,0x55,0x2a,0x55,0x55,0x55,0x55,0xe5,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x4e,0xfd,0x5f,
+ 0x29,0xa5,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0xa4,0x54,0x52,0x4a,0x55,0xa9,
+ 0xa4,0x24,0xa5,0x94,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x2f,0x1d,0xfe,0x3f,0x95,0x04,0x7c,0xff,0xfd,0xff,0xff,0xff,0x3f,0x49,0xa5,
+ 0x54,0xa9,0xa4,0x92,0x4a,0x49,0x4a,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xaf,0x44,0xfe,0x5f,0xa9,0x52,0x7d,0xff,0xe5,0xff,0xff,
+ 0xff,0x5f,0x55,0x92,0x2a,0x95,0x52,0x4a,0x52,0xaa,0x52,0x4a,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x16,0xff,0xbf,0x4a,0x05,0x7c,
+ 0xff,0xd9,0xff,0xff,0xff,0x5f,0x95,0x42,0xa5,0x52,0x95,0xaa,0xaa,0xaa,0x94,
+ 0x54,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x43,0xfe,
+ 0xbf,0x54,0x52,0x7d,0x7f,0x25,0xff,0xff,0xff,0xa7,0xa4,0x28,0x92,0x54,0x4a,
+ 0xa5,0x4a,0x92,0xaa,0x4a,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xab,0x12,0xfe,0x7f,0xa5,0x02,0x7c,0x7f,0x55,0xfd,0xff,0xff,0x95,0x2a,
+ 0x82,0x54,0xa5,0x54,0x2a,0xa9,0x2a,0xa5,0x52,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x27,0x4b,0xff,0xff,0x4a,0x29,0x7d,0xff,0x92,0xfe,
+ 0xff,0xff,0x55,0x92,0x20,0xa8,0x94,0x2a,0xa5,0x94,0x52,0x29,0xa9,0xf4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x01,0xff,0x7f,0x52,0x42,
+ 0x7c,0xff,0x25,0xf9,0xff,0x7f,0xaa,0x02,0x8a,0x40,0x29,0x49,0x09,0x41,0x4a,
+ 0x55,0x25,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x57,
+ 0xff,0xff,0x95,0x12,0x7d,0xff,0xa9,0xfa,0xff,0x7f,0x25,0xa9,0x20,0x2a,0xa5,
+ 0xaa,0x42,0x92,0x54,0x92,0x54,0x95,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xaf,0x83,0xff,0xff,0xa9,0x42,0x7e,0xff,0xaa,0xf4,0xff,0xaf,0x54,
+ 0x01,0x82,0x80,0xaa,0x54,0x14,0x08,0xa2,0xaa,0x4a,0xd2,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xef,0xcf,0xd7,0xff,0xff,0x52,0x12,0x7f,0xff,0x4a,
+ 0xea,0xff,0x57,0x92,0xaa,0x28,0x24,0x29,0x25,0x81,0x82,0x08,0x49,0x52,0x55,
+ 0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xdf,0xef,0xe7,0xff,0xff,0x2a,
+ 0x05,0x7e,0xff,0x55,0xd5,0xff,0xa5,0x2a,0x00,0x8e,0x10,0x4a,0x89,0x24,0x28,
+ 0xa0,0xaa,0x2a,0x49,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xe7,0xff,
+ 0xef,0xff,0xff,0xa5,0x50,0x7e,0xff,0x25,0xe5,0xff,0x2a,0xa5,0x52,0x7f,0x85,
+ 0x54,0x35,0x08,0x82,0x0a,0x55,0x95,0xaa,0xfc,0xff,0xff,0xff,0xcf,0xff,0xff,
+ 0xff,0xff,0xd7,0xff,0xff,0xff,0x7f,0x52,0x85,0x7e,0xff,0xab,0x94,0x1e,0x55,
+ 0x2a,0xc8,0xff,0x10,0x90,0x92,0xa0,0x08,0x20,0x24,0x52,0x25,0xfd,0xff,0xff,
+ 0xff,0xef,0xff,0xff,0xff,0xff,0xe9,0xff,0xff,0xff,0xff,0x94,0x10,0x7e,0xff,
+ 0x93,0xaa,0x6a,0x49,0x49,0xf2,0xff,0x85,0x52,0x09,0x0a,0xa2,0x4a,0x92,0x29,
+ 0xa9,0xf2,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0x7f,
+ 0x55,0x25,0x7f,0xff,0x55,0x49,0x49,0x95,0x0a,0xf9,0xff,0x17,0x48,0x26,0x50,
+ 0x08,0x00,0xa9,0x4a,0x95,0xfa,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xf2,
+ 0xff,0xff,0xff,0xff,0x92,0x80,0x7e,0xff,0xa7,0x54,0xaa,0xa4,0x52,0xfc,0xff,
+ 0xaf,0x42,0x89,0xfa,0xbf,0x54,0x20,0xa9,0xa4,0xd4,0xff,0xff,0xff,0xcb,0xff,
+ 0xff,0xff,0xff,0xf5,0xff,0xff,0xff,0xff,0x54,0x29,0x7f,0xff,0x4b,0xa5,0x92,
+ 0x2a,0x01,0xff,0xff,0x1f,0xa8,0x22,0xff,0xff,0x01,0xa5,0x2a,0x55,0xa9,0xff,
+ 0xff,0xff,0xd4,0xff,0xff,0xff,0x7f,0xfa,0xff,0xff,0xff,0x7f,0xa5,0x04,0x7f,
+ 0xff,0x57,0x2a,0x55,0xa9,0x54,0xfe,0xff,0x3f,0x05,0x89,0xff,0xff,0x5f,0x48,
+ 0x92,0x2a,0x95,0xff,0xff,0xff,0xea,0xff,0xff,0xff,0xff,0xd2,0xff,0xff,0xff,
+ 0x7f,0x2a,0x91,0x7f,0xff,0xa9,0x54,0x4a,0x52,0x02,0xff,0xff,0xff,0x50,0xd1,
+ 0xff,0xff,0x1f,0x81,0xaa,0xa4,0x52,0xfe,0xff,0x3f,0xe9,0xff,0xff,0xff,0x7f,
+ 0x1d,0xff,0xff,0xff,0xff,0x54,0x41,0x7f,0xff,0x93,0x92,0x52,0x95,0xc8,0xff,
+ 0xff,0xff,0x8b,0xc4,0xff,0xff,0x7f,0x24,0xa5,0x2a,0x49,0xf9,0xff,0x7f,0xd5,
+ 0xff,0xff,0xff,0xbf,0x4a,0xff,0xff,0xff,0xff,0x4a,0x14,0x7f,0xff,0x28,0xa5,
+ 0x94,0x2a,0xa0,0xff,0xff,0x7f,0x22,0xf0,0xff,0xff,0x7f,0x12,0x94,0xa4,0xaa,
+ 0xea,0xff,0xaf,0xea,0xff,0xff,0xff,0x5f,0x8e,0xff,0xff,0xff,0x7f,0xa9,0x40,
+ 0x7f,0xff,0x48,0x55,0x55,0x12,0xca,0xff,0xff,0xff,0x0a,0xf5,0xff,0xff,0xff,
+ 0x80,0x52,0x95,0x54,0xaa,0xfe,0x55,0xc4,0xff,0xff,0xff,0x5f,0xa5,0xff,0xff,
+ 0xff,0xff,0x94,0x14,0x7f,0xff,0x52,0x2a,0xa9,0x4a,0xe1,0xff,0xff,0xbf,0x24,
+ 0xf0,0xff,0xff,0xff,0x0b,0x28,0xa9,0x92,0x24,0x55,0x49,0xe5,0xd7,0xff,0xff,
+ 0xa7,0x8a,0xff,0xff,0xff,0x7f,0xa5,0xc0,0x7f,0xff,0x50,0x49,0x95,0x04,0xf8,
+ 0xff,0xff,0x5f,0x1f,0xfd,0xff,0xff,0xff,0x47,0x45,0x55,0xaa,0xaa,0x4a,0xaa,
+ 0xea,0xaf,0xff,0xff,0x2b,0xc3,0xff,0xff,0xff,0x7f,0x55,0x94,0x7f,0x7f,0x4a,
+ 0x55,0x52,0x51,0xfe,0xff,0xff,0x5f,0x4e,0xf8,0xff,0xff,0xff,0x1f,0x50,0x92,
+ 0x52,0x49,0xa9,0x92,0xe4,0xd3,0xff,0xff,0x4b,0xd5,0xff,0xff,0xff,0xff,0x94,
+ 0xc0,0x7f,0x3f,0xa0,0xa4,0xaa,0x04,0xfe,0xff,0xff,0xa7,0x1d,0xfd,0xff,0xff,
+ 0xff,0x9f,0x84,0xaa,0x4a,0xaa,0x24,0x55,0xf2,0x2b,0xff,0x7f,0xa9,0xc1,0xff,
+ 0xff,0xff,0x7f,0x4a,0x95,0x7f,0xbf,0x2a,0x95,0x24,0x50,0xff,0xff,0xff,0x97,
+ 0x5e,0xfe,0xff,0xff,0xff,0x3f,0x92,0x24,0x95,0x92,0xaa,0xa4,0xf2,0xcb,0xff,
+ 0x5f,0xd5,0xe5,0xff,0xff,0xff,0xff,0x52,0x80,0x7f,0x3f,0xa0,0x52,0x15,0x85,
+ 0xff,0xff,0xff,0xd7,0x38,0xfe,0xff,0xff,0xff,0xff,0x20,0xaa,0x52,0x55,0x55,
+ 0x55,0xf9,0x29,0xfd,0xab,0xa4,0xf0,0xff,0xff,0xff,0x7f,0x29,0xa9,0x7f,0xff,
+ 0x42,0x25,0x49,0xe8,0xff,0xff,0xff,0x69,0x7a,0xff,0xff,0xff,0xff,0xff,0x82,
+ 0x52,0xaa,0x24,0x89,0x4a,0xf8,0x55,0x2a,0x49,0x95,0xf5,0xff,0xff,0xff,0xbf,
+ 0x2a,0xc4,0x7f,0x7f,0x90,0x54,0x15,0xe2,0xff,0xff,0xff,0x25,0xbc,0xff,0xff,
+ 0xff,0xff,0xff,0x29,0x48,0x49,0xaa,0xaa,0xa4,0xfa,0x95,0x92,0x54,0x52,0xf0,
+ 0xff,0xff,0xff,0xbf,0x4a,0xd1,0x7f,0xff,0x05,0xaa,0x40,0xf8,0xff,0xff,0x7f,
+ 0xaa,0xfc,0xff,0xff,0xff,0xff,0xff,0x43,0xa9,0xaa,0x4a,0x52,0xa9,0xf8,0xa4,
+ 0xaa,0x52,0x95,0xfc,0xff,0xff,0xff,0x7f,0x52,0xc0,0x7f,0xff,0xa1,0x00,0x24,
+ 0xfa,0xff,0xff,0xff,0x0a,0xfe,0xff,0xff,0xff,0xff,0xff,0x17,0x92,0x24,0xa5,
+ 0x2a,0x55,0xfe,0xaa,0xa4,0x2a,0x29,0xf9,0xff,0xff,0xff,0xbf,0x2a,0xea,0x7f,
+ 0xff,0x05,0x92,0x90,0xfc,0xff,0xff,0xbf,0xa4,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0xa0,0xaa,0x54,0x49,0x25,0x7c,0x49,0x95,0xa4,0x12,0xfc,0xff,0xff,0xff,
+ 0x7f,0x8a,0xe0,0x7f,0xff,0xa3,0x04,0x05,0xfe,0xff,0xff,0xbf,0x06,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x49,0x95,0x52,0xaa,0x12,0x7f,0x55,0x52,0x55,0x0a,
+ 0xfd,0xff,0xff,0xff,0x3f,0x29,0xe8,0x7f,0xff,0x0f,0x50,0x50,0xff,0xff,0xff,
+ 0x5f,0xca,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x04,0xa9,0x4a,0x25,0x45,0x3e,
+ 0xa9,0x2a,0xa9,0xa2,0xfc,0xff,0xff,0xff,0x7f,0x55,0xe1,0x7f,0xff,0x27,0x05,
+ 0xc4,0xff,0xff,0xff,0x9f,0x91,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x41,0x4a,
+ 0x29,0xa9,0x12,0x5e,0x95,0x94,0x4a,0x0a,0xfe,0xff,0xff,0xff,0xbf,0x12,0xf4,
+ 0x7f,0xff,0x8f,0x50,0xf1,0xff,0xff,0xff,0xa7,0xc2,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x14,0x92,0xaa,0x4a,0xa2,0xbf,0xa4,0x52,0x95,0x22,0xff,0xff,0xff,
+ 0xff,0x3f,0x45,0xf2,0x7f,0xff,0x3f,0x04,0xf4,0xff,0xff,0xff,0xd7,0xe8,0xff,
+ 0xff,0xff,0xff,0x5f,0xff,0xff,0x83,0xa8,0x94,0x54,0x09,0x2f,0x55,0x4a,0x52,
+ 0x49,0xff,0xff,0xff,0xff,0x5f,0x99,0xf0,0x7f,0xff,0x7f,0x51,0xfc,0xff,0xff,
+ 0xff,0x6b,0xf1,0xff,0xff,0xff,0xff,0x5f,0xfd,0xff,0x2b,0x2a,0xa9,0x12,0x20,
+ 0x5f,0xa9,0xaa,0x54,0x00,0xff,0xff,0xff,0xff,0x5f,0x15,0xf2,0x7f,0xff,0xff,
+ 0x8f,0xff,0xff,0xff,0xff,0x2b,0xfc,0xff,0xff,0xff,0xff,0x2f,0xfd,0xff,0x87,
+ 0xa0,0x4a,0xaa,0x8a,0x9f,0x4a,0x52,0x15,0xa9,0xff,0xff,0xff,0xff,0x5f,0x8a,
+ 0xfc,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x94,0xf8,0xff,0xff,0xff,0xff,
+ 0x57,0xf2,0xff,0x2f,0x82,0x52,0x05,0xd0,0x2f,0x95,0x4a,0x49,0x84,0xff,0xff,
+ 0xff,0xff,0xbf,0x24,0xf8,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x12,0xfd,
+ 0xff,0xff,0xff,0xff,0x4b,0xd5,0xff,0x9f,0x28,0x54,0x48,0xc5,0xbf,0x52,0x55,
+ 0x0a,0xe1,0xff,0xff,0xff,0xff,0x9f,0x4a,0xfa,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1a,0xfe,0xff,0xff,0xff,0xff,0x57,0xa9,0xff,0x3f,0x82,0x00,0x21,
+ 0xf0,0x5f,0x2a,0x49,0x21,0xc4,0xff,0xff,0xff,0xff,0xaf,0x1a,0xfd,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x85,0xff,0xff,0xff,0xff,0xff,0x29,0xa5,0xff,
+ 0xff,0x24,0x52,0x88,0xfc,0xbf,0x92,0x2a,0x09,0xf1,0xff,0xff,0xff,0xff,0x9f,
+ 0x4c,0xfc,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x15,0xff,0xff,0xff,0x7f,
+ 0xff,0xa5,0x4a,0xff,0xff,0x90,0x08,0x01,0xfe,0x3f,0x55,0x52,0x24,0xf4,0xff,
+ 0xff,0xff,0xff,0xaf,0x02,0xfd,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xc6,
+ 0xff,0xff,0xff,0xbf,0xfe,0x95,0x54,0xff,0xff,0x05,0x42,0xa8,0xfe,0xbf,0xa4,
+ 0x2a,0x41,0xf9,0xff,0xff,0xff,0xff,0x5f,0x55,0xfc,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x4f,0xd0,0xff,0xff,0xff,0xbf,0x7c,0xaa,0x92,0xfc,0xff,0x53,0x08,
+ 0x01,0xff,0x1f,0x4a,0x01,0x04,0xfc,0xff,0xff,0xff,0xff,0x27,0x05,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xc5,0xff,0xff,0xff,0x4f,0xbf,0x52,0xaa,
+ 0xfe,0xff,0x07,0x42,0xea,0xff,0xbf,0x50,0x54,0x51,0xff,0xff,0xff,0xff,0xff,
+ 0x97,0x56,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xf0,0xff,0xff,0xff,
+ 0x2f,0x7f,0xa5,0x54,0xfd,0xff,0x3f,0x09,0xe0,0xff,0x1f,0x02,0x01,0x04,0xff,
+ 0xff,0xff,0xff,0xff,0xaf,0x02,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,
+ 0xf5,0xff,0xff,0xff,0xab,0x9f,0x94,0x92,0xfc,0xff,0xff,0x40,0xfd,0xff,0x9f,
+ 0x48,0x48,0xa1,0xff,0xff,0xff,0xff,0xff,0xa7,0x56,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x6b,0xf8,0xff,0xff,0xff,0xa4,0x5f,0xa9,0x2a,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x22,0x21,0xc4,0xff,0xff,0xff,0xff,0xff,0x2f,0x03,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0xfa,0xff,0xff,0x7f,0xd5,0x2f,0xa5,
+ 0xa4,0xfa,0xff,0xff,0xff,0xff,0xff,0xbf,0x08,0x08,0xf9,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0x4a,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x94,0xfc,0xff,0xff,
+ 0x7f,0x69,0xac,0x2a,0x55,0xf9,0xff,0xff,0xff,0xff,0xff,0x7f,0xa2,0x22,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0x53,0x21,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x15,0xfe,0xff,0xff,0x9f,0x2a,0x95,0x94,0x92,0xf4,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x08,0x88,0xfe,0xff,0xff,0xff,0xff,0xff,0x57,0x8b,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xa9,0xfe,0xff,0xff,0x5f,0x52,0xbc,0x52,0x55,0xf5,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xa1,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x7f,0x0d,0xff,0xff,0xff,0x57,0x15,0x3f,
+ 0x55,0x49,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xc8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xd7,0x89,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xbf,0xd6,0xff,0xff,
+ 0xff,0x4b,0x45,0x3f,0x49,0xaa,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xf9,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xc9,0xe2,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x81,0xff,0xff,0xff,0x29,0x11,0x5f,0x28,0x55,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0xc8,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0x5f,0xd6,0xff,0xff,0x7f,0xaa,0xc2,0x0f,0x55,0x49,0xea,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa5,
+ 0xe2,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x9f,0xe1,0xff,0xff,0xbf,0x4a,0xd1,
+ 0x5f,0x48,0xa5,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xe9,0xe0,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x27,0xf4,0xff,
+ 0xff,0xbf,0x94,0xc4,0x07,0x91,0x2a,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xca,0xea,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0xf1,0xff,0xff,0x9f,0x52,0xe0,0x4b,0x44,0x52,0xe9,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6a,0xe0,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0x4b,0xfc,0xff,0xff,0xab,0x2a,0xf5,0x0f,0x51,0xa5,
+ 0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x69,0xe5,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x55,0xf8,0xff,0xff,0x95,0x14,
+ 0xf0,0x5f,0x84,0x54,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x75,0xf0,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x13,0xfd,
+ 0xff,0xff,0xa5,0x42,0xf9,0x7f,0x91,0x4a,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xb2,0xfa,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0x54,0xfe,0xff,0x7f,0x52,0x12,0xfa,0xff,0x20,0xa5,0xe4,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x34,0xf8,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0x25,0xff,0xff,0xaf,0xaa,0x48,0xfc,0xff,0x0b,
+ 0x29,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xb5,0xf8,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x52,0xff,0xff,0x2f,0x49,
+ 0x02,0xfe,0xff,0x43,0xaa,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x3a,0xfa,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0x4a,
+ 0xff,0xff,0xa5,0x2a,0xa9,0xff,0xff,0x17,0x25,0xe9,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x9a,0xfc,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0x2a,0xff,0x7f,0x95,0x54,0x80,0xff,0xff,0x07,0xa9,0xea,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x1d,0xfc,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0x3f,0xa9,0xfe,0x7f,0xa9,0x12,0xe5,0xff,0xff,
+ 0x5f,0x4a,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x5f,0xad,0xfe,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0x95,0xea,0x97,0x54,
+ 0x4a,0xf0,0xff,0xff,0x1f,0xa8,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x5f,0x0e,0xfe,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,
+ 0x52,0x55,0xa9,0x92,0x02,0xfd,0xff,0xff,0x5f,0x53,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x5e,0xfe,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xbf,0x2a,0x49,0x4a,0x55,0x49,0xfc,0xff,0xff,0x3f,0x94,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0x0f,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4f,0xa5,0xaa,0x92,0xa4,0x20,0xff,0xff,
+ 0xff,0xbf,0xa4,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x5f,0x57,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,0x52,0x52,0xaa,
+ 0x2a,0x0a,0xff,0xff,0xff,0x7f,0x54,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x07,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xa7,0x94,0x4a,0x55,0x4a,0xa0,0xff,0xff,0xff,0xff,0xa8,0xfa,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x57,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0x2f,0x55,0xa9,0x92,0x12,0xe9,0xff,0xff,0xff,0x7f,0x24,
+ 0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,
+ 0x87,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0xa5,0x4a,0xaa,0x44,0xf4,0xff,
+ 0xff,0xff,0xff,0x55,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0xab,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xab,0x94,0xa4,
+ 0x92,0x12,0xf9,0xff,0xff,0xff,0xff,0xa8,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xab,0x83,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0x47,0xa9,0x2a,0x55,0x40,0xfc,0xff,0xff,0xff,0xff,0x25,0xf5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xe7,0xff,0xff,0xff,0xff,0xff,0xd7,0x97,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0x33,0x55,0xa9,0x24,0x15,0xfe,0xff,0xff,0xff,0xff,
+ 0x95,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,
+ 0x93,0xc3,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0x25,0xa5,0x2a,0x40,0xff,
+ 0xff,0xff,0xff,0xff,0xa9,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xff,
+ 0xff,0xff,0xff,0xff,0xe7,0xd5,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4b,0x92,
+ 0x54,0x92,0xd4,0xff,0xff,0xff,0xff,0xff,0x55,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xe9,0xff,0xff,0xff,0xff,0xff,0xd5,0xc1,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0x97,0xaa,0x4a,0x05,0xe2,0xff,0xff,0xff,0xff,0xff,0x25,0xf1,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xfd,0xff,0xff,0xff,0xff,0xd5,0xea,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0x55,0x25,0xa1,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0x95,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe8,0xfa,0xff,0xff,0xff,
+ 0xff,0xea,0xe0,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xa7,0x24,0x59,0x04,0xfa,
+ 0xff,0xff,0xff,0xff,0xff,0xa9,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe2,
+ 0xfd,0xff,0xff,0xff,0xff,0xc9,0xe9,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4f,
+ 0x52,0x05,0xa1,0xfc,0xff,0xff,0xff,0xff,0xff,0xa5,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x70,0xf9,0xff,0xff,0xff,0xff,0x74,0xe2,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0x47,0x95,0x92,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xe2,0xfa,0xff,0xff,0xff,0xff,0x72,0xe8,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x97,0xaa,0x20,0xd0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x55,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xb8,0xfc,0xff,0xff,
+ 0xff,0xff,0xea,0xe2,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x07,0x04,0x82,0xc2,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x29,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x71,0xfd,0xff,0xff,0xff,0x7f,0x2a,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0x4f,0x91,0x28,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x54,0xfe,0xff,0xff,0xff,0x7f,0x75,0xf2,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0x27,0x44,0x82,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x29,
+ 0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0xb8,0xfc,0xff,0xff,0xff,0xbf,0x14,
+ 0xf1,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x0f,0x11,0x20,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x55,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x9a,0xfe,0xff,
+ 0xff,0xff,0x7f,0x5a,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,0x40,0x85,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x09,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0x2d,0xfd,0xff,0xff,0xff,0x9f,0x12,0xf9,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0x3f,0x14,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0xa6,0xfe,0xff,0xff,0xff,0x5f,0x4d,0xfa,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0x40,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x09,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0x4b,0xfe,0xff,0xff,0xff,0xbf,
+ 0x2c,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x43,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x57,0xff,
+ 0xff,0xff,0xff,0x5f,0x0a,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x89,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xd5,0xa9,0xff,0xff,0xff,0xff,0xaf,0x5a,0xfc,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa3,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x81,0x95,0xff,0xff,0xff,0xff,0x9f,0x06,0xfd,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xc9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xca,0xa5,0xff,0xff,0xff,0xff,
+ 0x2f,0x95,0xfc,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xea,
+ 0xff,0xff,0xff,0xff,0xaf,0x26,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xf5,0xf4,0xff,0xff,0xff,0xff,0xaf,0x86,0xfe,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc1,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x70,0xe5,0xff,0xff,0xff,0xff,0x4f,0x2e,0xfe,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xb2,0xfa,0xff,0xff,0xff,
+ 0xff,0x57,0x83,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xf3,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x78,
+ 0xf2,0xff,0xff,0xff,0xff,0xa7,0x22,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x5f,0x5d,0xfd,0xff,0xff,0xff,0xff,0x97,0x87,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x3c,0xfd,0xff,0xff,0xff,0xff,0x53,0xa3,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xac,0xfe,0xff,0xff,
+ 0xff,0xff,0x57,0x95,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,
+ 0x9e,0xfe,0xff,0xff,0xff,0xff,0x97,0x81,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x57,0xfe,0xff,0xff,0xff,0xff,0xa9,0xa5,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0xaf,0xff,0xff,0xff,0xff,0xff,0x4b,
+ 0x89,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0x93,0xff,0xff,
+ 0xff,0xff,0xff,0x95,0xa2,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x83,0xab,0xff,0xff,0xff,0xff,0xff,0xd3,0xc8,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,
+ 0xff,0xff,0xff,0xff,0xe9,0xa5,0xff,0xff,0xff,0xff,0xff,0xa5,0xe1,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xd5,0xff,0xff,0xff,0xff,0xff,
+ 0xd5,0xc8,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xea,0xea,0xff,
+ 0xff,0xff,0xff,0xff,0x14,0xc1,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xff,0xff,
+ 0xff,0xe0,0xe4,0xff,0xff,0xff,0xff,0xff,0x65,0xe8,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,
+ 0xff,0xff,0xff,0xff,0x3f,0x72,0xe9,0xff,0xff,0xff,0xff,0xff,0x6a,0xe1,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xbf,0xb8,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0x52,0xea,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xff,0x1f,0x7a,0xf5,
+ 0xff,0xff,0xff,0xff,0x7f,0x2a,0xe0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,
+ 0xff,0x8f,0x58,0xfa,0xff,0xff,0xff,0xff,0x7f,0x25,0xf5,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xb5,0xff,0xff,0xdf,0xff,0x57,0x5e,0xfd,0xff,0xff,0xff,0xff,0xff,0x34,0xe0,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xca,0xff,0xff,0x8f,0xff,0x07,0xac,0xfc,0xff,0xff,0xff,
+ 0xff,0x7f,0x2a,0xf5,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd4,0xff,0xff,0x57,0xff,0x2b,0x2d,
+ 0xfd,0xff,0xff,0xff,0xff,0xff,0xb2,0xf0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd2,0xff,0xff,
+ 0x07,0xff,0x43,0x4a,0xff,0xff,0xff,0xff,0xff,0xbf,0x2a,0xf8,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0xc5,0xff,0xff,0x2b,0xfe,0x08,0xab,0xfe,0xff,0xff,0xff,0xff,0x7f,0xaa,
+ 0xf2,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0xea,0xff,0xff,0x83,0x36,0x20,0x55,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x15,0xf0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0xc2,0xff,0xff,0x48,0x4a,0x85,
+ 0x49,0xff,0xff,0xff,0xff,0xff,0x7f,0x59,0xfa,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0xf5,0xff,
+ 0x7f,0x10,0x29,0x50,0xa5,0xff,0xff,0xff,0xff,0xff,0x3f,0x15,0xf9,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0xe4,0xff,0x7f,0x05,0x95,0x42,0xd5,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x35,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xab,0xea,0xff,0xbf,0xa0,0x24,0xa8,0xd4,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x19,0xf9,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x27,0xe5,0xff,0x3f,0x92,0xaa,
+ 0x50,0xe9,0xff,0xff,0xff,0xff,0xff,0x9f,0x4a,0xfc,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa9,0xe2,
+ 0xff,0x9f,0xa0,0xaa,0x2a,0xf5,0xff,0xff,0xff,0xff,0xff,0x5f,0x1a,0xf9,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x95,0xf8,0xff,0x5f,0x4a,0x92,0x4a,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xbf,0x4a,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x52,0xf2,0xff,0x1f,0x20,0x49,0xa5,0xfa,0xff,
+ 0xff,0xff,0xff,0xff,0x5f,0x1a,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaa,0xf8,0xff,0x47,0xa9,
+ 0x2a,0x29,0xf9,0xff,0xff,0xff,0xff,0xff,0xbf,0x0a,0xfc,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x49,
+ 0xf2,0xff,0x17,0x92,0xaa,0xaa,0xfe,0xff,0xff,0xff,0xff,0xff,0x9f,0xac,0xfe,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x9f,0x2a,0xf8,0xff,0x43,0xa8,0x24,0x25,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0x0a,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x94,0xfa,0xff,0x91,0x54,0xaa,0x52,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x2f,0x4d,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0x45,0xfc,0xff,0x03,
+ 0x92,0x52,0xaa,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x06,0xfc,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,
+ 0x12,0xfe,0xff,0x50,0xaa,0x2a,0x95,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0xa5,
+ 0xfe,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x44,0xff,0xff,0x0a,0x25,0xa5,0xa4,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x97,0x06,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0x15,0xff,0xff,0x40,0xa9,0x92,0xea,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x55,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xa1,0xff,0x7f,
+ 0x92,0x4a,0xaa,0xd4,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x06,0xfc,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x95,0x8a,0xff,0x3f,0x84,0x54,0xa9,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,
+ 0x25,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x52,0xe0,0xff,0xbf,0x50,0xa9,0x4a,0xf2,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x8e,0xfe,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xa9,0xea,0xff,0x3f,0x24,0x95,0x54,
+ 0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x23,0xfe,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x4a,0xf0,0xff,
+ 0x9f,0x50,0x69,0x49,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x8b,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xa5,0xf4,0xff,0x0f,0x2d,0x75,0xaa,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xaf,0x03,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9f,0x14,0xfa,0xff,0x2f,0xa8,0xfa,0x25,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x97,0xd7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xaa,0xfc,0xff,0x0f,0x4d,0xfd,
+ 0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0x83,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x12,0xfc,
+ 0xff,0x27,0x92,0xfe,0xcb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0x0a,0xff,0xff,0x83,0x56,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xef,0xc7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xab,0x24,0xff,0xff,0x2b,0xaa,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xe7,0xef,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x45,0xff,0xff,0x05,0x95,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0x82,
+ 0xff,0xff,0x51,0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xa9,0xe8,0xff,0xff,0x85,0xca,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x52,0xc1,0xff,0xff,0x90,0xd5,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x4d,0xe8,0xff,0xff,0xa5,
+ 0xe4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x51,
+ 0xf2,0xff,0x7f,0x40,0xd5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x95,0xf8,0xff,0x7f,0xa9,0xea,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x15,0xfa,0xff,0x3f,0xa4,0xf4,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xa4,0xfc,0xff,0x7f,
+ 0x71,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,
+ 0x15,0xfe,0xff,0x3f,0x94,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x0a,0xff,0xff,0x1f,0x79,0xf2,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0xa4,0xff,0xff,0x5f,0x8c,0xfa,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x53,0x82,0xff,0xff,
+ 0x1f,0x5c,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xa4,0x92,0xff,0xff,0xbf,0x56,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9a,0xc4,0xff,0xff,0x0f,0x2e,0xfd,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa2,0xf0,0xff,0xff,0xaf,0xa7,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x55,0xe4,0xff,
+ 0xff,0x0f,0x57,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xbf,0x54,0xf2,0xff,0xff,0x9f,0x4b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9f,0x92,0xf8,0xff,0xff,0xc7,0xab,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x15,0xfe,0xff,0xff,0x97,0xd7,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa7,0x94,0xfc,
+ 0xff,0xff,0xc7,0xe3,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x2f,0x05,0xfe,0xff,0xff,0xcf,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x53,0xa9,0xff,0xff,0xff,0xd3,0xeb,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x05,0xff,0xff,0xff,0xe3,
+ 0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x54,0xc2,
+ 0xff,0xff,0xff,0xeb,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x95,0xc8,0xff,0xff,0xff,0xf3,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xa5,0xd2,0xff,0xff,0xff,0xff,0xf5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xaa,0xe0,0xff,0xff,0xff,
+ 0xff,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x49,
+ 0xf8,0xff,0xff,0xff,0xff,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x9f,0x2a,0xf5,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x4a,0xf8,0xff,0xff,0xff,0xff,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x14,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,
+ 0x4a,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xab,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0x52,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x53,0x85,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x54,0xa2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x4a,0xc9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xa5,0xe0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x94,0xe4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x5f,0x55,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0x12,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x54,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x0a,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x53,0x45,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x97,0x14,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x45,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x54,0x82,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x4a,0xe9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x52,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x55,0xe8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x24,
+ 0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x55,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x24,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x15,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,
+ 0x49,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x2f,0x95,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x01,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0xd5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x57,0x81,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x97,0xd4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xe0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x93,0xf4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x57,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x2b,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x89,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x05,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x49,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x89,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xe9,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x9f,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x6f,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x9f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f};
diff --git a/tests/auto/gui/image/qimagereader/images/grayscale-ref.tif b/tests/auto/gui/image/qimagereader/images/grayscale-ref.tif
new file mode 100644
index 0000000000..960531ea86
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/grayscale-ref.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/grayscale.tif b/tests/auto/gui/image/qimagereader/images/grayscale.tif
new file mode 100644
index 0000000000..5f4e11429d
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/grayscale.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/image.pbm b/tests/auto/gui/image/qimagereader/images/image.pbm
new file mode 100644
index 0000000000..67e5efa3e9
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/image.pbm
@@ -0,0 +1,8 @@
+P1
+16 6
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
+1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
diff --git a/tests/auto/gui/image/qimagereader/images/image.pgm b/tests/auto/gui/image/qimagereader/images/image.pgm
new file mode 100644
index 0000000000..443bf40964
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/image.pgm
@@ -0,0 +1,10 @@
+P2
+24 7
+15
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
+0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
+0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
+0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
+0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
diff --git a/tests/auto/gui/image/qimagereader/images/image.png b/tests/auto/gui/image/qimagereader/images/image.png
new file mode 100644
index 0000000000..7d4890a7ff
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/image.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/image.ppm b/tests/auto/gui/image/qimagereader/images/image.ppm
new file mode 100644
index 0000000000..2a5640e189
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/image.ppm
@@ -0,0 +1,7 @@
+P3
+4 4
+15
+ 0 0 0 0 0 0 0 0 0 15 0 15
+ 0 0 0 0 15 7 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 15 7 0 0 0
+15 0 15 0 0 0 0 0 0 0 0 0 \ No newline at end of file
diff --git a/tests/auto/gui/image/qimagereader/images/image_100dpi.tif b/tests/auto/gui/image/qimagereader/images/image_100dpi.tif
new file mode 100644
index 0000000000..fcf3cd89aa
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/image_100dpi.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/kollada-noext b/tests/auto/gui/image/qimagereader/images/kollada-noext
new file mode 100644
index 0000000000..2abd4bb763
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/kollada-noext
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/kollada.png b/tests/auto/gui/image/qimagereader/images/kollada.png
new file mode 100644
index 0000000000..2abd4bb763
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/kollada.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/marble.xpm b/tests/auto/gui/image/qimagereader/images/marble.xpm
new file mode 100644
index 0000000000..1c08049624
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/marble.xpm
@@ -0,0 +1,470 @@
+/* XPM */
+static const char *marble_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 240 240 223 2",
+/* colors */
+".. c #959595",
+".# c #c5c5c5",
+".a c #adadad",
+".b c #dedede",
+".c c #b7b7b7",
+".d c #d2d2d2",
+".e c #bebebe",
+".f c #c9c9c9",
+".g c #b8b8b8",
+".h c #d6d6d6",
+".i c #9e9e9e",
+".j c #eaeaea",
+".k c #b2b2b2",
+".l c #cecece",
+".m c #a5a5a5",
+".n c #e4e4e4",
+".o c #c4c4c4",
+".p c #d9d9d9",
+".q c #b1b1b1",
+".r c #d8d8d8",
+".s c #e0e0e0",
+".t c #d6d6d6",
+".u c #b6b6b6",
+".v c #bfbfbf",
+".w c #cbcbcb",
+".x c #a5a5a5",
+".y c #d1d1d1",
+".z c #cdcdcd",
+".A c #aaaaaa",
+".B c #9a9a9a",
+".C c #dedede",
+".D c #aeaeae",
+".E c #e6e6e6",
+".F c #d3d3d3",
+".G c #c8c8c8",
+".H c #bababa",
+".I c #c4c4c4",
+".J c #cccccc",
+".K c #bcbcbc",
+".L c #f0f0f0",
+".M c #b5b5b5",
+".N c #e3e3e3",
+".O c #c2c2c2",
+".P c #adadad",
+".Q c #c9c9c9",
+".R c #e1e1e1",
+".S c #a2a2a2",
+".T c #d1d1d1",
+".U c #bebebe",
+".V c #dbdbdb",
+".W c #dbdbdb",
+".X c #c8c8c8",
+".Y c #b9b9b9",
+".Z c #a8a8a8",
+".0 c #d3d3d3",
+".1 c #9f9f9f",
+".2 c #c1c1c1",
+".3 c #ebebeb",
+".4 c #b4b4b4",
+".5 c #d9d9d9",
+".6 c #cecece",
+".7 c #e8e8e8",
+".8 c #d6d6d6",
+".9 c #c5c5c5",
+"#. c #b0b0b0",
+"## c #dadada",
+"#a c #c5c5c5",
+"#b c #d1d1d1",
+"#c c #afafaf",
+"#d c #b1b1b1",
+"#e c #cbcbcb",
+"#f c #c1c1c1",
+"#g c #eeeeee",
+"#h c #9b9b9b",
+"#i c #c6c6c6",
+"#j c #c0c0c0",
+"#k c #cbcbcb",
+"#l c #bdbdbd",
+"#m c #a1a1a1",
+"#n c #b7b7b7",
+"#o c #a7a7a7",
+"#p c #e6e6e6",
+"#q c #c9c9c9",
+"#r c #bbbbbb",
+"#s c #e2e2e2",
+"#t c #b8b8b8",
+"#u c #cdcdcd",
+"#v c #d3d3d3",
+"#w c #cfcfcf",
+"#x c #e0e0e0",
+"#y c #d5d5d5",
+"#z c #bdbdbd",
+"#A c #cecece",
+"#B c #c0c0c0",
+"#C c #b7b7b7",
+"#D c #e5e5e5",
+"#E c #c4c4c4",
+"#F c #e3e3e3",
+"#G c #d3d3d3",
+"#H c #dddddd",
+"#I c #dddddd",
+"#J c #acacac",
+"#K c #a3a3a3",
+"#L c #eaeaea",
+"#M c #e1e1e1",
+"#N c #b9b9b9",
+"#O c #d5d5d5",
+"#P c #bababa",
+"#Q c #d7d7d7",
+"#R c #b5b5b5",
+"#S c #d1d1d1",
+"#T c #c6c6c6",
+"#U c #dcdcdc",
+"#V c #b4b4b4",
+"#W c #c6c6c6",
+"#X c #a8a8a8",
+"#Y c #a0a0a0",
+"#Z c #cbcbcb",
+"#0 c #bfbfbf",
+"#1 c #cbcbcb",
+"#2 c #a4a4a4",
+"#3 c #c0c0c0",
+"#4 c #bbbbbb",
+"#5 c #9c9c9c",
+"#6 c #a2a2a2",
+"#7 c #dcdcdc",
+"#8 c #c3c3c3",
+"#9 c #9d9d9d",
+"a. c #aaaaaa",
+"a# c #d5d5d5",
+"aa c #eeeeee",
+"ab c #b6b6b6",
+"ac c #b0b0b0",
+"ad c #b3b3b3",
+"ae c #c9c9c9",
+"af c #e9e9e9",
+"ag c #bdbdbd",
+"ah c #a0a0a0",
+"ai c #b0b0b0",
+"aj c #e8e8e8",
+"ak c #cacaca",
+"al c #c3c3c3",
+"am c #dbdbdb",
+"an c #d0d0d0",
+"ao c #d8d8d8",
+"ap c #c7c7c7",
+"aq c #dcdcdc",
+"ar c #c7c7c7",
+"as c #f0f0f0",
+"at c #a3a3a3",
+"au c #bfbfbf",
+"av c #d9d9d9",
+"aw c #dfdfdf",
+"ax c #d3d3d3",
+"ay c #c0c0c0",
+"az c #cacaca",
+"aA c #b3b3b3",
+"aB c #cfcfcf",
+"aC c #dadada",
+"aD c #b2b2b2",
+"aE c #e2e2e2",
+"aF c #d7d7d7",
+"aG c #c4c4c4",
+"aH c #b8b8b8",
+"aI c #cdcdcd",
+"aJ c #a6a6a6",
+"aK c #d2d2d2",
+"aL c #cecece",
+"aM c #acacac",
+"aN c #dfdfdf",
+"aO c #d5d5d5",
+"aP c #c9c9c9",
+"aQ c #bcbcbc",
+"aR c #c6c6c6",
+"aS c #cdcdcd",
+"aT c #bebebe",
+"aU c #f2f2f2",
+"aV c #b6b6b6",
+"aW c #e4e4e4",
+"aX c #c3c3c3",
+"aY c #e2e2e2",
+"aZ c #d2d2d2",
+"a0 c #dddddd",
+"a1 c #dcdcdc",
+"a2 c #ececec",
+"a3 c #eaeaea",
+"a4 c #cccccc",
+"a5 c #c7c7c7",
+"a6 c #c2c2c2",
+"a7 c #cccccc",
+"a8 c #a8a8a8",
+"a9 c #e7e7e7",
+"b. c #e4e4e4",
+"b# c #d9d9d9",
+"ba c #bababa",
+"bb c #cfcfcf",
+"bc c #d4d4d4",
+"bd c #d0d0d0",
+"be c #aeaeae",
+"bf c #e1e1e1",
+"bg c #d7d7d7",
+"bh c #cfcfcf",
+"bi c #b8b8b8",
+"bj c #e6e6e6",
+"bk c #c5c5c5",
+"bl c #e4e4e4",
+"bm c #d4d4d4",
+"bn c #dfdfdf",
+"bo c #dedede",
+"bp c #ececec",
+"bq c #bababa",
+"br c #bcbcbc",
+"bs c #b0b0b0",
+"bt c #cccccc",
+"bu c #a6a6a6",
+"bv c #c1c1c1",
+"bw c #bcbcbc",
+"bx c #ababab",
+"by c #d7d7d7",
+"bz c #b7b7b7",
+"bA c #b2b2b2",
+"bB c #b4b4b4",
+"bC c #bfbfbf",
+/* pixels */
+"aYbla9a9a9.7#D.N#L#La9.7a9#D#D.7#D#D#DaY#x#xa0ama0ama0am#xbnbnbnaYaYaYaYaY#DaYaYaYbn#x#x#xaY.N#Da9a9a9a9a9a9a9a9a9.7a9a9a9#Da9#D#L#L#L#L#L#La2#La2a2a2a2a2a2#ga2#ga2#ga2a2#ga2a2#L#L#L#Lafa9a9a9bl#Dbl#Da9a9a9#L#L#Laf#L#Laf#L#L#L#L#L#L#L#L#L#La2#La2a2a2#La2#L#L#Laf#L#Laf#L#Laf#L#Laf#L#Laf#Laf#Laf#Laf#Laf#L#D#DblblaYaYaCa0.t.Fb#bnbnaCbnblblblblblaYaY.RaYblblblblblblblbla9a9a9a9a9a9#pa9a9#pa9#pa9#pa9#pa9#pa9a9bl#D#D#D#pa9#pafa9a9a9a9#L#Lafa9a9a9#D#D#pbl#U.V.Vb#.8am#xbn#IaYbl.N.N#x",
+"am#I#Da9a9a9bj#D#La9.7#D#Da9#D#D#p#DaYaY#xbna0amamamb#a0a0a0a0bnawaYaYaYaYaYaYaY#xbnaY.R#xaYaY.Nafa9afa9afa9afa9.7a9.7a9bja9bja9#Lafa2afa2af#L#L.3#La2#La2bpa2#La2#ga2a2#ga2a2#g#L#Laf#L#La9afa9bl#Dbl#Da9afa9#L#Laf#L#Laf#L#Laf#L#L#L#L#L#L#L.7a2#La2a2#La2#La2#Laf#L#Laf#Laf#Lafajaf#L#Laf#L#L#Lafajafajafajaf.na9#s#Daw#xbnaCb#bg.Vbnbn.RaYaY#Mbl#pblaYblaYaYaYblblbl#D#Dbl#D#paf#pafa9#pa9afbla9#pa9#pa9#pa9#pa9#p#D#p#Da9#D#pa9#pa9#Da9#Da9af#L#La9.7#D#s#D#MaYbnaCb#aOb#aC#x#UaYaY#M#DaYbf",
+"aOambn.sa9bja9.7a9.7a9#Da9bj#D#D#D#DaYaY#x#xa0amaFaFbgb#aF.Va0.VaYaYaYaYaYaYaYaYbn#xaY#xaY.N#D#Da9a9a9a9a9a9a9a9a9bja9#Da9#Da9#D#L#L#L#L#L#La2#La2afa2a2a2a2#ga2#g#La2bpa2bpa2#L#L#L#L#Lafa9a9#p#DaY#D#Da9a9.7a9af#Laf#L#Laf#Laf#L.7#L#L.7#L#L#L#La2a2a2#La2#L.3#Laf#Laf#Lajaf#Laja9#Lajaf#Lajafaja9#La9#La9#La9a9a9blaYaYaYawa0b#b#.paYaYblaY.Rbla9#pblblaYblaYa9#p#D#pa9#pa9#pa9a9a9#pa9a9#pa9bl#pa9#pa9#pa9#pa9#pa9a9#D#Dbla9a9a9a9a9#pa9a9a9#L#Lafa9a9#D#D#Da9awbn.pb#bgamaCbn#xaw#D#D#D.N#x",
+"amamaC#x#D#s.7.7a9#Da9#D#D#D.N.N#xaYaYaY#xbna0a0aOaFb#aOb#bg.Vambna0bnaCa0aYaYaY#U.RaYaYaY#Dbl#Da9a9#La9af.7afa9.7a9.7a9bja9bja9#L#L.3#L.3#Laf#Lafa2#L#La2#La2bpa2a2#ga2#ga2a2#g#L#L#L#Lafa9afa9.Nblbl#Da9a9afa9#Laf#L#Laf#Laf#L#L#L#L#L#L#L.7#L#La2#L#La2aja2#Laj#Lafaj#Laf#L#Laf#Lafafajafaf#Lafaj#Lafajafaj#Laja9.n#D#MaY.R#xbga0bnbn.RaYbl#Ua9#pa9#D#Dbl#D#Dbl#Dbl#Dbla9#Da9a9#pafa9af#pa9#p#pa9#pa9#pa9#pa9#pa9#p#D#pa9#Da9a9af#pafa9af.7a9#Laf#L.7a9#s#D#saYaY#Ua0aObgao#x#IaYbl#D#s#D.sbf",
+"amaOama0.N.Na9a9bja9#Dbj#D#D#DaY.N#x#x#x#xbnaCa0#H.Vbgb#b#aFbgambnbn#Ubnbnbnbnbn#xaYawaYbl#Da9#Da9a9a9a9a9a9a9a9a9bja9#Da9#sa9#D#Laf#L#L#L#La2a2a2afa2#La2#ga2a2#g#L#g#La2bpa2#L#L#L#Laf#La9a9#pbl#Dbl#Da9a9.7a9#Lajaf#Lajaf#Lajafafajafafajafaf.j#L.3a2#Laf#La2af#Laf#Laf#Laf#L.n#L.n#La9#L#Lafa9afa9aja9#La9af.7afa9#Dbl#IaYawa0a0#UbnaYblblaY#pa9#pa9#D#D#D#Dafa9afa9af#pa9#pa9afa9#pa9a9a9a9#pa9#pa9#p#pa9#pa9#pa9a9#D#Dbla9a9a9a9a9a9.7a9.7af#Laja9a9#D#D#saYawbnaCb#aobn#x.Nbl#s#D#D#D.N.N",
+".CamaOao.WaY#D.7#s#Da9#D#D.NaY.N#x#I#xbn#xaY#x#U#xa0a0a0bgamb#ambga0ama0am#xa0a0.RaYaY#Dbl#Dbl#Da9a9a9a9afa9afa9.7a9#D.7#Dbja9.7af#La2#La2af#L#La2a2a2a2a2#L#g#L#ga2a2#ga2#ga2#g#L#L#L#Lafa9a9a9#Dawbl#Da9a9a9.7af#Laf#Laf#L#Laf#L#Laf#L#Laf#L#Laf#L.j#La2afajaf#Lafajaf.Eafaj#Laf#Laf#Lafaja9aj#Lajaf#Laf#Lafajafajaf.n#DblaYaYaCbn#xbnaYaYaY.Rbla9#p#Da9a9.7#La9a9a9a9a9afa9afa9a9afa9afa9afa9#p#pa9#pa9a9#pa9#pa9#p#D#pa9#Da9afafafaf.7a9a9.7#L#Lafa9.n#D#s#D#D#x#Ua0aCaC#x.saY.s#D.7a9.Ebj.N",
+"#xa0.8a#.8.Cbf.N#D#D.N.NaY.N.saY#x#xaY#IaYaYaYaYaYaY#x#x#xa0aCam.Vb#bg#yb#.Va0bnaYaYblaY#Da9#D#Da9afa9af.7a9a9a9.7a9bja9#s#Da9.7ajaf#Laf#L#La2#L.3#La2#La2a2#ga2a2bpa2#L#g#La2bp#L#L#Laf#La9af#paYbl#D#Da9a9a9a9#L#L#Laf#Laf#L#Lafafafafaf#Lafaf#La2#La2afajaf#Lajaf.7af#Lafa9aja9aja9#L.n#Lafafa9#L.n#L.n#La9#Laf#La9a9#Mbl#xaY#x#IaYawaYaYaYaYblbl#pa9a9.7#L.7afaf#Laf#Lafa9afa9a9a9a9a9a9a9a9a9#pa9#pa9#pa9#pa9#pa9a9#D#D#Da9af#Lafa9a9a9.7af#Laja9a9#D#D#D#M.N#I#xaCa0#UaY#D.NaY#D.n.7bj#Dbj",
+"#x#xa0#vbcaq#xbf#D#D.Nbl.s.NaYbf#x#x#xaYaYaYaYaYaY#M.NaY#x#x.Ca0b#bgb#bgbg.V.p.VawaYblbl#Dbl#Dafa9a9a9a9afa9afa9.7a9#Da9#D#s#Da9af#La2#La2#Laf#La2#La2#La2bpa2bpa2#ga2#ga2#ga2a2#L#L#L#Lafa9a9a9aYaYbl#Da9afa9a9ajaf#Lajaf#Lajafafaj#Lafajafafajafa2#La2#Laf#Lafa9#Lafaja9aj#Laf#Lafajaf#Laf.7afaj#Laf#Lafajaf.Eafajaf.n#Dbl#MaY#IaY#xaY.RaY.RaY#FaYa9a9a9#L#L#Lafa9afafa9#Laf#L#La9afa9afa9afa9#pa9#pa9#pa9#pa9#pa9#p#D#p#Da9a9afa9a9.7a9#L.7.7.naf#La9.n#D#s.N.N#x#UaCbnaY#s#DaY#sa9.7b..7#DaW",
+".7aw#x.CaoaB.y.5#s.N#I.Ca0a0ama0#x.N.NaY.NaY#D#Dbl#DblaYawaY#U.CbgbmaBaSaZbma0a0blaYaY#Dbla9a9#Da9af.7afa9a9a9a9bl#D#D#D#D.N#D#D.7a9a9a9a9a9#La9afafafafafaf#Lafa2#La2#L#L#L#La2a2a2af#La9a9#D#DawaY#sbla9b..7#La9a9a9a9.7a9a9a9afa9af.nafafafafafajafajafajafajafaja9a9bl#MaY#s#Da9#Da9#sa9.na9.7af.Eaf.7af#Lafafa9a9bl#M.NaY#Ibn#UaYaYaw#Da9a9.n#p#pa9a9.7.7.7.7a9.7a9.7a9a9#Lafafaf#Lafa9a9a9#pa9a9#pa9#pa9a9a9a9afa9.7af.7.7.7afa9a9a9a9a9a9#L.na9.na9.na9.n#Maw.Nawaw.N#D#D.E.7bj.7#Dbjb.#D",
+".7#D.s#x.5.y#va#.NaYbf.Ca0ao#xbn.s.N.N#D#D#Da9#Dbl#Dbl#DaYaYaYbn.p.taBan#uaZ.FbgbnawaYawbl#D#D#D#D#Dbl#D#D#D#D#D#Dblblawbl.N#D#Da9a9a9.7af.7a9a9afafafajafaf#L#L#La2a2a2a2a2#La2#La2af#La9#D#D#DaYaY#D#D#Da9a9.7a9a9.7a9a9a9.7a9#Lafafafaf#Lafafaja9af#pafa9af#pajaf.na9#s#DblaYa9a9.na9a9a9#Da9aj#Lafaj#La9aja9ajaf.nbl#DaYaw#xa0#x.b#xaY#D#D#p#p#p.na9a9a9#L.7a9a9a9a9a9.7a9#Lafafafafafafa9af#p.na9#pa9a9a9afa9af.7a9#L.7#L#La9a9.7a9a9.7.na9a9a9.na9.na9.na9#D#MaYaw.N#s#D.n.7.7.n.7.E#D#D.7",
+".7a9aY#xaCam#v#vaCaqa0aqama0#UaY.NaY#D#D#D#D#D#Da9#D#D#Dbl.NaY#Ibnambm#SaZa#a#b#aCa0a0#x#x#xaYbl#D#Da9#Dbl#Dbl#DblaYaYaYaYbl#D#Da9a9a9afa9afafafafafafafafaf#Laf#L#L#Laf#Laf#Laf.j#L#L.n.7a9#s#Daw#x#M#Da9#Daj.7a9.na9.7.na9a9.naf#Lafajafafajafafafajafajafafaf#pa9bl#Mbl#Daw#D.n#Da9#D.na9.na9a9af.7afafajaf#Lafa9a9#sblaY#x#IbnbnaYaYawbla9a9#p#pbl#pa9#D.7.7a9.7a9.7a9a9#L#Lafaf#Lafafa9a9a9a9#pa9.n#pa9a9a9afa9a9#L#Laf.7afa9a9a9a9.7a9a9a9.naf.na9.na9.na9#M.Nawaw#D#s#D#Daj.7aj.7#D.7b.a9",
+"a9#saY.s.Ca0aF#v#v.5#vaF.8a0#x#D#D.N#D#Da9bja9.7a9a9bl#D#DaYaY.N.R#Uama#aFaOaFaFb#b#b#a0aCa0#I#xaYblaYblbl#DblaYaw.R#IaYawaY#D#Da9a9a9a9a9a9a9a9a9#p.na9af#La9.7af#Laf#Lafajaf#L#L.3#La9#D#D.NaYaYaYbl#D#D.7a9.7a9.7a9a9a9.7a9.7a9a9a9a9.na9#pa9.n#pa9#pa9#p.na9#sbl#s#Dbl#DblaYa9a9a9.Ea9a9bja9a9.na9#sa9#Da9#Da9.nblbl#D#M#x#x#U#x#UaYaY#Da9#sa9#p.na9a9.7a9a9#La9a9#La9#L#L#L#Lafafa9#La9afa9#pa9#pa9a9a9a9.7#Laf#L#L#L.7#L.7.7a9.7.na9a9.na9.7.n#D#D#s#D#M#D#Mbl.s#D.s#Da9#D.7.na9a9.n.7#D.7",
+".N.N.NaY#Uaqamaoa#aB.0a#ambn#xbl#D#D#D#D#Da9.7a9a9.7a9#D#D.s.NaYaY.RaCamamaF.5b#amaob#amama0a0a0#IaYawaYaYaYaYaYbnbnbnaYaYaYbl#D.na9a9.7afa9a9a9a9af#paf.na9afa9.n.7#La9.7a9#L#Laf#La9a9#D#D.N.NaYaY#Dbl.n#D.7af.7a9.na9.na9a9.na9.na9a9#pa9.na9a9a9.na9.na9a9a9aY#MaYbl#sbl#s#D.n#Da9#Da9#sa9.n#Da9a9.7a9.na9.na9a9#DawaY#x#x#xbnbnaYawaYbla9a9a9a9#pa9#Da9a9.7a9.7af#L#L#La9#Laf#Laja9.7a9.7a9a9.n#pa9a9.7#Da9a9#L#La9#Laf.7afa9a9a9.7a9a9bja9#sa9#D#M#D#M#D#sbl#saY#saY#s#D#s.7a9.E.7#D#D#D#D",
+"#I.N#I#xamaCamaFaB.Gaz#u.8am#xaY#D#D#D.7a9bja9.7.7a9.7a9#D#D#D.N#Ubna0aCama0amao.Va0amaCama0aC.Cbnbnbnbn#x#Ubn#Uam#Ua0awaYaYaw#D#pa9a9#pa9a9a9#p.na9a9a9a9a9.7a9.7a9af.7afa9a9a9aj#La9.E#D#D#saYaY#Mbl#Dbja9.7.7a9a9a9.7a9#sa9#D#p#D#pbl#sbla9#D#sblbl#Dblbl#sblawaY.N#MaYbl#Dbla9.Ea9.na9.7a9a9#D#s#D#s#D#D#D#D#D#MaYbl.Naw#x#Ibn#I.R#xaY#Da9#Da9a9a9a9.na9a9a9.7a9a9#La9#La9a9#L#Laf#La9a9#Dbj#pa9a9a9#Da9.7.7afafa9.7a9.7#L.7a9.7a9a9#sa9.na9#D#D#D#s#D.sbl#Dawbl#saY#sbj#Da9#s#D.Nbl.saY.s.N",
+".Cbf.C.Cam.5aoa#.la5.G.waZ#va0.C#D#D#D.7a9a9#L#La9#L.7.7.7#D#D#D#x#x#x#x#x#xa0bnam.Va0.Va0a0#xbnaY#x#Ia0a0aCa0aCa0ambnbnaYawblbl#Dbl#M#Dblbl#D#Mbl#pa9a9#Da9a9.7a9.7a9.7a9.7a9a9#La9.n#D#D.NaY.NaYaY#D#Da9#Daja9.7a9a9a9a9.7a9.n#D#M#D#sbl#sblbl#D#M#D#M#D#M#D#M#x#xawaY#Dawa9#Ma9#Da9#Da9#sa9#s#D#D#D#D#D#s#D#sbla9blaw#x#x#xa0#UbnaYawaYbl#D.na9a9a9a9a9#Da9#pa9#La9#L#La9.7af#L#L#L.7#L.7.7.na9a9#D#s.7#D.7.7afa9#La9af.7a9.7.na9.na9a9a9#Da9#s#Dawblaw#D.sbl#sbl.s#D#D#s#D#saY.Naw#xaYbf#x#x",
+"aqaoamavam.8a##v.5#Saza7.w#u#vam#Da9#D.7a9.7a9a9.7#L.7#La9bj#D#D.Cbn#xbnaYaY#x#x.pb#.Vamaobnbn#xbnbn#xbn#xbn#xa0a0b#aCa0aw.R.Nblaw#Dbl#Dbl#Dblbl#pa9#Ma9a9.nbja9a9a9#La9a9a9.7a9.na9#D#D#DaY.N.NaYaYbl#D#sa9a9#La9.Ea9.7a9a9#Da9#M#Dbl#Mbl#sbl#s#Mbl#sbl#D#MaY#sa0#I.NaYaYblbl#Da9a9.na9.Ea9a9a9#D#D#s#D#s#D#D#D#Dbl#saY#x#xaC.Ca0#x.R#xaY#D#Da9a9a9a9a9a9#p.na9a9a9a9#La9#La9a9#L#L#L.7#La9.7.7a9a9a9#Da9.7af.7a9afa9.7a9.7#L.7a9a9bja9#s.7.na9#sbl.s.saYaw#saY#saY#saY#s#D#s#D#xaY#x.W.C.C.Waq",
+"amaFaOaFaOaFama0aY#x.8.0#u#uan#uam#xaY#Da9a9.7a9#Laf#L#La9#D#D.sbl#D#sbl#xaYaw#x.Rbn#Ub#.Va0b#b##Ubnbnbnbna0#xbnbnaYaYaYbnbn#UbnaYaYblaYblawblawa9.n#p#pa9#pafafa9a9a9.na9a9a9a9bl#Dbl#Dbl#sblblawaY#D#Da9.7.7#Laf#Laf.n.7#D.7#D.NaYawaY#xbn#Ua0#U#Ubn#UbnaC#UaY#xawaY#M#D.na9ajaY.N#Dbla9a9.na9.nbl#DblaYaYaw#x#MblaYawbn#Ibna0.b#U.RawaY#Mblbl.na9a9a9a9a9afa9#Dbj#D#D#D#D#D.7#Lafa9afa9.7#Da9#sa9a9a9#Da9.7.7afa9a9a9a9#D#s#D#D#Daw.N.NaY.NaY#D#sbl#saY#saY.N.na9#D#s#DaY.N.N#I#x.CamaoaFbya#",
+"bgb#amam.5aCa0.C#M#xa0aFaZ#uaB.0aO#xaY#Dafa9a9a9#L#L.7af.7#D#D#D#D#DaY#D.N.N#xaY.Cbna0a0b#aFb#aF.Vbnbna0#Ubnbn#x#U#x.R#xawaYbn#x.R#I.Raw.RaY#x.R#p#p#pbl.na9a9a9a9a9a9#Da9#s#D#M#Dblbl#sblbl#DblaY#Dbla9#Da9af.7ajaf#L.7a9.n#Da9#M#DaYaYaYaYbnaCbn.paCa0bgaoaC#UaC#I#xaY#MaYblbl#Mbl#M#D.na9a9.n#D#M#D#M#DaY#DaY#M#pawaY#Ibn.Ca0aYbnaY.RaYblbl#Da9a9.na9afa9a9af#D#D#D#D#D#Da9#Daf#L.7a9.7#Da9#D#pa9.na9a9b.a9.7.7a9.7a9bja9#D#D#D#D#DaY#Daw#Daw#D#D#M.N#saY.saY#sbl#sbl.Naw.Nawbna0aCa0.8a#aF.5",
+"amamaCa0a0#x#xaYblaY#Ia0bc#u#ua#amam#x#D#Da9.7a9#Laf#La9a9.7#D#Dbl#D#D#MaYaYboaYbna0a0aoamb#aOb#b#am.Va0bnbn#Ubnbn#xaYaY.R#xawaYbn#UbnaCbn#Ubn#U.RawaYblaYblawbl#D#D#D#Dbl#Dbl#Dbl#Dblbl#Dblbl#DaYaw#D#Da9bj.7#La9#Lafa9a9bja9bj#D#MblawaYaw.R#Ubn.V.8#vaB#S#waOaoa0aC#x#x.N#I.NaY.NaY#D#D#D.n#Dbl#sbl#Dbl#saYaYblawaYaYbnbnaCbn#U.baYawaY#M#Dbla9.na9a9.na9.na9#s#D#s#D#s#D#D#D.na9a9a9a9#D#D#D#pa9a9#Da9#D#L.7a9.na9#D.n#D#D#D.saY.saY.NaY.saY#sbl#s#Daw#DaY.NaY.NaY.saY.NaY#x.Wa0a0a0aOam.8a#",
+"#x#x#x#xaYaY.N.N.7#D#x#xb#aZ.ya#amaObn#Da9#Da9bj#L#L#D.7#Da9.7a9a9.nbl#D#DaYaY.NaC#xa0.Vamb#aFaF#vaFbga0a0bn#xaY#Ubn#U#xaYaYaYaYbn#xa0a0a0a0aCa0bn#Ubn.baYaYaYaYbl#D#M#Dbl#D#Dbl#Dbl#s#D#D#D#D#MaY#Dbl#D#Da9.7a9ajafaj.7a9a9#sa9a9#M#DaYaYaY.b#xbgb##vaBa7.Q.z#S.5aO.8aoao.Ca0.W#x#I.Naw.NawaY#DawaYblawaYaYawaYawaYaY#U.C#U.Ca0aY#x.RaY#xblbl#D#Dbla9a9a9a9a9a9#D#D#D.NaY.N#s#Da9a9#sa9a9#M#Dbl.na9a9a9a9bja9.7a9a9a9.7#D#D#D#saY#DaY#Daw#DaY.N#M#D#s#Dbl.s.N#M.Naw.N#xaY#x#I#x#Ua0a0aCamama0am",
+"aYaYbl.s#D#D#D#Da9#D#s.N.CaOa#aF.5ao#x#Dbl#Da9#Da9a9.7a9.7a9a9.7a9a9a9#Dbl.NblaY#x#xbna0a0amaFaFbmaFaFamaCbn#U#xbnbnbnaY.b#x.R#xaYbn#xbnaCa0bna0#Ubn#Ubnbn#I#xaY.NblaYaYawaYaw#Dbl#Dbl#D#M#Dbl#DaYaY#Dbl.na9.7a9#La9#La9a9bja9#D#MaYblawaY.R#x#U#S#SaB#uaz#u#vaO.8aOaOaOaOaOaOaO.Caoa0.W.C#I#x#I#x#I#x#x#I#x.NaY#x#Ubn#UbnaCbnaC#I.R#IaYawbl.sbl#M#D#Ma9#D.n#Dbl#D#D#s#D#D#D#D#D#Ma9bl#D#D#DblaYa9#p#sa9#D.n.7.7.na9#s#D#s#D.NaY.saY.saY.NaY.saY#s#D#p.s#saYaY.N#IaYaYaw#x#IaY#I#x#x#I#x#x#x#x#x",
+"#D#D#D.7.7.7.7.7.7a9a9#DaY.CaO.y.5.5bnaY#D#D#D#D#D#Da9bja9a9.7a9a9a9#Da9#sbl.N#MaYaY#xawbna0aCb#aOaFbgb#b#a0a0bn#Ibnaw#xaYaYaYaY#Ubn#IaYaYaYaYbnbn.R#xaw#x.R#Ibnaw#IaY.sbl.Nbl.N#D#M#Dbl#D#M#DblawaY#M#D#D#s.7a9aj#L.na9.n#D#s#D#DaY#IbnaY#UbnaCaB#SaB#u#uaBaO.5amaoam.8.5aO.y#1#1#u.yaOamamaoamamamaC.C.C#xbn#x#Ua0aC.CaCa0#Ia0.R#x#UaYaYblaY.N#D#p#D#sbl#Dbl#D#s#D#D#D#D#s#D#Da9#p#MblblawaYaY#Ma9bl#sa9bja9.7#Da9a9.7a9#Daw#DaY.saY#Daw#DaY#D#M#D#sbl.N#saY.saY#xbo.N.N.s.N.Naw.N#D#D#D#Da9#D",
+"a9.7.7af#Lajbp#L.7#L#La9#DaYa0#va#a0a0.Cbl#D#D#Dbj#D#Da9.7a9#L#L.na9a9a9a9#D#D#Dbl#DaYaY#xaYbna0b#aFb#b#aob#aoambnbnbnbn#U#x.R#xaY.RaY.R#IaYaYawblblaYblaYaYaYawbn#I#x#UaYawbl#Daw.N#D#D.NaY.NawaY#xbl#D#D#Da9.Eafaf#La9#D#D#D#D#I#x#xaCa0aCaoaO.FaO#v#u#u#uaFbgaC.Caoa0ao.5aB.z.U.Oaz.y.y#vbm.y#v#v.5amaoamao.8amaoa0aoa0#Ua0#x#U#xbnaw.N.saY#sbl#Dbl#Dbl#D#M#D#D#D#D#D#D#D#D#D.nbl#Dbl#xaYaYaY#pbla9bl#D#s.7.7.na9#Da9#s#D.NaY.NaY.Naw.Naw.Naw#D#M#D#D#Maw.Naw#x#IaYaY#s#Da9.nbj.7.7b..7.7bp#L",
+"#L.7#L#Lbpbp#Lbp.7#L#L.n#D.N.C.5a#amaCaoaY#D#D.N#Da9#Da9#La9#Lafafa9a9#Da9bl#Dbl.n#D.nblawaY#x.Ra0.Vbgamb#amaFaF#Ubn#U#xbnbnaYaYawaYawaYaYblaYaY.bblaYblblblaYaYaYaYaY#I#x#I#x#I.NaYaY.sbl.sbl.NaYaw.N#M#D#sa9.7a9a9.na9.n#D#s#D#xaCa0aoaob##SaBaOaF#S#uaB#v.5aoa0aCamaoao.8#v#v#3ar.wanazaz#3#C#3aX.w.yaOam.8amaCambga0aoa0aCbn#U#x#IaYaw.NaY.NaYaY#sbl#sbl#D#M#D#D#D#D#s#D#D#DblblaY#MaY#IaYawbl.nbl.n#D#Da9#D#Da9.Ea9#D#D#Daw#D#saY.Naw.NaY.N#M#D#s#D.saYawaY#I.N.N#sa9a9.7af#L.E#L#Laj#L#L#g",
+"#L#L#L#L#La2bpa2#L.j.7.7#D.Nbf#IaFaBa7an.5a0#Daf#D.7#D.7a9a9#L#L#D#Da9#D#M#D#Dbl#Dbl#Dbl#Dbl#sblaw.RbnaCb#aOaFa#bg.VambnaCbnaw#x.RaYaYaY.baYawbl#pbl.n#Da9a9#D.7#s#D#D#D#D#D#MaYaw#IawaY#x.N#I#x#IaYaY#D#Da9.na9aja9.n#D.N.N#x.CaCb##vaB#uaBaB#v#SaOaOaOaObg.8am.W.WaCaCamaOaB#u#a#faz#Sa#aBaBaz#u#u#uaz.w.wa7#u#uaB.yao.5aC.C#Ia0.pa0aCbnawaY.sbl#saYaYaY#DaYaY#D#s#D#D#D#D#D#D#s#D#sblaY#x#I#x#D#D#D#Da9.n#D#sa9#D#D#D#s#D#D#D#sbl#s#D#saY.saY#MblaY.C.W#I.N#s#Da9#sa9.7.na9.7#L#L#L#L#L#L#L#L",
+"bpaj#Lbp#Lbp#Lbpa2#L#L.7#D.Nbfbf.Va#an#uaB.8bn#D#Da9#Da9.7a9ajafa9bl#Dbl#D#D#M#D#D#Dbl#D#Dbl.NblaYawbnamb#aFbm#Sb#.Vaobn#xbnaYaY.baY#MaYblaYblaY#pbl#p.n#Da9.n#D#D#D#s#D#s#D#D#saY.s#x.s#I#x#Ibn.W#I#xaw.N#s#D#D#D#D.NaY#I#x.WaCaCaCaF#SaB#v#SaOaOaOb#aOb#bgamao#x#I.CaCao.8#u.w.OaG.G#SaBaBbmaB#v#v#va#aB#u.G.Galbk#Taz.w#v#v.5bg.5bga0ao.C#IaYaY#Dbl#DawaY#D#M.NaY#D#s#D#D#s#D#D#MaYblaY#I#x#x#M#s#D#s#D#D#D#D#Dbj#s#D#D#D#s#D#D#s#D#Daw#Daw.N#M#s#x#I.Cbf.s#D#D.n.7a9.7a9.7.E.7#L.7#L.7#L#L#L",
+"#Lbp#L#g#La2bpa2a2#g#La9bj#D.Nbf.RaCaOaZ.yaFa0aY#D#D#s#Da9a9a9a9#D#Da9#Dbl#D#Dbl#D#M#D#D#M#Dbl#saY#xbnaCa0aOaF#Sb#bg.VbnaCbnaY#xaYaYaY.baYblaYbl#Ma9#p#Da9a9#D.7#D#sbl#Da9#Da9#D#D#D#saY.N#I#I#Iaoao.W#xaY.Naw.N#I#I#U.WaCaoamaobnaCaO#vaF#vaOaFbgambgambg.5.8amav.WaC.CaoaF#uaza6.OazaZaB#vaF#vaFaFam.5aF#v#SaB.G.O#3bv.G.GaPaP.w#u#vaFama0.C.C#IawaYawaY.NaYaYaY#MaYaYaYblaYawblaYaw.NaY#I#x#I#D.N#M#D#D#s#D#s#D#s#D#D#s#D#Dbl#s#p#saY#s.Naw.Nblaw#I#xaY.N.N#sa9.7a9.Ea9.Ea9#L#L#L#L#L#L#L#L#L",
+"#La2bp#L#Lbp#Lbp#L#L#L.7#Dbj#D.NaYbna0aoa##vam.C#D#D#D#D.7#D.7a9a9#D#Dbl#D#Dbl#Dbl#Dbl#Dbl#D#DaYaYaYawbna0b#aO.Fbgb#ama0bnbn#IaY.bblawblaYaY#MaYa9#p#sa9a9#Da9#Da9a9a9a9a9.na9a9#s#D#D.saY.NaY#x.C.C.C.W#I#x#I.WaF.8a0a0a0a0aCa0aCaCb##vaFaO#vbgaob#aoaoamaoaCam.W.Caoa0.8#v#ubkab#aan#vaZ#vaFa#aoaobga0aoamamaOa#aBaZ#u.w.w.G#3#3#a.w.y.yaOb#aCbnbn#I#xbn#UaYawbfaYbfaw#x.s#xaY.NawaYbl#x#Ibn#I#Daw#D.s#D#s#D#D#D#D#D#D#D#D#s#D#D#Dbl#saY#saY.saYaw#xaw.N#s#D#D.7.n.7a9.7a9.7#La9aj.7#L.E#L.7#L",
+"bp#L#L#g#L#g#La2#g#L#L#L.7#D#DbjawaYaCamaoa#.8aF.N.s#D#D#D.n#Da9#sbl#D#D#M#D#D#M#D#M#D#Dbl#sbl#saYaY#x#UbnaCb#b#bgb#bga0aCbn#x.RaYaYaYaYawblaYbl#p.n#pa9a9.nbja9.7a9.7#sa9#D.7.na9a9#D#D#D#saY.s#x#I#I#x.C.Wa0aoaoama0.W.C.Wa0#Ibn.paO#S#v#v#S#Sbgaoaoa0aoa0avaCaqaoavao.8#v.w#T.Y#3an#va#aOamaOa0bnaoambgamaoam.pa0bgb#aoaFaO.ybk#T.GaXaz.waBbyaCa0a0bnaCa0#Ibn#I#x#x#x#x#x#xaC#x#I#x#I#x#I.C#IaY#saY#saY#D#M#D#s#D#M#D#M#D#D#D.n#M#D.s#DawaYaw#x#IaYaw#sa9.7.n.7#L.7aj.7#L#L#L#L#L#L#L#L#L#L#L",
+"#L#g#L#g#g#gbp#L#L#L#L.7af.7.7.7#D.N#xaob#.8a#a##DaY#D#D#D#Da9bjbl#D#Dbl#Dbl#D#DaY#DaY#D#M#DaYaYaYawaY#x#Ibna0aCbgb#bg.VaCbn#U#xaw.Raw#FaYblaYbl#D#p#Da9#Da9a9#Dafaj#Laf#Lajaf.7a9#Da9#sa9#D.Nbl.NaY.NaYaY#I.C.Wamaoaoaobga0aoa0aCam#vaBa##SaBaBaobgaoaoaC.Waqaoav.8ao.5aOaBazaX#4alaza##vaOam.5aC.Wa0.Wa0aob#.8bnaCaCaCaC.W.WaC.y.yaB#ubkbkaX.Oazae#vaO.5ao.pbga0a0a0#Ua0aCa0ao.CaCaCa0#IaCa0#IaYaw#D.sbl#s.N#s#Dbl#D#s#D#D#sbl#D#D#saYaw.saw.NaC#xaw#D#sa9.n.7a9aja9#La9aja9#L#L#L#L#L#L#L#L#L",
+"#Lbp#ga2bpa2#L#g#L#L#L#L#L#L#LafbjaYaY#xama0.5aO.N.NaY.s#D#D#Da9#Dbl#s#Dbl#Dbl#D#M#D#M#DaYblaw#D#MaY#I.R#U#x#U#Ub#b#bga0aCa0#x.R.Raw.RaYawaYblaw#p.n#pa9.na9#Da9aja9af.Eaf#Lafajafaja9#Da9#s#Daw#D#s#D#s.NaY.NaY#U#Ua0.paobgb#bgaO#vaB#u#u.y#ua5aObgaoamaoamaoavam.8.8#v#v#u.w.GaTbw.G.0#vaFaoamaoa0aoama0aqamaoamaCaqaC.W.W#I#Iaxbgaobg#va7.Oau.U#3#3a5#uaB#vaFaoaoa0amaCamaob#aoamaoaoa0aC#Ibn.sawaY.sbl#saY#s#D#s#DaY#saY#D#D#s#p#s#DawaY#Iaw.C#I.N.naf.Ea9.7aj#L#Laj#L#L#Laj#L#L#L#L#L#L#L#L",
+"a2#L#g#g#g#gbp#L#L#L#L#L.7#L.7#L.N.N.s#x#xao.5b#.NaY.N#D#D#D#D#D#M#D#Dbl#D#D#sbl#D#Dbl#Dbl.sblaY.NaY#x#I#x#U#UaC.Vbgb#bgaCaC#U#I.R#x.baY.RaYblaYa9#pa9#Da9#Da9bjaf#Laf#Laf#L#La9#La9a9a9.7#Da9#D#sa9a9a9#D.NaY.Na9#paY#Ua0aoaO.yaBaBazazan#u.Gbk.daOaO.8aoavao.8.8.8bd.yaL#uazaX#0#4#TaZaOaO.5aoa0.Camaoamaoamambcby.8.C.C.W.W.W#U.rbgaO#S.yaB#uaP#3.U#3arbk#u#vaFbgbgaob#aob#bgamaOaoaoaoaC#U#IawaY.sbl.s#D#Daw#DaY#s.N#M#D#s#D#s#D#M.NawaY.s#xaC.C#Ma9aj#L.7.naf#Laf#Lafaj#Laf#L#L#L#L#L#L#L#L",
+"#g#g#Lbp#Lbp#Lbpa2a2#L#L#L#L.7#L#D.N.NaYbo.C.C.W.Vbn.N#Dbjbj.E.7#D#D#D#D#s#D#D#D#D#s#D#s#D#D#D#sawawaYaw#x#U#xaCa0aCa0aC.Vamb#a0aYaw.RaY#M#p#M#pajafaj#pa9a9#Mbl.na9a9a9a9a9a9afajafaja9#D#s#D#Dbl#D#s#D#s#D.n#Dbl#saYaYaw#x#IaCaOaB#1a5.w.wbkaV.Qbt.ybcbc.8bcbcaBaB#u#uaz.waP#T.O#zbw.6aF#vaOaFambga0amamaOaoaOaoaCa0.WaC.W.C#I.WaCaoaOaoaOaobg#v#v#S#1.Q#3agaV#1aB.8aOamaoaCbg#v.8aoa0aC#x#U#Iawaw#D.s#D#s#D#s.N#saY#s#Daw#D#Mbl#saYaw#x#I#xaC#D#sbj#D#D.7#s.7.7.E#L.7#Laf#L#La2a2a2#ga2#g#g#g",
+"#gasbp#g#Lbp#Lbp#L#g#L#L#L.7af.7#D.NaYbf#x#x#x#xaCbn#I.N#Dbja9.7#D#D#D#D#D#D#D#D#D#D#D#D#D#s#D#DblawaYawbn#I.WbnaCa0.pa0aoa0aoam#UbnaYaYaYblblbl#paf#p.n#pa9bl#Da9a9a9aja9af.na9.7af.7a9a9a9#D#sa9#M#D#D#D#D#D#D#D#D#M.NaY#x#x#xa0am#vaB.z#u#Ebi#nbCaX.Q.y.y.QaXbka5#u#u.w.wbkaP.O#4#4.wa##v.5a#aoamambg.5aO.5a#aoamaC.WaC.W.W#IaCaC.WaCaoaoaoao.8bg.8#v#v#u#uaPagagaXbka5aBaBaB.y.z#S.8bgaoamaC#x#IaYaw#D#sbj#D.sbl.sbl.N#saY.s#D#MaYawaY#U#x#Ibj#s#Db.#Db.#Dbj.na9#La9aj.7#L#La2#ga2a2#g#gas#g",
+"#ga2#ga2#g#g.7bpa2a2#L#L#L#L.7#L#D#D.N#M.N#I#x#xa0a0#x.s.N.N#D#D#D#s#D#D#D#D#D#s#D#s#D#D#s#D#D#M#D#MblawaYaw#x#I#Ubn#Ua0.pa0.pa0aCbn#Ubnaw.Rawbl.n#p#p#pa9a9bl#Dafa9a9#pa9a9a9afajafaja9.7#D.n#D#Dbl#D#s#D.n#D#s#D#D#DaY#saYaw.N#UbnaCaOaO#vaBbkbq#Rbqag#3.U#zaVau#Tazazbkbkbv#3#E#0ab.2#uaOaF#vaFaOaOaFaObyaO.8aCaCaC.C.W.W#I.W.WaCaC.WaC.WaCaCaCaCaoao.8.8#v#vbbbbap#3.U.U.U#4a5#E#1#SaFaOaOaFaC.W#x#IaY.s#D#saY.s#xawawaY.saY.sbl.NaY.s#x#x#Ia9.7.E.7.E.7.n.7a9#L.E#L.7#L#L.7#L#L#L#L#ga2bpbp",
+"#g#g#L#gbp#g#Lbp#L#g#L#L#L#Laf.7#Da9#D#DaY.N.N.sbn#Ua0.C#x.N#s#D#D#D#D#D#s#D#D#Da9a9.na9a9a9a9#Dawbl#saYawaY#U#x#U#x#Ubn#Ibna0aCa0a0#UbnbnbnaY.Rbl.n#D#p.n#pa9bla9af.nafa9afa9a9#Laf#La9a9a9bja9a9a9.na9a9.7a9.7a9a9#s#D#DaY.Naw#xaw#xaCamaoaOaB.v.O.Obqadbx.abzbi.U#3#T#3bvagag#3#4#caT.w#vaF.y#v.5#vaOa#ao.5.5aC.CaC#I#I#I#Ibo#I#Iaw#Iawaw#I#U#7.W#IaC.WaCav.W.8#v#v.y.w.G#T#3.Oag.O.w#uaB.ya#aoamaC#x#I#x.N.s#xaw#I#x#Ibfaw.Nbl.s.Naw.NaY.saY.E.7af.Eaf.7#L.E.7aj.7#La9aj#Lafajafaja2#L#ga2#g",
+"#ga2#ga2#Lbp#Lbpa2a2#L#L#L#L.7#La9.7a9#D#D#DaY.NaY#xa0#U.CaYbl#D#D#D#D#D#D#D#D#Da9a9#Da9#sa9.na9#D#M#Dbl#saYawaYawaYaYawbn#Ibn#IbnaC#xbn#Ibna0bnblblbl#Dblbla9a9.na9a9a9a9.na9a9af#L#L.na9bja9#D.na9a9a9.n.7.n.7.Ea9.7a9#s#D#D#D#sblaw#IaCaobg.d.O#ia5.G#zadadadabadaVaVbq#3#3bvbqaba8.YbkaBaO#uaFaOaFao.5aoaqaC#I#I#Iaw#I.s.sawbobo.sbo.sbobo.s#M#M.s#7aw#Iaw#I#U#IaCao.8aO#v#u.Q#3biag#3aXazaZ#vaOam.C#x#I#IaY#I#x#I#I#x#I#xaw.Naw#D#s#D#s#Da9#Laj#L#Laj#Laj#L#La9#L.E#L#L.7#Laf#Laf.7#L#L#L#L",
+"a2a2#L#g#L#L#L#La2bp#L#L#L#L#L#L#L.7#La9.7#Da9#D#DaYbnama0#xaY#s#D#D#s#D#D#D#D#Daj#Lafajaf#La9a9.na9#M#D#MaY#MaYbl#MawaYaYaYaw#x.RaY.b#xbnbn#Ibnaw#xawbl#D#Ma9#pafa9afa9afa9afa9aj#Laf.7a9.n#Da9ajafa9aja9#L.7#Laf#L.E#L.7.Ea9#sblawaw#xaCaCaO.8aBazbka5.Gbk.U#3biad.a.a.DaVaVaV.M#d.S.Yaz#u.0.y#vaF.8a0.W.C#I.C#Iaw.Naw.s.s.s#s#s#s#s#s#s#s#s#s#s#s#s#M#s#s#s#s.n.n#M.raC#OaO#w#u#E.vbkazbkbkbk.w.yaOamaC.C.C#I#I#I#x#I#x#I#x#Ibf.s.N#s#D.7a9.E#L.E#L.E#L#L#L#L.7aj.7af#L#L#L#Laf.nafaj#L#L#Lbp",
+"#gaa#ga2#L#L#L#Lbpa2#L#L#L.7#L.7#Laf#L#L#La9.7#D#saY#xa0ama0aYaY#D#D#D#D#Da9#D#Daf.7aja9#L.n#Laj#p.n#p#Dbl#s#DaY#sbl#D#MawaYaYaY#Mblbl.baYawbnbnaYaYaYaYbl#D#pa9a9a9a9a9a9a9a9a9afafaja9a9bja9#Dafafajaf#L.Eaf.Ea2#Lafaja9a9#s#D#sawaw#IaC.WaoaoaO#uae#1#u#uaz#u.O.Ubi.D#d.D#J.D.abu#6.Y.G.w.yaZ.8aoam.W#xaw#I.saw.saw.s.s#s#sbj.Eb.#sb.b.#sb..E#s#s#s#s.s#s.E#s#s#s#s.r#U#IaCaCbd#1#SaOao.ya5bkaza5.waOamaoaC#x.WaC.W#I#x#I#x#I.Naw#D#D#s.7#L.7#Laj#L#Laj#Laj#Laja9#L.E.7.n.7.Ea9a9a9a9a9.7#Laf",
+"a2#g#L#g#L#L.7#La2#g#L#L#L#L#L#L#La2#Laf#Lbja9a9#DaY.C.VaFa0#xaw#D#D#D#D#D#D#D#Dajafaf#Laf#Lafaf#p.nbl.n#Dbl#M#D#Ma9#M#DaYaw#Dawbl#MaY#Mbn.RaYawbn#xaw#x#Mbla9.naf#paja9af.nafa9aja9#La9a9a9#s#Daja9#La9#Laf.7#L#Laj.n#L.7.n.7#s#Daw#x#I.CaC.8.8#v#v#v#vaO.z#1.z.Gbk.O#zbibBbBad.x#5#9.YaPaz.y.0bgaoam#Iaw.N#s#Dawaw.s#s#D#s#s#s.E.7.E.7.E.E.E.Eb..Eb..E.E.E.E.E.s.saw#IaC.WaC#Oam.d#vao.8aFaO.8.G#3.OaB.8amaCaCaC.Wa0#I#I#I#I#x.s.N#s#D.na9.n#Laj#L#Laj#Laj#Laj.7#L.7af#L#Laf#Lafa9a9.na9a9.7.7",
+"#L#L#L#L#L#L#L#L#La2bpa2#ga2bp#L#L#L#L#L.7a9.7.7.NaY#xbnao.VaF.V#xaY#Ma9.na9a9#D#La9aja9aja9aj.7.na9.na9.na9.na9#p#s#p#D.na9a9.n#p.nbla9#sbl#saYaYaYaYaYaYaYaYaY#pa9#p#pa9#pa9.nafafaja9#D#D.N.N.nafajafaja9ajafajaf.7.na9#D.n#D#Dawaw#I.W#IaCaCaobdaO#v#v.y.y.y#u.QaX.9#TbC#r#r.aatatbB.2aX.GanaC.W#Ibobf.sbf#I#s#s#s#sb.b.bj#s.7.E.E.E.7.Ea9.Eaj#Lajajajajajaj.s#s#I.s.s#I.s.WaCaCaCaCa0.W.W.W#v#vbtbkbk#uaB.0aObgaoaoamaC.C.W.n.na9.E.7.E.7#Lbjb..Ea9aj#L#La2a2.jbpaj#L.E.7bjajaf#La9#Laf#Laf",
+"#L#L#L#L#L#L#L#L#L#ga2a2bpa2a2a2#L#L#L#L#L.7#L.7#DaY#Ibnb#b#aOb##xaY#D#Da9.n.7#Dafajaf#Laf#Lafafa9aja9a9.na9.na9.na9.na9#p.na9a9afa9.n#p#D#M#DblaYawaYaw#xaw#xaY#p.na9a9a9a9#p#pafaf#pa9#D#s.N#sa9a9#La9#Laf#Laf.7aja9.n.7.n#Da9.saYaw#x#I#x.W.WaCao.8.8aObc#v.y#v#ubkbvbvaXbvbC.k.Dai.UaXbv.Ga7aOaoaNboaWbo.s.Nb.#sb.#D#s#sbjb.b.a9b.a9.E.7.Ebjajaja2aj#Laj.naj#D#s.sbo#I.sbo.saCaCaC#I#I#I.W#xavaoaO.y.z#1bkbkaBaBaO.5aoaoav.Wa9#s#L.E#L#L.7.E.7#D.7.E#L#L#Laja2bpa2#L#L#L#L.7af.7afajafaj#L#L",
+"a2#La2#ga2#ga2#ga2#L#ga2a2#g#L#g#L#L#L.7af.7a9.7#Daw#x#xam#SaZa#aC#xaYa9a9a9#Da9aja9#L.n#L.n#Lajafa9.naf.na9a9.na9a9.na9.na9a9.n.na9a9.na9#D#D#saY#x.R#xaYbn#x#xblblbl#Mblbl#Dbl.n#p.nbl#D#D.N.N.naf.nafaja9#L.n#L#La9.7.n#D#s#saYaw#I#I#I#U#Ia0.Wao.8aObc.8.y.y#u#ubk#3bCapbkag.kbqaX.Q.Qbka5#u#v#vamava1bob..E.na9b..E#s.7.E.E.7.E.7.E.7.E.7.naj#L.jaja2ajajaj.n#D.s#I.s#I.saY#I#U#x#I#x#x#Ibo#x#I.CaoaO#v.y#1bkbk#u#vbcam.C#I#sa9.n.7.E#L.E.7#s#s.7.n#Lajbpa2bp.jbp.j#Laj#L#Lajafajaf#La2afa2",
+"#ga2#ga2a2a2#g#La2#ga2#g#L#ga2a2#L#L#L#L.7.7#La9#D#D#xaCaF.0aZana0#xaYbla9.na9#D#Laf#Laf#Laf#La9af#L.na9af.nafa9ajaf#Laf#Lajaf#Lafajaf#L#D.n#D#DawaYaY#IaY#I#x#IaYawaYaYaYawaYawbl#Mbl#D#sbl.s#Da9.na9.7afajaf#Laf.Ea9.Ea9#sa9#s.N#I#x#I#x#Ia0#I.Wao.8.8aObc.ybba5bkaXaX#3bvag#n.c.#bt#baLbcbdaBaB.y#vam.Wbfb..7#s#s#s.7.E.E.E.7#s.E.E.7.n.7.E.7aj#g.ja2.jaja2#L.E.n#s.s.s#I.s.s#x#I#I#x.s#I.Nbo#x#I#I.CaoaoamaObkaz.Q.z#v.8.Wbf.N#s.N#s#D.sa9.E#D#D.E.7#L#Laj#Laj#g#L#g#L#gbp#L#L#L#L#L#La2bpa2",
+"a2bpa2bpa2bpa2a2#g#La2bpa2a2bpa2#L#L#La9#L.7a9.E.7aYaY.Cam#vaZaZaobn#xbla9a9a9#s#L.n#L.n#L.n#Lajaf#Laf.na9a9ajaf#L#Laj#Laf#L#Laj#L#L#Laj.7a9.7a9#D#Dbl.NaYaY#xaY#xaY#x#U#xbn#IbnblaY#MaY.NaY#s#D.na9aja9af.7af.E#Laja9a9b.#D#s#Daw#x#I#I#x#I.Wbn.Wa0aoao.5.8.y.QazaX#3.O#3aVai#n#8aLax#O.W.Wao.8#1aB.y.5.Ca1bo.sbo#D#sb.#D.E.7aj.7.E#D.E.7.E.7.7.ja2.j#gbp.jaj.j.7#s#s#s#s.N.s#Iawaw#D.saw.N.s.s#D.s#x.W.WaoaC.8.0.y#v#v#v.d.8ao#I#Ibf.s#Db.bj.7#Dbj#L#Laj#L#L#La2aj#gaj#ga2asasa2a2a2a2#La2a2#g",
+"#ga2a2a2#ga2a2#ga2a2#ga2a2#L#ga2#L#L#L#La9.7.7a9.7.N.s#xamaF#va#.5am#x.N#D.na9.7af#Laf#Laf#Lafa9#L.n#La9.naf#Laf#Lajaf#L#Laj#Lafa2ajaf#Laf.7.7.na9.n#D.nbl#D#DawaYawaY#U#x#U#x#UaYaw.Nblaw#D#D#sa9.na9.nafajaf#Lafaj.7.na9#sa9#saY#I#I#xaC#xao.CaCavaoao#v.yaI.Qae.O#zaV.Dah#Xag#b#O.r#7#7#7.W#QaObdaB.y#vaoaqbo#Ibobf.N.Ebj.E.7.E.E.7.E.7.E.7.Ebp.j#g#g.ja2#L.j.E.7#s.nb.#s#D.saw.Naw.s#D.s#s.N.s.sbo#I.C.Wam.8bgbgamao.C.8axbcaxaoaobo.N#s#Db.#s.7.E#L#L#L#Laj#L#g#La2#gas.jasbp.j#L#g.j#g#L#g",
+"a2asa2asa2aa#ga2#g#L#g#Lbpa2#L#L#L#L#L.7.7.n.7.7a9.saYaY.Wa0amam.5am#IaYbla9a9a9aja9aja9aja9ajaf#Laf#L.na9#L.n#Lajaf#L.jafa2a2.ja2a2#Laj#Laja9#L#Laf#Lafa9.n#D#DaY#xaYaYaYawaY#U#xbnawaY.Naw#D#sa9.na9af.na9.na9.Ea9.na9.E#D#s#D#I#x#I#x.WaCaoaoao.8.8.8.y#1#1.Q#T#3bq.D#m#haibkavao#7aE.sbo.W.W.s.Wbd.GazaBbc.8##avbobfbobjbjb..7.7.E.7.E.7.E.7#g.j#g.j#g.jaja2.Eaj.n#D.nb.#sb.#D#s#s#D#s#D#s#s.s.N.N#I#x.Wam.WaC#x#I#xaCa0av.8.8.8ao.W#Ibo#s#s#Dbj.7#Lajaj#L#Laj#gaj#g#gasasaU#g#g#ga2bp#ga2#g",
+"a2a2#ga2a2#ga2a2a2#ga2aja2bp.ja2#L.7#L#L.7a9.7a9bj.N.N.N#xa0a0aCaF.5bnaY#D.na9.7af#Laf#Laf#Laf#L.n#L.na9.naf#Laf#Laja2#La2aja2#La2aja2#Laf#L.E#L#Lajafaj#La9#L.nblblbl#MblaYaYawbn#U#x#xaw.N.s#D.nafa9.na9a9a9.na9aj.7#sa9#sa9#s#x#I#x.Wbnavamaoao.8aObd.ybt#ubbag.O#3bA.iaJ#3bbav.h#7b.b.boa1#IaE#I#QaB#uaPaz.Gbcbcavavbobfb.bj.E.7.E.7.7.E.7#L.j#g#g#gaj#g.jajaf.E.n#s#s#D.E#D#s#s#D.s#Db.aW#sbf.Nbo.C.Wav.Cam#Mblaw#x#Iaoaqaoaqavavaoav.s.Nb.#D#s.7.E#L#Laj#g#Lbpa2asas.jaUaU#ga2bpa2#g.jbpa2",
+"#ga2#g#g#ga2#g#ga2#g#g#ga2#g#Lbpa2#L#L#L#L#La9.Ea9a9#saY#I.C.Wam#x#U#x#IaY.N#D#Daj#Laj.7.7a9.7.7a9#Laf#L#L#L.n#Lafafafajafaf#Laj#L#L#Laj#Laf#Laf.jaf#Laf#Laja9#Da9.na9#Da9.n#D#DawaYawawaYaY#MaY.7.n.7.n.7.Ea9.7ajaf.Ea9#s#D#D#D#Ibn#UaCaoao.8#vao.d.d.y.z.y#1bbagaX#3aAbx.caLav#7#I.s#7b.#sb.b..sbo#Iav#QaOaKbtau.GaZaFaq#Ibf.s.7.n#L.E#L.7aja3.Ebp.jbpbpajbpa3#s#D#s#s#s#s#D#sa9.n#D#s#D#s#D#s#x#Iaw#I.N#s#s#D#saY#saYaY#I#I#I#I#U.W#IaC.8ao.C#sa9#L.7.n#L#L#L.ja2.j#gasasas.jas#g.jas#gas#gas",
+"a2#ga2#ga2#g#ga2#ga2a2bp#ga2bp#Lbpa2#L#Laja9.7#La9#D#D.N#x#x.C.CbnbnbnaYaY#D#D#D#L#La9aja9.7.E#D.nafajaf.Eafafaj#Lajaf#Lafajafaf#Lafajaf#L#Laj#L#La2afaj#La9a9.na9bja9.na9#D.na9awblaYawaYawaYawa9.na9.Ea9a9.na9ajaj#L.n#D#s#s.N#U#Ibn.WamaO.8#v#OaObdbd.yaLbb.Q#8.v#3aV.abCbd.8#7#7.sb..sb..sbj#s.s.s#I.Cav.8.8#u#uaB.ybcao.Wbf#D#s#D.7.E.7.Ea3ajbpajbpajbp#L.E#s#D#s#D#s#D#s#D.n.7#s#D#s#D.s.N#x#I.NaY.s.N#s#D#s#D#M.N.s#I#x#I#x#I#x#IaCbd.8ao#s#D#s#L.7aj#L#L.j#gas#g#g.j#gas.jas#gas#g.j#g#g",
+"#g#La2#ga2#ga2bpa2bpa2#L#L#L#g#La2aj#L#L.7.7a9.7.n#D#saY.s.N#x#I#x#xawaY#Ibl.N.Naf.E#La9.7#sa9#D.n#Laf#Laf#La9afaf#Lajaf#Lafaj#Laj#L#L#Lajaf#Laf.j#Laf#Laf#La9a9a9a9.n#Da9.na9#D#D#s.N#s#D#s.N#s#D.Ea9a9.Ea9.7.na9.na9#s#D.s.N#x#Ibnbn.Waobg.8.8.d.d#vbd#v.z#1bb.QaX#3aA.kaXbcao#7.s.sb.b.b.b.#s#s#D.s.N.s#x.CavaFam#v.y#u.ybyby#Ibf.s.Nb..7.E#L.7.E#L.7.E.7.E.7#s#s#D#s#D#s#D#s#D#s#D#s#D.s.N.s#x#IaYbo.s#D#saW.n.7#s#D#s.N.s.s#I#I#I.CaCax#vaO.saw#s#D.n#Lafaja2a2.j#gas#g#g#g#g#g.j#g#gas#g.j",
+"#ga2#ga2#g#L#ga2#ga2#g#L#g#L#L#L#g#L#L#L#L.n#L.7#D#D#D#DaYaY.N.NawaY#xaY#x.NaY#Ma9.7a9.Ea9#D#Da9a9af.7af.Eafaj#Lajafafafaj#Lafaf#Lafaj#Laf#Laj#La2af.j#Laf#La9.7a9.7a9.7a9#Da9a9#s#Dbl.saY#saY#s#D#s#D.na9.Ea9.7a9.n#D#s.N.s#xbobna0aCa0am.8aOaO.8#vbd#vbd.yaL#1.Qbk.Obi#R#8#v.rbo.saE#sb.#sbjb..7.E.n.E#s.s#I#xbo.Wavbc.y#u.yanaoaq.Cbo.N#D.E.7.E.7#L.E.7.E.7#s#D#s#D#s#D#s#D#D#s#s#s.N#s.Naw.N#x#xaw.N#s#D#sbj.n.7.E#DaE#saYboaCaCaoaoaoao#Oao#Iawaw#s#D.n.7a9aj#g#L#g.j#ga2#g.jas#gas.j#gasas",
+"a2bp.jbpa2#ga2bpa2bpa2#L#Lbp#L#L#La2#L.7#L.7a9.7#s#D#D#D#D#s.NaYaYaY.s#x.s#xaYaY#D#s#D#D#D#s#D#sa9ajaf#Laf#La9af#Lajaf#Lafajafaj#L#Lafaj#L#L#L#L#L.jafa2#Laja9a9.na9a9.na9.na9#s#D#D#s#D#s#D#s#D#sa9#sa9#Da9.n#D#s#D#D.saY#xaY#IamaCamaobgaObcbdaOax#vbd#v#v.yaL#1.Qa5#3#R.vbc.W#7#s.sb.b.bjb.bj.E.7.Ea9bj#s#Daw#s.Nbo.C.8#van#ubc#v.8a0bf.s#D#sbj.7bj.7#D.7#sbjawaY#saY#s#D#s#Daw#DaY.saY.NaY.saY.saY.N.s#D#s#D.Ea9#s#s.N.sboawao.8.d.daoaC#I#x.sawbo#M#D#Daj.7#L#L.jbpa2bpa2#g#g#g.j#gas#gas#g",
+"#ga2#ga2#g#L#g.ja2#g.jbpa2aj#Lbpaj#L#Laj#Laf.7af#D#D#s#D#D#D#D#D.N.saYaY#xaY#x#IaY.N#D#D#s#D#Da9#L.na9.na9ajafajaf#Lafajaf#Laf#Lafaj#L#Lajaf#L#La2a2a2#Laf#La9a9.7a9.7#Da9bja9a9.7#sa9#D#s#D#s#D#s#D#D#s#D#s#D#sa9#s.NawaY#I.C.WaF.8b#ao.8bg#vbd.8#vbd#vbd#v.d#v#1#1.wagbi#8ao#O.saE.sb.#sb.#s.Eaf.Ea9.E.n#D#s#Db.#s.N#Iaqambca#aB.y#vaO#I.Cbf#I#s#Db.#Db.#Dbj#saYawaw#D.saY#M.N#M.N#saY.s#x.s#x.s#x.s.N#s#Db.#D#Db..N.s.N#Ibo.W.CaoaxaoaxaCaC#I#x#I#I#Iaw#s#D.n#Laj#L#Lbp#L#L#L.j#ga2#g.ja2.j#g",
+"#L#g#L#g.j#ga2bp#g#L#g#L#Lbp#L#L#La2.7#L.7.Ea9.EaY#D#D#s#D#s#D#saYbl.NawaY#UbnbnawaYawbl#D#p.na9afa9.n#La9#La9#Lajaf#Lafajafajaf#L#Laf#L#L#La2.ja2#La2#L#Laf.7a9a9a9a9.na9.na9a9.7a9#s#D.n#D#s#D#s.N#sbj#D#D#s#DblaYaw#x#I.CaCamaOaF.8.8aO#vbdaO#v.d#vaO.8aObd#v.zaBa5.O#r.Q#O.Wbo.s.sb.aEbjb.bjb.a9.E.7.n#s#D#s#D#D.s.N#Ibf.W.C#v#va#aOaF.8aoam.s#D#s#D#s#D#s.saYawaYaYawblaYaw#DaYaYaYbl.N#x#xaY.saY.N#s.N#saWawaY#I#x#I#x#IaC.C.WamaCaC.W#I#I#I#x#I#I#I.s#sa9.E#L.E#Laja2bpa2a2.j#ga2#ga2#ga2",
+"aj#g.ja2#g#L#ga2#ga2#ga2bpa2#L#L#Lajaf.Eaf.7a9.7aY#s#D#D#D#Da9a9.saY.saYbn#x#xa0#I#x.NaY#M#Da9.na9aja9a9.nafajafafafajaf#Laf#Lafaj#Lajafaja2#L#La2.3#L.jaf#L.na9.7.n.7a9bja9#D.n.7#sa9.n#D#s#D#s#D#s#D#D#s#D#s#DawaY#Ibn#Ia0aoa0#v#vaOaFaObd#vax.ybc.d.8.8.8.8bd.y#1a5aX.v#1ao.W#7.saE.s#sb.#Db.#s.7.E#D#s#D#sa9#s#D#s#D#s#D.s.saFaFamaO.y#v#v.5#I#Iawbf.s#x.s#xawaYawaYblaw#DblaY#Mbl#saYaw#x#I#x.Naw.N#sbj#s#D#I.WaC.WaC.Wamao.8aoao.W#IaY.NaY.N.N.s#D.saw#s#D.n.Ea9aj#Laj#Laj#ga2#gas.j#g.j#g",
+"a2#ga2#ga2aj#L#L.ja2a2aj#L.E#Laj#pa9a9#pa9.n#pa9#M#Dbl#Dbl#MaYaYaYawaYaYawaY#UaYa0.p.VbnaYawa9#La9a9ajaf#L#Lafaj#L#L#Laj#Laj#L#Laf#L#L#L#L#La2#La2a2#La2#La2#L#L#L#L#L.Ea9.7#s#D#La9.E#D.na9.na9.n#s#D#saw.Naw#xaw#I#x#I#U.CaCaoao.VaoaoaO.8aO.8#Oaoaxao.haC#Oao.daO#uagbibk#vav.W#I#s.E.Eaj.Ea3aj.n#L.E.7.nb.#s.N.saY.N#I.N#IaY#I#I.C.8#v.yaBaPaBa#aFa#.5aqaqaN#xbfbf.N.NaY.Naw.NaYaY.Naw.NbfaYawaYaYaw#x#I#xa1#U#I#U#I#x#I.N.s#D#s#D#Dbj#sbj.E.7.Ea9.7.7#L.7.7.7.7.E.7#L.7#Lbpa2.jas#g#gas#gas",
+"a2.ja2#L.j#L#La2a2#g#L#Laf#L.7#La9#pa9a9#pa9#pa9bl#Dbl#sbl.NblawblaYblaY#xaYaY#Ubna0b##UbnaY.n.7#s#Da9.na9.n#Laf#Lajaf#Laf#Lafaj#Lajafaj#L#L#L.j#L.j#La2af#La9a9#L.7#L#La9.7a9#Da9.Ea9.n.7.n.7#s.na9#M#Daw#x.s#xawbn#I#U.CaCaCaCaobgaCaoaOaOax#vao.hao.W.W.Wav.haoax.y#E#zagapbc.Wbo.s#s.E.Ea3.E.7aja9.Ea9b.a9.EaY.Naw.Naw.Naw.N#I#x#Ia0amaF.yaBa7#u.ya#aoaqavaq#x.C#x#I.Naw.NaYaw#x#I#I#x.s#xboaYaY#I#x#I#x#IbfblaYbl.NaY#D.N.N#Dbj#sbj.Ebj.7bja9#L.E#Laj#Laj#L.E#L#L.7aj#La3ajas#g.jas.j#g.j#g",
+"a2#gas.ja2#L#Laja2#Laj#L#L#La9.7.na9a9#Da9#Da9a9#s#D#D#s#D#s#D#Dbl#sbl#D#M#DaYaYaY#Ubga0bnaY#s#D#s#Da9a9.na9ajafaj#Laj#Laj#L#Laf#L#L#Laf#L.j#L#La2a2#La2#Lafa9a9ajafaja9a9#s#D#s#Da9.n#D#sbl#s#D#M#s#D#Maw.N#I#I#I#I#x#I#IaC.CaC.paCaCaoao#O.8ao.h.W.W.W.W.W.W.W#I#Q#v.w.Obiagbk.W.r#I#sb..E.E.Eaja9.E.n.7.n#D.saY.saY.Naw.NaY.Naw.N.s#xaCaq.8aF#Sa7a7#u.yaFam.5ao.Ca0.C#x#x#x#Ibn.R#x#x#xaY#xaY#Ibn#UaC.W#xbf.sbl#s#D#sa9.Ea9.7.E.7.7#L#L#Laj#Laj#L#L#L#L#L#L#Lbpajbp#Lbpbp#Lbp#g#gas#g#gas#gas",
+"a2.ja2#La2aja2#L#L#Laf#L.Ea9aja9a9a9a9.na9a9.na9#D.n#Da9#Da9a9.na9a9#sa9#D#D#D#saY#xaCa0#U#x.N#s#D#D.na9a9.n#La9#L.n#Laf#Laf#Lajafaj#Laj#Laf#L#Lafajafafaj#L.Ea9#La9a9.n#D#D#D#D#D#s.Nbl#D#s.N#M#D#M#D.saYawaw#IaY#I#U#I#x#IaC.WaC.CaC#IaCavao.W.Wav.W.Wbo#I.W.Wbo.W#Q.y.w.Uau#3bd.8bo.s#s#sbjb.a9.E.n.7b.#sbj#s.Naw.Naw.NaY.saY#s#s#D#I#x#Ia0aoaFa#aBaBaBa##va#aoa0aoa0aoa0aC.Ca0#xaCbn#I#xaw#xa0aCa0#x.Caw.N.Na9a9a9a9.7a9.Ebj#L#Laj#L.E#L.7#L#L#Laj#L#Laj#Lajbp#L#Lbpajbpaj#Las.j#g.jas#g.j#g",
+"a2a2a2.ja2#Laf#Lajaf#Laja9a9.7a9a9.na9a9a9a9a9a9.7a9.7.n.7.7a9.7.7#L.7a9#s#D#D#D#D#Mbnbn#x#xaY.N.s#D#D#sa9a9#Laj#L#L#Laj#Laj#L#L#Laf#Lafaj#Laj#La2a2afajafafa9a9a9.na9#Da9#s#D#D#MaYblawaYawaYbl.s.Naw#D.saYawawawaw.s#I#I.C.W.W#U#I#I#x.WaC.W.W.W#I#Ibo#xbo#I#Ibo.Wavbc.y#u.G#3.Qbc.Wbfaw.s#sbj.n.7.n.7#s#D.s#D.saY.NaY.N#M.NaYb.#D#s#Daw#Ia0#UaFaOamam.5.8.yaB.8aO.5ao.5amam.8amaCa0a0#x.C#I#Iaoam#I#xaY#D.N#Da9.7.7.7a9.7.7.7aj#L#L#L#L#Lajbp#Lbp#L#Laj#L#L#L#Lajbpaj#L#Lbp#L.j#gas#gas#gas#g",
+"a2a2.j#La2#L#L#Laf#Lafa9a9a9#D#D.7#Laf#L#Lajafaj.7aj#L#L#L#Laj.7aj#Laj#Lbj.7.7b.a9#D#D#xaCa0.W.NaYaw#D#Da9.na9af#Lafajaf#Laf#Lafaj#Laj#L#L#Laf#L.3ajaf#La9aj.7a9a9a9a9a9bl#DblaY#DaY.NawaYblawaY.NaYaw.sbl#s#Maw.N.saw#x#I#I#I.C#I#x#I#I.W#Ibo#Ibo.Wbf#Ibo#Ibfbo#Ibo.W.8#Qbc.ybkbv.Q.8#I.s.s#s#sb..nbj#s.N#sbj#saY.Naw.saY.NaY.s#D#s.Nbo.N#I#I#xaCamao.Ca0b#aobyaOaF#v#vaB.y.ya#aOaF.5aCa0aC.CaCbn#xaY#D#D#D.7#D#Laj#L#Laj#L.7#L#Laj#L#Lajbp#Laj#L#gaja2bpa2bp#g.jas#gas#gas.j#gas#g#g#g.j#g.j#g",
+"a2.ja2#L.j#Lajafajafa9a9a9#Da9.n#L#L.7#L#L#L.7#Laf#L#L#Laf#Laf#L#L#L#Laj#Laj.7.7#L.n#DaY#x.W.C.C.s.NaY#s#D#Da9#s#Laj#L#Laj#Laj#Laf#Laf#Lajafaj#Laja2afajafafa9.na9#pa9#M#Dbl#DaYaYaYawaY#xaYaYaYaw.Naw#D#sbl#s#M#s#saY.s.s#x#I#I#Iawawawbo.N.s#I.s.s.sbo.N.s.s#I#I#x#Ia1.Wao#vaLbkap.yaobo.N.N.s.7#s#sbj#s#D.sbjaY.saY.Nbl.saY.N.s.N.s.N.N#I#x.sbfbf.C.WaCaqamaq.5aoa##v.0#u#u#ua##vaOaFama0#x#xaYaY#D#Da9.7#L.Eaf#Lafaj#Lbpbp#Lbpa2bp.jbpa2#L#ga2aj#g#L.jbp.j#L#g#g.j#g.j#gas#g.j#g.jas#gas#gas",
+"a2#L.ja2a2#L#L#Lafafa9.na9a9a9#D.7#L#Laj.7#L#L#L#L#Laj#L#Laj#Lajbpaj#Lbp#L.7.7bj#L.7#DaY#xa0.C.WaYaw.N#D#D#D#sa9aj#L.Eafajaf#Laf#Laj#Laj#L#L#L#L.3#L#Laf.7#La9a9a9a9#p#Dblbl.NblawaYaYaYaYawaYawaY.NaY.sbl#sa9.n#D#D#saw.s#I#I#xaw#x.saY.s.s.N.s.N.s.Naw#D.s.N.sbn#I#Iboa1#b.d.8#Tap.Qbcbo#D#sbo.nb.#D#s.Nb.#D.s.Naw.Naw.NaY.Naw.Nbf.s.N.sbfaY.N.saY.sbf.C.Waqavbga#a#a#.yaZ.0anaBbm#vaOaobn#I#xblaY#Ma9a9af#La2#L#L#Lbp#Lbpaj#L#g.ja2bpa2aj#gaja2#g#L#g#L#g#L#g.j#gas#gas#g.j#gas#gas.j#g#g.j#g",
+"as.j#g#La2aj#Laja9ajaf#L#L.n#Laf#Laj#L#L#La2#ga2#ga2a2a2#ga2a2#g#L#Lbpaj#Laj#Laj#D.s#DblaY.VaObm.C#IaYaw#D#s#D#Dbl#Ma9a9af.7aj#Lajaf#Laf#Lajafaj#Lajafaj#Laj#L#Lajafa9a9.7#sa9#DaYaYaYaYaY#xaY#x.N#s#D#s#D#s#Db..n#sbj.n#D.sbfbo.s.s.N.s.N.s.s.N#s#D#s#D.s.N#Ibf.s#Ibo#I.Wav.8bcbta5.U#3aB.5.W.N#x#I#x.saY.s.N.N.s#D#Ma9b..E.7.nbfaw.NaY#xaY#Ibf#D#s.N.N#x.Waqavb#ambga#aO.0.y.yaoaCa0#x#xaY.N#D.Ebj.7.7.7.7.7.7#ga2#ga2#ga2#g#ga2#ga2aj#g#g#L#g#g#L.jbp#Lajbp#L#g.jas.jas#gas.j#ga2#ga2#g.jas#g",
+".ja2#Laj#L#L.7.7af#Lafajaf#Laf#Lbpa2#La2#L#L#Lbp.ja2#g#ga2#ga2#g#L#L#L#L#L#L#L#L.7#D.NaYaYaobmaZamaCbn#x.NaY.N.N#Mbla9.nafajaf.7a9#Laj#Lajaf#L#Laf#L#L#Laf#Lafaja9af.7.n#Da9bja9#xawaYaYawaYaYaw#Dbl#s#D#D#s.7.n.7b..nbj#sbj.s.saw.s#D#saw#D.s#D#s#s.s.N.sbfawbf#Ibf.sbo#Iav.8bc#uaz#3bi.G#vaq.W#I#x#I#x#x#x.s#DaY#s#D#s#D#s#Db.aY.saY.N#I#I#x#x#I#x#I.C.WaqamamaFaObm#vaBaZ#va#bna0#xaYaw#D#D#Dbj.7.7.7.7.7.7.7#g.ja2#g.j#ga2bpa2a2a2#g#La2#L#g.j#g#gajbpbp#Lbp.j#gas#g#g.j#gas#g.j#g.ja2a2#ga2",
+"#L#L#L#L#L.na9.n#Lafajaf#L#L.ja2#L#Lbp#Laj#g#L#L#gbp.j#L#gaj#ga2aj#g#Lbpajbp#Laj.7#D#sblaYb#aOa7b#amaoa0aC#x.baYbl#Mbla9#D#L.na9aj#Laf#L#Laj#Laj#Lajafaj#L#Laj#Lafajaf.7a9a9#Da9#Dblblblblblblbl#D#s#D#D.n.7.E.7.E.7.7.E#s#s#D.s.N.s#Db.#D#s#D#sbj#s#D#s.N.sbfboaYbo#Ibf.Wavbcbc.wa5au.M#3.w#v.5#Ibn#I#IaY.s.N.N#saY#s#D.s#D.s.NawaYawaY#I.C#Ibn.Wa0amamao.5.8.5#uanaB.ya#aoama0awaYaY.NaY#D#D#D#L#L#Lbp#L#L#L#Laj#gbpa2bpa2.j#g.j#L.j#L.jbp#g#Las#ga2#ga2aj#L#L#g.j#g.j#ga2#g.ja2#ga2#g#Laj#Laj",
+"#D.na9#sa9#Da9#Daj#L#L#Lajaf#L#L#g.ja2#g#g#g.j#ga2a2#g#ga2#ga2bp#ga2#ga2#ga2#g#g#Lb.a9aY#UambmaZaO.t#SaFb#a0a0#UblaY#s#D.na9.7.n.7aj#Lajaf#Laf#Laf#L#Lafaj#Laf#L#Laf.7af.7.n.7#D#M#D#D#D#D#D#D#s#D#Da9#sa9.Ea9aj.7.E.E.7.7b.#sbj.s#s#D#s.N#saW#s.N#s.Nb..N.Nbo.N#xbo#x#I.Wav.8.yaz#T#3#z#z.O#uaF.CaC.C#x#I.Naw#D.sbl.saY.s.Nbo#Ibn#U#x#Ua0#Ua0aCb#am.8a##va#aBan#u#u.0aFama0#xaY.NaY#D#s#D.7.7.7#Lbpaj#Lbpajbp#Lbp#L#L#L#Lbp#L#L#L#L#Lbp#L#Lajbpas.ja2.j#ga2bp#Laja2#L#La2aja2#L#L#L#Laj#L#Laj#L",
+"a9a9a9a9a9.na9a9#Lafajaf#L#La2a2aj#g#ga2#L#g#L#g.j#g#g.j#g#g.j#ga2#gaj#ga2#ga2#g#L#L#L#s#xb#aOa#.t#SaZaBbmbga0bnawaYblbl#Da9.n.7#Laf#L#Laj#Laj#L#Lajaf#L#L#Laj#Lajafajaf#La9a9a9#D#D.na9a9.na9a9a9.na9.7a9.E#L.Eafaj.7.E.7.nbj#s#Db.#Dbj#sbj#sbj#sbj#D#s.N.s.N#x.W#xbo#xavambcbb.O.O#a#a.Oba#3aBamaoa0.W#x.s.N#saY#saY#I#x#I#x#IaCa0aoamaob#aoamaF#v#vaB.0aB.0#ua#a#.5ao#xaY.Nbl#sbl#Da9.7.n.7.7aj#L#L#L#L#La2#Laj#Laj#L#g#L#L#Laj#Laj#L#L#Lbp#L.j#g#L#L#Laj.7#L#Laj#Laj#Laj#Laj.7aja9#La9aja9a9",
+"#Da9#s#L.n#L#L#Laj#L#L#g#L.jbpa2#ga2#g.j#gas#gas#g#g#g#g.j#g#gas.j#g#g#g#g.jas#g#gaj#L#D#xaOaZan.FbmaBaZbmaFb##UaYblawaY#s#Da9.7.n#Laj#Laf#Lafajaf#L#Lajafajaf#L.3#Laf#La9aj.7a9#Ma9a9#Da9#Da9#Da9#D#La9aj.7aj#L.E#Laj.7.Ebj.nb.#s#D#sbj#s.N#s#D.s#D#sbj.N.sbf.s.C.Wa0.Wam.8.ybb#a.O.GaPaz.M#C.faOaoaq.W#xaw#D.s#D#I.N#I#xaCamaoaFaO#vaO#S.y#S#v#v#S#va#aOaFaOaFamaoa0#xaY#D#sa9#D#Da9.7.7#L#L#La2#L#g#L#g#Lajbp#L#Lbp#Laj#Laj#L#Laf#L#Laj#Lajbp#L#Laj#L.n.7a9#sa9.n.7.nbj.nbj.na9a9a9.na9#Da9a9",
+".7#L#L#L#L#Laja2#L.jbp.j#L#g#L.j#g#g#gasas.jas#g.jas.jasasas.jas#gas.jasas#gas#gasbp#L.7awam.yan.Fbm.TaZaBaFam.R#IaYawbl.N#s#D#D#Lajaf#Laj#L#L#L#Lajaf#L#L#L#Laj#L.jafajafafafaja9#Da9a9a9a9a9.n#Lajaf.E#L#Laj.7.j#Laj#L.E.7.E#D#saW#D#sbj#sbj#Db.#DaE#D.sbf#IbfaCaq.Waoao#v.y.wbkaz.w.waz#3biau#uaOamao#xboaw.N.s#x#I#xaCambgbg#uaBa7#ua7an#ubh#vaFaOama0aCa0a0a0bn#UaY#sa9af#L#sa9.7a9aj#Lbpaj#g#L.j#gaj#g#L#Laj#Laj#L#L#Lbp#L.E#L.E#L#L#L.7#L.n.7a9#D#D.N.s.Na9#s#Da9#sa9#D.n#D#D#s#D#D#s#D.7",
+"aj.7aj#gaj#gas.ja2bpa2#L#gaja2bpas.jas#gas#g.jasasasasas.jasaU.j#gas#gas#gas#gas#g.ja2#LaYa0.0aZ.Fa#aBaZa#aFbn#UaYaY.N#MaY#D#D#Daj#L#Laf#Lafajafajaf#L#Lajafaj#L.3#La2af#L.Eaf.7a9a9.n.7a9.n.7a9af#Laf#Lafaj#L#L.j#g.E#L.E.7#s.Ebj#s#sbj#D.s#Db..N#s#D.s.sbf.s#Iaqa0ao.C.8#vbbaPbk#u.w.Q.w.wau#N.Q.yavam#I#x.sawaY#I#IaCaoaoaO#vaz.Gaz.GazaS#uanaoaCa0.Wa0.CaC.CawaY#Da9a9#La9aja9a9.7aj#L#L#Lbpaja2bpa2bpa2#Laj#L#L#L#L#Laj#Laj#La9#L.7.7.E.7.E#D#D.N.s.N.s.N#x.7.7.n.7a9#sa9#D#s#D#D#D#D.7#D#D",
+"#g#g.j#g#g#g.j#g#g.j#g.j#g#g#g.j#g#gas#gas#gas#g.jasasasas#gasasas#gas.jas#g.jas#g#g#ga2a9.C#SbhaFbgamam.8amaCa0aYaYaY#Da9.E#Laja9#Laj#Laj#L#L#L#L#Lajaf#L#Laf#Laja2ajaf#Lafa9a9.na9a9a9a9.7a9a9af.n#Lajaf.7#L.E#Lbpaj#g.n.7#s.N.s#DaY.saY.Naw#x.saYbo#x#x#I#x#I.8amaob##v#u.G.2bkaz#ubbaP.w.G.2.u.Oa#aoav#Ibfboawbo#xaoamaBan.Gba#a#ua#ao.5#Qaq.W#x#x#x#I#x#xaY#xawaYbl#D#M#Da9a9a9a9a9.7a9a9a9#L#Lajaf#Lajaf#La9.n#D#saY.NaYaY.N#sbl#D#MaY#M#D#D.n#Da9#D#D#D.n#Laj#L#L.E#Laj#L.7aj#Laj#Laj#Laj",
+"#g.j#gas.j#gas.j#ga2a2#ga2.jas#gas.j#g.jas#g.jas#g#g.j#gas#gas#g.jas#gas#gasas#g#g#La2.j.7bnaF#ub#b#amb#ama0bn.CaY#M.N#sa9.na9#Lajaf#Laf#Lafajafaj#Laf#Laj#Laj#La2afafaj#L#La9.7a9.7a9.7a9a9a9.7afafafa9#L.n#L.7ajaja2.j.7.E#D.N#Daw.Naw.N#I#x#x#I#x#I#x#IaC.CaC.5bg.8aO.0.w#T.2.G#u.ybbbb#u.GaX.e#z#SaoaC.s.W.W#I#Iaoam#v#u.G#TarazbmaoamavaN.C#x#xawaY#x#IaY.saY#Daw#D#Da9a9a9#sa9.na9a9.na9.na9a9a9#sa9#Da9#sa9a9a9#D#Mbl.NawblblaY#MaYaYaYaw#D#D#s#D#D.n#D#D.n#La9ajaf#Laf#Laj#L#L#L#L#L#L#L",
+"#g#g#g#gas#g#g#ga2.j#g.j#gas#g.j#g#gasas#g.jas#g.jas#gas.jas#gasas#gas#gas#g#gasa2aj#g#La9aYa0bmbgambgama0.C#x#xawaY.N#Da9.7#L#Laf#Laj#Laj#Laf#L#Lafaj#Laf#Laf#Laja2#Lafaf#L.na9.na9a9a9.Ea9a9.7ajafajaf#L.7#L.7bp.Ebp.Eaj.7#s.Naw.Naw.Naw#x#I.N#I#x#I.C.Wa0aoamao.5ao#vaBazal#3aB#vaF.y.yaB#u.wa6#z.w.8.C.Wam.CaoamaO#v#uaz.G.GaBaFama0#xawbfa1aY.NaY.NaYaY.NaY.N#D#D#D#Da9a9a9a9.7#D.n#D.7a9a9#D#s#D#D#D#s#D#Da9.na9a9#D#Daw.N#D#s#D#D#D#s#D#D.7.7.7.7.E.7.7.7#L#Laj#L#Laj#L#L#Laj#Lajbpaj#Lbp",
+"as.jas.j#g.jas.ja2#ga2as#g.j#gas.j#g#g.jas#g#gas#g.j#g#gas#gas#gas.j#gas.jasas.j#ga2#gaj#LaY#Uamb#ama0a0aCbn#Ibn.Nblaw#Da9aja9aj#Laj#L#Laf#L#Lafaj#L#Laj#L#Laj#L.3aj.3#L#L#La9.7a9a9.7a9a9.7a9a9afa9#La9aj#L.n#L.E.7aj#L.E#D.sbfaw#M.NaY.s#x#IaY.C.W.C.W.Caqaqao.5aoaF#v#uaz#T.o#vaO.8.8bcbcaB#ualbaa5#vaoa0avaoaF#vbm#uaz#u#uaZa0am#x#M.N.N.N.N#D.Naw.N#s#D#D#D#D#sa9#Da9.n#L#L.na9a9.7a9a9.7#s#D#D#Da9#Da9#D#s#Laf.7a9.n#Da9a9#L.7#L.7aj.7#L#Laj#Laj#L#L#Laj#L.j#L#La2#La2#La2ajbp#Lbpa2#L#ga2",
+"#g#g#g#gas#g#gas.j#g.j#g#gas#ga2#gas.j#g#g.jas.j#gas#g.jas#gas#gas#gas#gas#gas#gaa.j#g#L#LbjaY#Ua0aCa0a0#xbn#xawbl.N#D#Da9.7#L#Laf#Lafaj#Laj#L#Laf#Laf#Lafajaf#L#La2#Lajaf#La9a9.n.7a9a9a9a9a9#Lafafajafaf.7#L.7#L.7#Laja9#saY#IaY.saY.saY#I#x.s.C#xaC#x.Caoaqamao.8a##v#u.Ga5azaOaOaoao.8#v.ya5ba#z.w#vao.Wam#vaB#uaB#uaZa#aF.5#xawaYbla9.E#D#sa9#sa9#D.7.7a9#s.7a9.7.7#L#L#L#L#L#Lajaf#L#Lajafa9.7.na9a9.7a9a9.7aj#L.7#L.E#Lajafajaf#Laf#Lajaf#L#L#L#Laj#L#L#L#La2aj#gaj#gaj#g#La2.jbp.jbp.jbp",
+"as.jas#g.jas.j#ga2as#gas.j#g.j#g.j#gas#ga2#g#gas#g.jas#gas#gas.j#gas#gas#gas#gas#g#ga2bp#L.na9bla0bnbn#UaYawaYaYaYbl#Da9.n.7afaj#Laj#L#L#L#Lafaj#Laj#Laj#L#L#L#L.ja2a2a2af#L.n.7a9a9a9a9.7.n.7a9afaf#Lafaj.7af.E#Laj#L.Ea9aw#x#IaY.saY.NawbfaY#x#I#x#I.C#I.C.Wa0.8am#v.0#u.G.w#uaO#v.8#Q.8bdbb.Q.K#z#u#vaFaoaBa7a7#u#SaFaoamaCbnaYaY#Da9aja9a9bj.7a9.7a9.Ea9.7.7af.7#L#Laj#L#La2ajafaf#L#Lafafafaj#Laf#Lajaf#L#La9#L#Laj#La2a2a2#ga2.j#g.ja2a2#gaj#gaj#g#La2bp.j#g.j#ga2#ga2#g#g#g.j#g#g#ga2a2#g",
+"#g#g#g.jas#g#gas.j#g.jas#gas#ga2as.j#g.j#g.jas#ga2#g#g.jas#gasasas.jas#g.jas#g.jasaa#g#Lbp.7afajbn.RaYaYaYaYaYaYbl.N#D#D.7#L#L#Laf#Lafaj#L#L#L#Laf#Laf#L#La2#L.3#La2#L#L#Lafa9a9.n.7a9.7a9a9a9.7afaf#Laf#La9aj.7.7.7aja9#saw#x#I.N#saY#I.NaY.s#I#x#I#x#I#xaC.CaoamaO.yaB.waz#uaZ.8bc.8.8#Q.y.Q.w#4#4.wa##vaB.Qaz#vaFama0#x#x.N.s.N#D#sa9.7a9.E#D.E#L.7aj.7#Laja9aj.7#L#L#La2.ja2af#Lajafajafaj#Lafafajaf#Lafajaf#L#L#La2a2.j#ga2.jas#gas#g.jas#gasa2#g.j#g.j#g#g#g#g#g.j#g.jas.ja2#gas.ja2.j#g#g",
+"as.jas#g#gas.j#ga2as#g#gas.j#g.j#g#g#ga2a2#g#g.j#g.jas#gas.jas#g#gas#gasas#gasasa2#g.jbp#LajafafaYbnaYaYblaYaY#MaY#D#sa9a9.7#L#L#Laj#L#La2afa2#L#L#Laja2#Laf#L#La2.j#L.3aj#La9.7a9a9a9a9.n.7a9a9afaj#La9aj#L.7#L#D.na9#s.naw#x#Ibl.Naw.Naw.NaY#xawaYaw#x#I#xaC#I.8aO.yan.w.G.w#vb#by.8.8bc.ybb.Qay.Y.G#u#1a5.GaBamamaobn.s#Da9.7aY#Da9.7a9.7.7#Da9aj.7af.7af.7#L.7afaj#La2a2a2.j#Laf#Laf#Laf#Laf#La2#La2#La2a2a2.7.j#La2#gaa.jasas#gas.jasasas.j#g.j#gas#gas#gas.jas.j#gas#g#gas#ga2.j#ga2#ga2a2",
+"a2#ga2.jas#gasas#gas.j#g#g#gas#g.ja2a2a2.ja2a2#ga2#ga2.jas#gas#gas#gas.j#gas#gas#g.j#ga2bp#L#Laj#L.naY.R#xaYaY#D#Dbl#D.7#saf.7.n#L#L#L#L#Laj#L#Laja9#La9aj#L#L#La2a2a2.j#L#Lajafa9#sa9.7a9a9a9.E#Lafafajafa9.na9aj.na9#s#D.N#IaY#s.sbl.s#D#s#D#s.N#I#x.W.Cavam.5.8aF.0azal#T.w.0.8#v.8byaKbbaIaP#aba#N.O.GazaB.5#xaw.N.NaY#D#D#s.7.n.7#L#La9.7a9#L.7af.E#L.E#L#L#L#L#La2#La2bpa2#L#Laj#La2#L#Laja2aja2#ga2.jbpa2as#gas#gas#gas#g.j#g.j#g#g.j#gas#ga2.j#g.j#g.j#g#ga2#g#ga2.j#ga2a2#g#ga2#g.j#g#g",
+"#g.j#g#g#g.j#gas.j#g#gas.j#g.j#ga2a2#ga2#g.ja2a2#g.jas#g#gas#gasas.j#gas#gas.j#gasasas#g.j#g#Lbp#La9#Dbl.RaYaY#D#D#Da9#D.7a9.7#L#L#Lbp#L#Lbp#L#L#L#L#L#g#La2a2#Las.ja2a2#Laf#L.7a9.7.na9a9.7a9a9af#L#La9#Lafaja9.na9.n#D.s.s#x#I.Nbl.s#D#M#DaY.saY#I#xaC.Caqao.5bgaO#uaz.G.G#u.y#x.W.8#v#v.y.0.ybabaay.f#uaB.8a0bfaYaY.N.N#D#D#Da9.7.7af.7.7af.E.7aj.7#La9#L.n#L#L.jaf#L#gaja2#L#La2#Lafaj#La2#L#g#g#L#g#L#ga2#g#gas#gas.jas#gasasas#gas#gas#g#g.j#g#gas#ga2as#g#ga2#g#L#gbpa2bp.j#L#gajbpa2bpa2",
+"a2a2#g.jas#gas#g#gas.j#g#gas#g#g.ja2a2.ja2a2a2.jas#gas#gas#g.jas#gasas#gas#gasas#g#g#ga2#g#L#La2#La9a9#DaYbl#Dbl#Da9#Da9a9.7#L#La2#g.j#g#ga2#ga2.j#ga2.j#g#g#g#ga2a2#g#La2aj#L#L.n#Da9a9.na9a9.7#Lajafajaf.7a9.naf.na9aE.N#I#Ibn.saY.Naw.NaY.saY#x#I#x.Wa0ao.5.8aoaO#u.G.Gaz#ua##IaCaCaobg#va7azaH#zaz#uaFam#x#xaw.N.N#D#D.n#D.7.E#L#L#Laj#L#L#Laf.7#L#L.E#L#L#L#L#La2#La2#L#gaja2#L#La2#L#L#La2a2#g.j#ga2#g#L.jas#g.jas#gas#gas#g#g.j#gas.j#g.j#ga2.jas.j#g.j#g.j#ga2.j#ga2#g#L#g#gaja2bp.j#L#g",
+"a2#g.jas#g#g.jas.j#gasa2#g.j#g.ja2a2#ga2#La2a2#g.jas#gas.jas#gas#gas#gas#gas#gasas.j#ga2#gaj#Lbp.j#La9a9#D#Dbl#Dbl#D.7a9.7.7af.7a2a2a2a2a2a2.ja2bpaj#Lbp#Lbpa2#L.j#g#La2#L.7#L.7a9a9a9.7a9.7a9.n#Lafaf.7afafaja9.na9.n#D#s#I#x#IaY.sawaY.saYaw.N#I#x#I.C.W.5av.5bgaOaB.G.O.G.y.5aO.8bgaFaB.Gau#N#zaz.0aFa0#x.NaY.N.N#D.n#D.7.7a9#L#La9#L.7#L.7#L.E#L#L#L#Laf.7#L#La2#L.jbpa2#La2#La2#Lajafa2#L.j#L#g#L#gaja2#g#g#gasasas#gasasas.jasasas#gas#gasa2.j#g#gas#gas#g#ga2bpa2bpaja2aj#ga2#L#g#La2bpa2",
+"a2#ga2#g.jas#g#g#gas.j#ga2a2as#ga2aja2.j#g.j#La2#g#g.j#gas#g.j#g.jas#g.jas#g.jas#gas#ga2#g#La2#L#L#g#La2a9a9#D#D#Da9#Da9.7a9#L.7a2.j#g.ja2aja2#L#L#g#ga2.j#L.j#g#La2#Laj#L#La9.7.na9.na9a9a9a9a9#L#Lajafaja9a9.naf.n#s#s.N#I#x#U#I#x#x#I#x#I#x#I#x#I#x.Wamao.5.8ao#v#u.Garaz#ua#.y.0#u#u#aau#3alaza#b##I#xaw#D#sa9#s.7a9.7a9aj#L#La2aj#L#Laf#La2#L#La9aj.7#L#Laja2#L#g#La2#L#g#Laj#L#La2#L#La2#L#ga2#ga2#g#g#L#gas#g#gas#gasasasas#g#g.jasas.j#g#gas#g.j#g.j#ga2.jbpa2bpa2bpa2bp.jbp.jbp.jbp.jbp",
+".j#g.ja2#g.j#ga2.j#ga2.j#g.j#g.ja2#ga2a2a2a2a2#g.j#gas#g.j#gas#gas#gasas#gas#gasa2.j#gaj#g#Lbp#La2#La2#L#La9#Dblbl#Da9bja9#L.7#L#L#Laf#L#L#Laf#Laj#L#L.7#L#L#L#L#L#L#L#L#La9#L.7a9#Da9a9.7a9.Ea9#Lafaf#Lafa9.na9.na9.E#D#s#x#I#I#I#I#x#I#x#I#x#I#x#I#x.WaC.5.8.8.5aBa5#a#TaPaPbk.U#3al#3#T.G.w.0aFaC#x#x.N#D#Dbj#Dbj.7.7aj#L#L#La2#L#La2#La2aj#L.7#L#L#L#L#Laf#Lbp.j#La2bpa2aja2#La2af#L#Laja2#L#g.jbpa2bpa2#g.j#gas.jasas.j#gas#gasasas#g#gas#ga2.jas#ga2#g.j#g#L#gaja2aj#gaja2bpa2#L#L#L#g#La2",
+"a2#ga2#ga2a2#g.j#ga2#ga2a2#g#g#g.j#L.j#L.j#La2a2#gas.j#gas#g.jas#g.j#g.j#g.j#gas.j#ga2a2#gaj#L#L.ja2#g.j#g#L#Dbl#Da9a9a9.7a9.7a9a9a9a9a9a9#sa9#Da9a9.na9a9a9#Laf#Laj#L.7a9.E.7a9.n.7.n#Da9a9a9a9#Lajaf.Eaf.na9.naf#Ma9.s.s#I#x#I#x#I#x#I#x#I#x#I#x#I.CaCaq.8am#vaO#u.G.Uay#3#3bv.M#C.O#u.y.5am.C#UaYaYaw.N#D.7.7.7.7aj.7#L#Laj#ga2#ga2a2.ja2a2a2ajaf.7#L.7aj.7#La2a2bpa2aja2bpa2#L#Laja2#La2#L#ga2bpa2.j#g#ga2#gas#gas#gasasas.jas#g.j#gas.j#g.j#ga2a2.ja2a2#gas.j#L#g#L#g#L#gaj#Laj#L.j#La2aj#g",
+"#g.j#g.j#g.ja2a2#ga2.j#g.j#g.j#ga2a2a2a2#g.ja2#g.j#gas.j#gas#gas#gas#gas#gas#g#ga2#g.j#L#g#La2bp#La2#gas#g#La9bl#D#Da9bja9.7.n.7a9b.#D#s#D#D#D#s#p.nbl#p.na9a9a9#L.7#L#L#La9.7.7a9#Da9.na9.n.7a9#Laf#Laf#Lafa9.na9.n.E#s.N.s#x#U#I#x#x#I#x#x#I#x#I#xaC.Wa0.8.8.8.yaB#T#4beaM.Y#T.fa7#uaOa0bf.s.N#Mbl#s#D#D.s#DaW.E#L#L#Laj#L#g#ga2a2.ja2a2a2aja2.7#Laj#Laf#L#L#L#L#ga2#L#g#La2#L#La2#L#L#L#La2aj#ga2#g#g#ga2#ga2as#gas#gas#g#gas#gasas.j#g#gas#g#g.ja2#g#g.ja2.j#L#g#L.jbp.j#La2aj#L#Lbpaj#g#L#g",
+"a2a2a2#La2a2.j#ga2.ja2a2a2a2#ga2#ga2#ga2a2a2#ga2asaa#ga2#ga2#L.j#La2#L#Lajafa2#L.ja2#ga2#La2#L#L#L#Laf#Laj#L#L#La9bl#Da9blaYaYaYblbl#DaYaYawaYaYblblblblblblbla9#Da9#D#sa9#Da9#D.na9.7a9.7a9a9.n#Laf.Eaf.Eaf.naf.na9#M#D#saY.saw.N#s#s#D#s#s#D#s.C#I#I.C#Iao.5#v#u.OaVadbi#3#1aBbdaO.W.C#IaYbf.N#D#s.7#L#L#Laj#L#Lbp#Lbpbpa2bpa2.j#g#g#Lbp#Lbp#L#L#L.7.7.E#L.7#La2a2a2.ja2#ga2.ja2#L.3a2a2#g#g#g#L#ga2#ga2#g#ga2#ga2#ga2.j#ga2#g#gas#gas#g.jas.ja2#g#L.j#L#g#g#L.ja2a2#L#L#L.7#L#L#L#La2#L#Laj#L",
+"a2a2.j#L.j#La2a2a2a2a2a2#ga2a2a2.ja2a2.ja2#ga2a2asa2asa2.j#L#g#La2#L.jaf.3#L#La2aa#ga2a2#L#Laj#Lafaj#L#L#Lbpaj#La9#D#p#Dbl#DaYaYbl#DblaYaw#xaYaYbl#Dbl#Dbl#Dbl#Da9#sa9#D.7#D.7#D.7a9a9a9a9a9.7a9.n#Laf#Laf#La9a9.n#s#D#M#DawaY#I#s#D#s#s#D#s#D#sbf#Ibf#I#Ia0bc.y.G#zad#4aXbk#v.8bgao.C#x.N#x.N.s.7bj#L.7aj#Lbp#Lajbp.j#L#gaj#g#L#gbpa2bp#L#La2#L#L#L#Laf#La9#L#L.j#ga2#ga2a2a2a2a2#La2aj#L#g#L#ga2#g#ga2#ga2#ga2#g#ga2#g#ga2bpa2as.j#g#g.j#ga2#g#L#Laj#Laj#Laj#L#gaja2ajafaj#L.Eafaj#L#Lajaf#L#L",
+"a2#La2a2a2.j#ga2.j#L.j#ga2a2#ga2#ga2#ga2#ga2a2asa2.jasa2#ga2#La2#La2#L#L#Laf.j#L.j#L.jafaj#Laf#Lafafaf.7#L#L#Lbpa9#pa9#D#Dbl.sbl#D#MblaYaYaYaYawbl#D#M#Dbl#D#Mblbja9bja9#D.n#Da9.na9.7a9.7a9.na9#Laf.Eaf.Ea9.n.n#D#M#saYaw#IaY#IaY.s#D#s#D#s#D#s#I#x#I#I.Cao.y#1#T#rbq.G#u.yaOaCamaC#xawaY.s.N.N.7aj#Lbp#Lbpa2#ga2#Lbp#L#g#L#g#L#ga2#gaja2bp#Lbp#Laj.7aj.7aja9#L#L#L#L#L#Laj#L#L#L.j#La2#ga2#g#g#L#ga2#g#g#ga2#g#ga2#g#ga2#g.j#g#gas#g.jasa2.j#gaj#L#Laj#L#Laj#La2a2a2#L#L#La9#Lajaf#Lajaf#Laj#L",
+"a2.ja2.ja2a2a2#ga2a2#ga2a2#g.ja2a2a2a2a2a2.ja2a2asas#ga2a2#L.j#La2aja2a2a2#Laf#Lafa2af#Laf#Lafajaf.E#Laj#L#Lbpa2a9.na9#Da9a9#D#Dblbl#DaYaYaYaYaY#Dbl#Dbla9#D#D#Da9#Da9#Da9bja9bja9.7a9a9.na9#Da9#D.na9a9a9a9#D#sbl#saYaw.s#x#I#I.saw.saY.s.Naw.N.s.s#IaCaoao#u.G#z.UaX#uaOaOao.W#x#IaY.N.N.N#D#D#L.7#Laj#La2#ga2#gbpa2bp.jbpa2bp.ja2#g#L#Laj#L#La9.7a9.7a9.7.7a9#L#L#Laj#L#L#La2af#La2#L#L#g#L#ga2#g#ga2#ga2#g#ga2#g#ga2bpa2bpa2#g.ja2#ga2#g.ja2#Laj#Laj#Laj#L#La2.j#Lajafaj#L.E#L#Laf#L#L#Laf#L",
+"a2bpa2#La2.j#ga2aja2a2a2.ja2#ga2#g.j#ga2#ga2#ga2a2aa#ga2#ga2bpa2#La2afaja2afa2#Lajafajafajafa9a9af#Laf#L#L#L#Lbpafa9a9a9a9a9#D#D#Dbl#DblawaYaYaY#D#Dbl#D#Dbl#D#Da9b.a9.7a9#Da9#Da9.na9.7#D.na9.na9a9#D.n#D#s#D#M.NawaY#I#x#I#Ia0#IaY#Iaw.Nawbo#x.s#x#I.WaF.yaz#3.a#4a5#v#vaoaC#IaYaY.saYaw#D#sbj#Laj#Lbp#L.j#g.jbpa2aj#g#L#g#L#g#g#L#g#L#g#Lbp#L.na9a9.na9a9.na9#Lajaf#L#L#L#Laj#Lafa2#L#g#L#g#g#L#ga2#g#ga2#ga2#ga2#ga2.j#ga2#g.jas#g.j#g.j#ga2aj#L#Laj#L#Laj#Laj#La2#L#Laf.7af#Laj#Lajafaj#L#L",
+"a2.ja2.j#L#ga2a2a2#ga2#ga2#ga2a2a2a2a2a2a2a2.ja2as.jasa2.j#La2#La2#La2a2#La2afajafafafafaf#pa9.n#Laf#L#L#L#L#g#Lafa9a9a9a9a9a9a9a9#DblaY#DaYawaY#D#M#D#D#M#Da9#Da9#Da9bja9.7#s.7a9.7a9.na9a9.7#D#s#D#s#D#Dbl#s.N#M.Naw#I#I#IaC.W#I#xbo#xbo.N#IaYbo.W.Wa0#vaz.Y#.aVapaOaO#O#I#I#xawbl.N#D#D.7a9.E#L#L#L#gaj#g#g#ga2bp#gbpa2bp.j#La2#g.j#L#La2#Lbpa9.7#D#D#s#Da9#D#L#L#L#L#L#L#L#L#L#La2#L.j#Lbpa2#ga2#g#g#L#ga2#g#g#ga2#gbp#g#L#g#g#g#ga2a2#g.ja2aj#Laj#L#Laj#Laja2#Lajafaj#Laj.7aj#Laf#L#L#Laf#L",
+"a2#La2#ga2.ja2#ga2.ja2a2a2a2#g.j#ga2#g.j#ga2#ga2#gaa#ga2#ga2aja2#L.j#La2#L.jafaf.3ajaf.n#p.n#pa9afajaf#L.7#L#L#L#L#La9a9#D.7a9#Da9a9bl#DblaYaYaY#D#D#D#D#D#D#D#Da9bja9a9.7#Da9#Da9a9a9#Da9#sa9a9#D#D#D#D#s#D#saYaw#I#x#IaC#x.WaC#I#I#x#I#x#I#I#xa1ao#Q.8.w#4.P.4#u#Sao.WaCa0bobfbl#s#D.na9#L.7#L#Lajbpa2a2#g.jasbpa2#L#g#g#L#gbp#ga2#g#Lajbp#Laja9a9#M#Dbl#D.na9.7a9.7a9.Ea9a9.7af.jaf#La2#L#L#g.j#ga2#ga2#g#L#ga2#ga2bpa2a2.j#g.j#g.j#g.ja2#g.j#Laj#Laj#L#Laj#L#Lajaf#L#Laf.7af#Laj#Lajafaj#Laj",
+"a2.j#L.j#La2#L.ja2a2#ga2#g.ja2a2a2a2a2a2a2a2a2a2asa2asa2a2a2bpa2af#La2afa2#L#Lajaf#pafafa9#p.n#p.7af#L#L#Laj#Lbpaf#La9.7a9a9bja9a9#D#Dbl#DaYaYaY#D#D#D#Da9#Da9#D#sa9a9bja9a9bja9.Ea9.7a9.Ea9a9a9#s#D#s#D#Dbl.s#Daw#x#IaC.WaCaCao.Wav#Ia1#I.Ca1#I.Cav.8aO.G#dbs#BaLaB.8aC#I.WaYbf#sbl#Da9a9.n#L.E#L#L.jbp.j#gasasa2bp.j#L#ga2bpa2#g#L#g#L#g#L#L#La9#Da9bl#s#p#Da9.7a9.E.7a9.7.7.n#Laf#L#L#gaj#L#g#ga2#g#gbp.j#ga2#g#ga2#g.jbp#gbpas#ga2#ga2#g.ja2.E#Laj#L#Laja2#Laja2aj#Laj#L.E#L.Eafajaf#L#Laf#L",
+"#L#L#L#L#La2bpa2#Laj#L#La2bpa2bp.L.L.jasaa#ga2#gaja2a2a2a2#La2#La2a2#L.j#La2afa2.3aj#p#Mbl#D#D.7ajaf#Laj#L#Lbp#Laj#Laf.n.7a9a9.7#pa9#p.NaYaYbl#Dbl#D#Da9#Da9.7a9a9a9a9afa9.7a9.7#Dbl#Dbl#D#D#D#D#xaYaYawaYaYaY#Ubn#I#I#I.Wao#v#vaC#I#x.W#Ibo.C.WavaoaZ.o.Yab#3.QaOaoaC.W#I#x.s.Nbl#sa9a9aj#La9#L#L#g#L#ga2#g#L.j#g#g#g#ga2bp#ga2.ja2#L#Laf#La9.7bl#DblblaYaYaYaYaj#L#L#L#L#L#L#L#L#L#L#L#L#L#L#La2#ga2a2a2#g#La2#La2#g#La2a2#L#L.ja2.ja2.j#L#Laj#L#L#Laj#Laj#Laj.3#Lafajaf#Lajafa9.na9a9.na9.na9",
+"#L#Laj#L#Laj#La2bp#L#gaj#L#L#Lajaa.jaaaaa2#ga2bp.3#L#L#La2#L.j#La2a2a2#La2#La2#L.3af#pblbl#Da9a9afaja2#La2#La2#L#Laf#L.7a9a9bja9a9#p#DblaYaw.Nbl#Dbl#Dbl#D#D.7a9a9afa9a9a9a9aj.7bl#D#D#sbl#Dbl#MaYawaY#xaY#xawaY#x#U#x#I.Cao.8aBaxav.W.C.Waoao.8aO#vaPay#daVbk.0#OaoaC.W#x#I.N.N#Dbl.na9a9#L.7aj#g.j#ga2bpa2#g#gasas#g.j#g#ga2#g#La2.ja2#Laja9a9a9a9bl#DaYawaYaY#La9.Eaf#L#Laj#L#L#Laj#L#L#L#L#Lbpa2#L#g#La2#g#L#gaja2#ga2#ga2#La2a2a2#La2a2.3#L.jaf.jaf.j#L.3#Laj.3aja2#Laj.3#Laja9af.n#L#Laf#L",
+"a9ajafaf#L#L#L#L#L#L#L#L#L#L#L#Laa#ga2#g.j#gbp#La2#L.ja2#La2#La2a2#La2a2a2#L.j#L.jaf.n#pbl#sa9.Eaf#Lafaj#Laj#L#Lajaf#La9a9bja9a9#Ma9bl#DaYaYbl#DaYbl#Dbl#Da9a9a9a9#p.naf.7a9.7a9.n#Da9#D#D#s#D#DaYblaY#MaY#MaYaY#MaYaw#I#IaC.8aObgaoaoao.8ambc#v#uar.M#d#4.G.y.8bgaoaC#x#I.N.N#s#pa9a9.7ajaf#L#La2bpa2.j#g#gaj#g#g#gas#ga2#g#L#La2a2#Laf#Laf#La9a9a9a9#D#Dbl.Nbl.E#L.7#L.7af.7#La9#L.7#L#L#L#L#La2#ga2#ga2#g#La2#L#ga2#L#g#L#Laj#L#Laj#Laj#Laj#Laf#L#La2afaj#Lajaf#Lajaf#Laj#Laja9afajaf#Lajafaj",
+"afaf#Lafajafajafajaf.Eaf#Laj#L#L#La2#L#L#gbpa2bp#La2#L.3#L.jafa2#La2a2#La2a2#L.3afaf#p#Mbla9a9.7afajaf#L#L#L#g#L#La9aja9a9#Da9.7#pbl#DaYaYaYbl#DaYblaY#Dbl#D#D#Dafa9afa9a9a9.7.7.7#Da9bja9#D#D#s#D#D#saYbl.NblaY#M#D.saw#I.WaOaB#vaO#v.8aOaO#v.y#3ad.Z#.#T#vav.haoaC#x#IaY.s#D#D.n#Dajaf.7#Laj#L#ga2#g#gbpa2#ga2a2as#ga2#ga2bp#La2a2a2a2a2#L#L#La9afa9#M#DblawaY#L.7af.E#Laj#L#L#Lajaf#L#L#L#L#Lbpa2#L#g#La2#gaja2#L#ga2#g#La2a2aj#L#L#L#L#Laf#L#Laj#Laj#L#Laf#Laj#L.7aj#L.Eaf.7.na9#D.n#Da9#Da9",
+"a9.na9a9a9a9#pa9a9a9a9a9a9a9a9.nafaj#L#L#L#Lbp#La2aja2#La2#La2a2#La2a2a2a2a2#La2aj#p#pbla9a9#Lajaf#Lafajafaj#L#Lajaf#La9.7.nbj#Da9blaYaY#x.N#DblaYblaY#DaY#Dbl#Da9a9a9a9.7a9.7.7a9.7.E.7.7.7.7a9#D#D#D#D#s#D#s#D.sbl#s.s#xaoaO#S.yaBaB#u#u#ubk#E#.ab#4#3.G.y.8bo#U#I#x.s.N#D#s#Da9#L.7aj#L#La2bp.jbpa2#La2#g#L#g.jas#g#ga2#Laja2#L.j#La2af#L#L#La9.7a9bj#Daw.Nbl.E#L.7#La9#L.7#L.7#L.7#L#L#L#L#La2#ga2a2#ga2#L#g#La2bpa2#La2bp#L#Laf#L#Lafaj.7ajaf#Laf#L#Laj#Laja9.na9.7afa9.Ea9a9a9a9a9a9.na9a9",
+"a9a9a9a9a9a9a9.n#paf#paf#p.n#p#pbl#D.na9a9#L#L#L#La2#La2#La2#La2a2a2a2#La2#La2afa9#p#M#pa9.nafa2afajaf#L#Lbp#L#L#Laf#La9a9#Da9a9#D#DaY#x#xaYaY#DblaYblaY#Dbl#Dblafa9afa9#Da9.7a9#L.7a9#Laf.7.n.7a9a9#s#D#D#D#D#D#s#D.s#x#I.8#Saz#u#u#uaZ.w.GbiaV#4.U#3ara5#vao.W#x#IaYaw#D#sa9a9#L.n#Laf#L#gaj#L#ga2#g.ja2#g.j#gas#gas#gaja2bp#La2a2a2a2#L#Laf#L#L#La9a9#Dbl.NaY.7#L.n#L.E#L#Lafaj#L#L#L#L#L#L#Lbpa2#L#g#L#ga2#ga2#ga2a2#gaja2#L#L#L#Laj.7#La9#L#L#Lajafaj#Laf#L.n.7a9.Ea9.Ea9.n#D#s#D#s#D#D#s#D",
+"a9.n#pa9.n#pa9#pa9.n#p.n#p#p#p.nblblbla9.na9#Laf#Lafa2aj.3#L.j#La2#La2#La2aja2#La9.nblbl#pa9#L.j#Laf#Laja2#La2aj#L#Laja9a9.7#D#s#p#DaY#x#x#xaY#DblblaYaYbl.Nbl#D#Dbl#D#Da9#Dbj#D.7#L.7#L.7af.7#L.7.na9a9.na9a9.n.NaYbobfaoaFaBazaz.w#uaP#3#4ad#4ap.O.O.O.w#S.8.5#Uaw#x.saY#s#D.n.7#L#Laja2aj#gas#L#gbp#gbpa2bpa2#gas.j#g#g#L#La2#La2#La2#L#L#L#L.7#L.7.7.E#D#s#D.na9#L.7af#L.7#L.7#La9#L#L#L#L#La2#ga2a2#ga2#L#g#La2bpa2#ga2#ga2.7a9.7#La9.7.7a9ajaf#L#Laf.7.na9#D.Ea9.7a9.7a9b.#D#D#D#D#D#D#D#D",
+".n#pa9#paf#p.n#p.n#p#p#p#p#p.n#p.b.R#Mbl#p.nafajafaja2#La2#L.3#La2a2aja2#L.3#L.ja9#pbl#Mbl.nafa2afajaf#La2#Lbp#L#Laf#La9.n#D#s#DblaYaY#xbn#xaY#DblaYblaYblaY#Dbla9bla9#D#D#D#Dbja9#La9#La9.7.7a9.7a9.7.7.7.E.7#D.N.sbf.Wam.y#uaz.Oar.Gal.Mbxadalbkbkbkbkbka7.yaF#I#IaY#s#Da9#s#Daj#Laj#L#g#L#g#g#gaja2a2a2#ga2#gas#gas#ga2#g#gaja2a2a2af#Laf#La9#Lajaf.7a9#D#s#Da9.Ea9.E#L.E#Laj#L#L#L#L#L#L#L#L#L#g#L#g#La2#ga2#ga2#ga2#L#g#La2#L#L#L.7#Laf#La9#L.E.7.7.Ea9.n.7.n.7a9.7.n.7.na9#D#D#s#D#s#D#s#D",
+"#Lafaj#L.7#L#L#Lafafajafaja9#pa9aYawaYaYawblblblafafaf#Laf#L#L#L.jaaafa2#L#Lafaf.n#F#M#pa9afaj.7#Lbp#Lbpbpaj#L.Eaf#Laj#D#D.N#D.N.naYaYbna0a0bnaY#DblaY#x#xaYaYblbl#D#Da9a9.7#L#L.7.7.7.7.7.7.E.7#Dbj#D.s.N.N#DboaY#MaY.W.8aZal#P#PaT#P#.a.ad.ObkaX.G.O#Taz#SaoaC#x#x#I.N.s#D.E.7af.7#L.E#L.Eaf#Laj#g#gbp.jbpa2aj#ga2#g#L#ga2#ga2#L#L#L#L#L#L#L#L.7#L.7a9.E#Da9#D.Ea9.7a9.7a9#La9#L.7aj#L#L#L#L#L#L#L#L#L#Lbpa2#L#L#g#L#ga2a2#ga2bpa2#La2#L#Laj#L#Laf#Laj#L.7#L.7af.7.E#L.7#L.7#L#sa9.7a9.7#L.7#L",
+".E.7.7#La9aj.7#Lafajafafafa9a9.nblbl#MaYblbl#Dblafajafaj#L.E#L#Laaa2a2aja2afajaf#p#p#pa9.naf.7#L#gaj#Lajbp.7#L.7ajafa9#D#D.NaY#xblaY#x#xama0a0aY#p#Dbl#xbnaYblaY#Dbl#Da9a9.7af.7.7.7.7.7.7.7.7.7#D#s#D.N.N.N.N.N#IaY.N#Iamanay.P.PaDaD#..M.O.G#u#u.w.GaP#u.ybgaCaC#x#IaY.N#s.7a9.7aja9#La9#L.E#L#L#ga2a2#ga2#ga2#g#L#ga2#ga2#g#g.7#L.7#L.7#L.7.7af#L#L#La9#Db.#Da9.7a9.Eaf.7a9.7#L#L#L#L#L#L#L#L#L#L#L#L#La2#L#L#ga2a2#g#L#g#La2#ga2#g#L#ga2#La2#L.7#L.7a9aja9#L.E#La9aja9#L.n#L.na9aj#Laja9aj.7",
+"#L#Lafaj#L#Laf#Lajafaf.Eaf#sa9a9a9a9#pbl.nbl.n#p.nafa9#Laf.7#L#L#L.ja2#La2af#L.n#p#Mbla9a9aja9#Laj#Lbp#L#L#L.7.7#D#D#saYaw.N#xbf#MaYaw#xbna0a0aYblaYaY#xbn#xaYaYbl#D#D#Da9#D.7#L.7.7.7.7.7.7.7bj#s.7#D#s#D.N.sbfa0#UaoaO.yan.2.g#m.AbA#4ar#u.0#u#S#vaBaB#uaB#v.5aoamaC#x#IaY.N.na9.7.E#L.7af#L#La2#g#L#g#L#gbp#ga2#ga2#g#g#ga2#g#L#L#L#L#L#L#L#L#L.E#L.7.7a9#Da9.Ea9.7a9.7.7#L#L#L.7#L#L#L#L#L#L#L#L#L#L#Lbpa2#La2bpa2a2#ga2#ga2#L#ga2a2a2#g#La2#Laj#L#L#L#L#L#La9#L.7#L.7aj.7#La9.7#La9.7#La9#L",
+"#L#L.7#L.7#L.7#Lafaf#Laf#La9a9.na9#Da9.n#Da9#D#Dafaf#Lafaja9aj#La2a2af#Laf#Laja9#p#D#p.na9.7aj#L#L#L#L#Laj.7.7b.#D#saY.NaYbf#x#x#DaYaYaY#xbna0#xaYaYaY#xaYaYaYaY#Dblbl#D#Da9.7.7a9.7.7.7.7.7a9.7af.7#D.N.s.N#x#IaF.8amaF.0#uaybe#.ba#aaz#ua##vaOaOaO#v#v.y#uaBa#b#bga0a0awaYbl#D.Ea9a9a9.E.7a9.7#Laj#L#gaja2a2a2#ga2#g#ga2#ga2#g#L#L#L#L#L#L#L#L#L#L#L#La9.Ea9.7.7.n.7.n#La9.n.7af#L#L#L#L#L#L#L#L#L#L#L#La2bp#La2#ga2#g#La2bpa2#ga2#L#g#L#ga2#g#L#L#Laf.7#L.7#L#L#Laj#L#L#Laf#L.7#L.E#L.n#L.E#L",
+"#L#Laj#L#L#Laj#L#L#Laj#L.7.7a9.7a9a9a9#Da9a9.na9.naf.Eaf#L.7#La9ajaf#Lajaf#La9a9#M#pbla9a9#L#L.7aj#Laj#Lbjbj#sbjaY.N.Naw.N.Nawbf#DblaYaYaY#xbn.CbnaYaYaYaY#xaYa0bl#D#D#Da9#D.7#L.7#La9#La9#L.7.7a9#sblaYaYbnaCa0.5amaFaB#u#a#4abarazaBa#aO.5ao.5aoaoamaOaB#u#uaZaCa0bn#xaYaY#Dbla9a9.na9a9a9#La9#La2a2#L#g#g#L#g#g#ga2#ga2#g#ga2#ga2a2#ga2a2#La2#L#L#Laf.7.7.7a9a9.7a9.7.7.7#L.7#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#g#La2bpa2#ga2a2bpa2#ga2a2#g#La2#L#L.7#Laj#L#Laj.7af.7#La9#L.7ajaf.7#L#L#L.7af#L",
+"#L.7af.7#La9#L.7a2#L#L.7#L.n.7.na9a9.na9a9a9a9a9afaf#Laf#Laf.E#Lafajafaf#La9.na9#D#p#sa9.n.7aj#L.7#L.7a9.Ea9#Da9.NawaY.N.NaY.N.N#D#D#D#MaY#x#xa0ama0#xbnaYaYbn.CaYaYaY#D#D#D#D#Da9a9a9a9.7#Da9#s#D.NaY#x.Ca0amamaFaB.f.Oau#aazan#v#vaFam.5aCav.CavaoaoamaOaB#uan.Ca0#xawaY.s#D#s#Dbja9bja9.7a9a9a2#La2#La2a2a2a2#ga2#ga2#g#ga2#ga2#ga2a2#ga2#ga2#L#L#L.7a9.7a9.7.Ea9.Ea9.7af.7af#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#La2a2#ga2#ga2#L#ga2#g#La2bpa2a2bp#L#L#L#L.7#L.7af#L#L#L#Laj#L#L#L#Laj#L#La9aj.7#L",
+"#L#L#L#Laj#L#L#Lajaf#Laja9.7.7a9.7a9a9a9a9.na9a9aja9#Laja9#L.7#Laf#Lafaja9a9#D#D.nblbla9b.#L.7.E.7.n.7.n#D#D#s#D#D#D#D#s#D#D.n#D#D#D#s#Dblawa0.Cama0a0aYaY#xa0amblaY#D.N#D#Dbj#Dbj#D#D#D#D#D#D#D.N#x#x#xbg#vbmaBbk#a#Ea7a7aZ#va#amb#ao.C.W.Cbf#IaqaoaoaoaO#SaZ#ubn#I#xaY.Na9a9.7a9a9a9a9a9a9a9a9#Lajaf#L#L#L#La2a2#g#g#ga2#ga2#ga2a2#ga2a2#ga2a2#L#L#L#L.7.Ea9.7a9.7a9#La9#L.7#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#g#L#g#La2bpa2#g#La2#ga2#ga2#ga2#L#L#Lajaf#L#L#L.E#L.7#L.7#L.7#L.7af.7aj.7af.7#L",
+".E.7.n#L.7#L.7af#L#L#L.7aj.7a9.Ea9a9a9.7a9a9.7a9afafafafaja9aj.7afaja9#La9a9#s#D#p#M#D#s#D.n.E.7a9.na9#D#sa9#D#D#D#s#D#D#Da9a9.n.N#D#D#Dbl#xa0ama0ambnaYaYbnama0aYaYaY.N#D#D#Dbj#D#D#D#D#s#D#Daw.C#I.Caobm.G#faG.yaBbh.l.taFb#.5a0a0aoa0#xbo#xboaqavaoamaC#Sa7an#I#x.N.s#Dbjaj#L.n#Da9#sa9a9a9a9#Laf#L#Laf#Laf#L#ga2#ga2#ga2#g#g#ga2#ga2#ga2a2#g#L#L#La9.7a9.7.7.7.n.7.7.7#L.7#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#La2#ga2a2#ga2#ga2a2#g#L#g#La2bpa2#L#L#L#L.7#L.7#L#Lafaj#L#Lafaj#L#L#L#La9#L.7aj#L",
+"#L#L#L#Lajafaj#Laf#Lafaf#Lafajaf#L.jafajaf#Laja9aj#Laj#L#L#L#Laj.7.7.E#Laj#L.7.7bl.NawaY.NaY.N.s#s#D#sa9bj.Ea9.Ea9.na9.n#D#s#D#Da9.n#D#D.saY.s#x.R.Rbn#x#x#xaY.NbnaYblbl.na9.7.7#D.N.N.N.Nbfbfbfavama#aSaG#z.G.0aoa0aC#xaCbn.Wbn#I#xaY#I#x#x#I#x#Ia0avao#v.0aBa7#IaYa9.7.E.7#D#Da9a9a9a9.7a9.7afa2a2a2a2a2#g#ga2#ga2#g#ga2#g#ga2#ga2#g#ga2#g#ga2a2#g#L#L#L.7a9.7.na9a9afaj#La2a2#L#Laf#L#L#La2#L#L#La2#La2#La2#La2#L#L#L#L#L#L#La2a2a2a2#g#ga2#g#La2#La2#Lajafa2.7#L.7af.7#L.7afaj#L#Lajafafaf#L",
+"#Lafajaf#L#Laf#Lajafaj#L#Laf#Laf#Laf#Lafajaf#Da9.7a9.7.7af.Eaf.7.na9a9a9.7.7.n.7awaYawaYaw.s.N#D#Da9#D.na9.7a9.7.n.7.7.7#D#D.7.7#Da9#s#D.N#x.N#x#Ua0a0bna0bn#IaYb#am#xaY.N.N.N.Nbj#D.N#I#xaqaoa0a0a#a7#fa6az.0.5bnaCbnbn#x#x#x#xaYboaYbfaw.NaY#I#x#Iao.8.5#v#u.T#I.N#sbja9bj.7bj#sa9.Ea9a9.7a9a9#L.ja2a2.j#ga2#g.j#ga2#g#ga2#ga2#g#ga2#g#ga2#g#g#ga2#L#L#La9aja9a9af.7af#L#L#L#gafa2#La2afa2#La2.3#La2#La2#La2#La2#La2a2a2a2a2#La2a2#L#g#La2bpa2bpa2#ga2#L#La2#L#L#L#L#Laj#L#L#La2a2afafaj#Lajaf",
+"#L#L#L#L#L#Laj.7af#Laf#Lajaf.Eafajaf#Lafa9a9.n#D#D.n#Da9#s#D#D#D#D#s#D#s#D#D#D#sbl#s#D.s#D#s#D#s.7aj.7#L.7aj.7#L.7af.Ea9#L.7a9.7.na9#D#D#D.NaY#xa0.Vaoamama0ambna#b#amambn#x.C.Cawbf#xa0amamaF#v#vaBazaSa7a#aq.W#x#x.s#xaw#xaw#x.N.NaY#xaY#x#I.N#I#xavam.8.yana7#U#x#D.7b..7a9#Da9a9a9a9.7a9af.7a2#La2#L#ga2#g#g#ga2#ga2#g#ga2#ga2#g#ga2#g#ga2#ga2#L#L#L#L.7a9.7a9a9a9#La2#La2a2#L#Lafa2#La2#La2#L#L#La2#La2#La2#La2#L#L#L#La2#La2a2a2a2#g#ga2#g#La2bpa2a2#Laj#L#L#L#L.7#L.7#L.7af#L#Laf#Laf#L#L",
+".7#L#Laj#L#La9#La9a9a9a9a9a9a9a9af#L#D.n#D.7#D.7#D#D.N.s.N.N.N.sbl.NblaYblaYawaY#M#D#Ma9#D.nbj.7#L#L#Laj#L#Laj#Laj#L#L#L.7a9.E.7a9a9a9#DaY.s.N#xaCb#a#aFa#amamam#vaFamam#xa0#xam.CaCamamaObma7aza7aZbm.tam.C.Cbfaw#xaYaY.NaY.NaY#DaY.s#xawbfaY#x#x#Iaqao.8aZ#ua7ao#xaw#Da9b..7#Da9#s.7a9af.7a9a9a2#La2#La2#ga2#ga2#g#g#ga2#g#ga2#g#ga2#ga2#ga2#ga2#g#L#L.E#L.7afa9afa9#Laf#L#ga2#La2#La2#La2#La2af#La2#La2#La2#La2#La2a2a2#La2#La2a2#La2#La2bp#g#L#ga2a2#g#La2#L#L#L#L#L#L#Lafaj#Lafaj#Laf#Laf#L",
+"a9a9a9a9a9a9a9.n.7a9.n.7a9a9.n#D.na9#s#D#D#D#D#D#D#D.sblaY#saY#DaY#MaY#saYblaY#D#D#s#D.7.n.7bj.E#L#Laj#La2#La2#L#L#L#L#L.n.7a9.7a9.E#D#D.NaY.N#Iamam#v.0a#aFa#a#bmbgamaCbna0aoa0amaF#vaBa7a7.l.TaFb#b#amam#x.Nbj#x.N.s.NaY.NaY.N.N.NaY#x.N#IaY#I#x#Iaoaq.8.ybhazb#bn.N.N.7a9#D#s.7a9a9a9.7a9#La9#Lajaf#L#L#Lbp#L#ga2#ga2#ga2#g#ga2#g#ga2#g#ga2#ga2#L#L#L#L.7a9.Ea9a9a9a2#L#La2#g#La2#La2#La2#La2#La2#La2#La2#La2#La2#L#La2#La2#La2a2a2#ga2#g#ga2#ga2bpa2a2#L#L#L#L#L#L#L#L.E#L.7a9a9a9a9a9a9.7a9",
+".7a9a9a9.n.7a9a9#s#Da9#Da9#D#D#D.7#D#D#DaY.Naw.Naw.NaY.NaY.NaY#s#D#D#D#D#s#D#s#D.na9a9.n.7.7.7#L#g.ja2#g.j#g.j#g.j.3aj#L.7aja9.Ea9a9a9#D.N.s#x#x.Cb#aF.yaZa#a##Sa##SaFamamaOa#aZazazaza7a7bmaFaFa0a0a0bn#IaYaY.Naw.NaYaY.N.N.Naw.NaY.Naw#x.N#x.N#x#I.Cao.5.ya7az.5aoaY.s#D.E#D#Da9.na9.7.na9a9a9#Laf#L#L#L#L#Lbpa2#g#ga2#g#ga2#ga2#ga2#g#ga2#g#ga2#g#L#L#Laf.7#La9afa9#L#L#La2a2#La2#La2#La2#La2#La2#L#L#L#La2#La2#La2#La2#La2#La2a2#L#g#L#g#L#g#La2a2bpa2#g.j#L#L#L#L.7af#L#L#La9.7a9a9.Ea9a9a9",
+"a9a9a9a9a9a9.na9#D#D#s#D#s#D#s#D#D#D.saY.s#xaY#x#D#M#D.nbl.nbl#Da9.Ea9.7a9.7a9.7#Laj#Laj#Laj#Laj#gas#gas#g#gas#ga2#L#La2af.7#L.7a9#s#D#D.NaYaYboa0a0aOa#a#a#aBbh.GaPa7az#uaS#TalbaaGa7aZaFaoambnaCa0#x#I#D#DaYaw.N.N.s.N.N#D.N.N.N.N#I.NaY.saY#I.N#I.C.8.5.ya7azaOb##x.N#Da9a9#sa9a9#D.na9.7a9.7a9a9.7#L#L.7bp#L#ga2#g#ga2#g#ga2#g#ga2#ga2#ga2#ga2#L#L#L#L.7a9.7.na9.7a2af#L#ga2#La2#La2#La2#La2#La2#L.3#La2#La2a2#La2#La2#La2#La2a2a2a2a2#g#ga2#ga2bp.ja2bpa2#L#Laj#L#Laj.7#L.7.na9a9.7a9a9.7a9",
+"afa9afa9.na9a9a9#s#D#D#D#D#D#D#D.saY.NaY.Naw.NaY.n#Da9a9a9a9a9#Daj.7#L#Laj#Laj#Laj#L#L#Laj.7bp.7as.jas.jas.jas.ja2.ja2#L#Laja9aja9a9#D#D.Naw.N#x#xa0am#va#a#bmaB#l#0.2.2.2#0ab.4arazaZa#aFa0.W.C#x#x.NaYaYaYblbl.N.N.N.Nbj#Dbj.NaY.NaY.N.NaY.NaY.NaY.Waqao.0#ua7aBaO.Waw#D.na9#Da9.na9a9a9a9a9af.7afa9.7#L.7.7bpa2#g#ga2#ga2#g#ga2#ga2#g#ga2#g#ga2#g#L#L#L.7.Eafa9afa9#L#L#La2#g#La2#La2#La2#La2#La2#L#L#L#La2#La2a2#La2#La2#La2a2#La2#L#g#L#g#L#g#La2#Lbpa2#La2#La9#L.7#Laf#L#La9.7.na9a9a9.na9",
+"#D#Ma9#Da9bl#M#DaYaYawaYblawaYaYaYawaYaYbl#D#D#s.7af.E#L.7aj.7#L#Lajbp#Lbp#L#L#L#ga2.j#g#g.j#g.j#g#g#g#g#g#g#g#g#ga2a2aj.7a9.7.7a9.na9#M#DaY.Nawbn#UaoaF#v.8am#va6a6ba#V.Z#oab.I.TbmaFaoam.C.C#I#x.s.N.N#D#D#D#DaY#DaYbl.NaY.N.s#D#M#D#D#s#D#D#s#Daw#x.CaC.5bc.yaBaZ#vam.Nbj#Db.#D#D.7a9.7#D#D.Na9a9.7a9#L#L#L#La2a2a2#ga2#ga2a2#L#L#L#L#L#L#L#L#Laf#L.na9a9#D#Da9a9a9a9#L#L#L#La2#La2#L#L#L#L#La2#La2a2a2a2#L#La2#La2#La2#La2#La2a2a2a2a2a2a2a2#L#L#L#L#L#L#L#L#L#L#L#L#L.7a9.7af#La9.7a9bja9#D",
+"bl#D#D#M#D#Dbl#D#MaYbl.saY.NblawaYaYaY#M#D#s#D#D.7#L.7#L#L#L#Laj#g#L#gaja2aj#gajas.jas#gas#g.j#gas.jas.jas.jas.ja2.j#L#Laf.E#D#Daja9a9#DaY.s#x#IaCamama##uazaz.G#.a..Z#Valarak#aaZ#Sa#ama0#U.C.CaYaY.NawaY#D#D#DaYaY.sbl.N.s.N.Na9a9a9a9#D#D#D#D#s.N.N#I.CaobybcbhaB#vaF.WaY.s.Nbl.s#D.na9#D#DaYafa9a9a9#L#L#L#L#ga2#ga2#gaaa2as#L#L#L#L#L#L#L#L#L#L#La9a9#D.7#D.na9#D#L#L#L#L#L#L#L#L#La2a2a2a2#L#La2#L#L#La2#La2#La2#La2#La2#La2a2#La2#La2#La2#L#L#L#L#L#L#L#L#Laj#L#Laja9.7.Eafaja9a9#sa9#D#D",
+"#D#M#Dbl#D#M#DblaY.NaYbl.NawaYaYaY#M#D#D#D#D.7afaja9#Lajbp#Lbpbp#Lajbp#Lbpbpa2bp#g#g#g.j#g#gas#g.j#g#g#g#g#g#g#ga2a2aj.7a9#Da9#Da9a9#s#D.s#x#I.Ca0aO#uazal.Y.A.1a.aHaGaz.Ta#bma##SaFaFbgama0.C#x.s.NaY.N.N#s#D#Dblbl#Dbl#D#D#D#D#Da9#D#D.7.E.7a9#D.saY#x.Wa0.8.5#S#uaB#S.5.C#x#x.NaYbl#Da9#D#D.Na9a9.7a9#L#L#L#La2asa2aaa2#ga2a2#L#L#L#L#L#L#L#La2af#L#La9.7a9#Da9a9.7#La9#L#L#L#L.3#La2#L#L#La2#Lafa2#La2a2#La2#La2#La2#La2#La2a2a2a2a2a2a2a2a2#L#L#L#L#L#L#L#L#La2.7#L#L.7af.7a9a9a9bja9#D#D#D",
+"aYaYaYawaYaYaY.saY#M.NawblaY#Daw#Dbl#D#s#D#La9.7#L#L#L#L#L#L#Lbpa2bpa2aj#ga2bpa2as.j#gas.j#g.j#g#gbp.j#L#gaja2bp.j#Laf#L.7#s.N#sbjb..N#Ibf.Waq.8#vaz#zaHbs.m.B.BauaSa#aFaFbgama0ambga#aFamam.W.CaYaY.NawaY#D#D#D#sbl#D#D#D#D.Nb.a9a9.n.7#La9.7b.#Da9.s.Nbo.C.Cava#aZaBaBaOaOb#ao#x#IaY#D.n#Da9#Da9a9a9#L#L#L#L#La2a2#ga2#ga2#ga2bpa2#ga2a2#ga2a2#La2af#L.7a9a9.7a9a9#D#L#L#L#L#Laf#L#L#La2a2a2#La2#La2#La2#La2#La2#La2#La2#La2#La2#La2#La2#La2#L#L#L#L#L#L#L#L#L#L#Laf#L#La9.7.7a9.7a9#D#D#s#D#D",
+"aYboaY#x#x#I#x#x#I#xaYawaY.NaYaY#D#M#Da9.7.7aj#L#L.E#L#Lbp#L#L#Lajbp#Lbp#Lajbpaj#gas#g#gas#gas.j#L#Lbp#Laj#gbp#L#Laj.7a9.7#Dbj.N.N.sbo.Caq.8#v#u#3adbe.A#Y#9.PbranaBb#amamaYaYaYa0am#vbmaOb#.C#x.s.N.NaY.N#Da9#D#pa9.na9#Da9.7a9.7a9.7a9.7.7.7.7a9#D#D.N.N#xbo.Cb#aOaF#vbma##vbmamam#xbl#D#D#D#Da9a9.7#Laf#L#L#L#g#La2bpa2#L#ga2a2bp#Lbp#L#Lbpa2#L#L#La9a9.7a9.7a9af.7af.7#L#L#La2#La2a2#L#La2a2#La2#La2#La2#L#La2#La2#La2#La2#La2a2a2a2a2a2a2a2#L#L#L#L#L#L#Laj#Laj#L.7aja9#L.na9#D#s#D#D#D.N.N",
+"#x#x#x#I#x#x#IbnaYaY#IaYaY#MaY#M#D#D#Da9.7#L#L#L#L#L#L#L#Lbp.E#Lbpa2bp.j#L#g#L#g.j#gas.j#g.j#g#g#Lbpajbp#Lbp#Laj#L#Laj.7.n.N.N.sbf.C.Caoa#.w.ObB.u#.#oa8aMabalanaBa#a#a0#xaYaYaY.Wamb##Sa#b#a0.C#xaY.NaY.s#D#D#D.nbla9a9#D.n.7a9#L#L#L#Laj#L#L.7.E.7b.a9.s.N.N.s.Camam.8aF#vaZ#uaFb##xaYaY#D#D#sa9a9a9.7#L#L#L#La2a2#ga2#ga2a2#g#L#L#L#L#L#L#L#L#La2af.7a9a9.7a9a9a9#D#L#L#L#L#La2#La2#La2#La2a2a2a2a2#La2#L.3#L#La2#La2#La2#La2a2#La2#La2#La2#L#L#L#L#L#L#L.7#L#Laf#L#L#L.7a9.7bja9#D#s#D.N.saY",
+".CaC.Ca0.Ca0#x.CawaYaY.Nbl.N#D#D#Da9.E.7aj#Lbp#L#L.7#Laj#L#Lbp#Lajbpaj#Lbpaj#Lbp#gas.j#gas#gas.jbpaj.7#Lajbp#Lbp#La9a9#D.N.s.N#x.WaqaO#ubk#zaHbA#Pbsbeab#a#ua#ambm.Fa0bn#xaY.N.s.Nbnb#bmaBa#aC.Caw.NaY.NaY#D#D#D#pa9a9a9a9.7a9#Laj.7#L#L#L#L#L#Lbja9bjbj#D.7.N.Nbo.C.Ca0a##vana7an#Sa0aYawbl#D#Da9a9.7af#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#Laf#La9.n.7#Da9.7afa9#L.7a2#L#g#La2#La2#La2#L#L#La2a2#La2#La2#La2#La2#La2#La2#La2a2a2a2a2a2a2#L#L#L#L#L#Laj#Lafaj#L#L.Eaf.7#La9#s#D#DaY.NawaY#x",
+".C#xa0#x.W#x#x#x#DaY#Dbl.sblaY.Na9#D#L.7#L#L#Laj#Laj#L#Lbp#L.7#Lbpa2#L#g#L#g#L#g.j#gas#g#g.j#g.jbp.7#La3#La3aj.7.7aj.7#s.N.N#Ibf.8aF.y#3ad.A.MaT.P#V#P#Tan.5.C#Ia0b#bga0#xbf#xbf.N#xa0bm.T#Sao#x#x.NaY#s.N#D#D#D#p.nafa9.na9#L.7#L#L#L#Lbpaja3#L.Ebj.E.7#sbj#sbjbf.s#xavama#aBana7aZbgbnaY#D#D.7.na9a9.7#L#L#L#L#L#L#L#Lbp#L#L#L#L#L#L#L#L#L#L#La2a2#L.7a9a9a9.7a9a9a9#L#L#L#g#La2#La2#La2#La2a2#La2#La2#La2#La2#La2#La2#La2#La2a2#La2#La2#La2a2#L#L#L#L#L.7#L.7afaj#L#L#L.7a9#LaY.Naw.Naw#x#x#I",
+"aY.saY.NaY#DaY.N.na9.na9a9a9a9aja9a9a9a9.7a9.7a9#Laf#L#Laj#L#gaj#Lajbpaj#Lajbpaj#Lafaj#L#L.7.Ea3#L.Ebj#D.s.N#Db..7.7.N.N.WamamaOakaybs#Y.maDbaaHaga7#SamamaC.C.CaYamb#aFb##xaY#D.n.Nawa0#vaZaZa##xaw.N#Daf.na9#s#Da9a9a9.7af#Laf#La2#g#g#L#Lbp#L#L#L#L#L#L.7.7.7.7bj.N.Caoam#vaZaz.fanama0aY#Ma9aY#D#Da9a9.7.7#D#L#La2#La2#L#L#La2a2a2a2a2a2a2a2.7afa9a9#D.7#D.7af#L#L#L#La2#ga2a2a2a2a2#ga2#ga2a2a2a2a2a2a2a2a2#La2#La2#L#L#L#La2#La2#La2a2a2#La2#L#Lafa9a9a9bja9#D#D#DaY.s.N#x#Ibn#x#x#x#x#U#x",
+"aY.Naw#D#D#s#D#Da9a9a9a9a9afa9a9a9a9.Ea9a9.na9a9afajaf#La2#L#L#Lbp.7bp.7bp.7bp.7a2a2#Laj.7.E.7.E#L.E#D.s.N.Nbjbj.N.s.N#xa0aO#u#E#V#2....#KaD.YaGa7bmaFaFaoama0.CbnaCb#aOama0.N#D#Dbl#xa0bmaB#ua##x#xaY#sa9.7a9.7#D#D.7a9a9aj#L#L.j#La2bpa2#Lbp.E#Laj#L.E#L.7b.#Db.#D.s#xa0.8a##v.6azbhaOam#xaYbl#Dbl#Da9#Da9.7.7#La2#La2a2a2a2#La2a2a2a2a2a2#La2#L#L#L#D.7a9#Da9#L.3afa2#La2bpa2bp#g#L#g#La2#L#g#La2#La2#La2#La2a2#La2#La2a2a2#La2a2a2aja2#L#La2#Lafaj#La9.E#Da9#s#D#Daw.NaY#IaYaYaYawaYawaYaYaY",
+"a9a9a9a9.na9a9.na9.na9.na9.na9a9a9.7a9a9.7a9.7a9#L#L#L#L#Laj#L#Laj#Laj#Laj#Laj#L.jbp#L#L.E#L.Ea3.n#D.Nbf.Cbo.Caobf.CamaOaBaz#EaraQ#.#o.Abzay.Gana#aFaFaOamam.C.Wbna0a0b#ama0#I.N#D#M#x.CaoaZbhaBa0#IaY#Da9#s.7a9#sa9#Da9a9#Laf#L#L#ga2#g#L#Lbpbp#L#L#L#L#L.7.7.7.7#D.NaY.Cambga#a7.6#ua#b#aoa0#xbl#D#Da9.7a9#Laf#L#La2#La2a2a2a2#L#L#L#L#La2#La2.7afa9a9#D.7#D.7afaf#L#La2#L#L#ga2a2#ga2#ga2#ga2a2a2a2a2a2a2a2a2#La2#La2#L#La2#L#L#Laf#L#Lafajaf#L#Lafa9a9a9#Db.#D#DaY#DaY.N.N.N.s#D.N#D.N#D#s#D",
+"aj.7aj.7.7.7.7.7#Da9#Da9a9a9a9.7a9#Da9#s#D#D.n#Da9a9.na9.7.7bj.7bp#L#L#L#L#L#L#Laj#Laj.E.Ebjb..N#MawaCaoaoama0.Cb##va7#a.Oaz#uaZaZanaz#e.6anaZaFaBaOaF.5amama0a0#xaCa0ama0a0#xaYbl.NaY#xa0#vaZ.lama0#x#Mbl#D.7#D#Dbja9.Ea9af#L#La2#L#La2bp.j#Lbp#Laj#Lbpaj.7bj.7#s#D.s#x.Wa0amamanaB.0a##va#bgamaYaY#Da9a9a9#L#L#L#Laf#L#L#L.7#La2a2#La2#L#La2#L#L#L.7a9.7a9#Da9#L.3#La2#L#L#La2bpa2#g#La2bpa2bpa2#La2#La2#La2#La2#La2#La2a2#La2.3#L#La2#Laf#L#Lafaja9a9.7#s#D#D#Da9.s.N.s.Naw#Dbj.7b..7b..7bjbj",
+"#L#Laf#Lajafaj#Laf.7.7.7.7.7a9.Ea9bja9#D.7a9bja9a9.7a9.7a9.7.Ebjaj#Laj.7.E.E.7.E.7.E#D.s#xbo.C.WaCamb#a#.y.0.yaB.Gazazazbhbma#aFaFa#a#aZaBa#.5.5#SaFambgama0amam#x#xbna0a0aCa0#xaYawaY#Ia0aO.lbh#vb#bnaY#s#D#s#D#Da9#Da9.7ajaf#Laja2bp#g#L#Lbp#Lajbp#L#L#Lbj.7.7#Da9#DaY#x.CaCam.5a#aOa#a##va#a##xawaY#Da9.7#L#L.7af.7#La9#Laf#L.7af#Laf#L#Laf#Laf.7a9.7a9a9#D#Daf#L#La2#L#L#L#La2a2a2#ga2a2#ga2a2a2a2a2a2a2a2a2#La2#La2#L#L#L#L#Laf#Lafa9a9a9a9a9a9a9bj#D#D#D#D#D#D#Da9#Da9#D#s#L.7#L.7#L.E#L#L",
+"#Laj#Laj#L#L#L#L.7.n#La9aja9#L.7a9#s.7#Da9#Da9bj.n#Da9.7.E#Dbj#D#D#D#Da9#Da9#Da9.N#I#x.Wam.8.5#va#aBaP.G#a.U#4.Uaza7aZa#aFaFbmb#a#b#aFa#.8ama0ama0a0a0a0a0aC.Ca0#I#x#xa0b#a0a0a0aYaY.N.N#Iambm.lbmaFaobnaYaY#Dbj#D#s.7a9a9af#L#L#La2aj#ga2bp#Lbp#L#L#Lbp#L.7.E.7#D#D#D.saY#x.C.CaC.5am#v.5a#.0#va0bn#x.N#D#D.7.7a9.7a9.7a9.7.7a9#L#L#L.7af.7#L.7#L#L.7a9a9bja9#Da2afa2#La2#L#L#L#L#g#L#g#L#g#La2#La2#La2#La2#La2a2#L#L#La2afa2af#L#L#L.7a9.Ea9.7.n.7#Da9#s#D#D.N.N.sbj#sbjb..7bj#Laj#Laj#L#L.7#L",
+"bjbj.7bj.7.E.7.7.7.7a9.7a9.7a9.7#D#D#D#D#s#D#D#D#D#D#D#D#D.N.s.N.sbfbobf#Ibf#xboa0.8.5#v.yan.w.G#TabaMa8#cabalaZa#aFa#b#b#a0b#b#ama0aoa0a0#x#x.CawaYaY#Ubn#xaYaY#x#x#x.Rbna0a0amaYaY#D#DaY#UaF#GaZ#S.V#UaY.s#Dbj#s#Da9.n.7#La2af#L#La2#g#gajbp#L#Lbp#L#L#L.7bj.7a9#s#Dbl.N#x#x#x#x.C.Cam#va#a#.0aF.8a0#x#x#D#D#Da9#D.7#Da9a9.7.7#Laf#L#L#L#Laf#Laf.7a9a9.7a9#D#Daf#La2#La2#L#L#L#ga2#ga2a2#ga2bpa2a2a2a2a2a2a2a2#Lafa2#L#L#L#L#Laf#La9a9#La9a9a9a9#D.7#D#D#D#D#D.s.Nbja9.7.7a9.E#L.7.7.7.7aj.7aj",
+".7a9b..7.7bjbj#D.Eaf.7#L.7af.E#L#D#D#D#D#D#D#s#D#D#s#Dbj#D.s.N.N.C#x.C.C.C.W.C.Wby#vaBaz#T#4aH#..ga8bsbr.2al#TaZaFaFb#b#ama0a0a0.Cama0#xaY#x#x#xaYbl.NaYaYaYblaYbf#x#x#xbna0a0aobn#xaw#D.sa0.t#SbmbmaOa0#U.N#D#D#D#D#Da9a9#Laf#L#L#La2#L#g#L#Lbpa2ajbp#Laj.7.7.7#Dbl#DaY.N.N#Ibf.Naw.Cao.5.5a#a##va#ama0bf#D.N.N.7#Da9#D.7a9.7a9#L.7#La9#La9#L.7#L#La9.7a9bja9#Da2af#La2#L#L#L#L#g#La2bpa2bpa2#La2a2#La2#La2#La2#L#L#Laf#L.3#Laf.7a9af.7a9a9.7a9.7#D.n#D#D#D#D#Dbjbj#Dbj#s.7.E#La9.n.7.na9.7a9.7",
+"#Laj#Lafajafaj#La9#D#s#D#D#D#DaYaYaYawaYaY.NaY.N.C.C#x#IaYaY#M.namav.8.5#v.0.w.G#aau#4#4#z#3.Ga7#Z#0aM.gaTayaZa0a0a0a0#xbn#x#U#xawblawaY#D#M#D#D#D#Da9#D#sblaY#Mbl#Mblbl#DaYaYaYa0#IaY.N.NaY#Ua0.t.tbm.Fam#x.Nb.#Da9a9.7af#L#La2aj#L#L#L#L#Laj#L.7#L#L#L.7#L.7af.7.7a9.7.n#D#D.NawaYaY#x.CaCamao.0a#aB.0.taFb#.VaY#Da9a9af.7#D.N#Laf#L#L#L#L#Lafa9a9a9a9a9.7.7.7a2#La2a2a2a2a2a2a2a2a2a2a2a2a2a2#g#L#ga2a2#ga2a2a2a2a2a2#L#Laf.7#pa9a9a9#Dbj#D.N.na9a9a9b.#D#D#D#D#s#D#D#D#s#D#D.n.7#L#L#Laj#L.7",
+"aja2afaj#L.7.7#L#sa9#D#D#s#D#D.N#D#D#D.N.N.N.N#DaY.N#x#xaCamb#aF#SaZanaz.Galba.4.O#aaz#uaB.0aBan#Tbz.mab.2az.5#xa0bnaYaYaYaYaYaY#DaY.NaYbl#D#D#D#D.n#D#Dbl#Dbl.Na9bl#Dbl#DawaYaYbnaYaY#D.s.N#xaCbm.Fbm.tb#aC.N.Nbl.na9a9aj#L#L#L.7#L.7#L.E#L.7#L#L#L#L#L#L#Laj#La9aj.7.7.7#D.N#D#Dbl.N#xbn.Ca0ama##va##v#vbm#vaF#x#x#Da9a9#D#D#D#L#La9#L.7af.7#L#pa9afa9.7#D#La9#La2a2#La2#La2#La2#La2#La2#La2#La2#ga2a2bpa2bpa2a2a2a2a2a2#La9afa9.na9a9#D#D#Dbja9.nbj#D#D.NaY.saY.Nbl.sblaYaY.Na9.7#Laj.7.7#L.7",
+"#Laj#L#Laja9.E.7#La9.Ea9#D#D#s#Db.#D#D.Nbo.Caqaq.bbnbga#aZaS.G#q#t.HaQauaGar#a#a#vaOaF.5b#.8#vaB.2.A.1aDaka#amaYaYaYaYaYaYaY#D#D#D#D#s#D#D#D#D#D.7.7a9#D#D#D#Dbla9a9.n#D#D#D#Dblaw#xaw.N#DaYaYbnb#aF.taOb#.C#I.Na9a9.7a9a9#L.7#L#L#L#L#Laf#L#L#L.n#L#L#L#L#L#L#L#La9a9.7a9.Ebj#D#D#D.s.N#x#x.W.Ca0amamaFa##vbmaBb#bnaY#D#D#Da9bjaf#L#L#Laf#L#L#La9a9a9a9a9a9.7.7a2af#L#L#L#L#L#L#L#La2#La2#L#L#L#L#L#L#L#L#L#L#La2#L#Laf#La9.7a9a9afa9a9bj#s#D.Nbl.NblaY.NaY#xaYawaYawaYbl.sbl#M.7.E#L.7#L.Ea3.E",
+".7.7.E.7.Ebj.7.7.n.7a9.7#s.N.N#DaY.N#x.Cam.5a#aZaF#SaZa7arala6ay#W#W#kbhbmaFa#.5#x#x.CaCaoamaOaB#P#obsba#uam.C.NaYaYaY#D#D#D#D#Da9#Da9#D.7#Da9a9#La9.7.7a9bl#s#Da9a9a9bla9bl#D#DaY.NaYawaYaY#IaYa0aCb#.Va0a0#U.N#D#Da9.7a9.7aj#L#L#L#Laj.7#L#L#L#L#L#L#L#L#L#L.7#L#L.E#La9.7.7.7#D#D#DaY.s#x.C.C#x#Ia0aCama#a#aZa#.8a0#xaY#Da9af.7#Da9#D.7#Da9#Dafa9afa9.7a9#La9#L#L.3#L.3#L.3#L.3#Laf#L#L#L.3#L#L#L#L#L#L#L#L#L#L#L#L#La9.7a9a9a9#D.na9bl#DaY#s#x#x#x#Ia0#I#x#xawaYblaw.NaYaYaY.7#D.7.Ebja3.7.7",
+"#Db.#D#D#s.N.s.NaY.Naw.N.NaYbo#xa0b#a#bmaS#aa6.Kbaba#a.faZaFb#amb#b#ama0.C#xbf#xbobf.NaY#xao#v#u.q.qaGanamaYaY#DaY#sbl#Da9.7#L.7.7.E.7a9.E#L.7.E#L#L#La9.nbjbl#Da9a9.7a9.7#D#D#DblaY#xaYaY#IaYaY#xbna0bnbna0aCbn#sbl#Da9.7af.7a9#L#L.7#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#La9.7af.7a9aj.7#D#D.N.Nbo#x.Nbl#Ia0am.5aO.0aB.0b#.CaYbla9a9a9.7a9.7a9.7a9a9a9#pa9a9a9bj.7.7#L#L#L#L#L#L#L#L#L#L#Laf#L#L#L#L#L#L#L#L#L.7#La9#Lafa9bja9#D#D#D#Dbl#DaYaYaYaYaY.C#xama0.CaC.C.C#x#xboaYaY.NaY.N#s.N#D.N.s.NaEaW",
+".N.N.s.N.Nbf#xbfaCa0a0a0a0amam.8aZbhazaGau#j.e.e.6ana#.5ambn#xaY#I#x#xbo.N.N#saW#x#Ibfaw#x.5aZ.G.q.KaBam#xaY.s#D.7#Da9.7.E#L#L#L#Laf#L#L#L#L#L#L#Laj#L#L.7#Da9#Da9.7a9#D#D#Da9#D#DawaY#IbnaYaY.Naw#xbnbnbna0bna0aY#D#D#Da9.7#L.7#L#L#L#La9#L#L#L#L#L#L#L#L#L#L#Laj#L#L#L.n.7.7.7#La9.E.7#D.N.N.N#saY.N#x.Wa0.5aF.0aZ#v.5a0aY#Da9.7#Da9bja9#D.7#Dafa9afa9.7a9#La9#La9#La9#La9#La9#La9#L.7a9af.7af.7#L.7.7#L.7af.7.7a9.7#D#D#D#D.N.saYaY#x#I#xbnbnaOaoaoamaCa0a0bn#Ibn#x#x#x#x#I#x#xaYboaY.N#xbf#x",
+"#x#xa0.CaCa0aoa0aFa##v#vaZ#uaZaZarazazanbmaF.5a0.C#x#x.N#D#D#D#D#D#D.Nblbj#D.N.sbf#x#I.CbgaBaz.2baazaF#x.n.7#Dbla9.7.7#L#L#Lajbp#L#L.E#La9#L.7#L#Lbp#L#L.7#L#D.E#L#L.E.7.7.7.7#Dbj.N#xbna0#I.N#DaYawbna0bnbn.V#U#D#D#D#D#D.7a9.7#Laja9#Laj#L#L#L#L#L#L#L#L#L#L#L#La2#L#L#L#Laf.7#L#L#La9.7#s.N.N.7#D.N.N#x.CaCaq#vaZaBa#aF#xaYbl#D#D#D#D#D#D#D#Da9a9a9a9a9a9.7.7#L#La9.7a9a9#L#L#La9a9a9.7a9.7#L.7af.7af.7a9.7.7#D#D#D#D#D.N.NaY#x#x.Ca0b#ambgamaOb#aCa0.C#I#xaYa0a0#xbn#x#xbna0aCa0a0a0ao.CaCaq",
+"aoa0aoaO.5.8aFaO#u#uaSazaG#3araza#a#amam.C#x.s.Nafaf#La9bjaWbfbf.N.NaY#xawaYaYaY#x.C#xaCamaB#aaT.GaF.C#D#La9#L#D.7#Laj#L#Lbpbp#Lajaf#L#La2#L.j#Lbp#L#Lbpa9.7#Da9.7#La9#La9.7a9.7#Dbl#xaCbn#xaY.s#D.N#Ubnbnbnbna0bl#D#D.7a9.7#L.7a9#L#L#L#L#L#L#L#L#L#L.7#L#L#L#L#L#Laj#L.7#L#L.7a2.7#L.7.7#D.N.Nbj#D.s.N.N#I.Ca0aFaZaBaZ#vam#xaY.7#Da9#D.7#Da9#Dafa9afa9.7a9.7a9#L#Lafa9#La9#L#La9af.7a9a9a9afa9a9#L.7.7a9#L.7af#D#D#D.N.N.NaY.s#xama0.8aF#Sa##va0a0a0#xbnaYaYawbn.WbnaCbnaCa0aCaFb#aO.5aOaF.8aF",
+"aZ.ya#amaoaFaB.Taka6aGaraBaFa0#xbnaYaYaw#D#Da9#D#L.Eaf.7a9aj.7.7aja9.n.7#D#D.sbfaw.N.Wam#v.w.Ga7.C#IaY#D#s.7.n#Laja2#L#ga2#ga2#g#L#Lajafaj#L#L#Laj#L#L.na9a9.na9a9a9.na9a9#L.Ea9a9#saYaY#x.C#x#xaYbn#x#U#x#xa0aCbn#D.7#L.7a9a9#paj#L#L#L#L#L#L#L#L#L#L#L#g#L#L#L#L#L#L#L#L#L#L#Laj#Laf.Ea9.7.7a9#Da9#D#D#DaY.NawaY.pa#.0.0a#ambn.N.N#D#D#D#D#D.7a9af#L#L.7#L#L#L#L#L#La9a9.7a9#Da9a9#Da9bja9bj#D#D#D#D#D#D#D#D#D#s#D.saY#xbn.8aFaZaBaZa#aFama0aqaC#x.N#MaY#x.Ca0aFb#b#amamb#.5aFaoaOaFaOa#bmaZ.y",
+"aZa#aOa##v#vaB.T#4#z#a#uaFa0aC#xaYawaYbl#Da9#Da9.7a9.7#L.7a9.7a9af.Ea9.7#s.N.N.N#D#Ia0.8a#bkaraZ#IaY.s#D#Da9.7#Lbpa2bpa2#g.j#ga2ajaf#L#L#Laja2#Laf.7#L.7a9.7#Da9afa9a9a9a9.7a9#La9#Dbl#x#x#I#x#xawaY#U#xbn#Ia0.CbgaYa9#L#L#Lafa9#Laj#Lbp#Lbp#Lbp#Lbp#L#ga2#g#La2#L#L#Laj#Lbpaj#L#L.7#La9.7.7a9.7.E#D#D#D#D.saY.N#Ua0#va##S.0aOamaY.N#D#D#Da9#D#Dafa9a9af#L#L#L.7af#Laf#La9#Da9.7a9a9.7#D#D#D#D#Da9bja9a9#D#D#s#D.N.N#x.Ca0aoaF#vaZbmbmaOa0.W.C#x.C#xbl.NawaY.CamaCamaCamamambgamb#.5aOa##Sa#.yaZ",
+"#vaFaO#v.ybmaZazbaauazb#a0#x#xaYaYaY#D#sa9#D.E.7aj#L.7aja9aj#L.7aja9.n.7#D#D.sbfaY.WaCam#u#3a7aFaYaY#D#D.n.7ajafaj#gaj#g#L#g#Laj#L#Lajaf#Laf#Laj#L#L#La9a9#Da9a9.na9a9.7.n.7.7a9.na9aY#x#x#x#x#xaYaY#x.R#IbnbnaC.t.VaYa9.7aj#L#L#Lbp#L#Laj#La2#L.j#La2#g#g#g#gajbp#Lbp#L#L#L#Lbp#L#L#L.7a9.7.7.7a9#D#s#D#DaY.NaYaYa0ama#a#.yb#a0.N.N#D#Dbj#D#Da9a9a9.7a9bja9.7.7a9a9a9#D.7#D#D#D#D#Da9#Da9#D#D#Da9a9.n#D#DblaYaY.8b#.8aOaFaOaFaOb#bgama0#x#x#x.N#U#x#I#x#x#xaoama0bna0bnaoam.5amaOaFaFaF#va##vaZ",
+"aOaOaF#va#a#az#faS#ubmb#a0#xaY#Dbl.n#Da9a9.7#L#L#L#L#L#L#L#Laj#L#L.Ea9a9#s.N.N.s#x.Wb##v#Ebk#va0aw#D#D#Da9#L#L#Lbpa2#L#ga2#ga2#g#Laf#L#L#Laj#Laf#L.7#L.n.7#D.na9a9a9a9a9a9.7a9#La9#sbl.NaY#xaYaYblaYaw#x#x#x.C.C.Fb#bnbl#Da9.E#L#Laj#L#Lbp#Lbp#Lbp#Lbp#L#g#L#g#L#Laj#Lbp#Lbp#L#L.7#L.n#L#L.7af.7#Da9#D#D#D.NaY.saY#Ibn.5a#a#aFambf#x.NaY#D#D#D#Da9a9a9.7a9.7.7#L#D.nbj#D#D#D#D.Na9b.bl#Daw#xaYaYaYaYaY#Ia0a0aoam#uanaBa##vb#bgb#bnbnaYaYaYaYblaw#x#x#x#Ua0.Wa0a0.W.C.Wama0ambg.5aFaFa##va#a##va#",
+"b#ao#vbmaB#uaz.Gb#b#ama0#xaw.N#D#Da9a9a9.E#L#Laj#L#Laj#L#L#L#L#L.Ea9.n#D#D.N.N#x#Iao.5#u.Oazam.C#Dbl#sa9ajaf#La2.jbp.j#L#gajbpaj#Laj#Lajaf#L#Laj#L.n#La9a9a9a9#D.na9a9.Ea9.n.7a9a9#DaYaw#x.sbl#D#sblaYbl#I#x#Ua0b#bgb#bn#D#D.7#Lbj.7.7.7.7.E.7.7#L.j#La2#g#L#La2bp#L#Laj#L#Laj#L#L#L#L.7af.7.7.7a9.7#D#D#s.Nbl.NaYaY.CaCby#va#.8#xbfaY.N.s#D#Dbj#D#D#D#D#D#D#D#D#D#D#D#D.Naw.NaY#D.NaYaw#x#xa0aoamamaFaF#v.0bbanaBaZ#vaFb#am#x#xaYaYaYaY#IaY#D#D#x#x.Ca0avamama0.C#x.Ca0aoamaFa##uaZaBaZ.y#S.0.y",
+".8aOa##Sazar#ua#a0am#x#x#x.N#D.7.na9#L#L#Laj#Lbp#L#Lbp#L#Laj#Laj#La9.7.n#D.sbo#x.Wao#v.f#f.ya0bf#M#D#Da9a9#L.ja2#La2bp.j#L#ga2a2#Laf#Laf#Laj#Laf#L.7aj#Da9b.bl#Da9.na9a9a9a9.7.n#D#MaYbfaYaY#Da9#D#D#Daw.NaY#x#Ib#b#bg.VaYbl#s#L.Ebj.7b..7.7.7.7#Lbp#Lbp#L.jbp#L#L#Lbp#Lbp#Lbp#L.7aj#La9.7a9#L.7a9#s#D#D#DaY.Naw.N.s.CamamaOa#a#.W#xbf#xaY#D#D#Da9#Da9#Da9bj#Dbj#D.N.Naw.N#x#xbfaYaw#x.Ca0a0aFbma#aBaZbbaZ#uaZ.0bgb#a0am#x#x#xaYblaY#MaYaY#Dbl#DaY#xaCamamaoaqaC.C.Wamao.5a#a#.yaSazaZ#uaZ.yaOaF",
+".5aF#Sbhaza7aFa0a0bn#xaw.N#D.7.7af#L#L#L#La2#L.j#g#Lajbp#Lbp#Lbpaja9.n#D#s.N#I#I.WaF#uarazaF.W.Nbl#D.n#Laj#La2a2aj#g#L#g#L.jbpaj#Laj#L#Lajaf#Laj.7afa9.na9#D#D#Ma9#p#s#D#sa9.na9#DblawaYaw#Da9a9#D#D#saY.Naw#x#xaCb#.VaC.V#xaY#Dbj.nbja9bj#s.7.7aja2#L.j#Lbp#La2ajbp#L#L#L#L#L#L#L#L#L.Ea9.7.7a9#D.7#D#D#D#DaY.N.N.N#I.CaoaFa#aB.C#x#xbf#x.N.NaY#Dbl#D#D#D.N#D.NaY.saYaY.C.W.C.W.Caqa0.8a#aZaBan#u#uan#Sa#b#ama0bnaY#xaYaY.NaY.N#s#DaY#DblaY#Dbl#I#xam.8.5aOam.Cama0aoaFbmaBbha7#a#ea7an.y.yaF.8",
+"bc.y.wara7b#a0aoaYaYaYbl#Da9.7.7#Laja2#L#g.j#g#ga2bpa2bp.jbpaj#Laf.Ea9#s#D#I#I.C.WaOaz#EaZb#.C.N#sbla9afafaj#L.j#L#g#L.jbpa2bpa2#Lafajaf#L#L#Laf.E.7.n#Da9#D#sbl.n#D#M#s#D#s#D#s#DawaY.NaY#Da9.n#D#D#D#DaY.NaY#I.CaCam.Vb##U#xawa9bj.7b..7bj.7bj#Laj#Lbp#La2#L#Lbp#L#Lbpaj#Lbpaj.7#L.7af.7a9.7.Ea9#D#D#s#D.N.saYb..Nbf.Wa0aF.0#ua0.W.C#Ibfaw.NaY#saY.N.N.N.N.N.N.N#xaY#I#x.W#x.C.Wam.8aZ.waz#ubha#aFaFb#ambn.bblawaY#MaY.N.s.N.N#D#D#D#DaY.saY#I#xaCam.8aFbyaoaCaoamama#a7azararaya6.G.Gaz#u#v.8",
+".J.far.laobn#xaY#D#sa9#D.7a9aj#L#L#L#L#L#Lbp#Laj#g.j#ga2#L#L#Lbp.na9.7#s.N#I.Caobh#EaBaCbn.s#IaY#Ma9.n.7#L#L#L#Laj#Laj#L#Laj#L#L#L#L#L.7aja9.Ea9bl#M#D#M#DblaYblaYawaYaYawaY.NaYawaY#Mbl#D#D#D#Da9.n#D#s.Nbl.saY#x.RaY.N#xa0aFbm#IaYaY.N#s.7.E#L#L#La2#L#L#Lajbp#L#La2#L#L#L.7#La9a9a9.7#L.7.7.7#Da9#D#D#DaY.N.NaYaY#Ia0.5.8a#an.0.5bn#xbl.N#x.C#Dbl.sblaY#I#x.W.R#Ibna0aOa##vaZazararaz#ua#aFaO#x#I#x#Ibn#x#xaYaYaY#DblaY#Dbl#Dbl.NblaY.NaY#x#xaoaobnaY#xaCa#.0aOaOaOaFaFaFaFaF.l.Ta7bh.G.G#q#e",
+"araza7aFam#xaYawa9#Da9a9a9#L#L#L#L#Lbp.j#L#La2#Las#ga2#gbp#Laj#L.7.7.n#D#M#xaCaFbk#iaOaC#xblaY.Na9a9a9afaja9aj#L#L#Laf#Laf#Laf#Lajafaja9#L.7a9.Ebl.n#D#M#DawaYawbn#Ubn#I#x#I#xawaYawaYaY#D#s#D#D#D.n#D#DaY.s#x.N#U#IawaY#xbna0aF#x.W#xaw.N#D.7b.afajaf#L#Lbp#L#La2#L#L.E#L.7a9.7a9a9.na9.7a9.7.7#D#s#D#D#D.Nbl.Naw.N#x.CamaF.0.y.yaF.CaYaw#x.Caq#Ibn#x#x#x#xbna0aoamaF#vana7.wazaZan#uaZaOamamamaY.RaYaYawaYaYaYaYblaY#D#Dbl#DaY#DblaY.N#xaY#I#xbnbnawaYbnam#va#ama0a0aoamamaoam.taFbmaZ.6ar.2#4",
+".faBb#a0aY#xbl#Da9a9#D.E.7#L#L#L#g#ga2#g#g#g#g#g#g#g#ga2#L#L#L#L.n.7a9a9.N#Iam.8#f.Gb#bn#UaYaw.Na9.na9.7af#Laf#Lajafaj#Laj#Laj#Laf#Laf#L.na9a9#D#Mbl#M#DawaYaw#x#I#U#x#U#Ibn#I.NawblaY#s#D#D.N.sa9#s#D#M.NaY.s#xawaY#D.s#D.Nbnama0a0aC#x#xbl.NaY#La9#L.E#L#L#L#Laj#L#L#La9.7aja9a9a9a9#D.n.7a9.7#s#D#D.Naw.N.NaY#Dbl#I#xaC.5#va#aBaFa0aC.C.Caoa#ama0a0ambgaF#va##uan.w.wan.wanaZ#vaFb#ama0a0#x#xaYbfaY#xaY.Nbl.Nbl#D#D#Dbl#D#D#D#DaY#saY.N#x#x#xaYaYaYaY#Ia0bg.5bn#xbn#xbna0a0amaCb#ao.t#SaZar#a",
+"aFama0aY#xaY#Da9#D#Da9a9#L#L#L#g#ga2#gbpa2bpa2bpa2#ga2#gbpajbp#L#Da9.7#saYaY.W.5#EaraFa0#U.NblaYa9a9a9ajaf.E#La2#L#L#L#Laf#Lafaj#Lafaja9#D.n#D#D#s#DblawaY#I#x#Ibnbn#I#U#x#IaY.N.Rawbl#D#D#D.s.N#D#D.saY.saY#I#x.N#s#s.7bj.N#xa0aob#amaoa0#I#xaY#D.na9.7a9bpaj#L#L#L#La9.Ea9#D#D#D#D#D#D#D#Dbj#DaY.Nbl.N.N#x#xbfaw.NaY#xama0aOa#aBa#bgama0.5a#.0aFaOaF#SaZan#ua7bhazaBbhaBa#aFb#b#aCbnbn#x#xaYaw.Nblaw#D#Dbl#D#D#s#D#p#Da9#D#D#Dbl#DaY#x#xaw#x#xaY.NaY#x#x.C.C.CawaYaw#xaw#x#Ibn#x#Ua0a0amaFbmbm",
+"bn#xaYaYaY#Ma9af.7.n#L#L.7#L#ga2bp#ga2#g#ga2#ga2#ga2#L#L#L#L.7.7#s#D#s#D.N#xamaoaS.OaBam#xaYaw.N.na9a9#Laf#L#La2ajafaj#L#Laj#Lafaf.na9a9a9bl#D#Mbl#saYaw#x.b#x#x#U#Ibn#I#xawaY.saYaYbl#D#D#D.N#D#M#sblaw.N#I#x#I#D#sbj#Db..N.N.Camamb#am.pa0a0bn#D#Da9.7.7aj#Lbp#L#La9.7a9a9#s#D#MaY#D#Dbl.saY.N.N.N.s#x#xbf#I#x.NaY#I.CaCamam#vaBbm#SaF#va#a#aB#ubh#uanaBaBbmaZ.FaFb#b#a0aCbn#I#x.RaYawaYawaY.N#D#D#D#D#D#D#D#Da9#Da9#Da9#Da9a9.saYaw.Naw.N#xaY.N#x#xaY#xaC#xaYblaYaYaYaYaYaY#xaYblaY#Ua0a0.Vbn",
+".NaY#D#Da9a9a9#La9.7.7#L#L#g#L#ga2bpa2bpa2bp#gbp#g#Lbpaj#L.7.Ebjbj#D#Dbl.s#xaoa##TalaBam#x.NaY#Da9a9a9af#L#L#L#L#L#Lafaj#Laf#Lajafa9a9#p.n#D#M.NblaYaYawaY#x#I#x#Ibn#U#Ibn#I.NaYawaY#sbl#saY.s.N#sbl#s.NawaY#I#x#I.N#D#s#D.N#Ibnaoa0#Ia0a0b#aoamaw.N#Da9.7#L#L#L.7.n#L.7#s#DaW#DaYaYaY#I.NaY.N.N#I#x#xbf#x.C.C.C#x#I.Ca0amama#a#a7azaza7aZaB#uan#uan.laZ#SbmaFaF.V#Ubn#UaYaYawaYaYawaY.NaY.N#D.N.n#Da9#D.n#D.7a9#Da9bj.nbja9#s#DblaY#D#x#xaYaY#x#M.N#x#I#x#x#xaY#Dbl#DaYaYaY#xaw#x#IaYaYaY.baYaY",
+"#D#D#Da9a9#Lafaj#L#L#Laj#Lbp#ga2#g#ga2#g#ga2#ga2#g#L#Lbp.7.7.7#D#D#s#D.saY.C.8aB#4#zaZa0#xaYaw#Da9.na9#L#L#Laja2#Laj#L#Lafaj#L#L#p.n#pa9blblaYaYawawaYaY#I#x#x#Ibn#Ibn#I#x#U#x#IaYblaYaY.Nbl.saY#s#Daw#Dawbf#I#x#I#x.s.N.s#xa0aC.C.Ca0.CaCa0ambg#x.N.s#D.7aj.7aja9.7a9#sa9#D.s.NaYawaYaYaY.NaYaYbf#x.C#x.W.C.Caqavaqa0ao.5#va##vaS#W#aazazanbm#SaFaFa#aFaOaFbgb#aCbnbnaw#x#x.N.N#sbl#D#s.N.N.N.N.7.7.7.7.7.7a9.7.7.7a9.7a9.7.7.7aY#DawaY.NbfaY#x.NaY#x#x.C.WaY#D#M#DaY.NaY#x#x#x#x#x#xaYaY#Da9#D",
+"a9.7.7.7afaj#Laf#L#L#L#La2#La2#gbpa2bp#g#L#g#L#g#Lbp#L#L.7.7.7bj.s#D.NaY.Nao#v.QaD#za#am#xaY.N#D#pa9a9ajaf#Laf#L#Lafa2#La2#Lafaja9#p.na9#MblawblawaYaY#I#x#I#x#x#Ubn#Ibnaw#x#IaYaYawaY#M.saY.N.s#D#M#D.s.Naw#x#I.W#x#I.s#x.W#Ua0.Cava0.W.Ca0a0a0#I#IaY#D.7#L#L#La9.E#D#D#D.N#D.sbnbn#x#x#x#x#I#x.C#x.W.Caqamavam.C.5.5aFbya#.y.0.Gakar#e.TaBaFaF.5aFaOamb#a0aoambn#Ua0.C.Ca1bfbf.Nbl.N#D.N.N.N.Na9aj.7af#Laf#L.Eaf#L#L#L.7.n.7.n#DaYblbfaYaY#x#x.s#xbo#x.C#x.Na9#D#DaY.N#x#IaY#xama0bn#x#D#D.7#L",
+"#Laj#L#L.7#L#L#Laj#L#Lbp#g#g#g#La2a2a2a2#ga2#L#L#L#L#L#L.7a9.7a9#Da9.s#Iama##u#.bA.faFaYawaYaYbfa9a9afa9#L#L#Lajafajafafajaf#Lafafafa9a9bl#Dbl#s.RawaYaY.R#U.R#Ubn#Ubn#Ibn#U#x#x#M#D#D#Daw#D#s#DaYaw#s.n#D.s#I.Caoaoam.8.5aO##am#va#byaFbcaqav.CaFaOaFaC#x.N.saW.N#D.N.s.N#I#xbn#U#xaw.R#x#xbna0#U.Vamb#b#aFa#bmaBaZ#vaZ#v.0aB.yaFaO.5bgamamamaobn#U.C#Ua0aCbnbnawaY#MaYblaY.saY.7.n.7.na9.E.7.7#La9#Laj.7#L.7af#Lafaja9a9a9#Da9.Nbl.Naw#x.s#xaY#x#xbn#x.baYaY#Da9.na9#DaY#x#x#x#IaYaY#sbla9.na9",
+".7af.7#Lajaf.7#L#Lbp.j#L#g#L#g#ga2#ga2#g#La2#L#Laj#L#L.7a9.7.n.7#sbl.NaYaoa#azbAa6a7am.RaYaYaY#xafa9a9af#Laf#L#L#Lafaj#Laf#Lafajafaja9.n#D#M#DaYaw.R.RaY.baY#UaY#Ubn#UaYbn#x#I#x#M#D#M#D.s#D#s#D.s#Dbl#s#s#MbfavaCbgaCaoaC.5ao.5#vaOaOam.8.8amavb#b#aoaC#xaw.N.N#s.s.NaYaw#xbnbnaCa0a0a0amamaoaFaFaFa#.yan#u.G.6aBaBbmaO.5b#.5b#amaoa0a0amaCa0a0aY#xbn#Ibn#Ibn#IblawaYaY#M.Nbl.N.n.7a9.7a9.7afa9.7aj.7#L#L#L#L.7#Laf#La9a9#D.7#D#s#DaYaY.NaY#x#xbn#x#x#U#xaYawaYa9a9a9bl.NaY#x#x#xaYaYbl#Da9.7a9",
+"#L#L#L#L.7#L#L#L#La2#L#L#ga2#g#L#ga2a2a2#ga2#L#L#L.7#Laf.E.7.7#DawaY#I.CaoaBazbaaSa#.VbnawaYaY.N#pa9afa9a9#Laja9af#Lafafajaf#Lafa9#pa9blblbl#MaYaYaYaw.R#x#UaYbnaw#x.R#I.R#I#x#xaYaw.NaYaw.N.N.s#D.s.saw#I.CaoaoaO.F#vaOaO.8#vbc#va#aO#vaO.5.8aCaFaO#SaOaOao#I#x#MaYawbnbnaCa0b#a##va#a##vaZaZ#uazazbh.Galay.2alaFaOaFamaCa0aC.C#I#x#x#I#x#xaY#IaY#I#x#I#x#x#I#xbl#D#M#D#D#s#D#D.n.7.n.7.n.7.7.Eaf#L#L#L.7aj#L#Lajaf#La9.7a9a9.7bl#DaY.NaYaY#x#xaCa0#x#xbnawaY#D#Da9#D#DawaY#x#I#xaYaY#D#Da9a9a9",
+".7#L.Eaf#L#Laj#L#L#L#g#L#g#L#g#g.ja2a2#ga2bp#L#L#Laf#L.7.7a9.7#Dblaw#x.W.5az#aalaZb#a0bnaYaY#DaY#p#Da9afa9a9#L#Laja9aja9#La9aja9.na9#sbl.n.NblaYaw.R#xawbnaY#U#U#x.R#Ibn#I#x#I#xawaYaY.saY.s.N.N.s.saw.W.Waobc.yaBaB#u#S.y.y#va#aB#u.Qaz.waBaZ.yaZaB.0aBaB#vaO.5bn.Vb#am#Sa#aB#u.wbhazazbh.waz.GarazaSaz#a#a#a#ea0a0#Ubn#x#I#x#xaY#MaYblblawbl.NblaYaYaY#U#IaYaY#D#M#D#s#D#D.n#D.7a9.7a9.7a9.7a9#L#L.7af#L.7af.7af#L#L.na9a9bja9#D#D#DawaYbfaw#xbna0#x#UaYaYaYbl.n#Dbl#DaY.N#xaY#xaYaY#D#Da9a9.7",
+"#L#L#L#L.7#L#L#L#g#ga2#g#g#ga2bpa2#ga2a2#ga2#L#L.7#Laja9#La9#sa9.NaYaY.Wambk#zaraFamambnaYblaYbl#Dbla9a9.7a9.7a9a9.7a9a9.na9a9a9#Da9bl#DblawaY.N.RaYbnbnbn#Ubnbn#I#U#x#x#x#I#x#Ibl.Naw.NaYbf#I#x.s#x.WamaO.y#uazal.U#z.U#T.G.GaP#Tal#z.U#3al.Ualal#T.G#T.G#e.w.wa7#ua7a7aS.G#e#TaS.w.wanaz.wazaS#vaOa##va#aFaFam#UaY#xaYaY.NaY.s#D#D#D#s#D#D#D#s#D#saY.saY.NaY#sbl#D#M#D#D#Dbj#D.n#L.E#L.E#L#L#L.E#L#Laj#L#L#L#L#Laf#La9.7#Da9#D#D#DblbfaY.N#xaY.C#I#x#xaYaYaY#Dbl#D#D#Dblaw.NaYaYaYaY#D#pa9#La9",
+"#L#L.7aj#L#L#L#L#g#L#gbpa2bpa2#ga2asa2#g#La2#L#L#L#L#La9.7.7#D#sbl.N#Ia0#vaz#z#eam.Va0bnaYaYaYaY#Dbl#D#Da9a9.7.7a9a9a9.7#Da9#sa9bl#sbl.sbl.NblawaYbn#Ubn#Ibn.C#Ubn#x#U#x#I#x#IbfaYaw.NaY.N.saYboaYaCam.y#u#aau#4aH.4#..4aHbrbw#0.2bw.2aT.2ay.YaH#4#zal.o#T#Tal.U#aar.G.Ga4aPa4a4.ya#aZ.ya#a#a#aOa0bnaCbnaCbn#I#xblaYaY.s#D#sa9#Da9.na9a9a9.na9a9#D#D#D#D#s#D#s#D#D#s#D#D.n.7.E.7.n.7#La9#La9.E#Laf#La9#L.7#L.7afaj#L#La9a9.n#D.7bl#D#DaY.NaY#x#xbn#x.R#xaYaYaY#DaY#Dbl#D#D#DaYaYaYaYaY#D#Da9a9a9",
+"#L#Laf#L#L#L#L#La2#ga2#g#ga2#g#La2a2#ga2#ga2#L#L#L.E#L.7.n.7a9#D#D#I#xaoby.w#zaSa0aCa0bn#x.Rblblbl#D#D#D#D.7a9.Ea9.7a9a9.n.7a9a9#sbl#DblaYaw#x#x#xa0#xa0a0a0aCa0#I#U#x#I#x#I#xawaY#x#I.Nawbf#x#IaCbgaBaza6aT#P.uaybaay#3#aar.Gazaz.Gazaz.Gar#aa6.w#u#uaBaZaB#uazazazaS.0#S.0aFa#am.5aoa0am.Wam.C#I#x#x#I#x#I#xaw.N.N#s.N.N#Dbj#s#D#D.7.7.7#D#s.7a9.Ea9a9a9a9a9a9#s#p.na9bj#Dbjbj#Lajafaj#L#L#Laf.E#L#L#L#Laj#L#Laf#Laf.7a9bja9#D#D#DawaY#x.s#xaY#x#x#x#IaYaYawaYbl#D#D#DblaY#s#DaYaYaw#D#Daf.7af",
+"#L.7#L#L#L#L#L#L#L#gbpa2bp#g#L#La2#ga2a2#g#L#L#L#L#L.7a9#L.7#D#saY#x.C.8#va7albh.Ca0a0bnaY.RblblaY#Dbla9#Da9.7.7a9a9a9a9a9#D.n#Dbl#Dblaw#DaY#x#IbnbnaCa0#Ua0aCa0.CaC#x#I#x#I#Ibf#x#I#x#I#x#Ibo.C.paOa7#aay.K.K.K#Ear.faZa7#uaBaB#vbmaBaZa7an.TaZaOaF.FaFaOb#b##SaZ#va#aOama0.W#xavam.C.W.C#xaw#x#x#Ibfbf#xbf.N.N.saYaY#D.N.E#D.7a9#D#s.7#s#D#D#sa9.7a9.7.E.7.Ea9#s#D#s#D#s#D.Ea9.Eaf.E#Lajafaj#L.7#L.n.7#La9#L.E#Laf#L.na9#D.7a9#Dbl.NaY.NaY#x#x#x#U#x.RaYaYaYaY.N#xbl#D#D#D#DblaYaYaYbl#Da9a9.7",
+"#L.3a2a2a2a2asa2#ga2a2#ga2a2#ga2#ga2#ga2a2#ga2#L#L#Laj#L#L.7b..7#x#I#x#xaC#uar#e#Sa0.CaYaY#DaYaYa9#p#pa9a9a9a9a9#s#D#sbj#D#D#D#D#saYaY.Naw#x#x.Ca0aoa0a0aCbn#Ibnaw#U#U.CaCamaCaCaw#Mbn#UbnaCbgaoaZanaral.2alaPan.y.0.yaB.0a#a#a#.8aF#v.0#u.0#v.5aCam.8amaOamaoam.F.tbg#x.C.C#xaY.NaY.saY.Nawbf.N.N.N#D.s#D.N#D.Nbl#sbl#s#D#D#D.7.Ea9.7a9.7a9.7.7a9#s#D#D#Da9#D#D.na9.na9.na9a9.na9a9a9.naf#Lafaf.E#L.7#L#L#L#L#Lafaj#L#L#La9.na9bl#MblaYaY.baYaYbl#Dbl#DaYawaYaY#M#D#DaY#Dbl#D#DaYblbl#D#p#Dafa9",
+"afa2#La2a2#gaa#ga2a2bpa2#L#g#L#ga2a2#g#L#g#La2#g#L#L#Lbpaj#D.7bjaY.N.N#Iao#u#aayaFa0bnaYaYblaYaY#pa9a9blbl#D#M#D#Da9#Da9#Da9#s#Dbl#D#MaY#x#x#x.Wama0a0aCa0a0amao#Uaobg.8am.8amama0bgb#.8aFa#.0aZ#ua7#uaS#uanaBa#.8aFaOamaOamaCamb#ao.5a#.0#vaF.5a0a0aC.Ca0.Wa0am#ybgaC#xbf#I.NawaY.NaY.saY.NaYaw#D.s.N.N.N.s.N.sbl#sbl#D#D#D.n#D.7a9.7.n.7.n.7.n#D#D#s#D#s#Da9#Daja9a9.nafa9aja9aja9aja9af#L.n#L.7af.Eaf.E#L.7#Laf#Lafaf#La9.7a9blblblawaYaY.baY#Mbl#DaYaYaYaYaY.NaY#Dbl#s#Dbl#D#MaYa9bl#D#Da9a9",
+"afaf#La2a2a2#ga2#ga2a2#ga2a2#ga2bpa2a2#ga2#ga2#g#L#g#L#L#Lbj.Ebjaw#D.s#xaoana6abaOam#xaYaY#DaY.N#pa9#p#sbl#Dbl#D.n#D.na9.na9a9a9#sbl#DaY#I#x.Wbnb#bgb#amamao.8aFamaO.yaZ#u#u#S#vaZan.yaZaZ.6aSa4aBaZbma#aF.5ama0aCa0.CaCa0a0a0.Wbna0a0aoam.5aoa0#I#x#xbn#I#x#x#x.p.Vbn#x#I.NaYbl.N.NaY.N.NaY.N.NaYaY#DawblaY#DaYblaYblawaY.s#D#D.na9a9a9a9a9a9a9a9#D#D#Da9a9bja9a9.nafa9.Ea9a9.na9.na9.n#Lajaf#L.n#L.7#L#L#Laj#Lajaf#L#Laja9a9a9blblblaYaYaYaYaYbl#D#MblaYaYaYaYbl#saY#D#D#D.NaYblaYbl#D#p#Dafa9",
+"afajaf#La2a2a2a2a2#g#L#g#L#g#La2#ga2bpa2#La2bpa2aj#Lbp#Lajbj.7#s#D#Daw.C#v.GaTaD#vb#a0bnawaYaYaYaYblaYaYaYawaYaw#D#D#D#D#D#D#s#Dbl#saYaw#xa0a0a0bgamaOamaOa#a#a#.yan#u.G.Gaz.w.w#u#uan#uan.w.6.GaFaOaFaoaobn#I#x#I#x#I#x#x#I#xaY#x#I#xbn.CaC.Ca0#x#x#IaY#xawaYaw.R.bbnawblaYaw#DaY.saY.Naw.N#M.N#D#s#DaY.N.saY.NawaYaw#Dbl#DaYaY#D#s#D#s#D#s#Db.a9#D#s#D#s#D.n#Daf#L.na9aja9aja9afa9aja9afaf.7af.7#La9aj.7a9#L.7afaj#Laf#La9a9a9.na9blblaYawaYaYblbl#Dbl.saYaYawblaY#D#Dbl#DblblaYblbl#Dbl#Da9a9",
+"a9a9#L#L#L#L.jbpa2a2aja2#ga2#ga2#L#ga2#ga2#ga2#L#g#L#L#L#Lbj#s#D#saw#Iaq.y#3aH#Pa#bga0#UaYaY#xaYaYawaYaYaY#x.N#x.Naw.Naw.N.NaY.s#DblawbnaCamb#bgaFbma##S.0aB#u.yaz.w.waz.w#u.0a##SaFbma##Sa##Sa#amamaoa0#x#IaYawaYblawaYawaY#M.NaYaYawaY#I#x#x#U#x#x#xawaYaY#D#MaY#x.b#x#UaYaY#Daw#DaY#D#D#D#D#Dbl#Dbl#sblblbl#MaY.RaYaYawaY.s.Nbl#Dbl#D#Dbl#Dbl#D#s#D#D#D.7#D#Dajaf#La9.na9a9.na9.na9a9.n#Lajaf.E#L.7#La9aj.7#Lafaf#Laf#La9.Ea9a9#p.nblblaYaYaY#Dblbl.NblaYaYaY.Nbl#D#D#D#DaY#DaYblblbla9#Dafa9",
+"a9afa9ajafbpa2#L#ga2bpa2#L#g#La2bpa2a2bpa2#L#ga2#L#Lbp.7aj.7#Db.bl#x.Waobb.2a6ak#vb#a0#x.RaY#xaYaYaY.R#x#x#x#I#xawaYaYaYaY#xaw#xaYaw.Ca0b#aF#vaZaZana7.waz.G.Ga7#uaBaB.0a#aFamambnbnaCa0a0aCa0a0aoa0#IaYaw.Nbl.NaY#MaYbl#DblaY#DawaY.Nblbl#xbn.Ca0#I#xaY.N#Mbl#DawaY#Ibn#Ubn#I#x#D#D#D#D#D#D#s#D#D#saY#Dbl.s#DaYblaYaYawaYaYaYblbl.nbl.nbl.nbl.n#D#D#D#s#D#D#s#D#Lafaja9#paja9aja9af.naf.naf#Laf.7aja9aj.7#Laf.7afajaf#Laja9a9a9afa9#Dbl#sbl.Nblbl#sblaYaYaYaYaY#DaYaY#Dbl#DaYblaY#MaY#Dbl#Da9a9",
+"a9a9afa9#L#L#La2#ga2#La2#ga2a2#ga2#ga2a2#ga2a2bp#L.j#L#L.7#sbj#saY#Iaq.y.waXaraS#vb#a0#UaYaYawaYaYaYbn#x#U.Cbn.Caqaqavaqavaqaqaq#Ia0ao.5#vana7bh.Ga6al#aarbkaz#uaOamam.Cao#x#IaY#I#x#I#x#I#x#xawbn#xaw#D#D#D.sbfaY.N.saY.saY#D#D.Naw.N#saY.s.Cava0am.C#IaYaY#D#M.N#x.bbnaCa0a0#x#s#D#s#D#Da9#Da9blblbl#Mblblbl#MaYawblaYaYawaY.saYaYaYaYblblblbl#s#D#D#D#D#s#D#Daja9af.nafa9.na9.na9a9.na9#Lajaf.7af.7#L.n#L.E#Laf#L#Laf#La9a9.7a9a9a9a9#D#D#M#Dbl#Dblaw#DaYawaYaY#saYbl.Naw#DaYawblaYblbla9a9af",
+"afa9.7a9#L#L#L#L#La2#g#La2bpa2bpa2#L#g#L#g#L#ga2#Lbp#Laj.7bj.s#D.Waoao.waX#aazaSaFa0#xaYaYaYaYaYaYaY#xa0a0.Caoa0.8.8.5ao.5amaoamaCaoam#v#ubh.G#eayaTay.Gaza7aBa#aoaC.CaC.CaYaY#Mbf#x#xaY#xawaYaY.NaYaw#D#s.N#xaNaw.Nbl.Nbl.N.N#s#x.NaY#D.NaY#xaqa0aoa0#x.NaY#MaY#x#xbnbn.Vamaoam#D#D#D#s#D#sbja9.N#M.Nbl.N#M.NblblaY.RawaYaYaYaYblawblaYawaYawaY#D#s#D#M#D#D#D#Daf#L#La9a9.naf#La9af.n#L.nafafa9aj.7aj.7#L.7#L.Eafaj#Laf#La9a9a9aja9a9.na9bl#D#D#DblblaYaYaYaYaYaY#DaY#DaYblbl#DaYaYbl#sbl#Da9a9",
+".7a9a9.7a9a9.7a9#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#L#Lafa9a9#D#sbl.s.Waoan.G#Ea7aBaZ#vaFama0aCamamamb#.Va0aC.VaO.0#uaSaSazazan.Gak#a.Iay.Iar.Xar.Gazaz#uaB.yaO.5aoa0#Iaw.NaY.saY.N.N#D#s#D.N.N.N.N.s.NaY.NaY.NaY.saYa9bl#sbl#sbl.nbl#D#s#DawaY.saYawaY#x#U.CaC#xbf.N.s#I#x#Ia0aoamambf#I.N#D#DaYaY#Dbl#D#Dbl#D#Dbl#D#M#Dbl#Daw#D#M#DaYaYawaYblblaY#D.na9a9.na9.najaf.nafajaj#L#L#Laj#L.E#L.n#L.E#Lajaf#Laja9aja9.7a9#Lafafaj#L#Lajafa9a9a9bja9#D#D#sblaY#MaYaYaYaYaYaYaYawaYaYaY#xaY#UaYaYbl#Dafa9#L",
+"a9bja9a9.7a9a9.7#L#L#L#L#L#L#L#L.E#L#L#L#L#L#L.7aj#L#sa9#saY.saYbo.5.w.GazaB#San.l#vbgama0#xama0ama0a0bgaFbmanazak#aar#eazaz#aa6.e.e.XaraSazbhan#S#v#vaFaoa0aC.Cawaw.Naw.Naw.Naw#Da9#s#D.s.N.s.N.NaY.s.Naw.NaY.Nbl#saYblbl#Dbl#D#D#DaY#D.NaY.N#x#Ibna0a0a0.C#I#x#x#I#xaCamaFaOamaYaYaYaY.N.Nawbl#s#Dbl#D#sbl#D#Dbl#Daw#Dbl#Dbl#D#Mblblblaw#Dawbl.na9.na9.na9a9.naf.n#L.7aj#Laj#Laja9aj.7aja9aj.7#L.Eaf.7#L.7af.7afaj#L#Laf#Laf#La9.7a9a9b.a9#D#DaYblaYaYblaYaYaw.RaYbnaY#U#xbnbna0aYaYaYbl#Da9a9",
+"a9a9a9a9a9a9a9a9#L#L#L#L#L#Laf#Laf#Laf#L#Laf#Lafa9a9a9#D#D.Naw.N#x.8.w#e.lbma#az#uaZaFa0aC#x#x#x#x.WamamaF.y#ealayaG.G#eanaS#e#a.I#a.X.JanaZ#Sa#aOambga0.W#x#x.saY#saY.NaY.NaY.N#D#D#DaY.NaYaY#xawaYaYaYaYaY.saY#Dbl.N#M.Nawbl#D#M#D#MaYawaY#x#xbnaCam.8.5amamaCa0a0aob#aOaObm#v#x#I#x#xaY.N.NaY#Dbl#Dbl#D#Dbl#D#Dbl#Dbl#Dbl.sbl.N#Daw.NblaYblaYa9.n#p#sbl#Ma9bl.na9.na9.7.E.7.7.na9.na9a9.Ea9.n.7aja9.na9.Ea9.7af.7af#Laf#L#Lafa9a9a9#Da9#D#D#DblaYblaYawaYaY.R#xawaYaYaYbn.Cbn#xaYaYaY#D#D#D#D",
+"a9a9a9a9a9.7a9a9a9a9a9#Laf#L#L#La9.7.na9a9a9a9a9a9a9#s#D#s#D.Nbl#I#v.G.G#uaF#van#uaZ.8a0bnbnawbnavam.5#van#ealbra6#a#e.wana7#e#e.fakaz.TaBa#a#aFa0aoa0.Wbn.s#M.N#saY.sbl.saY.saY#s.Naw.Naw.N#I.N#x#I#x#x#IaYaY#IaYawaYawaYaY#xawaYaYaY.NaY#x#x#Iamb#aFa#a#aOamamamaob#b#aF#Sbmbmaoa0#x#xawbl#D#D#Dbl#D#sbl#Dbl#sbl#D#D#sbl#D#D#D#Mbl#DawblaY#saY#Mbl#Dbl#M#D#M#M#Da9#sa9.n#D#D#sa9.Ea9b..na9.7a9.na9.n.7.7a9.7a9aj#Lafaj#Lafaj#La9.Ea9.7#D.E#D#DblaY#MaYaYaYaYaYaY.R#x.R#xbn#U#xbnbnaYaYbl#Dbl#D",
+"a9a9a9a9afa9afa9af.nafaf#Lafa9a9afa9a9a9a9.na9.n#D#D#D#D#D#Daw.N#I.y.GazaZb#aOa#anaBa#aoa0aCbna0a0.5.8an.G.2.K#P#q#e.6anan.wazakazbha7aZaFam.8am#xaC.C#I#IaY#D#saY#saY.NaY.NaY.NblaYblaYaY#I#x#x#x#x#I#x#x#x#xaYaYbn#xbn#U#x.baY#x.s#x#x#I.Ca0.CbgaF#vbma#a#aOambgamb#aoaFaFaOaF#va0#x#I#x.Na9#D#s#Dbl#D#Dbl#D#Dbl#Dbl#D#Dbl#Dbl#DaYblaY#Dawbl#DaYaY#MaYawaYawaY.nbl#p#sa9#sa9#D#s#D#Da9#D.n#D.na9.na9a9.n#Da9#D#Lajaf#Laf#Laf#La9a9a9#Da9#Da9#DaYblaYaYblaYawbnawaYaYaYaYbn.Cbna0.Cbn#xaYaY#Da9",
+"#pa9a9a9a9a9a9a9a9a9a9a9a9a9a9.na9a9a9a9a9a9#Da9#D#s#D#s#DaY.NaYaCaZ.6az.0aOaF#van#uan#vamamamamaOa#analba.g#P#P#a#Tan.y#uaZaza7an.laZa#bgama0.C#U.C#U#I.N#s#s#D#s.Naw.N#M.NaY.saYaw.Naw#x#x#x#U#x.baYbnaw#xawaY#Ubn#U#x#Ubn#xbn#xbn#Ia0a0a0aCa0b#.t.tbma#aFaFb#amamamam.Vb#b#.V#Sbga0#x#xbl#D#Dbl#Dbl#Dbl#s#Dbl#D#M#D#Dbl#sbl#Dblaw#DawblaY#DaYawaYaYaY#Ibn#Ibn#Mbl#s#D#D#Db.#D#sa9#s#s#s#D#s#D.n#D.na9#D#D#s#Dafafaf#L#Laf#L#La9a9.7.nbja9bj#DblawblaYaYaYaYaYaYaY#x.R#x#xbnbnbnawaYaYbl#Da9a9",
+"a9a9#pa9#pa9#pa9a9a9a9a9a9a9#pa9a9.n#p.nbl.n#pa9#D#D#D#D#D.Nawbfbn#vazaS#SaF.8#vaZ.6aBa##va##v.0a7.faG#PaD#V.Kay.XazanaB.0#vbm#SbmaZ#vamama0aC#xa0.W#x#x#I.N#D#s.N#M.NaY.NaY.saYaYaYaYaYawbn#x#x#x#xbn#Ibn#x#x#xbn#xa0bna0bnaCbn#xa0#x#xbn.Ca0am.V.Vb#aOaFb#bgamaC.C.CaCa0a0aCa0a#aFbgbnaY.N#D.7#D#M#D#Dbl#Dbl#D#D#Dbl#D#Dbl#D#D#M.NblaY#DawblaYaY#Ibn#Ibn#Ubn#IaYawaYawaYawaY.s#D#s#Da9#sa9#s#D#sa9#Dbl#s#D#D#Daj#L#Lafaj#Lafaja9a9a9#Da9#D#Da9blaYblaYawaY.R#xaY#M.RaYawbna0#IaYbl#Da9a9afafa2",
+"#pafa9afa9a9a9a9#pa9#pa9afa9a9a9#p#p#D#pbl#p.na9#D#D#D#DaY.NaY#Ia0#v.Gaz.0#vaF#vanaz.w#u.0#u.waP#A.f.Xa6.Ia6akaSanaZa#aFaoaFaOaF#SaFaFama0aC#x#x.Wa0.W#Ibf.N#sbj#M.N.saY#s.NaY.NaYaYaw#xaY#x#I#x.R#x#x#x#xaYbnaY.Cbnbn#xbn#x#xbn#x#I#xbn#xa0.Ca0.pb#b#aFb#aFb#.V.C.C#x.CaCa0#xa0.FaFaOa0aYbl#D#sbl#D#Dbl#Dbl#s#Dbl#D#M#Dbl#D#M.Nbl#DaYblawaY.saY#UaYbn#x#U#x#Ubnaw.Rawblaw.NawaY#s#s#s#s#D#s#D#sbl#Mbl.n#Dblbl#Dafaj#Laf#Laf#L#La9.7a9.7#s.7#DbjblaYblaYaYaYaYaYblaY#xaY#x#xbnaYbla9#p#p.naf#La2",
+"#L#La9a9a9afa9af.j#L#La2af#La9a9#sa9#s#D#DaYaYblawaYaY#I#xbn.Ca0#Ubg.laz#uaBanaBa6#a.Xa6#aak#ebh#Sbm.Fa#aFb#amaoa0aCa0aoa0amb#.8b#aoa0aCa0#xaC#x#I#xaY.N#M#D#D#s#D#sa9.7a9.7.n.7#D#D#D#s#DaYaYaY#sbl#Mbl#Dbl#D#Dawbl.Naw.NaYaYawaYaYaYaw#DaYbl#DaY.RaYaYbnbna0a0#Ubnbn#x#x#x#I#xa0bgaBb#a0.s.s#L.NaY.N.saY.N.NaYbl.NblaY#I#x#x#x#Mbl#MaYaY#x.b#x#xbn.Wambgamamam#Ua0bnaCa0a0amaoaw#x#x#x#I#Iaw#Mblbl#sblbl#D#D#Da9#pa9a9a9a9#Laf.na9a9a9a9#paf#pa9a9#MaYaY#x#xbnaw.RaYbna0a0a0aY#D#pa9a9#La9#L#L",
+"#L.7#Laf.7a9.7a9#Laf#Laf#La9.7#Da9a9blbl.Nbl#DaY#xaYaY#xaCa0amam.t#uazar#e#T#a#zacbaayaraS#uaZa#aFaFaFb#amaoama0a0a0aCa0a0ama0amaoa0a0a0aC#xaC#xbn#I.saY.s#D#sa9a9#sa9a9.Ea9.7a9#D#s#DaY#D#D#s.Nbl#D#D#D#D#Dbl#DaY#DaY#Dblbl#DaY#D#Dbl#DaYbl.NaY.baYaYaYa0#Ia0a0#x#UaY#x#U#x#xaYbnam.FaOa0#x.s.7aY.saY.NaY.NaY.sblawaY.N#x#Ibn#xaYawaY#xawbnaY#U#x#IaCa0aCbg.paobn#U#Ua0aCaCaCb#aCaC.C.Wa0.C.baYawawaYblaw#D.s.Nbla9#p.nafa9ajafa9#pa9#pafa9a9a9#pa9blaYaY.b#xaYaYawa0#xa0a0#UaYbla9a9a9a9#L.7#L",
+"#Laf#La9.7af.7af#L#Laja9.7a9a9bj#D#D#D#MaY.NaYaY#MaY#Ua0amam.5.5aSal#PabbrayaTaTaGara7aZaZaZbm#vb#amamaCa0#x.C#x#I#x#x.CaC.CaC.5b#aob#aCamaC#xbn#I#xaY.s#D#sa9#s#Da9.Ea9.7a9.Ea9#D#D#D#D#s#D#D#D#Dbl#D#M#Dbl#sbl#DaYblaY.saY#DaY#MaY.Nbl.sbl#D#DaYaY.baYaYbn.CbnbnaYaYbn#x#x#x#xaYbnam#Sama0.N#s.NaY.Naw.Naw.NaY.NblaYaw#x#x#x#IaYaYawbl#x#I#xa0#Ia0aC.pbgb#bgb#.pa0.V.pb#.Vb#bgbm.taOaFaFao#U#x.bbn#IaYaYaY.NaYbl#Dbl#Da9a9a9a9a9a9a9a9a9a9.na9a9a9bl#DblaY#x#xaY.R#xaCama0#x#xbl#s#Daf.7af.7#L",
+"#L#L.7a9.7a9a9.7af#La9a9a9#D#D#D#D#MaYaY.N#x#I#x#xaY#x#xamaO.0bbaT#PaD#VaTaRar#eaBaZbmaFaFamb#ama0aCama0.C.C#x#I#xaY#I#x#x.W.CaCaOaFaob#aoamaC.C#I.b.NaY#s#Da9.7.n.7a9.7.n.7a9.7#D#D#D#D#D#D#D#D#D#M#D#Dbl#D#Dbl#D#D#sbl#Dbl#D#D#D#D#Dbl#D#Dbl#DaYaYaYbn#x#x#x#IaYbnaY#IaY#xaY#IaYbna0aBbmao#x.NaY.saY.NaY.NaY.saYaw.NaY#x#I#x#xaw#x.N#I.C.CavaCaFaOa#aBa##vbm#Sbm.taFbmbmaZaBbh#kbhbhaZ#Sa#b#a0aCa0a0#U#xaYaw.Nbl#Mbl.n#D.n.7a9a9.na9a9#sa9#Da9a9a9.n#D#D#xaY#xawaYbnama0ambnaYblbl#Da9#Da9#L.7",
+"a9a9a9afa9#La9a9.na9a9bj.n#D#D#saY.NaY#x#x#x#x#x#Ubnambga#.0#u#uaH#4#aazanaBaZbm#SaFaOb#bgamamama0.C.C.W.C#Ibf#xbf#I#x#x.C.Cao.8a#aOaOamaoa0.Wa0aY#xaw.N#D#s.7a9.7.n.7a9.7#L.7aj#D#D#s#D#D#D#s#D#D#Dbl#D#Dbl#D#Dbl#D#D#Dbl#D#Dbl#D#Dbl#D#D#D#DblaY.NaYawaY#xbn#xaYaYaYbn#x#x#x#x#U#xamaBaBaBa0.Caw#xaY#IaY#xaY#x#x#x#Ibn#xa0.Wa0.CaoamamaCamao.5azaz.G.Gar#e.G#a#eaz#ear#e#a.X#a#jaGak.faSaZ#vb#ambga0a0a0#I#x#xaw#xblaY#Da9#Da9#D#D#Da9#Da9#Da9.na9a9#D#DblaY#x.Rbna0.Cama0#x#xbl#Dbla9#D.7.7a9",
+"a9.7a9.7a9.na9.7a9.7#s#D#D#D#D.N#x#x#x#I#x#x.Ca0amaOa#.yanaBan#u.6aBa#amb#a0b#amamb#amamamaoa0aoa0aCambn.C.C#x#Ia0.C.CaCamao.5aO#vaFaOb#aoa0a0.WaYaw.NaY#s#D.7.n.7a9.7.n.7a9.7a9#D#D#D#D#D#D#D#Dbl#D#Dbl#D#Dbl#D#D#Dbl#D#D#D#D#Dbl#D#D#D#Dbl#D#D#sbl#D.NaYaYaY#xaYaYaY#xaYaYaY#xaYa0a0bmaz#uaOam.C.W.C.C.C.C.W#x.W#xamamamaoam.5aoaF#v.y.0#uaB.wal.2ayal.2aya6aTa6alaR.2ayayaT#P#t.K.e.X.GaSaZaBaFb#amaoa0a0bna0aYaYawblbl#sa9bj.n.7#D.7a9bja9#Dafa9afa9bl.Naw.N#U.CaCaFaoamama0aYaY#D#D#Da9#L.7",
+"a9a9.na9.7a9a9a9a9#D#D.N#s#DaY.saY#x.C.Ca0aoamao.0aZaBaZaB.0aBa#amb#a0aCaC.pa0a0aob#ama0am.C.Ca0.5b#amaCam.W.C.CaCa0ao.5amaOaF#vaF.8amamama0aqa0aYaw.Naw#D#Da9.7.n.7a9.7.7af.E#L#Da9#Da9#Da9#Da9#Da9#Da9#Da9#Da9a9a9afa9afa9afa9a9a9a9a9a9a9a9a9bl#D#Dbl.N.NaYaYaY.RawbnaY#x#I#xawa0b##Sazbha##vamaqao.Cavamao.5ao.5.8.8aF#v.0.yaZaB.waza7az.G.G#aararar.X#a.Xar#eazazaralalalayayaya6.Ial.XaSaS#va#aFaO.5aC.CaC#xbnaY.N#M#D#D#D.7a9.7.Ea9.7.7.Eaf#La9#D#D.N.NaYbnbnamamb#aoama0aYawblaY#D#D#D.7",
+".7a9.7a9a9a9.Ea9bja9#s.NaYaw.NaYa0.Wa0aCamamao.5a7az.waZa#aFaFaFamamaC#xbn#xam.5amamamaoama0aoa0aOaFaoambgamaCam.8aFaOaFaOaFaF#vaFaFaOb#aoamaCamawaY.Naw#D#D.Ea9.7a9.7.n.7.7a9.7#D#D#D#D#D#D#D#D#D#Dbl#D#Mbl#D#Ma9a9a9a9a9a9a9a9.na9a9.na9a9.na9#D#D#D#DblaY.saYaYaYaY#xaY#xaY#xaYbnaObmazaZ#Sa#.8.8.8.5am.8.5.8a##va#.ybbbb.w#uazarar#a#eazaSaz#ua7aZaZaZaZ.Tbm#SbmbmaZan#uaSaz#aalaR.2.IaGaraSaZaBa#aFaoama0aC.R#IawaYbl#D#D#Da9.7.7a9.7.7a9.7af#L.na9#D#s.N.NaYaCamaoaFamama0aYaYaY#D#D#Dbj#D",
+".N.N.N.N#D#D#D#DawaY.Nbf#xaqaqavamamaF#v.0#u.w#e#va#b#.5amamamaF#I#x#x#x#Ia0#x#x#x#I#x#xa0ao.5amamaoaFa#a#aBaZaZ.TaBaZ#SaFaFaF.5ao.5aoam.C.W#x#xaYaY.saY.N#s#D#Dajafaja9a9a9.7a9#Da9bja9#D.7#Da9#Dbl#Dbl#D#Dbl#D#Da9.7a9.7a9a9bja9#Da9#D#D#Dbl.Nbl#Dbl#D#D#Dbl.NaYaYaYaYaYawaYaY.Nbfa0b#bmaBana#bma#bm#u.6#T.oaR.Gararal#aalalal#Taraz.6#uan.0.0b#.8b#aob#aoambgamam.8aoamaO.8aFaBbhaz.Gar.X.X#abhazan.TaZbmbma#aCa0#xaYbfaY#s#D.s.N#D#D#sa9.7.7#s.7.7.7a9a9#D.7#DaYam.5aOa#amambf.N.N#s#D.NaYbf",
+"aYaYaY.saY#s#D#D#D.s#x.Wao.8aq.5.yaB#uanaBan#uanaFaOamaob#aoamaobn#x#U.Ca0.C.C.Wbna0a0aoaF.5#va#.ya#.yaBaZaBbh#u#SaBaZaOa#.8aFbg.5aoamaobn.Cbn#x.sbl.NaY#D#Da9#Daf#L#La9.7a9a9.7#D#D#D#D#D#D#D#Dbl#Dbl#DaY#DaY#D#Da9a9.7a9#D.7a9a9a9a9#Dbl#D#D#D#D#D#D#D#D#D#D#DaYaYaYaYaYaYaYaY.N#x#xbgaFaZ#ua#bgaF#vanaz#ealalazazaz.Garaz#q#ebhananaZaZa#a#a#aCama0a0aoa0ama0aqaoamamaFaoam.8a##SaZ#uana7aSbhaBaZaZbmaOaFaOaFb#ambnbn#IaY.NaY#D#D#D#D.7.7b..7#D#Da9.7#s#D.n#D#MaY#Iama#aFaoa0#x.saY#D#Dbl.N#x",
+".Nbo.N.N#xbf#xbf#x#Ia0a0aOa#aBaz.GaP.wan.ya#a#a#aCamambgama0a0a0.Wa0.C#xa0a0a0amamaoaFama#a#.0#vaSazbh#uanaBanaZa#aOaFaO.5aOaqamaoama0.C.C#Ibn#IaYaYaw#D#s#D.E.7#Laf#La9a9.7a9a9.7a9.7a9.7a9.7a9#D#D#D#D#Dbl#D#Da9.7#Da9.7a9.7#Da9.na9a9#D#Dbl#Dbl#Dbl#Dbl#D#D#p#D#D#D#D#D#D#D#D.N#DaYa0b##SaBaZamamaF#v.0#u.6.wan#u#uaSananaZaBa##vaFaFaoamamama0a0aCa0bna0#xaCa0a0.Cao.CaoamaoaF.5aOaFaFa#aFaFaF.5aoamaFamaFaob#bga0aobnbn#x#x#M#Dbl#s#Da9.7a9.s#D#D#D.N#DaY.N#Daw#xa0aoaF.5b##IaYaY#DawaYaw#x",
+".N.N#Ibf#x.W.C.W.5#v.yaZ.G#z.Kba.o#e.w.0a#a##va#amamaOaFaOaFbgamama0amaoam.8.5.5a#aFaFa#aBan#ubh#a.Xar.Gbh#uaZaBaO.5aoamamaC.C.Wa0a0.W.C#I#x#x#xaY#saY#D#D.7af.7af#L#La9a9.7#D.7#Da9.7a9.7a9bja9a9a9a9a9a9a9a9afa9.7a9.7#L.7a9afa9a9a9a9a9#Da9#D#Dbl#D#D#D#p#D#D#D#D#Dbl#Dbl#Dbl.s.NaY#xa0a#aB.0amamamaFa#a#a#a#aBaZaZaZ#va#.0a#b#b#bgamambn.Cbn.Wa0.C.C.C.Wa0.C.C.C.Wa0.Ca0.Ca0aoamama0a0bn#Ubn.Wa0.Ca0.W.C#U#xb#.Vb#b#a0ama0a0aYaY#D#D#D#s#D#saYaY.s.NaYaw.NawaYaY#Ia0amamaOam.C#x#xaYaw#x#x.C",
+".C.W.Caqaq.5.5.5anaP.o.Ya8#obs.g#TaS.wan.0#va##v.0bm.0a#.0a#a#.yamaoaFamaOa#aOa##va##S.0aZ#uaSaz#aaG#a.Gaz#uan#u#vaOam.8aCaq.W.C.C.Wa0#x#x#x#IaYawbl#D#sa9a9#L#Lajaf#L.na9a9.7a9.7a9#D.7#Da9.7a9a9a9af.7afa9.7a9.7af#L#Laf#La9.7afafa9.na9a9bl#Da9.na9a9a9a9a9afa9.na9a9.7a9a9a9.N#D.N#M#xaOaZaBamaOam.8am.8a#.5a##va#aoaFaFamamaoa0a0bnaC#x#x#x#x#I#xaY#xaY#xaY#I#x#x#x#I#x#I#xa0bn#I#xawbl.Nbl.Naw.NaY.NaY#xaYaCa0ao.Vbgb#b#b#awbnaYaYblblaYbl.NawblaY.NaYaYaYawaY#x#Ia0bga#aOamaC.C#xa0.Wa0am",
+"aoaFa#aOa##v.y.ya4.2#4.4a8aDaTaRanananaZaBaFaFaF#v.0#v.0#v.0#v.0amb#aob#amam.5aFamaOaFa##v.0.yaZaz.wanazaz.w.w.waO#vao.5aoamaCam.Wa0#x#xaw#xaYaY#D#M#Da9a9.E#L#L#L#Laf.7a9.7#Da9.7a9#L#L#L#L.7#L#L#L#L#L#L#L#La2#La2#L#L#L#L#L#Lafajafafa9a9a9afa9a9a9a9a9afa9a9a9.7a9.7a9a9.7a9.N#D#D#DaYam#SaZaF.5aFamamamamaoaFamamb#amamaoa0a0bnaC#x#x#xaY#IaYaYaYaYaYaYaYaY#xaY#IaYaYaYaYaY.s#xaY#D#D#D.7.n#D#D#D#M#D.N.saY#xa0a0amamambgambnbn#UaY#x#xaY.saY#x.NaYaw#x#I#x#x#I#xa0a0aF#vaZ.5a#amaCa0am#v.5",
+"an#uan#uan#ua7#uaz#a.Gaz.GaSaZaZ#vbybca#.5aoamb#.5b#amb#amb#amb#aCama0amamaob#amaCa0a0aoaFaFa#byaOby#v.yaZaB#u#ua##v#S#v.5ao.5aoa0#I#xaY#x#IaYaw#Dbla9#s#L#L#La9#Laf#La9#La9.7a9#L#L.7af.7af#Laf#L#L#L#L#L#L#L#Laf#Lafa2af#L.3#Lafafafafa9afa9a9#Laf#Laf#L#Laf#L#L#L#L#L#L#L#L#L.s#D#s.7#DaCa##ua#.0.5.5amama0a0amaoamaCamaCa0#xbn#x#x#x#xawbfaY.N.N.N.s.N.N.s.Nbl.Nbl.NaY.NaY.Nbl#D#D#s.7.7#D.7a9.n#p#Dbl#DblaY#x#x#xbnbnama0am.Vama0b#aCa0#x#xbn#I#x#x#xbnbn#x.Ca0a0aCam#van.wan#vbyaF#va#.yan",
+"alal.Ga7bhaZaZaZa##Sa#aFb#ao.5.8aFaFamama0amamaobn#Ubn#Ua0#Ibn#Ua0a0a0aCa0amamao#x#xaCa0aoamao.5avam.8.8#v.yaB#u#SaBaB#u#S#vaO.8amaCbn#x#I#xawaYbl#sa9a9#La9.7ajafaj#La9#L.7#Da9.7#Laf#L#L#L#L.7a2#ga2a2a2a2a2a2#La2#L#La2#L#L#La2af#Laf.na9a9a9af#Laf#La9af.7af#L#L#L#L#Laj#L#L#D#D.7#s#D.CaBbhbb.y.0aOama0aoa0ama0ama0bnbn#xaYaCbnbn#x#xaYaY.Naw.NaY.NaY.NaY.NaY#DaY#M#Dbl#M#D#Da9.7a9#Dbjb..7afa9.na9bl#DaY.N#Ibf.W#xaC.Ca0amamb#b#a0ama0ama0#xbn#x#U#x#U.C#UamaCama0ao.0.w.6.wan.yan.yan.waP",
+"#q.6a#aF.5aCa0a0bnbna0aCa0amb#am#U.Vbnbn#xa0.C#x#x.NaY.NaY.N.N.N#D#s.NaY.NawaY.N#M.s.N#x.C.Wamaq#UaCaCb#bgaOa##vbg#v#v#u.w#uaZ.yaO.5aoama0.RaYaw#D#D.7.n#Laj#L#L#L#La2#La2#La2#g#Laf#L#L#L#La2#La2#L#La2#La2#L#La2af#L.3#Laf#Lafajaf#La2#La2#La2#L#L#Laf#La2#L#L#L#La2#L#Laf#L#La2#La9#D#x#xaoaO.Xbha#ama0#x#x.CaC.Ca0aC.C#x#IbnaYaYawaYaYaYaYaY.N#D#D#D#D#D#D#D#D#D#D#D#D#D#D#D.7.E.7.7.7af.7.7aj#L#L.7.E.N.N.NaY.N.N.N.NaY.NaYbl#IaYbna0aoaFaOamaoamamamaFaF.5b#aOa#a#aZ#u#a.2.waP.w.w.waZan#u",
+".GanaB.5a0a0#xaCbn#Ibna0a0a0amam.Va0bnbn#x#x#I.C.NaY.Naw.N#s#D#D#D#D#s#D#D#D#saY#D#DaY.saY#x.W.Cbn#Ua0aCaoamaOaFaob##v#uaB.y#vaOa#aO.5bga0#U#x.R#D#D.n.7.7#Lbp#L#La2#L#g#L#g#La2#L#L#Lafa2a2#La2#L#La2#La2#La2#Lafa2#L#La2#La2#Laf#L#Laf#Laf#L#L#Laf#L#La2#La2#La2af#Lafa2#L.3#L.j#La9#DaY#xa0#v#aa7a#b#a0bn#x.C#x#x#x#x#xbn#x#x#IaYaYaYaYaYawaY#D#D#D#D#D#D#D#D#Da9#D#D#Dbj#Da9a9#La9af.E.7a9#Laf#Laf.7a9#D.N.N.saY.Nbl#DaY#D.NaYaYaY#xa0b#.5aFbga#aFaFbma#.ybm#vaZ#SaBan.G#q.2.w#u.6#uan.y.0.0",
+".6#u.0b#a0#x#xa0bnbn#x#xbn#Ibn#x.RawaY#x#I#x#xbfaYaw.N#D#D.7.7.7a9#D#Da9#Da9#D#Da9a9#D#D.N.N#x#x#I#x#Ia0ao.8am.8aCa0bg#v#vaOb#aoaFaOaFama0a0#Ubn#s#D#Da9.E#L#Lajbpa2#ga2a2aja2#gafa2#La2#La2#La2#Laf#La2#L#Laf#La2#Laf#Laf#Laf#L#Laf#L#Laf#La2afa2#La2af#La2#L.3#La2a2#L#L#L#L#La2#La9#s.N#xa0bg.Xana#aFamam.C#xbn#xbn#x#x#x#xbnaYaYaYawaYaYaYaY#Da9#Da9#Da9#Da9.7#D.7a9.7a9a9.7.7.7.7.7a9#L.7.n#L#Laja9a9#D.saY#D.N#D#D#D#D.saY#DaYaYa0a0amb#aFbm#SbmaBaB#ubha7aB#u#uazaz#Tal#q#uanaB.0a#.0a##u",
+"azaBa#aobn#x#x#x#x#x#Ibn#xaY#xaYaYaYaYaY.NaY.NaY#D#D#D#D#D.7a9.7#sa9a9bja9.7#D.Ea9bj.n#D#D.NaY.N#MaYaY#Ia0aoaoam#IaCa0ao.5ao.CaCbg.5b#aoa0aC#xa0aYaY#s.7a9#Lbp#La2bpa2#L#g#L#ga2#Laf#L#La2#La2#La2#La2#La2#La2#Lafa2#Laf#L#L#L.3aj#L#La2ajaf#L#La2#L#La2#La2#La2#La2#La2a2a2afa2#La2#L#DblaY#IamazaSaBaFama0#x.C#xaY#xaY#x#U#x#xaYaYaYaYaYaYaY#D#D#D#Dbj#D#Dbj#Da9a9a9.7a9a9bja9.7afa9aja9.7af.7#Lafa9a9#D#D#D#D#D#D#D#D#D#D#D.NaY#I#xbnaoamam.5a#bma#aZaZaZaZ#uaZanaz#q#TaR.o#q#uaB.0a#.0#uaZ#u",
+"an#vb#a0#x#x#xaYaYblaYaYaYaYaYaYaYaYaYblaY.N.N.sbl#D#Da9#D.7a9#L#D.7#sa9.7a9.7#Da9a9#Da9a9#s#D.Naw#Daw#xaCa0.C#x#U#xaCaoaCa0#Ibna0a0aoa0aCa0a0#UaY#M#D#Da9.7#L.7a2a2#ga2a2#ga2#g#La2#La2#La2#La2#La2#La2#Laf#L#Laf#Lafaj#Laf#L#Lafa2af#L#La2#Lafa2#Laf#La2#La2#La2#La2#L#La2#L#La2#Laj#Dbl.NaY#UaZ.TaBaFam.C.C#xaYaYaYaYaYaY#x#xawaYaYaYaYaY#Dbl#D.Ea9a9.7a9a9.7#D.7#Da9bja9.7a9a9.n.7a9a9a9.na9a9a9a9.na9a9a9#D#D#D#D#D.7#D#D#DaY#x#x#xbna0aCamaFaOa#bma#bmaBaZaZaB.6.Gal.o#e.GazanaBaZ#u#u#uan",
+"#vaFama0awbnaYaYaY.NaY#D#DaY#D#M#Dbl#s#D#D#s#D#D#Dbl#D.n#Daf.E.7a9a9.7a9a9a9a9a9.7a9.7a9.7a9a9a9#D.n#D.N#x#I#I.W.C#I.Caoam#U#xaw#Ia0#I#x#x#I#x#IaYaY#Dblbja9a9#L#La2bpa2bpa2#La2#Laf#Laf#La2#La2af#L#La2#La2afa2#Laf#L#Lafaj#Laf#L#L#La2#Laf#La2#L#La2#La2#La2#L#La2#La2#L#La2#L#L#Lafa9#sblaY#xb#bm#SaFambn#xaYaYaYaYaYaYaYaYaYaYaYaYawaYaY#Dbl.7a9bja9.7a9bja9#L#L#La9.7a9a9.7a9.7a9a9.7a9.7a9a9a9a9a9a9a9a9a9#D#Da9#D#Da9#Da9.N.NaYaY#x#x#xaYa0ama0am.5aF.5a##vaZan#TaR.Gazana7.wan#uaZan#uaZ",
+"b#a0#xaYaYaYaY#x#DaY#D#D#M#Da9a9#D#D#D#D#Da9#D#p#Da9#D.7a9.7#L#La9a9a9.7#L#L.7a9.na9a9.7af#L#L#L#La9.7#s.N#I#x#x.C.CaCa0.W.W#xawaYawaYawaY.NaYaYaYawaY#sbl.7#D.7#L.ja2#ga2#ga2#g#La2#La2#Laf#L#L#La2af#L#L#L#Laf#Lajaf#Laf#Laf#Lajafaf#Laf#L#La2#Laf#Lafa2#La2#La2#L#L#L.3#Laf#La2#L#La9a9#D#MaY.b#yaFbgam#x.N#saYaYaYaYaYaYaYaYaYaYaYaYaYaY#Dbla9.7#L#L.7#L#L#L.7af#La9#La9#La9afafafafa9a9a9a9a9.na9a9a9.n#pa9.n.7a9.7a9.7a9.7#D#D#D#s#DblaYblaY#x#xaCa0aCa0amaOaZ#u#q.G.6#uaBana7azaZaZaZaZa#",
+"a0a0a0aYblaYaY#xaYaY#Dbl#Da9a9af.7.7#Da9a9a9a9a9a9a9.n#Da9.7#L#L#La9.7af#L#Lafa9.7a9#L#Lajafa2aj#L.7.n#D.N#xbo#I#x.Waq.8aoa0#I.Nawbl#sbl#DaY#saYawaYaYbl#D#Da9a9#L#Lbpa2#L#g#La2#Laf#Laf#La2#L.3#Laf#L#Lafaf#Laf#Laf#L#Laf#L#Lafaf#L#Laf#Laf#Lafa2#La2#L#La2#Laf#L#L.3#L#L#L#L#L#L#L#L.na9a9blblbn#Hbga0#xaYaYa9blaYblaYblaYblaYaYawaYaYaYaYbl#Da9a9a9a9a9a9a9a9#L#L#L.7a9.7a9a9#La9a9a9a9af.nafa9#pa9#pa9#pa9a9#Da9#D.7#Da9bja9a9.7a9a9a9#D#Dbl#D#saYaY#x.Cbn.WaF#San.Ga4aZa#a#aZ#uanaZaBa#bma#",
+"bnaYaYawaYaY#M.N#D#D#D#D#D#D#Da9a9#D.nbja9.7a9.7a9.7.7a9#La9a9a9.7a9#L#L.7af.7a9#Laf#Lafa9.7a9a9#L.7#La9a9#DaY#Ua0#UaCa0#I#x#I#I.N#s#D#D#sa9#D#Da9#D#s#D#Daw#DaYajaf#L#L#Laf#L#La2a2a2#La2#La2#L#La2a2a2a2bpaj#Lajaf#Lajaf#Lajafaja9ajafajaf#L#Lafafafafa2#L#L#La2#L#L#L.3#L.3#L#La2#L#Lafa9.na9aYbnb#b#am.C.NaWa9bj#D#Dbj#D.N.NaYaY#DawaY#DaY#D#D.7a9.7a9.7a9a9#Laf#Laf#Laf#L#Lafafaf#La9#D#D#D#L#Lafajaf#Laf#L#L#L#L#L#L.7.7.7a9a9.7a9#D#D#D#DaYaY.N#x#Ia0.Ca0aF#vaF#vaOb#aob#aoaFaBaZ.0a#.5am",
+"#U#x.RaYaYaYbl#D#D#D#D#s#D#Da9#D#D.7#Da9.7a9bja9.7a9af.7a9a9.7a9af.7a9af#L#L#La9a2afaj#L#La9.7a9aj#L#La9.nblaYaY#Ia0aC.W#x#I.N.s#D#s#D.n#D#D#D#sa9a9a9#Dbl#D#D.Na9a9a9a9a9#La9#L#Laf#Laf#Laf#Laf#Laj#L.7aj#L#L.7afajafaf#Laf#Laf#Laf#L#Laf#L#Lafafafaf#Lafa2#L#L#L#La2af#L#L#L#La2a2af#L#La9bja9.Rawa0.8a0.C.Nbj#Da9a9#Da9#D#DaY#DaYbl.Nblaw#Dbl#D.7a9a9.7a9a9bjaf#Lajaf#L#Laf#Lafafafa9a9#Da9#D#Laf#Laf#L#L#Lafaj#L#L.7#L.7af.7#La9a9.7#D#D#D#D#D.NaY#x#x.C.CaoaFaFaOaOamamamamaCaF#v#v.0#vb#am",
+"bnbnawaYaYaY#Dbl.n#D#D#Da9bja9bj.n#D.7a9#D.7a9a9a9.7a9a9#La9a9a9#L#L#L#L#Laf#L#La2a2a2af#La9a9a9#L#Laf.7a9#D#IaY#UbnaC#xaY.N.saY.s#D#Db.#D.n#D.7a9a9#Da9#D#D#D#Da9bja9#Da9#Da9#Da9a9a9a9a9a9a9a9#Laf#L#Lafafajaf#La9#Lajaf#Lajaf.7#Laf#L#Lajaf#Lajafaf.3#L#L#L#Laf#Laf#La2a2#La2#La2#La2af.Ea9.naY#xaCamam#x.Nbj#s.7#D#D#D#Dbj#D#Dbl#Dbl.Nbl#Dbla9a9a9a9a9a9a9a9afafafafajafafajafaf.na9a9a9#D#D#Lajaf#L#Lafa2#L#Laf#L#L#La9.7a9a9.7a9a9#Da9#D#D#D#MaY#x#x.CaCa0aFaOaFamaFaCa0a0bnaCb#aOaFaOama0",
+"#IaYaYaYawaYaw#D#D#D#s#D#sa9#sa9.7a9a9a9.7a9#L.7#La9af.7a9a9.Ea9afaj#Laf#L#La2#La2a2a2#La2#La9#L#L#Laja9a9blaYaY#I#U#xaw.Naw#D#Da9#sa9#sa9.7a9.7ajaf.Ea9a9.7a9#D#D#D#D#Dbj#D#D#Da9#D#D#D#sbl#D#sa9a9a9a9a9#Da9#Dafajafaf.Eaf.7afajaf#Lajafaf#Lafafafajaf#Laf#L#L#Laf#L#L#Lafa2#La2a2af#L#La9a9a9aw#x.Vaoa0#x.Nbja9#D#D.7#D#D#D#Dbl#DaY#DblaYaY.Na9a9a9a9a9.7a9a9#La9afa9afa9af#pafa9#pa9a9a9.7a9#Laf#Laf#L#L#L#Laf#L#Laf.7a9#D.7a9.7a9.7#D#Dbj#Dbl.NaY#x#I.Ca0aqbgaFamaoambn.Cbn#U#xbna0aCama0a0",
+"aYaY#IaYbl.N.N#D#s#D#D#D#D#D#Da9a9a9.7a9a9a9a9#Laf#L#Laf#L#Laf#L#Lafa2a2a2a2a2a2a2a2a2a2a2#L#Lafa2#L#La9a9#DaY#Ubn#I#xaYaw#D#s.sa9bj.n#Da9.Ea9.7#L.7#L#L.7a9.7#L#Da9#Da9#Da9#Da9#Dbl#Dbl#D#Dbl#Dbl#s#D.na9#s#D#Ma9a9.n#Laf#Lajaf#Laf#Laf#L#Lafajafafafaf#Laf#L#L#La2#L.3#L#L#Lafa2a2#L#Lafa9.na9#Dawa0bga0#x.N#s#Da9#D#D#D#D#D#D.Nbl#DaYaYaYawaYa9.na9#La9afa9afa9a9a9a9a9a9a9a9a9#pa9a9a9a9a9a9#L#Lafaj#L.3#La2afafa2af#La9a9a9afa9.7a9#D#D#D#D#DaY.N#x#xa0a0aoaFbgama0a0a0aCa0aYaY.baYbnbnaC#x",
+"aYaYblbl#D#Da9.7a9a9a9a9.na9a9.7ajafaj#L#L#La2#L#L#L#L#Lafaj#Lafa2a2#L.j#La2#La2a2a2a2#La2af#L#L#L#L#L#La9#MaYaY#Ibn#MaY#D.s#D#s.7.na9.Ea9.7aj#La2aj#L#Laj#L#L.7.7a9.7.7a9.7a9.7#M#Dbl#MblblaYbl.sbl#Dbl#D#Dbl#Daf.Ea9af.Eafa9af#Lafaj#L#Laf#Lafafafafafaf#Laj#L#Laf#L#La2afa2#La2#L.3#L#L.7#Da9#DaYaCama0#Ibla9#Dbj#D#Da9#D#D.N#MaY#DblawaYaYaY#pa9a9a9#pa9a9a9afa9afa9#p.na9a9#Mbla9a9a9#La9.7afaj#Laf#L#Laf#Laf#Laf.7afa9afa9a9.7a9#D.7#D#D#D#Dblaw#x#x.WamamaOb#aOa0aC.Cbn.C#U.RaYaY.b#xbna0",
+"aYaY#D#D#D#s.7.7a9.7a9.7a9a9.7a9#Laf#Laf#Laf#Lafa2a2a2a2#La2a2aja2a2.3a2a2a2a2a2aaaaa2a2a2a2a2#La2#L#La9a9#DaY#I.RaYaw#D#M#D#s#D.n.7a9.n#L.7af#La2a2a2#La2#L#L#La9a9.7a9a9.7a9a9a9#pa9a9a9.n#pblaYaY#IaY#IaYaw#x.na9af#Laf#Laj#Laf#La9afajaf#L#Lafafafaj#Laf#L#Lafa2#L.3#L#L#L#La2a2#L#Laf.na9.n#D.NbnaCaobn#D#s#D.n#D#D#D.N.NaY#DaY#Dbl.NaYaYaw#D#pa9#p.n#pa9#pa9a9.n#pa9#pa9#pa9#D#pa9afafajaf#Laf#L#Laf#L#Laj.3af.3afafa9a9a9.7a9.7a9#D#D#D#D.NaY.N#xa0ama0aob#ama0a0a0bn#Ibna0#x.bbnaY#Uamam",
+"#MaY#s#D#D.7#La9#L.7.na9a9.7a9a9#L#L#L#La2#La2#La2a2a2aja2#La2afa2aja2#La2a2a2a2#gaaa2a2a2a2a2a2a2#L#La9a9blaYaYaY#MaY#M.N#D.n#D.na9.n.7#L.E#L#L.ja2a2a2#g#L#L#L#Lajaf#Lajaf#L#La9a9#pa9#pbla9.naYawaYaYaY.RaYaY.na9.na9aj.7af.n#Lafaj#Laf#Lajafafajafafaf#L#L#L#Laf#L#La2afa2af#L#La2af#L.7a9a9.7aw#xaCa0#IaYa9#D#D#D#D#D.NaY.saY#Dbl#DaYaYaYaY.na9#pa9a9#p.na9af#p#pa9a9a9#pa9#Dbl#Da9.na9#L#Laf#L#Lafajaf#Lafafafafafafafa9a9afa9a9bja9bj#D#D#D#DaY#x.Wa0av.5.pamaCa0#Ua0#x#xa0bnaYaw.R.Cb#am",
+"amam#xbla9a9a9a9a9a9.7a9.7afa2#Laf#Laf#La2#La2#La2a2a2a2a2a2a2a2#Laf#Laf#La2#L.3a2a2a2a2asa2#La2#gafa9blaYawaYaYawbn#IaYawaw#D#Da9.Ea9#Lafaf#L#L#L#La2a2a2a2a2a2a2a2#La2af#L#Lafajaf#L.na9bja9#D#p#pbl#M#x#Ia0bn#I.NaY#D#Da9a9.7af.Eafa9aja9#Lafa9a9a9a9#Lafa9afajafafafaf#Lafafa2.ja2afajaf#L.na2a9aY.Cbgam#x#Ma9.n#Lajafa9.N.N#pa9bl.N#MaYaYaY#p#pa9#pa9#pa9#p#pa9#p.n#p#p.n#pa9#pa9a9#paf#pa9a9.n#pafafafafafafafa9afa9afa9a9.na9a9a9a9a9#D#D.n#paYaYa0amb#amb#a0a0a0.Ca0#I#xaw#xaY#x#xaCa0aC",
+"ama0#xbla9.na9a9bja9#Da9a9ajaf#La2aj#Lafa2#La2#La2a2#La2#La2#La2af#Lafa2#Laf#L#La2a2a2asa2a2a2a2a2#La9blaYaYaYawaYaY#xawaY.N#s#Daja9#Lafajaf#Laf#L.j#La2#La2#La2#La2#La2#L#L#L#L#L#Laf.7a9#D.n#Da9.nblblaYaY#xaC#x#IaY.s#D#sa9.na9a9a9a9a9a9a9a9a9afa9afa9a9#La9afafaj#Lafaf#Lafa2#La2#Lafafaj#La2.naw.CamaC#xaY#D#D#La9a9#sbl.Na9#M#DblaYaYaY#xbla9#p#pa9#pa9#pa9#pa9#p#pa9#p#p#pa9.n#pa9a9a9af#pafa9afa9a9afa9#La9af.7afa9afafa9afa9a9.na9#Dbl#p#pblbn#U.5bg.5a0aoa0a0#Ua0#xbnaYaYaY#U#xbn#xa0",
+"amaCaYaYaw#Dbl#sa9#D.7a9.7af#L#Lafaf#L#La2#La2#La2a2a2a2a2a2a2a2#L#L#Lafaja2#L.3a2a2a2#La2a2a2a2#ga9#D#MaYaY#UaY#xaw#Ibl.Naw#D#Dafafaja9#L#Laf#La2#La2a2a2a2a2a2a2.jafa2#Laf#Laf#Laf#La9a9.7#Da9a9a9#sblawaY#x#x#IaY.NaY#D#D#D#D#sbl#s#D#sa9a9.na9.na9a9.nafa9afafafafafafafajafa2#L.3#L#Laja9#Daj#DaY.Ca0aoa0aY#D#Ma9.na9#D#DaYblblblaYaYaYaYaYbl#pa9#pa9#pa9#pa9#p#Ma9bl#p#D#pa9a9#pa9#pa9#pa9#pa9#pa9#paf#pa9afa9afa9afa9afa9a9a9a9a9a9a9#Da9bla9awaYa0a0ama0b#a0a0a0#x#U#x#xaw#xaw#xbn#I#xa0",
+"b#b#aCaYaYbl#Dblbja9#D.na9#Lajaf#L#L#Lafa2#La2#La2a2#La2#La2#La2afafaj#L#Laf#L#La2#La2a2a2a2#La2#La9blaYbnbn.R#IaY#U#xaYaw.N#D#s#L.Eaf#Lafaj#L#L#La2#La2#La2#La2afa2a2a2#L#L#L#Lafajaf.7.n#Da9b.afa9a9a9#DaY#I#x.NaY#saY#s#D#s#DaYaYaYblaY#DaY#Dbla9a9a9a9a9a9a9.na9a9.na9a9a9a9#La2aj#Lafa9a9a9af#Mawa0aCa0a0bn.NaYbl#D#M#DaY.NaYaYaYawaYaYawaYbl.na9#pa9#pa9#pblbla9#p#pa9#p.na9#pa9.n#pafa9af.naf#pajafafafafa9a9a9afa9af.7afaf.nafa9a9af#D#DblblaYaY#xaCa0.Ca0aobnaCbn#xawaYaY.RaYaYaY#xbn#x",
+"a0bnbnbnaYaYbl#D.n#D#sa9a9#Laf#L#L.3#L#L#La2#Lafa2a2a2a2a2a2a2a2#L#Lafaf#L#La2#L#La2#L#L#La2#L#Laf.nblaY.bbn#U#x#Ubn#Ibl.NaYa9.7a9afaja9#Lafaf#La2a2aja2a2a2a2a2a2a2a2a2af#Laf#L#L#L#La9a9.7#Da9#Laja9#D#D.NaYaY#s#D#D#DaY.NaY.saY.saY.NblaY#DaY#sbl#sbla9#Da9#Da9a9.na9a9afa9ajafaf#Lafa9a9#D#sa9blaY#Ua0aob#aC#xaYaw#D#DblaY#IaYawaYaYaYaYaYaYbl#pbla9#pa9#pa9bl#M#p#D#p#M#p#pa9#pa9#pa9a9#pa9#p#pa9#p#pafafaf.nafa9a9#La9afafa9afa9a9afa9#Da9bl.NaYawbn#x#x#x#Ubna0#xbnaY#xaYawaYaw#xawaY#x#U",
+"#Ubn#Uam#UaYaYbl#Da9bja9a9#L#Laf#L#Laf#Laf#La2#La2a2#La2#La2#La2af#L#L#L#Laf#La2af#L#La2#L#La2#Lafa9bl.Ra0.pa0bn#U#xawaY#M.N#s.7.na9#Lafaj#L#Lafa2a2a2a2#La2#La2a2a2a2a2#L#L#L#Laf#Laf.7a9#D.7#Dafaf#L.na9#Daw.N.n#D#D#s#Daw#DaYaYaYaYawaYaYawbla9bla9bla9.n#D#Ma9a9a9#Da9#sa9#p#Laf#La9.7.n#D#D#DaYawa0a0aob#amaCa0aYaYaY#DaY#xaYaYaYaYaYbl#Dbl#p#pa9#pa9#pa9#p#pbl#p#pa9#pa9bl#p.na9a9#pa9#pa9af#pafa9af.na9afa9a9aja9a9afa9#Laf.7afa9.7afbl#D#D#DaYaYaY#xaY#xa0bnbn#U.RawaY.baYaYblaY.R#IaYaY",
+".Rbnb#a0a0#xaYbl#s#D#sa9.Eaf#L#La2#Laj#La2a2#L#La2a2a2a2a2a2a2a2#La2afa2afa2#Laf.7af#La9a9#Lafa9a9a9.R.Ra0.V#UbnaYaYaY#D#D#D#D.7afajaf.Eafaf#L#La2#La2#La2a2a2a2a2a2#La2#L.3.7#Lafaj#La9a9.n#Da9#Laj.7a9.7#D.N.Na9.n#D#DaY.NaY.sbl#Mblbl#Dbl#Dbl#D#Dbl#s#Dbl#Dbla9#Da9.nbla9a9#Dajaf.na9#D#D#D#sblawaY#x#Ub#b#aO.5a0aCaYaYawaY#x#xaYaYaY.sblbl.na9#pa9#pa9#pa9#pblbla9#M#p#Dblbl.n#p#p.na9#p.n#p.na9#pa9#pa9af#pa9afa9a9af#Laf#Lafafa9afa9a9#Da9bl#D#M.NaY.Naw#x#UbnbnaYaYaY#xaYbl#MblaYaYaYaY#I",
+"#Fbn.Vaoa0bnaYblbja9#Da9a9#Lajaf#Laf#Laf#L#L.3#La2a2#La2#La2#La2af#L#L#L#Lafaj#La9#L#La9a9#L#Lafa9blaw.R#Ua0bnbn#IaYaw#D#s#Da9#s#La9#Laf#L#L#L#La2a2a2.j#L#La2#La2a2a2a2#L#Laf#L#Laf#Laf.7#D.7#s#L#L#La9.7#D.sbf.n#Da9#Daw#DaY.N#pbl#M#D#p.n#pa9#sbl#D#D#Dbl#D#D.na9#Dbl.n#Da9a9af#La9.7a9#s#DaYaY#x.baYbnaoamaFaFaoa0#IbnaYaY.R#x#xaYaYbl#Da9#pa9#pa9#pa9#pbla9#M#pa9#pa9#p#Mbl#pa9a9a9#pa9a9#pa9#paf.naf#pafafa9a9a9afa9af.7afa9#L#La9a9af#D#D#D#DaY#D#DaY.NaYbnbn#U#x.baYaYaw#paY#D#MaY#IaYaY",
+"blaw#xa0ambn#xaYawblbl#D#pa9afafa2a2a2a2a2a2#La2#L#La2#La2#La2#La2a2a2afa2#La9a9a9a9a9#D#D#D#D#D#pbl#paY.Rbn#I#x#pa9a9a9a9.7.7a9afajaf.n#Laf#L#L#L#L#La2a2a2#ga2a2bpa2#L#L#L#L.7af#Laf.7a9a9a9#Da9a9#sa9#D#D#D.Na9a9a9#sbl#D#Ma9bl#Dblbl#Dblblbla9a9a9afa9a9a9a9a9a9afa9a9a9a9.nafa9a9.na9a9#D.naY.RaYbna0a0b#aobgb#bg.Va0aCaY#D#Mbl#Mbl#Dblbl#Dbl#Dbl#Dbl#Dblbla9#pbla9#p#pa9#p#p#p#p#p#pa9#pa9#p#p#p#pa9a9afa9aja9afaf#Lafaf#La9afa9#Lafa9a9af#sa9#Dbl#DaYbl.N#UbnbnbnaYaY#IaYaY#MaY#xaYaYaYaY",
+"aYaYbn.Ca0a0#I#xaYaYblbl.naf#Lafaja2#La2#La2a2a2#La2#La2#La2#La2a2a2#L#L#L#L#L#Lafa9af#D#p#Dbl#D#F.nblblaYaYaYaYa9.n.7a9a9.7a9.7afafaf#L#L#L#L#La2#ga2#ga2bpa2#L#ga2a2#L#L#L#L#L#Laj#Laf.7a9bja9.7#D.7#D#D#D.Naw#D#M#D#p#D#p#D#Dbl#sbl#Dblbl#Dbla9.na9.naf#paja9afa9.na9a9afa9a9afajafa9a9a9blblaYawaY#Ua0aC.5am.V.Vb#ama0aYaY#xblaY#DaYbl#M#Dbl#Dbla9bla9bla9bl#D#p.n#pbla9bl#p#p.na9#p.na9#p.na9bl.na9afa9a9a9a9afa9#La9af.7afa9a9#Laf#Lafa9a9a9a9a9#D#DaY#saYbnbn#U#x#UaYaYaYaYaYaYawaYaYaY#x",
+"aY#xbna0a0a0a0bnaYaY#Mbla9a9a9af#L#Laf#L#L#L#Lafa2#La2#La2#La2a2#La2afa2af#L.7#La9a9#D#D#D#D#DaY#pblbl#MaYaYbl.Na9a9a9.7a9#L.Eaf.naf#Laf#L#L#L#La2a2bpa2#ga2#ga2a2#L#L#L#L.7a9a9a9a9afa9a9#D#D#sa9.nbl#DaYblaYaYbl#D#D#D#M#Dbl#sblbl#Dbl#sbl#D#Ma9a9a9a9a9a9a9a9a9a9a9a9.na9a9a9.n#pa9a9#D#sbl#saYaY.RaY#xa0a0aCa0#Ua0aCbnaYaYawbl#sbl#M#Dblbl#D#pa9a9a9a9a9a9a9#p#p#D#p.n#pa9.n#p#p#pbl#pa9a9#p#pa9#p#pa9a9afa9af#Lafaf#Lafaf#La9a9afa9af#La9afa9a9bl#D#p#DaY#DbnaCbnbnaYaY#IaYaYaw#xaYaYbn#I.R",
+".Raw#xa0aC.Ca0a0.baYaYblbla9a9af#Laf#L#La2afa2#L#La2#Lafa2#La2a2a2a2a2#L#L#Laf#L#D#p#Dbl#DblaYaY#pblblbl#Dbl#D#Dafa9af#L#La9#L.7afaf#Lajaf#L#L#L#L#ga2a2#La2bpa2#L#L#Laf#La9.7#Da9a9a9#D#Dbl#DaYblblaYaYaYawaYaY#xawaYaYaYaYaYaYaYaYaYaYaY.NblaYa9a9#pa9a9#pa9#p.n#Da9a9a9#Da9#D#pa9bl.na9blaYblblaYaY#IaYbnbna0#Ua0b#b#a0aYaYblblbl.Nblbl#Dbl#Da9a9afa9afa9afa9#Ma9#pa9#pbl#pbl#p#p#pa9#pa9#pa9a9bl#p.na9a9a9a9#La9af.7afa9#La9afa9a9af.7afafafa9a9a9#D#D#DblaYbnbn#Ibn#IaY.RawaYaYaYaYaYaY#x#x",
+"bnbnbnbna0a0a0amaYaYaYaY#D.na9a9afa9afa9#L#L#Laf#L#L#La2#La2#L#La2#L#Laf#L#L#Laf#D#Dbl#DblaYaYaYa9.nblbl#D#D#Dblafaf#L#L#L#L#L#L.naf#Laf#L#L#L#L#ga2bpa2#ga2a2#gaf.3af.7afa9a9.n#D#Dbl#sblbl.NaYaYaYaYawaY#x#xaYaYaYaYaYawaYawaYaYawaYawaYblaYblblbl#Dbl#M#Dblbl#Dbl#D#Dbl#s#Dbl.n#pa9blawblawaYaw.RaY.RaY#U#xbn#UbnaCaOama0aYbl#Dbl#Mbl.Nblbl#Da9.na9a9a9a9a9a9a9#pbl#pa9#pa9#p#p#p#M#p#p.n#pa9.n#pa9#pa9a9afa9#Lafa9afa9#Lafafa9afafa9af#La9#La9af#Dbl#Daw.NawbnbnbnbnaYaY#xaYbn.baY.RaY#xbnbn",
+"ama0bna0#Uambgb#aY.RawaYbl#Da9a9a9.7a9.7a9af.7#L#La2af#Laf#L#L#La2a2#La2#Laf#L.7#pblblaYaYblaYaYblblbl#Da9a9a9.7afajaf#L.3#L#L#L#Lafaf#L#L#L#L#L#L#ga2a2bpa2bpa2#La9#Lafa9af#D#D#Dbl#DaYaYaw#xaYaYawaYaY#xbnbnaYawaYaYaYaYbnaYaYaY.RaY.RaY.baYawbl#Mblblblbl#Mblbl#D#D#M#Dbl#D#D#pbl#MblblaYaYaY.RaYaYawbnaYbnawaYaYa0aO.Fa0#x.R#Dbl.Nbl#Mbl#sbla9a9a9a9afafafaf#p#p.na9bl.nbl#p.n#p#pa9#pa9a9#p#pbl#pa9a9a9a9a9#La9afa9a9afa9#Laf#La9afa9af#Lafa9a9#D#Dbl#DblaYbna0#Ubn#I.RawaYawaYaYaY#UbnaCbn",
+".Va0bna0.V.Vb#.5bn#xaYaYaY#Da9a9a9#La9#La9#L#Laf#L#L#La2#La2afa2#La2#Laf#La9a9a9blaY#MaYaYaYaYaYbl#Dbl#Dafa9#L#Lafa2a2a2a2a2#L#Lafaj#Laf#L#L#L#La2a2bpa2#ga2a2#gafafafa9a9a9bl#pbl#DblaYaYaYaY#xaY.Rbnbn#Ua0a0a0aYaYaYaYaYaYaY#U.R.b.R.R#U.Rbn.RaYaYawblaYblaYbl.N#MaY#DaYblaYbl#sblblblawblaYaYawbnaY.RaYaw.RaY#IbnaCb#aOb#.Vbn#DblblawaYblbl#Da9a9a9a9.7a9.7a9#D#pbl#p#p#pa9#p#p#p#pbla9#pa9a9#pa9.n#pa9.na9a9afafa9a9afa9#Laf.7af#La9afa9#Lafa9a9a9bl#s#DaY#sbnbnbnbnaYaY#x.Rbnbnbnbnbn#xa0a0",
+"a0.Vbn.bbna0b#b##UbnaYaY#D#Ma9a9.Ea9a9a9.7a9.7#Lafa2a2#La2af#L#La2a2#L#L#Laf.7.7blblaYblaYaYaYaY#DaYa9a9a9#La2#La2a2#La2#L#ga2#Lafafafa2#L#L#L#L#L#ga2#g#La2bpa2afafa9af#p#Da9#D#DaY#D#DaYaYaY#x.RaYaYbnbna0a0a0aYaYaY.RaY#UaYaYaYaYaYaYaYaYaYaYawblaYaYaYblaYblaYbl.NblaY#s.Nblblbl#MblaYawaYaY.Raw.RawaY.b#x.baY#xa0aob#bga0bnbl#sblaYaYbl#sbla9.n.7a9.n.7a9a9#pa9#pa9#p#D#pbl#p#p.na9#p.na9#p.n#pbl#pa9a9a9af.7a9afa9.na9a9afaf#Lafa9afa9af#La9.nbl#D#D#DblaYbnbn#UaYaYaYawaY.RaY.Rawbnbna0a0",
+"aYaYaYaYaYaY.N#xaYaYawbnaYaYaYaYbl#Dafa9afa9.7#L#L#L#L#L#L#L#L#L.3a2afafa9#D#DaY.R.R#x.RaYawaYaYa9.7a9#L#L#Lafa2a2a2a2a2#g#L#L#Lafafajafafa2#L#L#L#L.7#L#L#L#L#L#L#L#Laf.7#La9a9a9.7a9#D#D#D#D#Dblbl#IaY#xaY#xaYaYaYaYawaYaYaYaYaYawaYaYawaYaYaw#Fbl#M#FblaYaYaY.R.R.R.R.R.R.R.RawaYaYaYaYaYaYawaYbl.NaYaYaYbn#Ibn.baY#Ua0aOb#.Vbg#HaY.bbla9a9.na9a9a9a9.7a9a9.Ea9#p.na9a9.n#pa9#pbl#p#pa9#p#pa9#p#pa9#pa9#pa9a9#pa9.na9afafaf#L#Laf#L#L#L#L#Lafa9a9a9#pblbl.Nbl#x.R#xaY.R#x#xaYaw.RaYaYaYaYaY#D",
+"aYblaYaYaY#IaY.NblawaYaYaYaYaYaY#Dbla9a9a9a9a9#L#L#L#L#L#L#L#L#L#Laf#Lafa9#Dbl.N.R.Raw.RaYaYaYaY.7#Da9.7af#La2#La2#ga2#ga2#L#L#Lafafafaf#L#L#L#L.7#L#L#L#L.7#L.7a2a2#L#Laf#La9bja9#D.7#D#D#D#D#D#D#DaYaYaYaYaY#xaYaYaYaYaYaYaYaw#xaY#xaYaYawaYaYbl#FblaY#MaYblaw.R.b.R#MaY#FaY#FaYaYaYblaY#MaYaYblawaY.RawaYawaYbnaY#Ibnao#SaBaF.p#H#U.RaY#Ma9#Da9a9.7a9a9a9a9a9a9a9a9#pa9#pa9.na9#pa9a9#pa9#pa9#p#D#p#s#pa9a9afa9af#pafafafafaf#L#L#Lafaj#Lafaja9#pa9a9#Dbl#DblaY#UaYaYaw#x#xbnaYblaw.RaYaY#Dbl",
+"blaYblaYaY#D.NaY#pblblaY.RaYaYaYbl#Dbl#Da9a9.7a9#L#L#L#L#L#Laf#Laf.nafa9#D#DaYaYbn.RbnaYaY.R#xaYa9.7a9#L#L#La2#La2a2#g#L#L#L#L.7afajafaf#Laf#L#L#L#L#L#L#L#L#L#La2#La2a2#L#L#L#L#L#La9.7#Da9bj#DblblaYaYaYaYaYaYbl#Dbl#D#Dbl#Dblbl#Mbl#MaYblaY#Mbl.nbl#pa9aYblaYblaYaYaY.RawaYaY#M#F#M#Fbl#F#F#M#p#p#p#MblaYaYaY#UbnbnaCam#SaBbm#H.p.p.RaYaYbla9.na9a9.na9a9a9a9a9#pa9a9#pa9#pa9#pbla9#pa9#pa9#pa9#p#p#pa9#pa9#pa9#pa9a9afafafaf.3afajafafafafafa9.n#pa9#p#Dbl.N.RbnaY.RaYbnaY#x.b.RaYaYblbl#Dbl",
+"#DblblaY#Dbl#D#Dbl#DawaYaYawaYaYaYaYbl#Dbl#D#Da9#Da9#Da9#Da9.7a9a9#p#Dbl#DaYaYaw.R.RaYbnaYaY#xaY#D#Da9.7#L#L#L#La2#ga2#L#L#L.7afafafafafaj#L#L#L#L#L#L#La2#L#L#La2a2a2#La2#L.7#La9#L.7a9.7#D#D#D.N#Dbl.sbl#D#Dbl#D#D#D#Dbl#D#D#Da9#D#D#Da9#D.n#D#pa9#pa9a9blblblblaYblblblblblbl#p#Fbl#p#pbl#pbl#p#M#pblbl#Faw#FbnbnaCamaCaF#SaZ#Hb#bgbnaw.Raw#Da9a9a9a9a9a9.na9afa9a9#p.na9a9#p.na9#pa9#pa9#pa9#M#p#D#p.na9a9a9af#pajafafafafaf#Lafa9afa9a9afaf#paf#p.n#Dbl#DblbnaYbn#Ubn#x#U#xbn.baYblaY#DaY#D",
+"blblaY#DaY#D#D#Dbl#Dbl#DblaYaYaYaYaYaYaY#M#Dbla9#D#D#D#D#D#D#D#Dbl#Dbl#DaYaYaYaYbn.R#U.RaY.R#xaY.7a9.7#Laf#La2#La2a2#L#L#L#La9.7afafafaf#Laf#L#La2#g#L#g#L#ga2a2a2a2#La2a2#La2#L#L#Laf.7a9a9#Da9#DblaYaYbl.Nbl#Da9a9a9a9a9a9a9a9.na9.na9a9.na9a9ajafa9.na9a9.na9blblbl#Dblblblbl#M#p#p#p#p#p.n#p#p#p#p#M#pblbl#MbnbnbnaCa0aF#SaZ.V.V.VbgbnaYaYaYbl#D#D#D#D#D#Dbla9#p.na9#pa9#pa9#pbla9#pa9#pa9#pa9#pa9#pa9#pa9af#pa9#pafafaf#Lafa9a9a9a9a9afa9a9afafa9#p#Dbl#saY#x.bbn#xbn#I#xbnbnbnbnawbl#Dblbl",
+"a9#pa9bl#M#Dbl#Da9a9#D#D#D#D#D.Nbn#U.RaYaYaY#D#Dbl#D#Dbl#D#Dbl#DaYblaYaYaYawaYaYaY.RaYbn#xaw#xaY.7a9#D#L.7a2#Laf#L#Laf#La9a9#Da9afafajaf#L#L#L#Lbpa2a2a2#ga2a2bpa2a2a2a2a2a2#La2.3#L#L#La9.7a9.7bl.NaYaY#D#pa9#pa9a9a9afafa9a9a9afafafajafafafafafajaf#La9a9a9bj.na9#D.n#Da9#s#D#p#p#p#p.n#pbl#p#p.n#pa9bl#Mblbl#UaY#U#x#Ub#aB.l.V.V.V.VaCbnaY.R#D#Mblbl#Mblblbla9#pa9#pafa9a9#pa9#p#pa9#pa9#pa9#pbl.n#D#pa9#pa9afafafafafafafafafa9#p.na9a9a9a9afafafa9#p#DaYaY.Rbn#x#Ubnbn#xaCa0aCbnaYaYblbla9",
+"#pa9#p#Dbl#Da9#Da9afa9bla9bl#DblaYaYbnaYaYaYaYaYblaYblaYblaYaYblaYaYaYaYaYaYaYaY.Rbn.R#xaY.RaYaYa9.7a9#Laf#L#L#Lafaf#Lafa9a9a9.nafafafaf#Laf#L#Laa#ga2#ga2a2#ga2aaasa2a2#La2a2#L#L#L.3#La9.7a9#DaYblaYblbla9a9ajaf#Laf#L#Lafajaf#Lafafaf#Laf#L#La2#L#L#L#L#L.7.7a9a9a9a9a9.na9a9.na9a9a9a9a9a9.na9a9.n#D#D#D#D#D#MblawawbnaC.F.t.Fb#.Vb#.Vbnaw#xaYaYaYaY.NaY#D#Da9#pa9a9#p.n#pa9.nbla9#pa9#pa9#pa9#p#p#pa9.na9afafafafafafafafafa9a9afa9af#pafafafafa9#p#Dblblaw#xbn#Ubn#x#IbnaCb#aCbnawaY#D.na9",
+"#pa9#pa9a9#Dbla9a9a9af#D#Da9#D#D#xbn#xbnaYaYblaYaYaYaYaYaYaYaYaYbnaYaYaYaYaYaYaY.R.R.RbnaYaYaYaY#D.7#Da9#La2#Lafajafafa9a9a9a9#Dafafafaf#La2#L#La2a2#ga2a2#gaaa2asaaa2a2a2a2a2a2a2#L#L#La9a9.7a9#D.saY#D.n#pafaf#Lafaj#L#Laf#L#Laf#L#L#L#L#Lafaja2a2a2a2#L.E#L#La9a9a9.7a9a9a9a9a9.7a9.na9a9a9a9.E#L.7.7#D#s#D#s#Fblbl#M#xbnbg.t.F.t.V.V.VaCa0aY#DaYaYaYaY.Nblbl.na9#p.na9a9#pa9#p#pa9#pa9#pa9#pa9#p#D#pa9#p#pa9afafafaf#Lafafa9af#pa9#pa9afa9afafaf#pa9a9#D#DaYbnbn#xbn#Ua0bna0bg.Va0aYblbl#pa9"
+};
diff --git a/tests/auto/gui/image/qimagereader/images/namedcolors.xpm b/tests/auto/gui/image/qimagereader/images/namedcolors.xpm
new file mode 100644
index 0000000000..f6485d510e
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/namedcolors.xpm
@@ -0,0 +1,18 @@
+/* XPM */
+static char *xman[] = {
+/* width height ncolors chars_per_pixel */
+"8 8 3 1",
+/* colors */
+"e g4 black c pale turquoise 4",
+"f m white c light golden rod yellow g4 grey",
+"g g white c lemon chiffon m black",
+/* pixels */
+"eeeeeeee",
+"ffffffff",
+"gggggggg",
+"gggggggg",
+"gggggggg",
+"gggggggg",
+"gggggggg",
+"gggggggg"
+};
diff --git a/tests/auto/gui/image/qimagereader/images/negativeheight.bmp b/tests/auto/gui/image/qimagereader/images/negativeheight.bmp
new file mode 100644
index 0000000000..875887acef
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/negativeheight.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/noclearcode.bmp b/tests/auto/gui/image/qimagereader/images/noclearcode.bmp
new file mode 100644
index 0000000000..1a5ca9c9bd
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/noclearcode.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/noclearcode.gif b/tests/auto/gui/image/qimagereader/images/noclearcode.gif
new file mode 100644
index 0000000000..27784d61b2
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/noclearcode.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/nontransparent.xpm b/tests/auto/gui/image/qimagereader/images/nontransparent.xpm
new file mode 100644
index 0000000000..00c21ef7d7
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/nontransparent.xpm
@@ -0,0 +1,788 @@
+/* XPM */
+static char *dummy[]={
+"8 8 777 2",
+"#R c #000000",
+"fn c #000001",
+".e c #000069",
+".f c #00006d",
+".g c #00006e",
+"#d c #0042b4",
+"aJ c #010101",
+"g0 c #010102",
+"dr c #010202",
+"gd c #010203",
+"#J c #0157bb",
+"e. c #020202",
+"du c #020304",
+"fR c #030303",
+"jJ c #040404",
+"hf c #040608",
+"fE c #040609",
+"cO c #04070a",
+"k# c #050505",
+"gC c #050709",
+"ka c #060606",
+"br c #06080a",
+"dY c #06090d",
+"hI c #070707",
+"in c #07090b",
+"cL c #070a0e",
+"cd c #070b0f",
+"e0 c #080808",
+"gZ c #080b0e",
+"eu c #080b0f",
+"dz c #080c10",
+"hD c #090909",
+"fq c #090d11",
+"cH c #090e13",
+"jB c #0a0a0a",
+"#U c #0a0d0f",
+"a4 c #0a0d10",
+"g3 c #0a0d11",
+"fu c #0a0f14",
+"cj c #0a1016",
+"kb c #0b0b0b",
+"#n c #0b0d0f",
+"a1 c #0b0e10",
+"g8 c #0b0f13",
+"f4 c #0b0f14",
+"hE c #0c0c0c",
+"bf c #0c0f12",
+".X c #0c28a0",
+"bT c #0d0d0d",
+"ax c #0d1014",
+"hr c #0d1217",
+"dH c #0d141b",
+"jy c #0e0e0e",
+"aW c #0e1115",
+"eH c #0e141b",
+"bE c #0f0f0f",
+"ar c #0f1317",
+"g5 c #0f1419",
+"hg c #0f151a",
+"fh c #0f151c",
+"dJ c #0f171f",
+"gI c #101010",
+".z c #101094",
+"h. c #10161b",
+"gm c #10161c",
+"eL c #10171f",
+"hK c #111111",
+"at c #11161b",
+"fC c #111820",
+"dA c #111922",
+"aj c #1163c4",
+"bJ c #121212",
+"#Z c #12161a",
+"ba c #12171c",
+"ho c #12181e",
+"jK c #131313",
+"iq c #13191d",
+"cA c #131e2a",
+"c7 c #141414",
+"dR c #141e29",
+"jr c #151515",
+"aA c #151a1f",
+"hq c #151c23",
+"fl c #151e28",
+"eV c #151e29",
+"d4 c #161616",
+"hw c #161e25",
+"jk c #171717",
+"bs c #171d23",
+"g9 c #171f27",
+"eC c #17212b",
+"b9 c #172432",
+"d5 c #181818",
+"as c #181e24",
+"bn c #181f25",
+"bS c #191919",
+"gr c #19232d",
+"ed c #1a1a1a",
+".d c #1a1a6e",
+"gB c #1a242e",
+"eK c #1a2531",
+"dQ c #1a2633",
+"hL c #1b1b1b",
+"g1 c #1b242d",
+"g# c #1b252f",
+"eJ c #1b2734",
+"d1 c #1b2937",
+"bW c #1c1c1c",
+"gW c #1c262f",
+"ci c #1c2b3b",
+"cs c #1c2c3c",
+"e# c #1d1d1d",
+"#3 c #1d232a",
+"f8 c #1d2833",
+"fI c #1d2936",
+"eO c #1d2a38",
+"cw c #1d2e3f",
+"jR c #1e1e1e",
+"a2 c #1e262e",
+"eP c #1e2b39",
+"dE c #1e2d3d",
+"cF c #1e2f41",
+"aO c #1e6ec9",
+"c4 c #1f1f1f",
+"gx c #1f2a36",
+"c# c #1f3043",
+"j2 c #202020",
+"bk c #202931",
+"ht c #202c36",
+"eF c #202f3e",
+"b7 c #203245",
+"cB c #203246",
+"hG c #212121",
+"aE c #212932",
+"bp c #212a32",
+"hl c #212d38",
+"cc c #213347",
+".M c #214eb7",
+"hF c #222222",
+"#7 c #222a32",
+"fw c #223040",
+"eU c #223141",
+"jC c #232323",
+"bb c #232c35",
+"ga c #23303d",
+"cv c #23364a",
+"cn c #23364b",
+"jl c #242424",
+"gj c #243240",
+"cm c #24374c",
+"c. c #24384d",
+"bF c #252525",
+"be c #252f39",
+"gt c #253341",
+"dU c #253649",
+".Y c #256cc9",
+"jG c #262626",
+"h8 c #26333d",
+"hb c #263440",
+"gs c #263443",
+"cr c #263b51",
+"cW c #272727",
+"aC c #27313b",
+"a9 c #27313c",
+"fk c #273748",
+"eR c #27384b",
+"cq c #273d55",
+"jV c #282828",
+"#5 c #28313b",
+"b0 c #2877ce",
+"gL c #292929",
+"#Y c #29323c",
+"hu c #293744",
+"fK c #293a4d",
+"jP c #2a2a2a",
+"#w c #2a323b",
+"bg c #2a3540",
+"dF c #2a3f55",
+"jn c #2b2b2b",
+"a6 c #2b3641",
+"jY c #2c2c2c",
+"h5 c #2c3b47",
+"hp c #2c3c4a",
+"gp c #2c3c4d",
+"cx c #2c445e",
+"bU c #2d2d2d",
+"h# c #2d3e4c",
+"dS c #2d435b",
+"e5 c #2e2e2e",
+"cG c #2e4762",
+"jF c #2f2f2f",
+"aG c #2f3b48",
+"gU c #2f3f4e",
+"ck c #2f4966",
+"j0 c #303030",
+"a0 c #303d4a",
+"he c #304251",
+"cQ c #307ace",
+"e4 c #313131",
+"ew c #31465d",
+"dW c #314862",
+"ce c #314b68",
+"jm c #323232",
+"bm c #323f4d",
+"k. c #333333",
+"e3 c #343434",
+"hi c #344757",
+"eT c #344b64",
+"b8 c #34506f",
+"dj c #347fd1",
+"bX c #353535",
+"f9 c #35485c",
+"ac c #363636",
+"#V c #36434f",
+"fv c #364c64",
+"dV c #36506d",
+"c2 c #373737",
+"ev c #37506a",
+"bI c #383838",
+"bw c #384655",
+"h4 c #384b5a",
+"hk c #384c5d",
+"ea c #393939",
+"bh c #394857",
+"gX c #394d5f",
+"#e c #3981d2",
+"e6 c #3a3a3a",
+"eS c #3a546f",
+"em c #3a81d2",
+"#F c #3b3b3b",
+"eQ c #3b5571",
+"dT c #3b5776",
+"cI c #3b5c7f",
+"gJ c #3c3c3c",
+"hX c #3c5060",
+"fi c #3c546f",
+"gG c #3d3d3d",
+"jv c #3e3e3e",
+"az c #3e4e5e",
+"fL c #3e5772",
+"bK c #3f3f3f",
+"gD c #3f576f",
+"fJ c #3f5874",
+"d2 c #3f86d5",
+"jx c #404040",
+"#8 c #404e5d",
+"bv c #405161",
+"cf c #406389",
+"jL c #414141",
+"iG c #415561",
+"im c #415663",
+"gz c #415971",
+"et c #415d7c",
+"cz c #41658c",
+"f# c #418ad7",
+"jT c #424242",
+"gy c #425b74",
+"fs c #425d7a",
+"#K c #4288d4",
+"jQ c #434343",
+"eX c #438cda",
+"j8 c #444444",
+".L c #44449a",
+"eZ c #454545",
+"#s c #455362",
+"fx c #45617f",
+"cK c #456b94",
+"aP c #458cd5",
+"ab c #464646",
+".n c #46469f",
+"aH c #46586a",
+"gV c #465f74",
+"d0 c #46678c",
+"c9 c #474747",
+"aF c #47596c",
+"a3 c #475a6d",
+"ex c #476687",
+"jU c #484848",
+"by c #485b6e",
+"gq c #48627d",
+"dI c #486b91",
+"cC c #48709b",
+"js c #494949",
+"#2 c #495a6b",
+"ih c #49606f",
+"hm c #49637a",
+"gk c #49647f",
+"j7 c #4a4a4a",
+"dt c #4a6e94",
+"ak c #4a8dd7",
+"b1 c #4a90db",
+"c1 c #4b4b4b",
+"bx c #4b5f72",
+"fr c #4b698a",
+"dG c #4b6e95",
+"co c #4b75a2",
+"fW c #4b91db",
+"bD c #4c4c4c",
+"hc c #4c687f",
+"j6 c #4d4d4d",
+"#Q c #4d5f71",
+"ik c #4d6676",
+"hH c #4e4e4e",
+"#0 c #4e5f72",
+"aD c #4e6277",
+"b. c #4e6377",
+"gN c #4e91dc",
+"c0 c #4f4f4f",
+"bj c #4f6378",
+"dZ c #4f759e",
+"cD c #4f7aa9",
+"hN c #4f8dcd",
+"kd c #505050",
+"#S c #506275",
+"#6 c #506376",
+"ge c #506e8c",
+"af c #515151",
+"b# c #51667b",
+"dk c #5195df",
+"cT c #525252",
+".c c #525280",
+"bq c #52677d",
+"iH c #526b79",
+"fj c #527397",
+"eW c #52769d",
+"dy c #527aa5",
+"hJ c #535353",
+"#x c #536476",
+"eG c #53789f",
+"jM c #545454",
+"#r c #546577",
+"bz c #546a80",
+"dM c #547ca8",
+"fP c #5499e2",
+"jp c #555555",
+"iK c #556f7e",
+"bM c #565656",
+"fB c #56799f",
+"dC c #567fab",
+"gE c #569be2",
+"cU c #575757",
+"h7 c #57748b",
+"gc c #577797",
+"fN c #577ba1",
+"dx c #5780ad",
+"cg c #5787bb",
+"i4 c #585858",
+"iF c #587483",
+"hy c #587792",
+"g2 c #587893",
+"fy c #587ca3",
+"eA c #587ea7",
+"jW c #595959",
+"bu c #597087",
+"ia c #5984b2",
+"ae c #5a5a5a",
+"#t c #5a6c7f",
+"bd c #5a7189",
+"ij c #5a7789",
+"eI c #5a81ab",
+"bR c #5b5b5b",
+"ch c #5b8dc3",
+"en c #5b9be1",
+"ke c #5c5c5c",
+"cP c #5c8fc5",
+"j5 c #5d5d5d",
+"iN c #5d7fa0",
+"gl c #5d80a3",
+"fp c #5d83ac",
+"cl c #5d8fc6",
+"b2 c #5d9de6",
+"c8 c #5e5e5e",
+"hh c #5e7f9c",
+"hn c #5e809d",
+"i3 c #5f5f5f",
+"#1 c #5f758c",
+"a8 c #5f7890",
+"g7 c #5f819e",
+"cJ c #5f93cc",
+"jz c #606060",
+"ct c #6094cd",
+"bO c #616161",
+"eN c #618cb9",
+"jH c #626262",
+"iW c #627c8d",
+"hd c #6285a3",
+"ey c #628dbb",
+"dO c #6290c4",
+"ca c #6297d1",
+"jI c #636363",
+"eM c #638fbd",
+"jN c #646464",
+"fH c #648db9",
+"eE c #648fbe",
+"cb c #649ad5",
+"hA c #64a8e2",
+"jw c #656565",
+"#k c #65798f",
+"fF c #658eba",
+"fA c #658fbb",
+"fa c #65a4e7",
+"b3 c #65a6e8",
+"jX c #666666",
+"hW c #6688a3",
+"gh c #668cb2",
+"aI c #6696cb",
+"dN c #6697cc",
+"bA c #6699ce",
+"cu c #669edb",
+"#C c #676767",
+"f3 c #678db4",
+"dl c #67a6eb",
+"kc c #686868",
+"cS c #696969",
+"dK c #699bd2",
+"cN c #69a2e0",
+"cy c #69a3e1",
+"fX c #69a6e8",
+"jD c #6a6a6a",
+"av c #6a84a1",
+"ds c #6a9cd3",
+"dL c #6a9cd4",
+"jt c #6b6b6b",
+"fo c #6b97c6",
+"cE c #6ba5e4",
+"jS c #6c6c6c",
+"aV c #6c88a4",
+"ir c #6c8ea4",
+"il c #6c8fa5",
+"eD c #6c9bce",
+"dB c #6c9ed7",
+"dq c #6c9fd8",
+"cM c #6ca7e7",
+"cp c #6ca8e8",
+"eo c #6cabed",
+"i2 c #6d6d6d",
+"#T c #6d869f",
+"#W c #6d87a0",
+"gY c #6d94b5",
+"aa c #6d9bcb",
+"eB c #6d9dd0",
+"dw c #6da0d9",
+"dD c #6da1da",
+"b4 c #6dacee",
+"h9 c #6dafe2",
+"i6 c #6e6e6e",
+"bt c #6e8aa7",
+"fM c #6e9bcb",
+"dP c #6ea3dc",
+"b5 c #6eabee",
+"jd c #707070",
+"ix c #7088a2",
+"hx c #7098ba",
+"f7 c #7099c3",
+"dv c #70a5df",
+"b6 c #70adef",
+"iy c #70aff1",
+"dm c #70aff2",
+"jE c #717171",
+"#m c #7188a0",
+"#u c #7189a1",
+"aY c #718eac",
+"gO c #71aced",
+"jq c #727272",
+"gb c #729cc6",
+"hO c #72afee",
+"ib c #72afef",
+"e7 c #737373",
+"#y c #738ba4",
+"#A c #739eca",
+".j c #747474",
+"#9 c #748fab",
+"hs c #749ec1",
+"f6 c #749fca",
+".i c #757575",
+"#q c #758da6",
+"a5 c #7593b1",
+"bo c #7594b2",
+"ii c #759bb3",
+"fb c #75b3f4",
+"ep c #75b4f3",
+"is c #75b8e2",
+"ag c #767676",
+"fz c #76a6da",
+"ez c #76a9e0",
+"dX c #76adeb",
+".h c #777777",
+".m c #777794",
+"iX c #77a6b3",
+"dn c #77b1f4",
+"gK c #787878",
+"#4 c #7894b0",
+"fG c #78a9dd",
+"j# c #797979",
+"bV c #7a7a7a",
+"do c #7ab4f4",
+"jA c #7b7b7b",
+"io c #7ba3bc",
+"dp c #7bb5f5",
+".k c #7c7c7c",
+"bc c #7c9cbd",
+"gi c #7caad8",
+"aQ c #7cb0e7",
+"fY c #7cb8f9",
+"iM c #7cbee2",
+"j1 c #7d7d7d",
+"aX c #7d9ebf",
+"fm c #7db0e7",
+"j4 c #7e7e7e",
+".8 c #7ea5ce",
+"#D c #7f7f7f",
+"hv c #7facd3",
+"gn c #7faedd",
+"eb c #808080",
+"er c #80bdf9",
+"j3 c #818181",
+"hz c #81afd6",
+"gu c #81b0e0",
+"eq c #81bbf9",
+"fc c #81bbfc",
+"#b c #828282",
+"iE c #82aac0",
+"i5 c #838383",
+"ha c #83b1d9",
+"es c #83bcf9",
+"ad c #848484",
+"go c #84b5e6",
+".v c #858585",
+"#p c #85a0bc",
+"bN c #868686",
+"hZ c #86b3d6",
+"fD c #86bcf6",
+"fO c #86bcf7",
+"gP c #86c1ff",
+"di c #878787",
+"ft c #87bdf8",
+"bH c #888888",
+"iT c #88cfe2",
+"jZ c #898989",
+"#z c #89a5c3",
+"g. c #89bbee",
+"fg c #89c0fc",
+"fd c #89c2fd",
+"hP c #89c3ff",
+"jb c #8a8a8a",
+"#o c #8aa6c4",
+"jc c #8b8b8b",
+".S c #8baccf",
+"iI c #8bb6ce",
+"al c #8bb9e8",
+"hj c #8bbde7",
+"gw c #8bbef2",
+"ff c #8bc3ff",
+"fe c #8bc4ff",
+"fZ c #8bc6ff",
+"ec c #8c8c8c",
+"gv c #8cbff3",
+"jO c #8d8d8d",
+"a# c #8dadce",
+"ic c #8dc7ff",
+"#H c #8e8e8e",
+"a. c #8eaed0",
+"#L c #8ebae8",
+"hY c #8ebee3",
+"g4 c #8ec1ec",
+"iO c #8ecbff",
+"ju c #8f8f8f",
+"bi c #8fb5da",
+"h6 c #8fc0e5",
+"f5 c #8fc4f9",
+"jf c #909090",
+"bl c #90b6dc",
+"i1 c #90dfe2",
+"bC c #919191",
+"aB c #91b5dc",
+"aZ c #91b7dd",
+"hV c #91c2e8",
+"gf c #91c6fc",
+"gg c #91c7fd",
+"f0 c #91c8ff",
+"i7 c #929292",
+"gA c #92c8fe",
+"iz c #92ccff",
+"iU c #939393",
+"a7 c #93b9e0",
+"f2 c #93c9ff",
+"gQ c #93ccff",
+"e8 c #949494",
+".y c #9494b0",
+"h1 c #94c6ec",
+"f1 c #94caff",
+"j9 c #959595",
+"#X c #95b7da",
+"cX c #969696",
+"ay c #96bbe3",
+"#f c #96bde8",
+"aR c #96c3ee",
+"gR c #96cfff",
+".J c #979797",
+"hQ c #97cfff",
+"fT c #989898",
+"#j c #98b6d7",
+"#l c #98b7d8",
+"iJ c #98c7e1",
+"g6 c #98cffd",
+"jj c #999999",
+"aS c #99c4ee",
+"h3 c #99ccf4",
+"gS c #99d0ff",
+".l c #9a9a9a",
+".b c #9a9aa4",
+"aw c #9ac1ea",
+"gT c #9ad1ff",
+"dg c #9b9b9b",
+".N c #9bbee8",
+"aq c #9bc1eb",
+"am c #9bc4ee",
+"eg c #9c9c9c",
+"au c #9cc3ed",
+"ao c #9cc5ee",
+"c5 c #9d9d9d",
+"aT c #9dc7ef",
+"hU c #9dd2fb",
+"hR c #9dd3ff",
+"dh c #9e9e9e",
+"#v c #9ebee0",
+".Z c #9ec3e8",
+"#M c #9ec3ed",
+"#N c #9ec5ed",
+"ap c #9ec5ef",
+"aU c #9ec7f0",
+"h2 c #9ed4fd",
+"id c #9ed6ff",
+"df c #9f9f9f",
+"an c #9fc5ee",
+"h0 c #9fd5fe",
+"aM c #a0a0a0",
+"hT c #a0d6ff",
+"jh c #a1a1a1",
+"hS c #a1d7ff",
+"ji c #a2a2a2",
+"#P c #a2c7ed",
+"i8 c #a3a3a3",
+"#O c #a3c8ed",
+"iA c #a3daff",
+"j. c #a4a4a4",
+"je c #a5a5a5",
+"#g c #a5c8ed",
+"ip c #a5dafb",
+"iv c #a6a6a6",
+".F c #a6bed4",
+"de c #a7a7a7",
+"#h c #a7c9ed",
+"if c #a7ddff",
+"ie c #a7deff",
+"eh c #a8a8a8",
+"#i c #a8caee",
+"iL c #a8dbf8",
+"ig c #a8deff",
+"iP c #a8e0ff",
+"iY c #a8e2e6",
+"hC c #a9a9a9",
+".0 c #a9caed",
+"#B c #aaaaaa",
+"fU c #ababab",
+".5 c #abc9e9",
+"iB c #abe3ff",
+"e2 c #acacac",
+".6 c #accaea",
+"jo c #adadad",
+".1 c #adcbed",
+".7 c #adccec",
+"iD c #ade2ff",
+"iC c #ade3ff",
+"fS c #aeaeae",
+".4 c #aecded",
+"db c #afafaf",
+".A c #afbbe7",
+".2 c #afccee",
+".3 c #afceee",
+"d6 c #b0b0b0",
+"iQ c #b0e9ff",
+"bG c #b1b1b1",
+"jg c #b2b2b2",
+"#E c #b3b3b3",
+".O c #b3d1ed",
+"gF c #b4b4b4",
+"cY c #b5b5b5",
+"iR c #b5ebff",
+"hM c #b6b6b6",
+"iS c #b6ecff",
+"d9 c #b7b7b7",
+".U c #b8b8b8",
+".u c #b9b9b9",
+"dd c #bababa",
+".P c #bad4ee",
+"bL c #bbbbbb",
+".Q c #bbd4ef",
+".R c #bbd5f0",
+"e9 c #bcbcbc",
+"c3 c #bdbdbd",
+"f. c #bebebe",
+"d8 c #bfbfbf",
+".o c #bfc2e8",
+"iZ c #bffdff",
+"iw c #c0c0c0",
+"iV c #c1c1c1",
+"i0 c #c1feff",
+"ei c #c2c2c2",
+"ej c #c3c3c3",
+"#a c #c4c4c4",
+"el c #c5c5c5",
+"d7 c #c6c6c6",
+".r c #c6cbda",
+"ek c #c7c7c7",
+"aN c #c8c8c8",
+"#G c #c9c9c9",
+"aL c #cacaca",
+"ai c #cbcbcb",
+".B c #cbddf2",
+"bZ c #cccccc",
+".C c #cce0f3",
+"dc c #cdcdcd",
+"ah c #cecece",
+"da c #cfcfcf",
+".E c #cfe1f3",
+".D c #cfe1f4",
+"#I c #d0d0d0",
+"cV c #d1d1d1",
+"fQ c #d2d2d2",
+"bB c #d3d3d3",
+"#c c #d4d4d4",
+"d# c #d5d5d5",
+"aK c #d6d6d6",
+"cZ c #d7d7d7",
+"c6 c #d8d8d8",
+"gH c #d9d9d9",
+".W c #dadada",
+"gM c #dbdbdb",
+"bQ c #dcdcdc",
+"e1 c #dddddd",
+"cR c #dedede",
+"d. c #dfdfdf",
+"bP c #e0e0e0",
+"i# c #e1e1e1",
+"bY c #e2e2e2",
+".K c #e3e3e3",
+"ee c #e4e4e4",
+"d3 c #e5e5e5",
+"ef c #e6e6e6",
+".p c #e6e9f6",
+"fV c #e7e7e7",
+"eY c #e8e8e8",
+".a c #e9e9e9",
+".q c #e9edf8",
+".V c #eaeaea",
+"## c #ebebeb",
+"Qt c #ececec",
+".w c #ededed",
+".x c #eeeeee",
+"#. c #efefef",
+".# c #f0f0f0",
+".9 c #f1f1f1",
+".I c #f2f2f2",
+".T c #f3f3f3",
+"ja c #f4f4f4",
+"i9 c #f5f5f5",
+"hB c #f6f6f6",
+".H c #f7f7f7",
+".G c #f8f8f8",
+"i. c #f9f9f9",
+"kg c #fafafa",
+"kf c #fbfbfb",
+".t c #fcfcfc",
+".s c #fdfdfd",
+"it c #fefefe",
+"iu c #ffffff",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt"};
diff --git a/tests/auto/gui/image/qimagereader/images/qt-gif-anim.gif b/tests/auto/gui/image/qimagereader/images/qt-gif-anim.gif
new file mode 100644
index 0000000000..8bca4a8354
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt-gif-anim.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt-gif-noanim.gif b/tests/auto/gui/image/qimagereader/images/qt-gif-noanim.gif
new file mode 100644
index 0000000000..b6a854067d
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt-gif-noanim.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt.gif b/tests/auto/gui/image/qimagereader/images/qt.gif
new file mode 100644
index 0000000000..e0a5a80b13
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt1.gif b/tests/auto/gui/image/qimagereader/images/qt1.gif
new file mode 100644
index 0000000000..0ce910cee0
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt1.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt2.gif b/tests/auto/gui/image/qimagereader/images/qt2.gif
new file mode 100644
index 0000000000..993a315d0f
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt2.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt3.gif b/tests/auto/gui/image/qimagereader/images/qt3.gif
new file mode 100644
index 0000000000..7391678a99
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt3.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt4.gif b/tests/auto/gui/image/qimagereader/images/qt4.gif
new file mode 100644
index 0000000000..41109a9c3f
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt4.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt5.gif b/tests/auto/gui/image/qimagereader/images/qt5.gif
new file mode 100644
index 0000000000..5a3fb54ff5
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt5.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt6.gif b/tests/auto/gui/image/qimagereader/images/qt6.gif
new file mode 100644
index 0000000000..f22e7c980a
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt6.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt7.gif b/tests/auto/gui/image/qimagereader/images/qt7.gif
new file mode 100644
index 0000000000..a315671417
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt7.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qt8.gif b/tests/auto/gui/image/qimagereader/images/qt8.gif
new file mode 100644
index 0000000000..2a7d09e859
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qt8.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/qtbug13653-no_eoi.jpg b/tests/auto/gui/image/qimagereader/images/qtbug13653-no_eoi.jpg
new file mode 100644
index 0000000000..605e8a85da
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/qtbug13653-no_eoi.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/rect.svg b/tests/auto/gui/image/qimagereader/images/rect.svg
new file mode 100644
index 0000000000..c56549a69a
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/rect.svg
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="128"
+ height="128"
+ viewBox="0 0 105.427 137.439"
+ id="Livello_1"
+ xml:space="preserve"
+ style="overflow:visible"><defs
+ id="defs2727"><linearGradient
+ x1="26.294399"
+ y1="11.6704"
+ x2="71.901901"
+ y2="133.0273"
+ id="linearGradient3352"
+ xlink:href="#XMLID_34_"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ x1="36.838902"
+ y1="7.7075"
+ x2="82.446297"
+ y2="129.0645"
+ id="linearGradient3354"
+ xlink:href="#XMLID_34_"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ x1="33.882301"
+ y1="23.583"
+ x2="39.972198"
+ y2="23.583"
+ id="XMLID_34_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2672"
+ style="stop-color:#ff5d5d;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2674"
+ style="stop-color:#e20800;stop-opacity:1"
+ offset="1" />
+ </linearGradient><linearGradient
+ x1="33.882301"
+ y1="23.583"
+ x2="39.972198"
+ y2="23.583"
+ id="linearGradient3368"
+ xlink:href="#XMLID_34_"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ x1="54.356899"
+ y1="1.124"
+ x2="99.964401"
+ y2="122.481"
+ id="linearGradient3370"
+ xlink:href="#XMLID_34_"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ x1="15.8457"
+ y1="15.5972"
+ x2="61.453098"
+ y2="136.9541"
+ id="linearGradient3376"
+ xlink:href="#XMLID_34_"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ x1="43.438"
+ y1="5.2275"
+ x2="89.045403"
+ y2="126.5845"
+ id="linearGradient3382"
+ xlink:href="#XMLID_34_"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ x1="8.1176996"
+ y1="14.9019"
+ x2="70.759598"
+ y2="117.2331"
+ id="linearGradient3792"
+ xlink:href="#XMLID_30_"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9991,-4.18e-2,4.18e-2,0.9991,-2.4309,1.195)" /><linearGradient
+ x1="10.5708"
+ y1="10.1548"
+ x2="73.2117"
+ y2="112.4844"
+ id="linearGradient3794"
+ xlink:href="#XMLID_30_"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ x1="6.2178001"
+ y1="72.223602"
+ x2="79.360802"
+ y2="72.223602"
+ id="XMLID_26_"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,2.1512354)">
+ <stop
+ id="stop2578"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2580"
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="1" />
+ </linearGradient><filter
+ id="filter5869"><feGaussianBlur
+ id="feGaussianBlur5871"
+ stdDeviation="1.2254964"
+ inkscape:collect="always" /></filter><filter
+ id="filter5873"><feGaussianBlur
+ id="feGaussianBlur5875"
+ stdDeviation="1.3615922"
+ inkscape:collect="always" /></filter><filter
+ id="filter2854"><feGaussianBlur
+ id="feGaussianBlur2856"
+ stdDeviation="0.8944793"
+ inkscape:collect="always" /></filter></defs>
+<filter
+ id="AI_Sfocatura_1">
+ <feGaussianBlur
+ id="feGaussianBlur2545"
+ stdDeviation="1" />
+</filter>
+<g
+ transform="translate(-3.2052027,3.2058836)"
+ id="g2547">
+ <g
+ transform="matrix(0.9982563,0,0,0.9982563,-1.5492234e-2,0.2232388)"
+ id="g2549">
+ <g
+ id="g2551">
+ <linearGradient
+ x1="6.2178001"
+ y1="68.029297"
+ x2="79.360802"
+ y2="68.029297"
+ id="XMLID_24_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2554"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2556"
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 9.542,121.224 C 7.713,121.224 6.217,119.728 6.217,117.9 L 6.217,18.16 C 6.217,16.331 7.713,14.835 9.542,14.835 L 76.036,14.835 C 77.864,14.835 79.36,16.331 79.36,18.16 L 79.36,117.9 C 79.36,119.728 77.864,121.224 76.036,121.224 L 9.542,121.224 z"
+ id="path2558"
+ style="fill:url(#XMLID_24_)" />
+ </g>
+ <g
+ id="g2560">
+ <linearGradient
+ x1="10.5718"
+ y1="15.3989"
+ x2="73.212097"
+ y2="117.7277"
+ id="XMLID_25_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2563"
+ style="stop-color:#77b753;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2565"
+ style="stop-color:#00892c;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 11.204,18.159 C 10.29,18.159 9.542,18.907 9.542,19.821 L 9.542,116.237 C 9.542,117.151 10.29,117.899 11.204,117.899 L 74.375,117.899 C 75.289,117.899 76.037,117.151 76.037,116.237 L 76.037,19.821 C 76.037,18.907 75.289,18.159 74.375,18.159 L 11.204,18.159 z"
+ id="path2567"
+ style="fill:url(#XMLID_25_)" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.9982563,0,0,0.9982563,1.05825,0.2232388)"
+ id="g2569">
+ <path
+ d="M 11.639,126.468 C 9.811,126.468 8.314,124.972 8.314,123.143 L 8.314,23.403 C 8.314,21.574 9.811,20.078 11.639,20.078 L 78.134,20.078 C 79.962,20.078 81.458,21.574 81.458,23.403 L 81.458,123.143 C 81.458,124.972 79.962,126.468 78.134,126.468 L 23.696022,126.468 L 11.639,126.468 z"
+ transform="matrix(1.041449,0,0,1,-4.451967,3.1512354)"
+ id="path2575"
+ style="opacity:0.6;filter:url(#filter2854)" /><path
+ d="M 9.542,127.56924 C 7.714,127.56924 6.218,126.07324 6.218,124.24624 L 6.218,24.505236 C 6.218,22.677236 7.714,21.181236 9.542,21.181236 L 76.037,21.181236 C 77.865,21.181236 79.361,22.677236 79.361,24.505236 L 79.361,124.24624 C 79.361,126.07324 77.865,127.56924 76.037,127.56924 L 9.542,127.56924 z"
+ id="path2582"
+ style="fill:url(#XMLID_26_)" />
+ <g
+ transform="translate(0,2.1512354)"
+ id="g2584">
+ <g
+ transform="matrix(1.0276326,0,0,1,-2.2508995,0)"
+ id="g2586"
+ style="opacity:0.5;filter:url(#AI_Sfocatura_1)">
+ <path
+ d="M 11.639,123.321 C 9.811,123.321 8.314,121.824 8.314,119.997 L 81.458,119.997 C 81.458,121.824 79.962,123.321 78.134,123.321 L 11.639,123.321 z"
+ id="path2588" />
+ </g>
+ <linearGradient
+ x1="6.2178001"
+ y1="69.078102"
+ x2="79.360802"
+ y2="69.078102"
+ id="XMLID_27_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2591"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2593"
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 9.542,122.272 C 7.714,122.272 6.218,120.776 6.218,118.947 L 6.218,19.207 C 6.218,17.378 7.714,15.882 9.542,15.882 L 76.037,15.882 C 77.865,15.882 79.361,17.378 79.361,19.207 L 79.361,118.947 C 79.361,120.776 77.865,122.272 76.037,122.272 L 9.542,122.272 z"
+ id="path2595"
+ style="fill:url(#XMLID_27_)" />
+ </g>
+ <g
+ transform="translate(0,3.2268531)"
+ id="g2597">
+ <g
+ transform="matrix(1.0368435,0,0,1,-3.0011994,-1.0756177)"
+ id="g2599"
+ style="opacity:0.5;filter:url(#AI_Sfocatura_1)">
+ <path
+ d="M 11.639,120.175 C 9.811,120.175 8.314,118.679 8.314,116.85 L 81.458,116.85 C 81.458,118.679 79.962,120.175 78.134,120.175 L 11.639,120.175 z"
+ id="path2601" />
+ </g>
+ <linearGradient
+ x1="6.2178001"
+ y1="65.931602"
+ x2="79.360802"
+ y2="65.931602"
+ id="XMLID_28_"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-1.0756177)">
+ <stop
+ id="stop2604"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2606"
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 9.542,118.05038 C 7.714,118.05038 6.218,116.55438 6.218,114.72638 L 6.218,14.986382 C 6.218,13.157382 7.714,11.661382 9.542,11.661382 L 76.037,11.661382 C 77.865,11.661382 79.361,13.157382 79.361,14.986382 L 79.361,114.72638 C 79.361,116.55438 77.865,118.05038 76.037,118.05038 L 9.542,118.05038 z"
+ id="path2608"
+ style="fill:url(#XMLID_28_)" />
+ </g>
+ <g
+ transform="translate(0,1.8317954)"
+ id="g2610">
+ <g
+ transform="matrix(1.0184218,0,0,1.0158314,-1.4821779,-1.8527316)"
+ id="g2612"
+ style="opacity:0.5;filter:url(#AI_Sfocatura_1)">
+ <path
+ d="M 10.639,117.029 C 8.811,117.029 7.314,115.532 7.314,113.704 L 7.314,13.964 C 7.314,12.135 8.811,10.639 10.639,10.639 L 77.134,10.639 C 78.962,10.639 80.458,12.135 80.458,13.964 L 80.458,113.704 C 80.458,115.532 78.962,117.029 77.134,117.029 L 10.639,117.029 z"
+ id="path2614" />
+ </g>
+ <linearGradient
+ x1="6.2178001"
+ y1="62.785599"
+ x2="79.360802"
+ y2="62.785599"
+ id="XMLID_29_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2617"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2619"
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 9.542,115.98 C 7.714,115.98 6.218,114.483 6.218,112.656 L 6.218,12.916 C 6.218,11.087 7.714,9.591 9.542,9.591 L 76.037,9.591 C 77.865,9.591 79.361,11.087 79.361,12.916 L 79.361,112.657 C 79.361,114.484 77.865,115.981 76.037,115.981 L 9.542,115.981 L 9.542,115.98 z"
+ id="path2621"
+ style="fill:url(#XMLID_29_)" />
+ <linearGradient
+ x1="10.5708"
+ y1="10.1548"
+ x2="73.2117"
+ y2="112.4844"
+ id="XMLID_30_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2624"
+ style="stop-color:#73bdf2;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2626"
+ style="stop-color:#3592ee;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 11.204,12.916 C 10.289,12.916 9.541,13.664 9.541,14.578 L 9.541,110.994 C 9.541,111.909 10.289,112.657 11.204,112.657 L 74.373,112.657 C 75.288,112.657 76.036,111.909 76.036,110.994 L 76.036,14.578 C 76.036,13.664 75.288,12.916 74.373,12.916 L 11.204,12.916 L 11.204,12.916 z"
+ id="path2628"
+ style="fill:url(#linearGradient3794)" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.9961334,-6.5068755e-2,6.5068755e-2,0.9961334,-5.7493275,-6.3015051)"
+ id="g2630">
+ <g
+ transform="matrix(1.0311837,0,0,1.0154411,-2.8218065,-1.9088007)"
+ id="g2632"
+ style="opacity:0.6;filter:url(#filter5869)">
+ <path
+ d="M 10.744,123.615 C 8.917,123.691 7.36,122.259 7.283,120.432 L 3.118,20.779 C 3.042,18.952 4.474,17.395 6.301,17.319 L 72.737,14.542 C 74.563,14.465 76.121,15.898 76.198,17.725 L 80.363,117.377 C 80.439,119.204 79.007,120.761 77.181,120.839 L 10.744,123.615 z"
+ id="path2634" />
+ </g>
+ <g
+ id="g2636">
+
+ <linearGradient
+ x1="3.7607"
+ y1="67.532204"
+ x2="76.909698"
+ y2="67.532204"
+ id="XMLID_31_"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9991,-4.18e-2,4.18e-2,0.9991,-2.4309,1.195)">
+ <stop
+ id="stop2639"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2641"
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 9.695,121.518 C 7.868,121.595 6.311,120.163 6.234,118.335 L 2.069,18.682 C 1.993,16.855 3.425,15.298 5.252,15.222 L 71.688,12.444 C 73.514,12.368 75.072,13.8 75.149,15.627 L 79.314,115.28 C 79.391,117.106 77.959,118.663 76.131,118.741 L 9.695,121.518 z"
+ id="path2643"
+ style="fill:url(#XMLID_31_)" />
+ </g>
+ <path
+ d="M 7.051,18.474 C 6.138,18.513 5.422,19.291 5.46,20.204 L 9.486,116.535 C 9.525,117.448 10.303,118.164 11.217,118.126 L 74.331,115.489 C 75.244,115.451 75.96,114.672 75.922,113.759 L 71.897,17.427 C 71.859,16.513 71.08,15.797 70.167,15.836 L 7.051,18.474 z"
+ id="path2652"
+ style="fill:url(#linearGradient3792);fill-opacity:1" />
+ <path
+ d="M 9.5625,22.375 C 10.84375,52.927083 12.125,83.479167 13.40625,114.03125 C 32.885417,113.21875 52.364583,112.40625 71.84375,111.59375 C 70.5625,81.041667 69.28125,50.489583 68,19.9375 C 48.520833,20.75 29.041667,21.5625 9.5625,22.375 z"
+ id="path4189"
+ style="opacity:0.6;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:1.00000001, 1.00000001;stroke-dashoffset:0;stroke-opacity:1" /></g>
+ <g
+ transform="matrix(0.9982563,0,0,0.9982563,10.72193,-5.1454722)"
+ id="g2654">
+ <g
+ transform="translate(-4.2156998e-8,1.0756177)"
+ id="g2656"
+ style="opacity:0.6;filter:url(#filter5873)">
+ <path
+ d="M 10.854785,112.52047 C 9.0174891,112.09656 7.8676311,110.2731 8.2990859,108.46891 L 31.839177,9.9940152 C 32.271664,8.1888112 34.127539,7.0580233 35.964835,7.481942 L 102.78149,22.901224 C 104.61776,23.325142 105.76865,25.149615 105.33616,26.954819 L 81.79607,125.42768 C 81.364615,127.23289 79.507708,128.36368 77.671444,127.93976 L 10.854785,112.52047 z"
+ id="path2658" />
+ </g>
+ <g
+ id="g2660">
+
+ <linearGradient
+ x1="16.688499"
+ y1="-8.9546003"
+ x2="94.108398"
+ y2="105.6356"
+ id="XMLID_33_"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9735,0.2287,-0.2287,0.9735,14.4454,7.996)">
+ <stop
+ id="stop2663"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2665"
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 12.707,111.688 C 10.927,111.271 9.813,109.472 10.231,107.692 L 33.037,10.593 C 33.455,8.813 35.254,7.698 37.034,8.116 L 101.767,23.32 C 103.546,23.738 104.661,25.537 104.243,27.317 L 81.436,124.415 C 81.019,126.195 79.219,127.31 77.44,126.892 L 12.707,111.688 z"
+ id="path2667"
+ style="fill:url(#XMLID_33_)" />
+ </g>
+ <path
+ d="M 33.925,25.17 L 35.435,25.3 C 35.369,25.76 35.413,26.134 35.567,26.422 C 35.721,26.71 35.941,26.887 36.226,26.954 C 36.538,27.027 36.832,26.947 37.114,26.715 C 37.396,26.483 37.594,26.116 37.712,25.615 C 37.821,25.149 37.805,24.759 37.661,24.445 C 37.517,24.132 37.298,23.939 37.004,23.87 C 36.811,23.825 36.571,23.817 36.281,23.846 L 36.797,22.386 C 37.187,22.487 37.522,22.455 37.801,22.292 C 38.076,22.127 38.26,21.847 38.353,21.451 C 38.431,21.12 38.41,20.843 38.291,20.618 C 38.172,20.392 37.984,20.25 37.729,20.19 C 37.473,20.13 37.226,20.187 36.987,20.358 C 36.749,20.531 36.562,20.825 36.427,21.24 L 35.104,20.624 C 35.455,19.78 35.886,19.208 36.401,18.909 C 36.915,18.61 37.492,18.536 38.131,18.686 C 38.85,18.855 39.36,19.244 39.663,19.853 C 39.967,20.462 40.045,21.076 39.9,21.695 C 39.802,22.113 39.618,22.468 39.35,22.758 C 39.081,23.049 38.726,23.276 38.287,23.439 C 38.699,23.661 38.996,24.004 39.18,24.471 C 39.362,24.937 39.383,25.471 39.242,26.073 C 39.036,26.949 38.604,27.613 37.948,28.064 C 37.29,28.515 36.601,28.655 35.88,28.486 C 35.189,28.323 34.661,27.944 34.297,27.347 C 33.931,26.751 33.808,26.025 33.925,25.17 z"
+ id="path2676"
+ style="fill:url(#linearGradient3368);fill-opacity:1" />
+ <linearGradient
+ x1="26.294399"
+ y1="11.6704"
+ x2="71.901901"
+ y2="133.0273"
+ id="XMLID_35_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2679"
+ style="stop-color:#ff8080;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2681"
+ style="stop-color:#e20800;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 32.977,38.964 C 33.619,37.58 34.903,36.55 35.811,35.945 C 36.752,35.319 37.49,34.55 37.729,33.53 C 38.094,31.979 36.471,30.257 34.621,31.997 C 33.74,29.616 31.507,30.433 31.143,31.984 C 30.903,33.003 31.223,34.019 31.786,35 C 32.329,35.946 33.021,37.439 32.977,38.964 z"
+ id="path2683"
+ style="fill:url(#linearGradient3352);fill-opacity:1" />
+ <path
+ d="M 80.223,109.559 L 78.711,109.43 C 78.779,108.969 78.734,108.595 78.58,108.308 C 78.426,108.02 78.205,107.842 77.922,107.776 C 77.61,107.703 77.315,107.782 77.033,108.014 C 76.751,108.246 76.553,108.614 76.433,109.114 C 76.324,109.581 76.341,109.97 76.484,110.284 C 76.629,110.598 76.849,110.79 77.142,110.859 C 77.335,110.904 77.576,110.913 77.865,110.883 L 77.349,112.343 C 76.958,112.242 76.624,112.274 76.345,112.439 C 76.07,112.603 75.886,112.883 75.792,113.279 C 75.714,113.609 75.735,113.887 75.854,114.112 C 75.973,114.339 76.161,114.481 76.416,114.541 C 76.672,114.602 76.918,114.545 77.156,114.372 C 77.394,114.2 77.582,113.906 77.717,113.49 L 79.039,114.106 C 78.689,114.95 78.258,115.521 77.742,115.82 C 77.228,116.119 76.652,116.193 76.013,116.043 C 75.294,115.874 74.783,115.486 74.48,114.876 C 74.175,114.268 74.097,113.653 74.244,113.034 C 74.342,112.616 74.525,112.262 74.795,111.971 C 75.063,111.681 75.418,111.453 75.857,111.289 C 75.445,111.069 75.146,110.725 74.964,110.259 C 74.78,109.793 74.761,109.259 74.902,108.657 C 75.109,107.78 75.541,107.117 76.197,106.666 C 76.855,106.216 77.543,106.075 78.265,106.244 C 78.956,106.406 79.484,106.786 79.849,107.382 C 80.217,107.978 80.34,108.704 80.223,109.559 z"
+ id="path2694"
+ style="fill:#e20800;fill-opacity:1" /><path
+ d="M 81.063,95.83 C 80.422,97.214 79.138,98.244 78.23,98.85 C 77.29,99.477 76.55,100.246 76.311,101.264 C 75.947,102.815 77.57,104.536 79.419,102.797 C 80.301,105.178 82.533,104.361 82.898,102.811 C 83.138,101.791 82.819,100.776 82.255,99.795 C 81.711,98.849 81.021,97.355 81.063,95.83 z"
+ id="path2701"
+ style="fill:url(#linearGradient3382);fill-opacity:1" />
+ <linearGradient
+ x1="54.356899"
+ y1="1.124"
+ x2="99.964401"
+ y2="122.481"
+ id="XMLID_39_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2704"
+ style="stop-color:#ff8080;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2706"
+ style="stop-color:#e20800;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 63.174,42.222 C 64.361,39.656 66.742,37.748 68.427,36.625 C 70.171,35.463 71.54,34.04 71.985,32.15 C 72.66,29.274 69.651,26.081 66.22,29.307 C 64.585,24.892 60.448,26.406 59.772,29.281 C 59.329,31.172 59.921,33.055 60.965,34.873 C 61.97,36.628 63.253,39.396 63.174,42.222 z"
+ id="path2708"
+ style="fill:url(#linearGradient3370);fill-opacity:1" />
+ <linearGradient
+ x1="36.838902"
+ y1="7.7075"
+ x2="82.446297"
+ y2="129.0645"
+ id="XMLID_40_"
+ xlink:href="#XMLID_39_"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop2711"
+ style="stop-color:#ff8080;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop2713"
+ style="stop-color:#e20800;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <path
+ d="M 55.486,74.959 C 56.672,72.393 59.054,70.485 60.737,69.362 C 62.481,68.2 63.851,66.777 64.296,64.886 C 64.97,62.01 61.962,58.818 58.532,62.043 C 56.897,57.628 52.759,59.142 52.082,62.018 C 51.638,63.908 52.23,65.792 53.275,67.609 C 54.281,69.364 55.565,72.132 55.486,74.959 z"
+ id="path2715"
+ style="fill:url(#linearGradient3354);fill-opacity:1" />
+ <path
+ d="M 51.37,92.488 C 50.182,95.054 47.801,96.961 46.117,98.084 C 44.373,99.246 43.004,100.67 42.559,102.561 C 41.884,105.436 44.893,108.627 48.323,105.404 C 49.958,109.82 54.096,108.304 54.772,105.428 C 55.217,103.538 54.623,101.655 53.579,99.836 C 52.573,98.082 51.291,95.314 51.37,92.488 z"
+ id="path2724"
+ style="fill:url(#linearGradient3376);fill-opacity:1" />
+ </g>
+</g>
+</svg> \ No newline at end of file
diff --git a/tests/auto/gui/image/qimagereader/images/rect.svgz b/tests/auto/gui/image/qimagereader/images/rect.svgz
new file mode 100644
index 0000000000..c2e193b989
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/rect.svgz
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/rgba_adobedeflate_littleendian.tif b/tests/auto/gui/image/qimagereader/images/rgba_adobedeflate_littleendian.tif
new file mode 100644
index 0000000000..78868b0d48
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/rgba_adobedeflate_littleendian.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/rgba_lzw_littleendian.tif b/tests/auto/gui/image/qimagereader/images/rgba_lzw_littleendian.tif
new file mode 100644
index 0000000000..107eab74e7
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/rgba_lzw_littleendian.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/rgba_nocompression_bigendian.tif b/tests/auto/gui/image/qimagereader/images/rgba_nocompression_bigendian.tif
new file mode 100644
index 0000000000..c314bae4c0
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/rgba_nocompression_bigendian.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/rgba_nocompression_littleendian.tif b/tests/auto/gui/image/qimagereader/images/rgba_nocompression_littleendian.tif
new file mode 100644
index 0000000000..4f820f6649
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/rgba_nocompression_littleendian.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/rgba_packbits_littleendian.tif b/tests/auto/gui/image/qimagereader/images/rgba_packbits_littleendian.tif
new file mode 100644
index 0000000000..ddeec38fbc
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/rgba_packbits_littleendian.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/rgba_zipdeflate_littleendian.tif b/tests/auto/gui/image/qimagereader/images/rgba_zipdeflate_littleendian.tif
new file mode 100644
index 0000000000..50a3024246
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/rgba_zipdeflate_littleendian.tif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/runners.ppm b/tests/auto/gui/image/qimagereader/images/runners.ppm
new file mode 100644
index 0000000000..fda1c97073
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/runners.ppm
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/teapot.ppm b/tests/auto/gui/image/qimagereader/images/teapot.ppm
new file mode 100644
index 0000000000..b8ab85f3a5
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/teapot.ppm
@@ -0,0 +1,31 @@
+P6
+256 256
+255
+\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[7 eOLjQLmSMoTMnSMlRMhPL_9 \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀnSMtVMzYN~[N~[N\N\O€\O€]O€]O€]O€]O€\O€\O}[NyYNtVM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-wXN}[N€]O„^O†_O†`O‡`Oˆ`Oˆ`OˆaO‰aO‰aO‰aO‰aO‰aO‰aOˆaOˆ`O†_Oƒ^O\N \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaMLyYN…_O‰aP‹bPcPŽcPŽdPŽdPdPdPdPdPdPdPdPeP‘eP’eP’eP‘ePdPcP…_OpUM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN…_OdP“fP•gQ–hQ˜hQ˜iQ™iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœjQœjQœjQ›jQœjQ™iQ“fP‡`O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJiQL‹bP—hQkQ¡mR¤nR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦pR¨pS©qSªqS«rS¬rS«rS©qS¤oRœjQ€]O\KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀfOLrUMcPŸlR©qS¯tS²uTµwT·xT¸xT¹yTºyT»zT»zU¼zU¼zU¼zU»zUºyT¸xT¶wT¯tS¡mR‰aOhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àa0 cNLqUM€\O”fQ¦pS²wVºzV¿|VÂ}VÄVÆVÇ€VÉ‚WÌ…[Õeæ w÷³‹êª…Ĉg§qT“fQ{ZNYIK9\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀO1{G#‘JkRMqUMtVN–iS¨v\·€d¹bµzZ±vU°uT®sSªqS¤nRœjQ’eP„^OrUMHh>!T4\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-V5wE"~I#†M%U+¥e7²l:°g2®b*­a(­`(©^(¥])¡^-›]1ŠS,qC$`9 R3G-\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@)J/i>!pA"tD"wF$yH&xH&tE$wE#yG%}M+ƒT4S5mE*Z7!K/B*;'\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‰aO¦oR½{UÇ€VÏ…X<(F-a: e<!h>!j@#k@$h>"d<!c=$hD-fF2[<)K0@);'5$Ë‚VÇ€V¿|U_LKYIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À…_O·xTÉ‚Wó«€ûµ‹Ö’k¼|X×>µf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&c<!b=%jH2_A/I0!<(8&5$”J¥Y’S%8&;'?)E,<:HA=HE?IJAISFJYIKXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À£nRÁ}UܘqÊŠe±vU²e,™V&¥V†C €@ |> y< u: r9 o7 l6
+j5
+h4
+g3
+5$D,K/b; h>"wM1tK.e="a<#cA,U8&E-<(9&.!a0 b1 c1    
+
++3#@)46G<:HMCIXHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀU*´vT¿~X¸{YÃk+›W&‰N$|> u: p8 k5
+f3
+a0 _/ ]. [- I¡\*ª_(‘LkRMmSMmSMnSMnSMD,R3W5mA"|O0|P1j?"c<!a=%Y7"N1F,;'NCJNCJNDJODJODJODJh>!a: X/K%
+g3
+a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d<!yF#O+€N,rC#qB"pB#k?"a: Z7 6ODJPDJPEJQEJQEJREJREJREJRFJSFJSFJSFJSFJe<!X/
+^/ V+Q(L&I$r9  TlRMnSM46G47G47G46G46G46G46G46G36G36G25G25G15G04G/4F.3F
+
+X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?<H@<HA=HC>HG@ILBIREJ[JKcNLjQL§pR±uTºzUÃ~VÈWË‚XÖŽcäsÒŽe¼{V²vT¨pSžkR•gQŒbP†_O‚^O]O€\O€\O€\O€\O€]O]O]O]O]O]O]O]O]O]O]O€\O€\O~\N}[N|ZNxXN•T%H$
+›W&rVMvWNyYNzYN|ZN}[N}[N><H?<H?<H?<H?<H?<H@<H@<H@<HA=HA=HB=HC>HE?IG@IIAIKBIODJSFJWHK—hQŸlR§pR°b(¾i*Én+Ù|7Û|6Ïr,Íq+Êp-Ãl+»g)±b(®sS§pS lRšiQ•gQePcPŠaPˆaO‡`O‡`O†_O†_O…_O…_O…_O…_O…_O…_O…_O„_O„^O„^Oƒ^Oƒ^O‚]O]O€\O~[N{ZN•T%
+
+ 
+@%<-$G?@…pfdNLuWM\NdNL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJvWN‰aP./01„E}[N]O…_Oˆ`O‰aP‹bPŒbPcPcPŽcPdPdPdPeP‘eP’eP’eP“fP“fQ”fQ•gQ•gQ–gQ–hQ—hQ˜hQ™iQšiQ›jQœjQkQkRžlRŸlRžY&¤\'¨^'µ^½bÀcÃeÇi ÄgÀc½b¼a¹`µ^´]¯X¢[' Z'žY&¢mR¡mR¡mR lRŸlRŸlRžkRkQœkQœjQ›jQšjQšiQ™iQ™iQ˜iQ˜hQ—hQ—hQ—hQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘ePdPcP‰aP—O
+ B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6
+ 
+$5 ¬`(¶e)£nRœjQƒ^OJAI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXIK^KKdNLhPLuWM‚]OŒbP”fQeP m6
+†`OŽcP“fQ—hQ˜hQ™iQšiQšjQ›jQ›jQ›jQœjQœjQœjQœkQkQkQkRžkRžkRžkRžlRŸlRŸlRŸlR lR lR lR¡mR¡mR¡mR¡mRºg)³c(²c(±b(­V¿cÂeÅi!Åi!Àd¼bº`¹`·_·_¶^¢Q§]'ª_(­`(¹f)£nR£nR£nR£nR£nR£nR£nR¢nR¢nR¢nR¢nR¢nR¢nR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR¢mR¢mR£nR¢mR¢mR¡mR mRkR—hQˆGa0 ŠbP mRœjQ“fQ‰aP}[NrUMmSM…L$\À\À\À\À\À\À\À\À B B #C, 8&H.Z7 §pR›jQ{ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJ[JK`LKdNLhQLqUM{ZN…_OŽcP–gQ—hQ
+‹bP‘eP–hQšiQ›jQœjQkQkQkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlR lR lR lR mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢nR£nRÀj*ºg)·e)¶d)Âd°XÅgÅhÂe¿c½b½b¾bªU­`(®a(¯a(³c(¾i*¤oR¤oR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¥oR¥oR¤nR¡mR›jQŽQ%Z- œjQ£nRŸlR—hQŽdP…_OuWMpTMnSMkRLa: \À\À\À\À\À\À\À B B&D2 @*S6#G@IPDJ˜hQmSM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ]KKbMLeOLiQLlRMvWN\OˆaO‘eP—hQœjQ•gQ
+!C+E'0F.4F7%8%U/lG.SFJZIK]KKZIKB=H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀREJZJK`LKdNLgPLjQLlRMnSMpTMqUMtWMxXN{ZN~[N]O„^O†`O‰aO‹bPdP•gQ™iQœkQ lR¤nR§pSªrS­sS¯tT²uT´vT¶wT·xT¹yT¹yTºyTºyT¹yT¶xT´vT¬rS¢nR—hQ¿|U¿|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ}UÀ}UÁ}UÁ}UÁ}UÁ}UÂ}UÂ~UÃ~UÃ~VÃ~VÄVÅ€WÆX®a(ŸlRªrS´vT¸yT¼zU¾|UÁ~VÃXÆ‚[Ɇ_΋dÓ‘jÔ“mÔ“nБlÊŒhĆd½_¶{[°vWªsU¦pS¢nRžkRšiQ˜hQ•gQ“fQ‘ePdPŒbP‰aO†_Oƒ^O€\O|ZNxXNsVMpTMnTMmSMjQL€C B)D&/F-3F47G6%>" Y7 kA$YIK]KK^KKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\KKbMLeOLhPLkRLmSMnTMpTMrUMuWNyYN|ZN\N‚]O„_O‡`OŠaPŒbPŽcPeP“fP—hQ›jQžlR¢nR¥oS©qT¬sT¯uU²vU´wV¶xV¸yV¹yUºzU»zU¼{U½{U¾{U¾|U¿|U¿|U¿|U¿|U¾{U½{U¼{U¼zU»zTºyT¹yT¸xTµwT³vT´vT´vT´vT´wT´wTµwT·xT¹yTºzT¼zU½{U¾{U¿|UÀ|UÂ}UÄVÅ€WÇ‚YÉ„\͈_ÑŒdÙ”láuç£|쩂ſt명æ¦ÞŸ{Õ—sËŽl†d¹^³yZ­uW¨qU¤oSŸlRžkRœjQšiQ˜hQ–gQ”fQ‘ePdPcPŠaP‡`O„^O]O}[NyYNuWMpTMoTMmSMkRLgPL&D#.E,3F46G;'<(D"iB(VGJ]KK`LK[JKB>H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRMmSMoTMqUMsVMvXNzYN}[N€\O‚^O…_Oˆ`OŠaPŒcPdP‘eP“fQ•gQ—hQ™iQkR mS¤oT¨rU¬tW°wY´zZ¸}\»]¾€^À^Á‚^‚^Â\Á€ZÁYÁXÁ~WÁ~WÂ~VÂ~VÂ~VÃ~VÃ~UÃ~UÄ~UÄ~UÄUÄUÅVÅVÅVÅVÆVÆ€VÆ€VÇ€WÇWÈ‚XɃZË…[͇^ЊaÓdØ’iÜ—nâtè£zî©ó¯‡ø´û¸‘üº“û¹“÷¶ñ±Œé©…à¡~Ö˜vËmÇf»€`´z[®vX©rU¥pT£oS¢nS lRžkRœkRšjQ˜iQ–hQ”fQ’ePdPcP‹bPˆ`O…_O‚]O~[NzYNvWNpTMoTMnSMkRMhQLo7 ,2F36G99HC+@ ]8 nA"\JK`ML_LKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_OˆaO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRžlR mS£oU§rW¬vZ²{]¹€a¿…fÅŠjËnГqÓ•sÕ–sÕ–rÕ–qÕ”oÓ’mÑjÏgÍŠcˈaɆ^È„\Ç‚[ÆYÅ€XÅ€WÅWÅWÅVÅVÅWÅ€WÆ€WÇXÈ‚YɃ[Ê…\͇_ÏŠaÒeÕ‘hÙ•mÝ™qávä¡zç¤}꧀멃몄騃奀ߠ|Ù›wÓ•rÌmƉh¿„c¸~^²yZ®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRœkR›jQ™iQ—hQ•gQ“fPePŽcP‹bPˆaO…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQL~I#26G99G?<HA*E$ i@$ZIKaMLbML[JK;:H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ]KKbMLeOLhPLjRLlSMnTMpTMrUMuWMxXN{ZN~\N]O„^O†`O‰aO‹bPŽcPdP’eP”fQ–gQ˜hQšiQœkRžlS mT£oU¦rWªuZ¯y]´~aºƒfŠlË’sÔšzÜ¡€ã§†è«‰ë®‹í¯Œí®‹ë¬ˆè¨„ã£~ßžyÚ™tÖ•oÒjÎŒfˈbÈ…_ƃ\ÅZÄ€YÃXÂWÂ~WÂ~WÂ~WÃXÀXÄ€YÅZƃ\Ç…^Ɇ`ˈbÌŠdÍ‹fÎgÎŽiÎŽjÎŽjÍŽjËŒiljgÆd¿ƒaº^¸}]¶|\´{[²yZ°xY®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRkR›jQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aO†_Oƒ^O€\O|ZNxXNtVMpTMnSMmSMjQLgPL99G?<HG-E&b;!YIK`MLdOM`LKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlRºyTÄ~UÊ‚XʃYÄXº{W­tUšW'¢[(—hQ lRcP€\OhQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRLmSMoTMqUMrVMvWNyYN|ZN\N‚]O„_O‡`O‰aPŒbPŽcPdP’fP”gQ–hQ˜iQšjRœkRžlS¡nT¤pU§sW«vZ°z]µb»„gŠlÉ‘sИyØžÞ¤…ã©Šè­ì±ï³‘ﳑ뭊穅⣀ݞzؘtÒ“nÎiɉdÆ…`Â]Á€[¿~Y¾}X½|W½|V¼{V¼{V¼{V¼{V¼{V¼|W¼|W½}X½}Y½~Z½~Z¼~Z»}[º}[º}[º~\º~\º~]º~]¹~]¸~]·}]¶|\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS mRŸlRkR›jQšiQ˜hQ–gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O}[NyYNuWNpTMnTMmSMkRLhPL|H$D>IQ2P+XHK_LLfQOcNLXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À©qSºyTÃ~VΈ`遲ޜv¾€]ªqS–LŽG|> g3
+S)?*%.—hQ—hQ‘eP‡`OuWM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMoTMqUMsVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽdP‘eP“fP•gQ—hQ˜iQšjRœkRŸlS¡nT¤pV§sX«vZ°z^¶b¼…gËmÊ’sјzØŸ€Þ¤…ã©Šè­ê¯ë°ê¯Žè¬‹å¨‡à¤‚Ûž|Ö™wÑ“qÌŽlljgÃ…bÀ‚_½\»}Zº{X¹zW¸yV·yU·xU·xU·xT·xT·xU·xU·xU·yV·yV·yW¸zW¸{X¹{Y¹|Zº}[º}[º}\º~\¹~]¹~]¸}]·|\µ{\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS¡mRŸlRkRœjQšiQ˜hQ–gQ”fQ’ePdPcPŠbP‡`O…_O‚]O~[NzZNvWNrUMoTMmSMlRMiQLeOLJAIJ(h>!]KKfQOgQN_LKD>I\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À™iQ°tS¸yT¼{UÂYÎŒeï­ˆô´Õ—u¶|\ Z'™LˆD |>
+
+ &3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!'
+ %' %$#" ! !$ 
diff --git a/tests/auto/gui/image/qimagereader/images/test.ppm b/tests/auto/gui/image/qimagereader/images/test.ppm
new file mode 100644
index 0000000000..05d627c0cb
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/test.ppm
@@ -0,0 +1,2 @@
+P6 10 10 1023
+¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ \ No newline at end of file
diff --git a/tests/auto/gui/image/qimagereader/images/test.xpm b/tests/auto/gui/image/qimagereader/images/test.xpm
new file mode 100644
index 0000000000..5fcf075b7f
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/test.xpm
@@ -0,0 +1,260 @@
+/* XPM */
+static char * test_xpm[] = {
+"256 256 1 1",
+" c grey",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/tests/auto/gui/image/qimagereader/images/test32bfv4.bmp b/tests/auto/gui/image/qimagereader/images/test32bfv4.bmp
new file mode 100644
index 0000000000..37060373ed
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/test32bfv4.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/test32v5.bmp b/tests/auto/gui/image/qimagereader/images/test32v5.bmp
new file mode 100644
index 0000000000..8ad3cfa60d
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/test32v5.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff
new file mode 100644
index 0000000000..3fcb8a9aca
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff
new file mode 100644
index 0000000000..6f3e9d5297
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff
new file mode 100644
index 0000000000..aab9cf2596
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff
new file mode 100644
index 0000000000..aad96ffc6c
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff
new file mode 100644
index 0000000000..05d23dcb86
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff
new file mode 100644
index 0000000000..9ffe7fcaa4
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff
new file mode 100644
index 0000000000..eeeb01937e
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff
new file mode 100644
index 0000000000..87cf2fd774
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_1.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_1.tiff
new file mode 100644
index 0000000000..3b589b2232
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_1.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_2.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_2.tiff
new file mode 100644
index 0000000000..9a662239db
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_2.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_3.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_3.tiff
new file mode 100644
index 0000000000..eed242388c
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_3.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_4.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_4.tiff
new file mode 100644
index 0000000000..055480e0ca
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_4.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_5.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_5.tiff
new file mode 100644
index 0000000000..b4d0974ec8
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_5.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_6.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_6.tiff
new file mode 100644
index 0000000000..3b1e02af56
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_6.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_7.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_7.tiff
new file mode 100644
index 0000000000..b752c745c3
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_7.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_8.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_8.tiff
new file mode 100644
index 0000000000..e228d05659
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_8.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_indexed.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_indexed.tiff
new file mode 100644
index 0000000000..7507e526a5
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_indexed.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_mono.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_mono.tiff
new file mode 100644
index 0000000000..8ff9db80f5
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_mono.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_rgb.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_rgb.tiff
new file mode 100644
index 0000000000..321ea3ebf5
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/original_rgb.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff
new file mode 100644
index 0000000000..2756a82fbb
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff
new file mode 100644
index 0000000000..ae9af0999d
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff
new file mode 100644
index 0000000000..a2f432526b
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff
new file mode 100644
index 0000000000..f35bfc4c9c
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff
new file mode 100644
index 0000000000..70e5478065
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff
new file mode 100644
index 0000000000..b2635fe14f
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff
new file mode 100644
index 0000000000..1fb0cd9df6
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff
new file mode 100644
index 0000000000..666b1b4c55
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/transparent.xpm b/tests/auto/gui/image/qimagereader/images/transparent.xpm
new file mode 100644
index 0000000000..5ddcf0b00e
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/transparent.xpm
@@ -0,0 +1,788 @@
+/* XPM */
+static char *dummy[]={
+"8 8 777 2",
+"#R c none",
+"fn c #000001",
+".e c #000069",
+".f c #00006d",
+".g c #00006e",
+"#d c #0042b4",
+"aJ c #010101",
+"g0 c #010102",
+"dr c #010202",
+"gd c #010203",
+"#J c #0157bb",
+"e. c #020202",
+"du c #020304",
+"fR c #030303",
+"jJ c #040404",
+"hf c #040608",
+"fE c #040609",
+"cO c #04070a",
+"k# c #050505",
+"gC c #050709",
+"ka c #060606",
+"br c #06080a",
+"dY c #06090d",
+"hI c #070707",
+"in c #07090b",
+"cL c #070a0e",
+"cd c #070b0f",
+"e0 c #080808",
+"gZ c #080b0e",
+"eu c #080b0f",
+"dz c #080c10",
+"hD c #090909",
+"fq c #090d11",
+"cH c #090e13",
+"jB c #0a0a0a",
+"#U c #0a0d0f",
+"a4 c #0a0d10",
+"g3 c #0a0d11",
+"fu c #0a0f14",
+"cj c #0a1016",
+"kb c #0b0b0b",
+"#n c #0b0d0f",
+"a1 c #0b0e10",
+"g8 c #0b0f13",
+"f4 c #0b0f14",
+"hE c #0c0c0c",
+"bf c #0c0f12",
+".X c #0c28a0",
+"bT c #0d0d0d",
+"ax c #0d1014",
+"hr c #0d1217",
+"dH c #0d141b",
+"jy c #0e0e0e",
+"aW c #0e1115",
+"eH c #0e141b",
+"bE c #0f0f0f",
+"ar c #0f1317",
+"g5 c #0f1419",
+"hg c #0f151a",
+"fh c #0f151c",
+"dJ c #0f171f",
+"gI c #101010",
+".z c #101094",
+"h. c #10161b",
+"gm c #10161c",
+"eL c #10171f",
+"hK c #111111",
+"at c #11161b",
+"fC c #111820",
+"dA c #111922",
+"aj c #1163c4",
+"bJ c #121212",
+"#Z c #12161a",
+"ba c #12171c",
+"ho c #12181e",
+"jK c #131313",
+"iq c #13191d",
+"cA c #131e2a",
+"c7 c #141414",
+"dR c #141e29",
+"jr c #151515",
+"aA c #151a1f",
+"hq c #151c23",
+"fl c #151e28",
+"eV c #151e29",
+"d4 c #161616",
+"hw c #161e25",
+"jk c #171717",
+"bs c #171d23",
+"g9 c #171f27",
+"eC c #17212b",
+"b9 c #172432",
+"d5 c #181818",
+"as c #181e24",
+"bn c #181f25",
+"bS c #191919",
+"gr c #19232d",
+"ed c #1a1a1a",
+".d c #1a1a6e",
+"gB c #1a242e",
+"eK c #1a2531",
+"dQ c #1a2633",
+"hL c #1b1b1b",
+"g1 c #1b242d",
+"g# c #1b252f",
+"eJ c #1b2734",
+"d1 c #1b2937",
+"bW c #1c1c1c",
+"gW c #1c262f",
+"ci c #1c2b3b",
+"cs c #1c2c3c",
+"e# c #1d1d1d",
+"#3 c #1d232a",
+"f8 c #1d2833",
+"fI c #1d2936",
+"eO c #1d2a38",
+"cw c #1d2e3f",
+"jR c #1e1e1e",
+"a2 c #1e262e",
+"eP c #1e2b39",
+"dE c #1e2d3d",
+"cF c #1e2f41",
+"aO c #1e6ec9",
+"c4 c #1f1f1f",
+"gx c #1f2a36",
+"c# c #1f3043",
+"j2 c #202020",
+"bk c #202931",
+"ht c #202c36",
+"eF c #202f3e",
+"b7 c #203245",
+"cB c #203246",
+"hG c #212121",
+"aE c #212932",
+"bp c #212a32",
+"hl c #212d38",
+"cc c #213347",
+".M c #214eb7",
+"hF c #222222",
+"#7 c #222a32",
+"fw c #223040",
+"eU c #223141",
+"jC c #232323",
+"bb c #232c35",
+"ga c #23303d",
+"cv c #23364a",
+"cn c #23364b",
+"jl c #242424",
+"gj c #243240",
+"cm c #24374c",
+"c. c #24384d",
+"bF c #252525",
+"be c #252f39",
+"gt c #253341",
+"dU c #253649",
+".Y c #256cc9",
+"jG c #262626",
+"h8 c #26333d",
+"hb c #263440",
+"gs c #263443",
+"cr c #263b51",
+"cW c #272727",
+"aC c #27313b",
+"a9 c #27313c",
+"fk c #273748",
+"eR c #27384b",
+"cq c #273d55",
+"jV c #282828",
+"#5 c #28313b",
+"b0 c #2877ce",
+"gL c #292929",
+"#Y c #29323c",
+"hu c #293744",
+"fK c #293a4d",
+"jP c #2a2a2a",
+"#w c #2a323b",
+"bg c #2a3540",
+"dF c #2a3f55",
+"jn c #2b2b2b",
+"a6 c #2b3641",
+"jY c #2c2c2c",
+"h5 c #2c3b47",
+"hp c #2c3c4a",
+"gp c #2c3c4d",
+"cx c #2c445e",
+"bU c #2d2d2d",
+"h# c #2d3e4c",
+"dS c #2d435b",
+"e5 c #2e2e2e",
+"cG c #2e4762",
+"jF c #2f2f2f",
+"aG c #2f3b48",
+"gU c #2f3f4e",
+"ck c #2f4966",
+"j0 c #303030",
+"a0 c #303d4a",
+"he c #304251",
+"cQ c #307ace",
+"e4 c #313131",
+"ew c #31465d",
+"dW c #314862",
+"ce c #314b68",
+"jm c #323232",
+"bm c #323f4d",
+"k. c #333333",
+"e3 c #343434",
+"hi c #344757",
+"eT c #344b64",
+"b8 c #34506f",
+"dj c #347fd1",
+"bX c #353535",
+"f9 c #35485c",
+"ac c #363636",
+"#V c #36434f",
+"fv c #364c64",
+"dV c #36506d",
+"c2 c #373737",
+"ev c #37506a",
+"bI c #383838",
+"bw c #384655",
+"h4 c #384b5a",
+"hk c #384c5d",
+"ea c #393939",
+"bh c #394857",
+"gX c #394d5f",
+"#e c #3981d2",
+"e6 c #3a3a3a",
+"eS c #3a546f",
+"em c #3a81d2",
+"#F c #3b3b3b",
+"eQ c #3b5571",
+"dT c #3b5776",
+"cI c #3b5c7f",
+"gJ c #3c3c3c",
+"hX c #3c5060",
+"fi c #3c546f",
+"gG c #3d3d3d",
+"jv c #3e3e3e",
+"az c #3e4e5e",
+"fL c #3e5772",
+"bK c #3f3f3f",
+"gD c #3f576f",
+"fJ c #3f5874",
+"d2 c #3f86d5",
+"jx c #404040",
+"#8 c #404e5d",
+"bv c #405161",
+"cf c #406389",
+"jL c #414141",
+"iG c #415561",
+"im c #415663",
+"gz c #415971",
+"et c #415d7c",
+"cz c #41658c",
+"f# c #418ad7",
+"jT c #424242",
+"gy c #425b74",
+"fs c #425d7a",
+"#K c #4288d4",
+"jQ c #434343",
+"eX c #438cda",
+"j8 c #444444",
+".L c #44449a",
+"eZ c #454545",
+"#s c #455362",
+"fx c #45617f",
+"cK c #456b94",
+"aP c #458cd5",
+"ab c #464646",
+".n c #46469f",
+"aH c #46586a",
+"gV c #465f74",
+"d0 c #46678c",
+"c9 c #474747",
+"aF c #47596c",
+"a3 c #475a6d",
+"ex c #476687",
+"jU c #484848",
+"by c #485b6e",
+"gq c #48627d",
+"dI c #486b91",
+"cC c #48709b",
+"js c #494949",
+"#2 c #495a6b",
+"ih c #49606f",
+"hm c #49637a",
+"gk c #49647f",
+"j7 c #4a4a4a",
+"dt c #4a6e94",
+"ak c #4a8dd7",
+"b1 c #4a90db",
+"c1 c #4b4b4b",
+"bx c #4b5f72",
+"fr c #4b698a",
+"dG c #4b6e95",
+"co c #4b75a2",
+"fW c #4b91db",
+"bD c #4c4c4c",
+"hc c #4c687f",
+"j6 c #4d4d4d",
+"#Q c #4d5f71",
+"ik c #4d6676",
+"hH c #4e4e4e",
+"#0 c #4e5f72",
+"aD c #4e6277",
+"b. c #4e6377",
+"gN c #4e91dc",
+"c0 c #4f4f4f",
+"bj c #4f6378",
+"dZ c #4f759e",
+"cD c #4f7aa9",
+"hN c #4f8dcd",
+"kd c #505050",
+"#S c #506275",
+"#6 c #506376",
+"ge c #506e8c",
+"af c #515151",
+"b# c #51667b",
+"dk c #5195df",
+"cT c #525252",
+".c c #525280",
+"bq c #52677d",
+"iH c #526b79",
+"fj c #527397",
+"eW c #52769d",
+"dy c #527aa5",
+"hJ c #535353",
+"#x c #536476",
+"eG c #53789f",
+"jM c #545454",
+"#r c #546577",
+"bz c #546a80",
+"dM c #547ca8",
+"fP c #5499e2",
+"jp c #555555",
+"iK c #556f7e",
+"bM c #565656",
+"fB c #56799f",
+"dC c #567fab",
+"gE c #569be2",
+"cU c #575757",
+"h7 c #57748b",
+"gc c #577797",
+"fN c #577ba1",
+"dx c #5780ad",
+"cg c #5787bb",
+"i4 c #585858",
+"iF c #587483",
+"hy c #587792",
+"g2 c #587893",
+"fy c #587ca3",
+"eA c #587ea7",
+"jW c #595959",
+"bu c #597087",
+"ia c #5984b2",
+"ae c #5a5a5a",
+"#t c #5a6c7f",
+"bd c #5a7189",
+"ij c #5a7789",
+"eI c #5a81ab",
+"bR c #5b5b5b",
+"ch c #5b8dc3",
+"en c #5b9be1",
+"ke c #5c5c5c",
+"cP c #5c8fc5",
+"j5 c #5d5d5d",
+"iN c #5d7fa0",
+"gl c #5d80a3",
+"fp c #5d83ac",
+"cl c #5d8fc6",
+"b2 c #5d9de6",
+"c8 c #5e5e5e",
+"hh c #5e7f9c",
+"hn c #5e809d",
+"i3 c #5f5f5f",
+"#1 c #5f758c",
+"a8 c #5f7890",
+"g7 c #5f819e",
+"cJ c #5f93cc",
+"jz c #606060",
+"ct c #6094cd",
+"bO c #616161",
+"eN c #618cb9",
+"jH c #626262",
+"iW c #627c8d",
+"hd c #6285a3",
+"ey c #628dbb",
+"dO c #6290c4",
+"ca c #6297d1",
+"jI c #636363",
+"eM c #638fbd",
+"jN c #646464",
+"fH c #648db9",
+"eE c #648fbe",
+"cb c #649ad5",
+"hA c #64a8e2",
+"jw c #656565",
+"#k c #65798f",
+"fF c #658eba",
+"fA c #658fbb",
+"fa c #65a4e7",
+"b3 c #65a6e8",
+"jX c #666666",
+"hW c #6688a3",
+"gh c #668cb2",
+"aI c #6696cb",
+"dN c #6697cc",
+"bA c #6699ce",
+"cu c #669edb",
+"#C c #676767",
+"f3 c #678db4",
+"dl c #67a6eb",
+"kc c #686868",
+"cS c #696969",
+"dK c #699bd2",
+"cN c #69a2e0",
+"cy c #69a3e1",
+"fX c #69a6e8",
+"jD c #6a6a6a",
+"av c #6a84a1",
+"ds c #6a9cd3",
+"dL c #6a9cd4",
+"jt c #6b6b6b",
+"fo c #6b97c6",
+"cE c #6ba5e4",
+"jS c #6c6c6c",
+"aV c #6c88a4",
+"ir c #6c8ea4",
+"il c #6c8fa5",
+"eD c #6c9bce",
+"dB c #6c9ed7",
+"dq c #6c9fd8",
+"cM c #6ca7e7",
+"cp c #6ca8e8",
+"eo c #6cabed",
+"i2 c #6d6d6d",
+"#T c #6d869f",
+"#W c #6d87a0",
+"gY c #6d94b5",
+"aa c #6d9bcb",
+"eB c #6d9dd0",
+"dw c #6da0d9",
+"dD c #6da1da",
+"b4 c #6dacee",
+"h9 c #6dafe2",
+"i6 c #6e6e6e",
+"bt c #6e8aa7",
+"fM c #6e9bcb",
+"dP c #6ea3dc",
+"b5 c #6eabee",
+"jd c #707070",
+"ix c #7088a2",
+"hx c #7098ba",
+"f7 c #7099c3",
+"dv c #70a5df",
+"b6 c #70adef",
+"iy c #70aff1",
+"dm c #70aff2",
+"jE c #717171",
+"#m c #7188a0",
+"#u c #7189a1",
+"aY c #718eac",
+"gO c #71aced",
+"jq c #727272",
+"gb c #729cc6",
+"hO c #72afee",
+"ib c #72afef",
+"e7 c #737373",
+"#y c #738ba4",
+"#A c #739eca",
+".j c #747474",
+"#9 c #748fab",
+"hs c #749ec1",
+"f6 c #749fca",
+".i c #757575",
+"#q c #758da6",
+"a5 c #7593b1",
+"bo c #7594b2",
+"ii c #759bb3",
+"fb c #75b3f4",
+"ep c #75b4f3",
+"is c #75b8e2",
+"ag c #767676",
+"fz c #76a6da",
+"ez c #76a9e0",
+"dX c #76adeb",
+".h c #777777",
+".m c #777794",
+"iX c #77a6b3",
+"dn c #77b1f4",
+"gK c #787878",
+"#4 c #7894b0",
+"fG c #78a9dd",
+"j# c #797979",
+"bV c #7a7a7a",
+"do c #7ab4f4",
+"jA c #7b7b7b",
+"io c #7ba3bc",
+"dp c #7bb5f5",
+".k c #7c7c7c",
+"bc c #7c9cbd",
+"gi c #7caad8",
+"aQ c #7cb0e7",
+"fY c #7cb8f9",
+"iM c #7cbee2",
+"j1 c #7d7d7d",
+"aX c #7d9ebf",
+"fm c #7db0e7",
+"j4 c #7e7e7e",
+".8 c #7ea5ce",
+"#D c #7f7f7f",
+"hv c #7facd3",
+"gn c #7faedd",
+"eb c #808080",
+"er c #80bdf9",
+"j3 c #818181",
+"hz c #81afd6",
+"gu c #81b0e0",
+"eq c #81bbf9",
+"fc c #81bbfc",
+"#b c #828282",
+"iE c #82aac0",
+"i5 c #838383",
+"ha c #83b1d9",
+"es c #83bcf9",
+"ad c #848484",
+"go c #84b5e6",
+".v c #858585",
+"#p c #85a0bc",
+"bN c #868686",
+"hZ c #86b3d6",
+"fD c #86bcf6",
+"fO c #86bcf7",
+"gP c #86c1ff",
+"di c #878787",
+"ft c #87bdf8",
+"bH c #888888",
+"iT c #88cfe2",
+"jZ c #898989",
+"#z c #89a5c3",
+"g. c #89bbee",
+"fg c #89c0fc",
+"fd c #89c2fd",
+"hP c #89c3ff",
+"jb c #8a8a8a",
+"#o c #8aa6c4",
+"jc c #8b8b8b",
+".S c #8baccf",
+"iI c #8bb6ce",
+"al c #8bb9e8",
+"hj c #8bbde7",
+"gw c #8bbef2",
+"ff c #8bc3ff",
+"fe c #8bc4ff",
+"fZ c #8bc6ff",
+"ec c #8c8c8c",
+"gv c #8cbff3",
+"jO c #8d8d8d",
+"a# c #8dadce",
+"ic c #8dc7ff",
+"#H c #8e8e8e",
+"a. c #8eaed0",
+"#L c #8ebae8",
+"hY c #8ebee3",
+"g4 c #8ec1ec",
+"iO c #8ecbff",
+"ju c #8f8f8f",
+"bi c #8fb5da",
+"h6 c #8fc0e5",
+"f5 c #8fc4f9",
+"jf c #909090",
+"bl c #90b6dc",
+"i1 c #90dfe2",
+"bC c #919191",
+"aB c #91b5dc",
+"aZ c #91b7dd",
+"hV c #91c2e8",
+"gf c #91c6fc",
+"gg c #91c7fd",
+"f0 c #91c8ff",
+"i7 c #929292",
+"gA c #92c8fe",
+"iz c #92ccff",
+"iU c #939393",
+"a7 c #93b9e0",
+"f2 c #93c9ff",
+"gQ c #93ccff",
+"e8 c #949494",
+".y c #9494b0",
+"h1 c #94c6ec",
+"f1 c #94caff",
+"j9 c #959595",
+"#X c #95b7da",
+"cX c #969696",
+"ay c #96bbe3",
+"#f c #96bde8",
+"aR c #96c3ee",
+"gR c #96cfff",
+".J c #979797",
+"hQ c #97cfff",
+"fT c #989898",
+"#j c #98b6d7",
+"#l c #98b7d8",
+"iJ c #98c7e1",
+"g6 c #98cffd",
+"jj c #999999",
+"aS c #99c4ee",
+"h3 c #99ccf4",
+"gS c #99d0ff",
+".l c #9a9a9a",
+".b c #9a9aa4",
+"aw c #9ac1ea",
+"gT c #9ad1ff",
+"dg c #9b9b9b",
+".N c #9bbee8",
+"aq c #9bc1eb",
+"am c #9bc4ee",
+"eg c #9c9c9c",
+"au c #9cc3ed",
+"ao c #9cc5ee",
+"c5 c #9d9d9d",
+"aT c #9dc7ef",
+"hU c #9dd2fb",
+"hR c #9dd3ff",
+"dh c #9e9e9e",
+"#v c #9ebee0",
+".Z c #9ec3e8",
+"#M c #9ec3ed",
+"#N c #9ec5ed",
+"ap c #9ec5ef",
+"aU c #9ec7f0",
+"h2 c #9ed4fd",
+"id c #9ed6ff",
+"df c #9f9f9f",
+"an c #9fc5ee",
+"h0 c #9fd5fe",
+"aM c #a0a0a0",
+"hT c #a0d6ff",
+"jh c #a1a1a1",
+"hS c #a1d7ff",
+"ji c #a2a2a2",
+"#P c #a2c7ed",
+"i8 c #a3a3a3",
+"#O c #a3c8ed",
+"iA c #a3daff",
+"j. c #a4a4a4",
+"je c #a5a5a5",
+"#g c #a5c8ed",
+"ip c #a5dafb",
+"iv c #a6a6a6",
+".F c #a6bed4",
+"de c #a7a7a7",
+"#h c #a7c9ed",
+"if c #a7ddff",
+"ie c #a7deff",
+"eh c #a8a8a8",
+"#i c #a8caee",
+"iL c #a8dbf8",
+"ig c #a8deff",
+"iP c #a8e0ff",
+"iY c #a8e2e6",
+"hC c #a9a9a9",
+".0 c #a9caed",
+"#B c #aaaaaa",
+"fU c #ababab",
+".5 c #abc9e9",
+"iB c #abe3ff",
+"e2 c #acacac",
+".6 c #accaea",
+"jo c #adadad",
+".1 c #adcbed",
+".7 c #adccec",
+"iD c #ade2ff",
+"iC c #ade3ff",
+"fS c #aeaeae",
+".4 c #aecded",
+"db c #afafaf",
+".A c #afbbe7",
+".2 c #afccee",
+".3 c #afceee",
+"d6 c #b0b0b0",
+"iQ c #b0e9ff",
+"bG c #b1b1b1",
+"jg c #b2b2b2",
+"#E c #b3b3b3",
+".O c #b3d1ed",
+"gF c #b4b4b4",
+"cY c #b5b5b5",
+"iR c #b5ebff",
+"hM c #b6b6b6",
+"iS c #b6ecff",
+"d9 c #b7b7b7",
+".U c #b8b8b8",
+".u c #b9b9b9",
+"dd c #bababa",
+".P c #bad4ee",
+"bL c #bbbbbb",
+".Q c #bbd4ef",
+".R c #bbd5f0",
+"e9 c #bcbcbc",
+"c3 c #bdbdbd",
+"f. c #bebebe",
+"d8 c #bfbfbf",
+".o c #bfc2e8",
+"iZ c #bffdff",
+"iw c #c0c0c0",
+"iV c #c1c1c1",
+"i0 c #c1feff",
+"ei c #c2c2c2",
+"ej c #c3c3c3",
+"#a c #c4c4c4",
+"el c #c5c5c5",
+"d7 c #c6c6c6",
+".r c #c6cbda",
+"ek c #c7c7c7",
+"aN c #c8c8c8",
+"#G c #c9c9c9",
+"aL c #cacaca",
+"ai c #cbcbcb",
+".B c #cbddf2",
+"bZ c #cccccc",
+".C c #cce0f3",
+"dc c #cdcdcd",
+"ah c #cecece",
+"da c #cfcfcf",
+".E c #cfe1f3",
+".D c #cfe1f4",
+"#I c #d0d0d0",
+"cV c #d1d1d1",
+"fQ c #d2d2d2",
+"bB c #d3d3d3",
+"#c c #d4d4d4",
+"d# c #d5d5d5",
+"aK c #d6d6d6",
+"cZ c #d7d7d7",
+"c6 c #d8d8d8",
+"gH c #d9d9d9",
+".W c #dadada",
+"gM c #dbdbdb",
+"bQ c #dcdcdc",
+"e1 c #dddddd",
+"cR c #dedede",
+"d. c #dfdfdf",
+"bP c #e0e0e0",
+"i# c #e1e1e1",
+"bY c #e2e2e2",
+".K c #e3e3e3",
+"ee c #e4e4e4",
+"d3 c #e5e5e5",
+"ef c #e6e6e6",
+".p c #e6e9f6",
+"fV c #e7e7e7",
+"eY c #e8e8e8",
+".a c #e9e9e9",
+".q c #e9edf8",
+".V c #eaeaea",
+"## c #ebebeb",
+"Qt c #ececec",
+".w c #ededed",
+".x c #eeeeee",
+"#. c #efefef",
+".# c #f0f0f0",
+".9 c #f1f1f1",
+".I c #f2f2f2",
+".T c #f3f3f3",
+"ja c #f4f4f4",
+"i9 c #f5f5f5",
+"hB c #f6f6f6",
+".H c #f7f7f7",
+".G c #f8f8f8",
+"i. c #f9f9f9",
+"kg c #fafafa",
+"kf c #fbfbfb",
+".t c #fcfcfc",
+".s c #fdfdfd",
+"it c #fefefe",
+"iu c #ffffff",
+"#RQtQtQtQtQtQt#R",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt",
+"#RQtQtQtQtQtQt#R"};
diff --git a/tests/auto/gui/image/qimagereader/images/trolltech.gif b/tests/auto/gui/image/qimagereader/images/trolltech.gif
new file mode 100644
index 0000000000..f674369efc
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/trolltech.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tst7.bmp b/tests/auto/gui/image/qimagereader/images/tst7.bmp
new file mode 100644
index 0000000000..6d3ac9241c
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tst7.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tst7.png b/tests/auto/gui/image/qimagereader/images/tst7.png
new file mode 100644
index 0000000000..96efae4e79
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tst7.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/txts.png b/tests/auto/gui/image/qimagereader/images/txts.png
new file mode 100755
index 0000000000..99be1eb4f9
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/txts.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/qimagereader.pro b/tests/auto/gui/image/qimagereader/qimagereader.pro
new file mode 100644
index 0000000000..43d587ea48
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/qimagereader.pro
@@ -0,0 +1,36 @@
+load(qttest_p4)
+SOURCES += tst_qimagereader.cpp
+MOC_DIR=tmp
+QT += widgets widgets-private core-private gui-private network
+RESOURCES += qimagereader.qrc
+!symbian:DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+win32-msvc:QMAKE_CXXFLAGS -= -Zm200
+win32-msvc:QMAKE_CXXFLAGS += -Zm800
+win32-msvc.net:QMAKE_CXXFLAGS -= -Zm300
+win32-msvc.net:QMAKE_CXXFLAGS += -Zm1100
+
+wince*: {
+ images.files = images
+ images.path = .
+
+ imagePlugins.files = $$QT_BUILD_TREE/plugins/imageformats/*.dll
+ imagePlugins.path = imageformats
+
+ DEPLOYMENT += images imagePlugins
+ DEFINES += SRCDIR=\\\".\\\"
+}
+
+symbian: {
+ images.files = images
+ images.path = .
+
+ DEPLOYMENT += images
+
+ qt_not_deployed {
+ imagePlugins.files = qjpeg.dll qgif.dll qmng.dll
+ imagePlugins.path = imageformats
+
+ DEPLOYMENT += imagePlugins
+ }
+}
diff --git a/tests/auto/gui/image/qimagereader/qimagereader.qrc b/tests/auto/gui/image/qimagereader/qimagereader.qrc
new file mode 100644
index 0000000000..2c70652389
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/qimagereader.qrc
@@ -0,0 +1,71 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/16bpp.bmp</file>
+ <file>images/4bpp-rle.bmp</file>
+ <file>images/YCbCr_cmyk.jpg</file>
+ <file>images/YCbCr_cmyk.png</file>
+ <file>images/YCbCr_rgb.jpg</file>
+ <file>images/away.png</file>
+ <file>images/ball.mng</file>
+ <file>images/bat1.gif</file>
+ <file>images/bat2.gif</file>
+ <file>images/beavis.jpg</file>
+ <file>images/black.png</file>
+ <file>images/black.xpm</file>
+ <file>images/colorful.bmp</file>
+ <file>images/corrupt-colors.xpm</file>
+ <file>images/corrupt-pixels.xpm</file>
+ <file>images/corrupt.bmp</file>
+ <file>images/corrupt.gif</file>
+ <file>images/corrupt.jpg</file>
+ <file>images/corrupt.mng</file>
+ <file>images/corrupt.png</file>
+ <file>images/corrupt.xbm</file>
+ <file>images/crash-signed-char.bmp</file>
+ <file>images/earth.gif</file>
+ <file>images/fire.mng</file>
+ <file>images/font.bmp</file>
+ <file>images/gnus.xbm</file>
+ <file>images/image.pbm</file>
+ <file>images/image.pgm</file>
+ <file>images/image.png</file>
+ <file>images/image.ppm</file>
+ <file>images/image_100dpi.tif</file>
+ <file>images/kollada.png</file>
+ <file>images/marble.xpm</file>
+ <file>images/namedcolors.xpm</file>
+ <file>images/negativeheight.bmp</file>
+ <file>images/noclearcode.bmp</file>
+ <file>images/noclearcode.gif</file>
+ <file>images/nontransparent.xpm</file>
+ <file>images/runners.ppm</file>
+ <file>images/teapot.ppm</file>
+ <file>images/test.ppm</file>
+ <file>images/test.xpm</file>
+ <file>images/test32bfv4.bmp</file>
+ <file>images/test32v5.bmp</file>
+ <file>images/tst7.bmp</file>
+ <file>images/tst7.png</file>
+ <file>images/transparent.xpm</file>
+ <file>images/trolltech.gif</file>
+ <file>images/qt.gif</file>
+ <file>images/qt1.gif</file>
+ <file>images/qt2.gif</file>
+ <file>images/qt3.gif</file>
+ <file>images/qt4.gif</file>
+ <file>images/qt5.gif</file>
+ <file>images/qt6.gif</file>
+ <file>images/qt7.gif</file>
+ <file>images/qt8.gif</file>
+ <file>images/endless-anim.gif</file>
+ <file>images/four-frames.gif</file>
+ <file>images/qt-gif-anim.gif</file>
+ <file>images/qt-gif-noanim.gif</file>
+ <file>images/rect.svg</file>
+ <file>images/rect.svgz</file>
+ <file>images/corrupt.svg</file>
+ <file>images/corrupt.svgz</file>
+ <file>images/qtbug13653-no_eoi.jpg</file>
+ <file>images/txts.png</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
new file mode 100644
index 0000000000..ffedc69a7f
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
@@ -0,0 +1,2026 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QBuffer>
+#include <QDebug>
+#include <QFile>
+#include <QImage>
+#include <QImageReader>
+#include <QImageWriter>
+#include <QLabel>
+#include <QPixmap>
+#include <QSet>
+#include <QTcpSocket>
+#include <QTcpServer>
+#include <QTimer>
+
+#include "../../../platformquirks.h"
+
+#if defined(Q_OS_SYMBIAN)
+# define SRCDIR "."
+#endif
+
+typedef QMap<QString, QString> QStringMap;
+typedef QList<int> QIntList;
+Q_DECLARE_METATYPE(QImage)
+Q_DECLARE_METATYPE(QRect)
+Q_DECLARE_METATYPE(QSize)
+Q_DECLARE_METATYPE(QColor)
+Q_DECLARE_METATYPE(QStringMap)
+Q_DECLARE_METATYPE(QIntList)
+Q_DECLARE_METATYPE(QIODevice *)
+Q_DECLARE_METATYPE(QImage::Format)
+
+//TESTED_FILES=
+
+class tst_QImageReader : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QImageReader();
+ virtual ~tst_QImageReader();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void readImage_data();
+ void readImage();
+ void jpegRgbCmyk();
+
+ void setScaledSize_data();
+ void setScaledSize();
+
+ void setClipRect_data();
+ void setClipRect();
+
+ void setScaledClipRect_data();
+ void setScaledClipRect();
+
+ void imageFormat_data();
+ void imageFormat();
+
+ void blackXPM();
+ void transparentXPM();
+ void multiWordNamedColorXPM();
+
+ void supportedFormats();
+
+ void readFromDevice_data();
+ void readFromDevice();
+
+ void readFromFileAfterJunk_data();
+ void readFromFileAfterJunk();
+
+ void devicePosition_data();
+ void devicePosition();
+
+ void setBackgroundColor_data();
+ void setBackgroundColor();
+
+ void supportsAnimation_data();
+ void supportsAnimation();
+
+ void readFromResources_data();
+ void readFromResources();
+
+ void dotsPerMeter_data();
+ void dotsPerMeter();
+
+ void physicalDpi_data();
+ void physicalDpi();
+
+ void sizeBeforeRead_data();
+ void sizeBeforeRead();
+
+ void sizeBeforeFormat_data();
+ void sizeBeforeFormat();
+
+ void imageFormatBeforeRead_data();
+ void imageFormatBeforeRead();
+
+ void gifHandlerBugs();
+ void animatedGif();
+ void gifImageCount();
+ void gifLoopCount();
+
+ void readCorruptImage_data();
+ void readCorruptImage();
+ void readCorruptBmp();
+
+ void supportsOption_data();
+ void supportsOption();
+
+ void tiffCompression_data();
+ void tiffCompression();
+ void tiffEndianness();
+
+ void tiffOrientation_data();
+ void tiffOrientation();
+
+ void tiffGrayscale();
+
+ void autoDetectImageFormat();
+ void fileNameProbing();
+
+ void pixelCompareWithBaseline_data();
+ void pixelCompareWithBaseline();
+
+ void task255627_setNullScaledSize_data();
+ void task255627_setNullScaledSize();
+
+ void testIgnoresFormatAndExtension_data();
+ void testIgnoresFormatAndExtension();
+
+ void saveFormat_data();
+ void saveFormat();
+
+ void readText_data();
+ void readText();
+
+ void preserveTexts_data();
+ void preserveTexts();
+};
+
+static const QLatin1String prefix(SRCDIR "/images/");
+
+// helper to skip an autotest when the given image format is not supported
+#define SKIP_IF_UNSUPPORTED(format) do { \
+ if (!QByteArray(format).isEmpty() && !QImageReader::supportedImageFormats().contains(format)) \
+ QSKIP("\"" + QByteArray(format) + "\" images are not supported", SkipSingle); \
+} while (0)
+
+// Testing get/set functions
+void tst_QImageReader::getSetCheck()
+{
+ QImageReader obj1;
+ // QIODevice * QImageReader::device()
+ // void QImageReader::setDevice(QIODevice *)
+ QFile *var1 = new QFile;
+ obj1.setDevice(var1);
+
+ //A bit strange but that's the only way to compile under windows.
+ QCOMPARE((QIODevice *) var1, obj1.device());
+ obj1.setDevice((QIODevice *)0);
+ QCOMPARE((QIODevice *) 0,
+ obj1.device());
+ delete var1;
+}
+
+tst_QImageReader::tst_QImageReader()
+{
+}
+
+tst_QImageReader::~tst_QImageReader()
+{
+
+}
+
+void tst_QImageReader::init()
+{
+}
+
+void tst_QImageReader::cleanup()
+{
+}
+
+void tst_QImageReader::readImage_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<bool>("success");
+ QTest::addColumn<QByteArray>("format");
+
+ QTest::newRow("empty") << QString() << false << QByteArray();
+ QTest::newRow("BMP: colorful") << QString("colorful.bmp") << true << QByteArray("bmp");
+ QTest::newRow("BMP: test32bfv4") << QString("test32bfv4.bmp") << true << QByteArray("bmp");
+ QTest::newRow("BMP: test32v5") << QString("test32v5.bmp") << true << QByteArray("bmp");
+ QTest::newRow("BMP: font") << QString("font.bmp") << true << QByteArray("bmp");
+ QTest::newRow("BMP: signed char") << QString("crash-signed-char.bmp") << true << QByteArray("bmp");
+ QTest::newRow("BMP: 4bpp RLE") << QString("4bpp-rle.bmp") << true << QByteArray("bmp");
+ QTest::newRow("BMP: 4bpp uncompressed") << QString("tst7.bmp") << true << QByteArray("bmp");
+ QTest::newRow("BMP: 16bpp") << QString("16bpp.bmp") << true << QByteArray("bmp");
+ QTest::newRow("BMP: negative height") << QString("negativeheight.bmp") << true << QByteArray("bmp");
+ QTest::newRow("XPM: marble") << QString("marble.xpm") << true << QByteArray("xpm");
+ QTest::newRow("PNG: kollada") << QString("kollada.png") << true << QByteArray("png");
+ QTest::newRow("PPM: teapot") << QString("teapot.ppm") << true << QByteArray("ppm");
+ QTest::newRow("PPM: runners") << QString("runners.ppm") << true << QByteArray("ppm");
+ QTest::newRow("PPM: test") << QString("test.ppm") << true << QByteArray("ppm");
+ QTest::newRow("XBM: gnus") << QString("gnus.xbm") << true << QByteArray("xbm");
+
+ QTest::newRow("JPEG: beavis") << QString("beavis.jpg") << true << QByteArray("jpeg");
+ QTest::newRow("JPEG: qtbug13653") << QString("qtbug13653-no_eoi.jpg") << true << QByteArray("jpeg");
+
+ QTest::newRow("GIF: earth") << QString("earth.gif") << true << QByteArray("gif");
+ QTest::newRow("GIF: trolltech") << QString("trolltech.gif") << true << QByteArray("gif");
+
+ QTest::newRow("MNG: ball") << QString("ball.mng") << true << QByteArray("mng");
+ QTest::newRow("MNG: fire") << QString("fire.mng") << true << QByteArray("mng");
+
+ QTest::newRow("SVG: rect") << QString("rect.svg") << true << QByteArray("svg");
+ QTest::newRow("SVGZ: rect") << QString("rect.svgz") << true << QByteArray("svgz");
+}
+
+void tst_QImageReader::readImage()
+{
+ QFETCH(QString, fileName);
+ QFETCH(bool, success);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ for (int i = 0; i < 2; ++i) {
+ QImageReader io(prefix + fileName, i ? QByteArray() : format);
+ if (success) {
+ if (!io.supportsAnimation())
+ QVERIFY(io.imageCount() > 0);
+ } else {
+ QCOMPARE(io.imageCount(), -1);
+ }
+ QImage image = io.read();
+ if (!success) {
+ QVERIFY(image.isNull());
+ return;
+ }
+
+ QVERIFY2(!image.isNull(), io.errorString().toLatin1().constData());
+
+ // No format
+ QImageReader io2(prefix + fileName);
+ QVERIFY2(!io2.read().isNull(), io.errorString().toLatin1().constData());
+
+ // No extension, no format
+ QImageReader io3(prefix + fileName.left(fileName.lastIndexOf(QLatin1Char('.'))));
+ QVERIFY2(!io3.read().isNull(), io.errorString().toLatin1().constData());
+
+ // Read into \a image2
+ QImage image2;
+ QImageReader image2Reader(prefix + fileName, i ? QByteArray() : format);
+ QCOMPARE(image2Reader.format(), format);
+ QVERIFY(image2Reader.read(&image2));
+ if (image2Reader.canRead()) {
+ if (i)
+ QVERIFY(!image2Reader.format().isEmpty());
+ else
+ QCOMPARE(image2Reader.format(), format);
+ } else {
+ if (i)
+ QVERIFY(image2Reader.format().isEmpty());
+ else
+ QVERIFY(!image2Reader.format().isEmpty());
+ }
+ QCOMPARE(image, image2);
+ do {
+ QVERIFY2(!image.isNull(), io.errorString().toLatin1().constData());
+ } while (!(image = io.read()).isNull());
+ }
+}
+
+void tst_QImageReader::jpegRgbCmyk()
+{
+ QImage image1(prefix + QLatin1String("YCbCr_cmyk.jpg"));
+ QImage image2(prefix + QLatin1String("YCbCr_cmyk.png"));
+
+ if (PlatformQuirks::isImageLoaderImprecise()) {
+ // first, do some obvious tests
+ QCOMPARE(image1.height(), image2.height());
+ QCOMPARE(image1.width(), image2.width());
+ QCOMPARE(image1.format(), image2.format());
+ QCOMPARE(image1.format(), QImage::Format_RGB32);
+
+ // compare all the pixels with a slack of 3. This ignores rounding errors in libjpeg/libpng
+ for (int h = 0; h < image1.height(); ++h) {
+ const uchar *s1 = image1.constScanLine(h);
+ const uchar *s2 = image2.constScanLine(h);
+ for (int w = 0; w < image1.width() * 4; ++w) {
+ if (*s1 != *s2) {
+ QVERIFY2(qAbs(*s1 - *s2) <= 3, qPrintable(QString("images differ in line %1, col %2 (image1: %3, image2: %4)").arg(h).arg(w).arg(*s1, 0, 16).arg(*s2, 0, 16)));
+ }
+ s1++;
+ s2++;
+ }
+ }
+ } else {
+ QCOMPARE(image1, image2);
+ }
+}
+
+void tst_QImageReader::setScaledSize_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QSize>("newSize");
+ QTest::addColumn<QByteArray>("format");
+
+ QTest::newRow("BMP: colorful") << "colorful" << QSize(200, 200) << QByteArray("bmp");
+ QTest::newRow("BMP: font") << "font" << QSize(200, 200) << QByteArray("bmp");
+ QTest::newRow("XPM: marble") << "marble" << QSize(200, 200) << QByteArray("xpm");
+ QTest::newRow("PNG: kollada") << "kollada" << QSize(200, 200) << QByteArray("png");
+ QTest::newRow("PPM: teapot") << "teapot" << QSize(200, 200) << QByteArray("ppm");
+ QTest::newRow("PPM: runners") << "runners.ppm" << QSize(400, 400) << QByteArray("ppm");
+ QTest::newRow("PPM: test") << "test.ppm" << QSize(10, 10) << QByteArray("ppm");
+ QTest::newRow("XBM: gnus") << "gnus" << QSize(200, 200) << QByteArray("xbm");
+
+ QTest::newRow("JPEG: beavis A") << "beavis" << QSize(200, 200) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis B") << "beavis" << QSize(175, 175) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis C") << "beavis" << QSize(100, 100) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis D") << "beavis" << QSize(100, 200) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis E") << "beavis" << QSize(200, 100) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis F") << "beavis" << QSize(87, 87) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis G") << "beavis" << QSize(50, 45) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis H") << "beavis" << QSize(43, 43) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis I") << "beavis" << QSize(25, 25) << QByteArray("jpeg");
+
+ QTest::newRow("GIF: earth") << "earth" << QSize(200, 200) << QByteArray("gif");
+ QTest::newRow("GIF: trolltech") << "trolltech" << QSize(200, 200) << QByteArray("gif");
+
+ QTest::newRow("MNG: ball") << "ball" << QSize(200, 200) << QByteArray("mng");
+ QTest::newRow("MNG: fire") << "fire" << QSize(200, 200) << QByteArray("mng");
+
+ QTest::newRow("SVG: rect") << "rect" << QSize(200, 200) << QByteArray("svg");
+ QTest::newRow("SVGZ: rect") << "rect" << QSize(200, 200) << QByteArray("svgz");
+}
+
+void tst_QImageReader::setScaledSize()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QSize, newSize);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImageReader reader(prefix + fileName);
+ reader.setScaledSize(newSize);
+ QImage image = reader.read();
+ QVERIFY(!image.isNull());
+
+ QCOMPARE(image.size(), newSize);
+}
+
+void tst_QImageReader::task255627_setNullScaledSize_data()
+{
+ setScaledSize_data();
+}
+
+void tst_QImageReader::task255627_setNullScaledSize()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImageReader reader(prefix + fileName);
+
+ // set a null size
+ reader.setScaledSize(QSize(0, 0));
+ reader.setQuality(0);
+ QImage image = reader.read();
+ QVERIFY(image.isNull());
+ QCOMPARE(image.size(), QSize(0, 0));
+}
+
+void tst_QImageReader::setClipRect_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QRect>("newRect");
+ QTest::addColumn<QByteArray>("format");
+ QTest::newRow("BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: test32bfv4") << "test32bfv4" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: test32v5") << "test32v5" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: 4bpp uncompressed") << "tst7.bmp" << QRect(0, 0, 31, 31) << QByteArray("bmp");
+ QTest::newRow("XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
+ QTest::newRow("PNG: kollada") << "kollada" << QRect(0, 0, 50, 50) << QByteArray("png");
+ QTest::newRow("PPM: teapot") << "teapot" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("PPM: runners") << "runners.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("PPM: test") << "test.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("XBM: gnus") << "gnus" << QRect(0, 0, 50, 50) << QByteArray("xbm");
+
+ QTest::newRow("JPEG: beavis") << "beavis" << QRect(0, 0, 50, 50) << QByteArray("jpeg");
+
+ QTest::newRow("GIF: earth") << "earth" << QRect(0, 0, 50, 50) << QByteArray("gif");
+ QTest::newRow("GIF: trolltech") << "trolltech" << QRect(0, 0, 50, 50) << QByteArray("gif");
+
+ QTest::newRow("MNG: ball") << "ball" << QRect(0, 0, 50, 50) << QByteArray("mng");
+ QTest::newRow("MNG: fire") << "fire" << QRect(0, 0, 50, 50) << QByteArray("mng");
+
+ QTest::newRow("SVG: rect") << "rect" << QRect(0, 0, 50, 50) << QByteArray("svg");
+ QTest::newRow("SVGZ: rect") << "rect" << QRect(0, 0, 50, 50) << QByteArray("svgz");
+}
+
+void tst_QImageReader::setClipRect()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QRect, newRect);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImageReader reader(prefix + fileName);
+ reader.setClipRect(newRect);
+ QImage image = reader.read();
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.rect(), newRect);
+
+ QImageReader originalReader(prefix + fileName);
+ QImage originalImage = originalReader.read();
+ QCOMPARE(originalImage.copy(newRect), image);
+}
+
+void tst_QImageReader::setScaledClipRect_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QRect>("newRect");
+ QTest::addColumn<QByteArray>("format");
+
+ QTest::newRow("BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: test32bfv4") << "test32bfv4" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: test32v5") << "test32v5" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
+ QTest::newRow("PNG: kollada") << "kollada" << QRect(0, 0, 50, 50) << QByteArray("png");
+ QTest::newRow("PPM: teapot") << "teapot" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("PPM: runners") << "runners.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("PPM: test") << "test.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("XBM: gnus") << "gnus" << QRect(0, 0, 50, 50) << QByteArray("xbm");
+
+ QTest::newRow("JPEG: beavis") << "beavis" << QRect(0, 0, 50, 50) << QByteArray("jpeg");
+
+ QTest::newRow("GIF: earth") << "earth" << QRect(0, 0, 50, 50) << QByteArray("gif");
+ QTest::newRow("GIF: trolltech") << "trolltech" << QRect(0, 0, 50, 50) << QByteArray("gif");
+
+ QTest::newRow("MNG: ball") << "ball" << QRect(0, 0, 50, 50) << QByteArray("mng");
+ QTest::newRow("MNG: fire") << "fire" << QRect(0, 0, 50, 50) << QByteArray("mng");
+
+ QTest::newRow("SVG: rect") << "rect" << QRect(0, 0, 50, 50) << QByteArray("svg");
+ QTest::newRow("SVGZ: rect") << "rect" << QRect(0, 0, 50, 50) << QByteArray("svgz");
+}
+
+void tst_QImageReader::setScaledClipRect()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QRect, newRect);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImageReader reader(prefix + fileName);
+ reader.setScaledSize(QSize(300, 300));
+ reader.setScaledClipRect(newRect);
+ QImage image = reader.read();
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.rect(), newRect);
+
+ QImageReader originalReader(prefix + fileName);
+ originalReader.setScaledSize(QSize(300, 300));
+ QImage originalImage = originalReader.read();
+ QCOMPARE(originalImage.copy(newRect), image);
+}
+
+void tst_QImageReader::imageFormat_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QByteArray>("format");
+ QTest::addColumn<QImage::Format>("imageFormat");
+
+ QTest::newRow("pbm") << QString("image.pbm") << QByteArray("pbm") << QImage::Format_Mono;
+ QTest::newRow("pgm") << QString("image.pgm") << QByteArray("pgm") << QImage::Format_Indexed8;
+ QTest::newRow("ppm-1") << QString("image.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
+ QTest::newRow("ppm-2") << QString("teapot.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
+ QTest::newRow("ppm-3") << QString("runners.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
+ QTest::newRow("ppm-4") << QString("test.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
+
+ QTest::newRow("jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg") << QImage::Format_Indexed8;
+ QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg") << QImage::Format_RGB32;
+ QTest::newRow("jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg") << QImage::Format_RGB32;
+
+ QTest::newRow("gif-1") << QString("earth.gif") << QByteArray("gif") << QImage::Format_Invalid;
+ QTest::newRow("gif-2") << QString("trolltech.gif") << QByteArray("gif") << QImage::Format_Invalid;
+
+ QTest::newRow("xbm") << QString("gnus.xbm") << QByteArray("xbm") << QImage::Format_MonoLSB;
+ QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm") << QImage::Format_Indexed8;
+ QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
+ QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
+ QTest::newRow("bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp") << QImage::Format_RGB32;
+ QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp") << QImage::Format_RGB32;
+ QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
+ QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
+ QTest::newRow("mng-1") << QString("ball.mng") << QByteArray("mng") << QImage::Format_Invalid;
+ QTest::newRow("mng-2") << QString("fire.mng") << QByteArray("mng") << QImage::Format_Invalid;
+ QTest::newRow("svg") << QString("rect.svg") << QByteArray("svg") << QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("svgz") << QString("rect.svgz") << QByteArray("svgz") << QImage::Format_ARGB32_Premultiplied;
+}
+
+void tst_QImageReader::imageFormat()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+ QFETCH(QImage::Format, imageFormat);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QCOMPARE(QImageReader::imageFormat(prefix + fileName), format);
+ QImageReader reader(prefix + fileName);
+ QCOMPARE(reader.imageFormat(), imageFormat);
+}
+
+void tst_QImageReader::blackXPM()
+{
+ QImage image(prefix + QLatin1String("black.xpm"));
+ QImage image2(prefix + QLatin1String("black.png"));
+ QCOMPARE(image.pixel(25, 25), qRgb(190, 190, 190));
+ QCOMPARE(image.pixel(25, 25), image2.pixel(25, 25));
+}
+
+void tst_QImageReader::transparentXPM()
+{
+ QImage image(prefix + QLatin1String("nontransparent.xpm"));
+ QImage image2(prefix + QLatin1String("transparent.xpm"));
+ QCOMPARE(image.format(), QImage::Format_RGB32);
+ QCOMPARE(image2.format(), QImage::Format_ARGB32);
+}
+
+void tst_QImageReader::multiWordNamedColorXPM()
+{
+ QImage image(prefix + QLatin1String("namedcolors.xpm"));
+ QCOMPARE(image.pixel(0, 0), qRgb(102, 139, 139)); // pale turquoise 4
+ QCOMPARE(image.pixel(0, 1), qRgb(250, 250, 210)); // light golden rod yellow
+ QCOMPARE(image.pixel(0, 2), qRgb(255, 250, 205)); // lemon chiffon
+}
+
+void tst_QImageReader::supportedFormats()
+{
+ QList<QByteArray> formats = QImageReader::supportedImageFormats();
+ QList<QByteArray> sortedFormats = formats;
+ qSort(sortedFormats);
+
+ // check that the list is sorted
+ QCOMPARE(formats, sortedFormats);
+
+ QSet<QByteArray> formatSet;
+ foreach (QByteArray format, formats)
+ formatSet << format;
+
+ // check that the list does not contain duplicates
+ QCOMPARE(formatSet.size(), formats.size());
+}
+
+void tst_QImageReader::setBackgroundColor_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QColor>("color");
+
+ QTest::newRow("BMP: colorful") << QString("colorful.bmp") << QColor(Qt::white);
+ QTest::newRow("BMP: font") << QString("font.bmp") << QColor(Qt::black);
+ QTest::newRow("BMP: signed char") << QString("crash-signed-char.bmp") << QColor(Qt::red);
+ QTest::newRow("XPM: marble") << QString("marble.xpm") << QColor(Qt::darkRed);
+ QTest::newRow("PNG: kollada") << QString("kollada.png") << QColor(Qt::green);
+ QTest::newRow("PPM: teapot") << QString("teapot.ppm") << QColor(Qt::darkGreen);
+ QTest::newRow("PPM: runners") << QString("runners.ppm") << QColor(Qt::red);
+ QTest::newRow("PPM: test") << QString("test.ppm") << QColor(Qt::white);
+ QTest::newRow("XBM: gnus") << QString("gnus.xbm") << QColor(Qt::blue);
+
+ QTest::newRow("JPEG: beavis") << QString("beavis.jpg") << QColor(Qt::darkBlue);
+
+ QTest::newRow("GIF: earth") << QString("earth.gif") << QColor(Qt::cyan);
+ QTest::newRow("GIF: trolltech") << QString("trolltech.gif") << QColor(Qt::magenta);
+
+ QTest::newRow("MNG: ball") << QString("ball.mng") << QColor(Qt::yellow);
+ QTest::newRow("MNG: fire") << QString("fire.mng") << QColor(Qt::gray);
+
+ QTest::newRow("SVG: rect") << QString("rect.svg") << QColor(Qt::darkGreen);
+ QTest::newRow("SVGZ: rect") << QString("rect.svgz") << QColor(Qt::darkGreen);
+}
+
+void tst_QImageReader::setBackgroundColor()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QColor, color);
+ QImageReader io("images/" + fileName);
+ io.setBackgroundColor(color);
+ if (io.backgroundColor().isValid())
+ QCOMPARE(io.backgroundColor(), color);
+}
+
+void tst_QImageReader::supportsAnimation_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<bool>("success");
+
+ QTest::newRow("BMP: colorful") << QString("colorful.bmp") << false;
+ QTest::newRow("BMP: font") << QString("font.bmp") << false;
+ QTest::newRow("BMP: signed char") << QString("crash-signed-char.bmp") << false;
+ QTest::newRow("BMP: test32bfv4") << QString("test32bfv4.bmp") << false;;
+ QTest::newRow("BMP: test32v5") << QString("test32v5.bmp") << false;
+ QTest::newRow("XPM: marble") << QString("marble.xpm") << false;
+ QTest::newRow("PNG: kollada") << QString("kollada.png") << false;
+ QTest::newRow("PPM: teapot") << QString("teapot.ppm") << false;
+ QTest::newRow("PPM: teapot") << QString("teapot.ppm") << false;
+ QTest::newRow("PPM: runners") << QString("runners.ppm") << false;
+ QTest::newRow("XBM: gnus") << QString("gnus.xbm") << false;
+
+ QTest::newRow("JPEG: beavis") << QString("beavis.jpg") << false;
+
+ QTest::newRow("GIF: earth") << QString("earth.gif") << true;
+ QTest::newRow("GIF: trolltech") << QString("trolltech.gif") << true;
+
+ QTest::newRow("MNG: ball") << QString("ball.mng") << true;
+ QTest::newRow("MNG: fire") << QString("fire.mng") << true;
+
+ QTest::newRow("SVG: rect") << QString("rect.svg") << false;
+ QTest::newRow("SVGZ: rect") << QString("rect.svgz") << false;
+}
+
+void tst_QImageReader::supportsAnimation()
+{
+ QFETCH(QString, fileName);
+ QFETCH(bool, success);
+ QImageReader io(prefix + fileName);
+ QCOMPARE(io.supportsAnimation(), success);
+}
+
+void tst_QImageReader::sizeBeforeRead_data()
+{
+ imageFormat_data();
+}
+
+void tst_QImageReader::sizeBeforeRead()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImageReader reader(prefix + fileName);
+ QVERIFY(reader.canRead());
+ if (format == "mng") {
+ QCOMPARE(reader.size(), QSize());
+ return;
+ }
+
+ QSize size = reader.size();
+ QVERIFY(reader.canRead());
+ QImage image = reader.read();
+ QVERIFY(!image.isNull());
+ QCOMPARE(size, image.size());
+}
+
+void tst_QImageReader::sizeBeforeFormat_data()
+{
+ imageFormat_data();
+}
+
+void tst_QImageReader::sizeBeforeFormat()
+{
+ QFETCH(QString, fileName);
+
+ QByteArray formatA, formatB;
+
+ {
+ QImageReader reader(prefix + fileName);
+ formatA = reader.format();
+ }
+
+ {
+ QImageReader reader(prefix + fileName);
+ QSize size = reader.size();
+ formatB = reader.format();
+ }
+
+ QCOMPARE(formatA, formatB);
+}
+
+void tst_QImageReader::imageFormatBeforeRead_data()
+{
+ imageFormat_data();
+}
+
+void tst_QImageReader::imageFormatBeforeRead()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+ QFETCH(QImage::Format, imageFormat);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImageReader reader(fileName);
+ if (reader.supportsOption(QImageIOHandler::ImageFormat)) {
+ QImage::Format fileFormat = reader.imageFormat();
+ QCOMPARE(fileFormat, imageFormat);
+ QSize size = reader.size();
+ QImage image(size, fileFormat);
+ QVERIFY(reader.read(&image));
+ QCOMPARE(image.format(), fileFormat);
+ }
+}
+
+void tst_QImageReader::gifHandlerBugs()
+{
+ SKIP_IF_UNSUPPORTED("gif");
+
+ {
+ QImageReader io(prefix + "trolltech.gif");
+ QVERIFY(io.loopCount() != 1);
+ int count=0;
+ for (; io.canRead(); io.read(), ++count) ;
+ QVERIFY(count == 34);
+ }
+
+ // Task 95166
+ {
+ QImageReader io1(prefix + "bat1.gif");
+ QImageReader io2(prefix + "bat2.gif");
+ QVERIFY(io1.canRead());
+ QVERIFY(io2.canRead());
+ QImage im1 = io1.read();
+ QImage im2 = io2.read();
+ QVERIFY(!im1.isNull());
+ QVERIFY(!im2.isNull());
+ QCOMPARE(im1, im2);
+ }
+
+ // Task 9994
+ {
+ QImageReader io1(prefix + "noclearcode.gif");
+ QImageReader io2(prefix + "noclearcode.bmp");
+ QVERIFY(io1.canRead()); QVERIFY(io2.canRead());
+ QImage im1 = io1.read(); QImage im2 = io2.read();
+ QVERIFY(!im1.isNull()); QVERIFY(!im2.isNull());
+ QCOMPARE(im1.convertToFormat(QImage::Format_ARGB32), im2.convertToFormat(QImage::Format_ARGB32));
+ }
+
+ // Check the undocumented feature.
+ {
+ QImageReader io(prefix + "endless-anim.gif");
+ QVERIFY(io.canRead());
+ QCOMPARE(io.loopCount(), -1);
+ }
+}
+
+void tst_QImageReader::animatedGif()
+{
+ SKIP_IF_UNSUPPORTED("gif");
+
+ QImageReader io(":images/qt.gif");
+ QImage image = io.read();
+ QVERIFY(!image.isNull());
+ int i = 0;
+ while(!image.isNull()){
+ QString frameName = QString(":images/qt%1.gif").arg(++i);
+ QCOMPARE(image, QImage(frameName));
+ image = io.read();
+ }
+}
+
+// http://bugreports.qt.nokia.com/browse/QTBUG-6696
+// Check the count of images in various call orders...
+void tst_QImageReader::gifImageCount()
+{
+ SKIP_IF_UNSUPPORTED("gif");
+
+ // just read every frame... and see how much we got..
+ {
+ QImageReader io(":images/four-frames.gif");
+
+ QVERIFY(io.canRead());
+ QImage blackFrame = io.read();
+
+ QVERIFY(io.canRead());
+ QImage whiteFrame = io.read();
+
+ QVERIFY(io.canRead());
+ QImage greenFrame = io.read();
+
+ QVERIFY(io.imageCount() == 4);
+
+ QVERIFY(io.canRead());
+ QImage blueFrame = io.read();
+
+ QVERIFY(!io.canRead());
+ QImage emptyFrame = io.read();
+
+ QVERIFY(!io.canRead());
+ QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0));
+ QCOMPARE(blackFrame.size(), QSize(64,64));
+
+ QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff));
+ QCOMPARE(whiteFrame.size(), QSize(64,64));
+
+ QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0));
+ QCOMPARE(greenFrame.size(), QSize(64,64));
+
+ QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff));
+ QCOMPARE(blueFrame.size(), QSize(64,64));
+ QVERIFY(emptyFrame.isNull());
+ }
+
+ // Read and get the size
+ {
+ QImageReader io(":images/four-frames.gif");
+
+ QVERIFY(io.canRead());
+ QCOMPARE(io.size(), QSize(64,64));
+
+ QVERIFY(io.canRead());
+ QCOMPARE(io.size(), QSize(64,64));
+ QCOMPARE(io.size(), QSize(64,64));
+ QVERIFY(io.canRead());
+ QImage blackFrame = io.read();
+
+ QVERIFY(io.canRead());
+ QCOMPARE(io.size(), QSize(64,64));
+ QCOMPARE(io.size(), QSize(64,64));
+ QVERIFY(io.canRead());
+ QImage whiteFrame = io.read();
+
+ QVERIFY(io.canRead());
+ QCOMPARE(io.size(), QSize(64,64));
+ QCOMPARE(io.size(), QSize(64,64));
+ QVERIFY(io.canRead());
+ QImage greenFrame = io.read();
+
+ QVERIFY(io.canRead());
+ QCOMPARE(io.size(), QSize(64,64));
+ QCOMPARE(io.size(), QSize(64,64));
+ QVERIFY(io.canRead());
+ QImage blueFrame = io.read();
+
+ QVERIFY(!io.canRead());
+ QCOMPARE(io.size(), QSize());
+ QCOMPARE(io.size(), QSize());
+ QVERIFY(!io.canRead());
+ QImage emptyFrame = io.read();
+
+ QVERIFY(!io.canRead());
+ QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0));
+ QCOMPARE(blackFrame.size(), QSize(64,64));
+
+ QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff));
+ QCOMPARE(whiteFrame.size(), QSize(64,64));
+
+ QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0));
+ QCOMPARE(greenFrame.size(), QSize(64,64));
+
+ QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff));
+ QCOMPARE(blueFrame.size(), QSize(64,64));
+ QVERIFY(emptyFrame.isNull());
+ }
+
+ // Do a Size query as substitute for canRead
+ {
+ QImageReader io(":images/four-frames.gif");
+
+ QCOMPARE(io.size(), QSize(64,64));
+ QCOMPARE(io.size(), QSize(64,64));
+ QImage blackFrame = io.read();
+
+ QCOMPARE(io.size(), QSize(64,64));
+ QCOMPARE(io.size(), QSize(64,64));
+ QImage whiteFrame = io.read();
+
+ QCOMPARE(io.size(), QSize(64,64));
+ QCOMPARE(io.size(), QSize(64,64));
+ QImage greenFrame = io.read();
+
+ QCOMPARE(io.size(), QSize(64,64));
+ QCOMPARE(io.size(), QSize(64,64));
+ QImage blueFrame = io.read();
+
+ QCOMPARE(io.size(), QSize());
+ QVERIFY(!io.canRead());
+ QImage emptyFrame = io.read();
+
+ QVERIFY(!io.canRead());
+ QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0));
+ QCOMPARE(blackFrame.size(), QSize(64,64));
+
+ QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff));
+ QCOMPARE(whiteFrame.size(), QSize(64,64));
+
+ QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0));
+ QCOMPARE(greenFrame.size(), QSize(64,64));
+
+ QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff));
+ QCOMPARE(blueFrame.size(), QSize(64,64));
+ QVERIFY(emptyFrame.isNull());
+ }
+ {
+ QImageReader io(":images/trolltech.gif");
+ QVERIFY(io.imageCount() == 34);
+ QVERIFY(io.size() == QSize(128,64));
+ }
+}
+
+void tst_QImageReader::gifLoopCount()
+{
+ SKIP_IF_UNSUPPORTED("gif");
+
+ {
+ QImageReader io(":images/qt-gif-anim.gif");
+ QCOMPARE(io.loopCount(), -1); // infinite loop
+ }
+ {
+ QImageReader io(":images/qt-gif-noanim.gif");
+ QCOMPARE(io.loopCount(), 0); // no loop
+ }
+}
+
+class Server : public QObject
+{
+ Q_OBJECT
+public:
+ Server(const QByteArray &data) :serverSocket(0)
+ {
+ connect(&server, SIGNAL(newConnection()), this, SLOT(acceptNewConnection()));
+ server.listen();
+ this->data = data;
+ }
+
+public slots:
+ void runTest()
+ {
+ connect(&clientSocket, SIGNAL(connected()), this, SLOT(connected()));
+ clientSocket.connectToHost(QHostAddress::LocalHost, server.serverPort());
+ }
+
+public:
+ inline QTcpSocket *socket() const { return serverSocket; }
+
+signals:
+ void ready();
+
+private slots:
+ void acceptNewConnection()
+ {
+ serverSocket = server.nextPendingConnection();
+ connect(serverSocket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(remoteHostClosed()));
+ }
+
+ void connected()
+ {
+ clientSocket.write(data);
+ clientSocket.disconnectFromHost();
+ }
+
+ void remoteHostClosed()
+ {
+ emit ready();
+ }
+
+private:
+ QTcpServer server;
+ QTcpSocket clientSocket;
+ QTcpSocket *serverSocket;
+ QByteArray data;
+};
+
+void tst_QImageReader::readFromDevice_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QByteArray>("format");
+
+ QTest::newRow("pbm") << QString("image.pbm") << QByteArray("pbm");
+ QTest::newRow("pgm") << QString("image.pgm") << QByteArray("pgm");
+ QTest::newRow("ppm-1") << QString("image.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-2") << QString("teapot.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-3") << QString("teapot.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-4") << QString("runners.ppm") << QByteArray("ppm");
+
+ QTest::newRow("jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-4") << QString("qtbug13653-no_eoi.jpg") << QByteArray("jpeg");
+
+ QTest::newRow("gif-1") << QString("earth.gif") << QByteArray("gif");
+ QTest::newRow("gif-2") << QString("trolltech.gif") << QByteArray("gif");
+
+ QTest::newRow("xbm") << QString("gnus.xbm") << QByteArray("xbm");
+ QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm");
+ QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
+ QTest::newRow("png") << QString("kollada.png") << QByteArray("png");
+
+ QTest::newRow("mng-1") << QString("ball.mng") << QByteArray("mng");
+ QTest::newRow("mng-2") << QString("fire.mng") << QByteArray("mng");
+
+ QTest::newRow("svg") << QString("rect.svg") << QByteArray("svg");
+ QTest::newRow("svgz") << QString("rect.svgz") << QByteArray("svgz");
+}
+
+void tst_QImageReader::readFromDevice()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImage expectedImage(prefix + fileName, format);
+
+ QFile file(prefix + fileName);
+ QVERIFY(file.open(QFile::ReadOnly));
+ QByteArray imageData = file.readAll();
+ QVERIFY(!imageData.isEmpty());
+ {
+ QBuffer buffer;
+ buffer.setData(imageData);
+ QVERIFY(buffer.open(QBuffer::ReadOnly));
+
+ QImageReader reader(&buffer);
+ QVERIFY(reader.canRead());
+ QImage imageReaderImage = reader.read();
+
+ QCOMPARE(imageReaderImage, expectedImage);
+
+ buffer.seek(0);
+
+ QImage image1;
+ QVERIFY(image1.loadFromData((const uchar *)buffer.data().data(),
+ buffer.data().size(), format.data()));
+ QCOMPARE(image1, expectedImage);
+
+ QByteArray throughBase64 = QByteArray::fromBase64(imageData.toBase64());
+ QVERIFY(image1.loadFromData((const uchar *)throughBase64.data(),
+ throughBase64.size(), format.data()));
+ QCOMPARE(image1, expectedImage);
+ }
+
+#if defined (Q_OS_SYMBIAN) && defined (__WINS__)
+ //the emulator hangs in socket write (this is a test bug, it assumes the TCP stack can accept a whole image to its buffers)
+ if(imageData.size() > 16384)
+ QSKIP("image larger than socket buffer (test needs to be rewritten)", SkipSingle);
+#endif
+ Server server(imageData);
+ QEventLoop loop;
+ connect(&server, SIGNAL(ready()), &loop, SLOT(quit()));
+ QTimer::singleShot(0, &server, SLOT(runTest()));
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+ loop.exec();
+
+ QImageReader reader(server.socket(), format == "xbm" ? "xbm" : "");
+ if (format == "xbm")
+ QVERIFY(!reader.canRead());
+ else
+ QVERIFY(reader.canRead());
+ QImage imageReaderImage = reader.read();
+ QCOMPARE(imageReaderImage, expectedImage);
+}
+
+void tst_QImageReader::readFromFileAfterJunk_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QByteArray>("format");
+
+ QTest::newRow("pbm") << QString("image.pbm") << QByteArray("pbm");
+ QTest::newRow("pgm") << QString("image.pgm") << QByteArray("pgm");
+ QTest::newRow("ppm-1") << QString("image.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-2") << QString("teapot.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-3") << QString("teapot.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-4") << QString("runners.ppm") << QByteArray("ppm");
+
+ QTest::newRow("jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg");
+
+ QTest::newRow("xbm") << QString("gnus.xbm") << QByteArray("xbm");
+ QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm");
+ QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
+ QTest::newRow("png") << QString("kollada.png") << QByteArray("png");
+ QTest::newRow("svg") << QString("rect.svg") << QByteArray("svg");
+ QTest::newRow("svgz") << QString("rect.svgz") << QByteArray("svgz");
+}
+
+void tst_QImageReader::readFromFileAfterJunk()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QFile::remove("junk");
+ QFile junkFile("junk");
+ QVERIFY(junkFile.open(QFile::WriteOnly));
+
+ QFile imageFile(prefix + fileName);
+ QVERIFY(imageFile.open(QFile::ReadOnly));
+ QByteArray imageData = imageFile.readAll();
+ QVERIFY(!imageData.isNull());
+
+ int iterations = 3;
+ if (format == "ppm" || format == "pbm" || format == "pgm" || format == "svg" || format == "svgz")
+ iterations = 1;
+
+ if (format == "mng" || !QImageWriter::supportedImageFormats().contains(format)) {
+ for (int i = 0; i < iterations; ++i) {
+ junkFile.write("deadbeef", 9);
+ QCOMPARE(junkFile.write(imageData), qint64(imageData.size()));
+ }
+ } else {
+ for (int i = 0; i < iterations; ++i) {
+ QImageWriter writer(&junkFile, format);
+ junkFile.write("deadbeef", 9);
+ QVERIFY(writer.write(QImage(prefix + fileName)));
+ }
+ }
+ junkFile.close();
+ junkFile.open(QFile::ReadOnly);
+
+ for (int i = 0; i < iterations; ++i) {
+ QByteArray ole = junkFile.read(9);
+ junkFile.ungetChar(ole[ole.size() - 1]);
+ char c;
+ junkFile.getChar(&c);
+ QImageReader reader(&junkFile);
+ QVERIFY(reader.canRead());
+ QVERIFY(!reader.read().isNull());
+ }
+}
+
+void tst_QImageReader::devicePosition_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QByteArray>("format");
+
+ QTest::newRow("pbm") << QString("image.pbm") << QByteArray("pbm");
+ QTest::newRow("pgm") << QString("image.pgm") << QByteArray("pgm");
+ QTest::newRow("ppm-1") << QString("image.ppm") << QByteArray("ppm");
+
+ QTest::newRow("jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg");
+
+ QTest::newRow("gif-1") << QString("earth.gif") << QByteArray("gif");
+
+ QTest::newRow("xbm") << QString("gnus.xbm") << QByteArray("xbm");
+ QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm");
+ QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
+ QTest::newRow("png") << QString("kollada.png") << QByteArray("png");
+ QTest::newRow("svg") << QString("rect.svg") << QByteArray("svg");
+ QTest::newRow("svgz") << QString("rect.svgz") << QByteArray("svgz");
+}
+
+void tst_QImageReader::devicePosition()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImage expected(prefix + fileName);
+ QVERIFY(!expected.isNull());
+
+ QFile imageFile(prefix + fileName);
+ QVERIFY(imageFile.open(QFile::ReadOnly));
+ QByteArray imageData = imageFile.readAll();
+ QVERIFY(!imageData.isNull());
+ int imageDataSize = imageData.size();
+
+ const char *preStr = "prebeef\n";
+ int preLen = qstrlen(preStr);
+ imageData.prepend(preStr);
+ if (format != "svg" && format != "svgz") // Doesn't handle trailing data
+ imageData.append("\npostbeef");
+ QBuffer buf(&imageData);
+ buf.open(QIODevice::ReadOnly);
+ buf.seek(preLen);
+ QImageReader reader(&buf, format);
+ QCOMPARE(expected, reader.read());
+ if (format != "ppm" &&
+ format != "pgm" &&
+ format != "pbm" &&
+ format != "gif") // Known not to work
+ QCOMPARE(buf.pos(), qint64(preLen+imageDataSize));
+}
+
+
+void tst_QImageReader::readFromResources_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QByteArray>("format");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QString>("message");
+
+ QTest::newRow("corrupt.bmp") << QString("corrupt.bmp")
+ << QByteArray("bmp") << QSize(0, 0)
+ << QString("");
+ QTest::newRow("negativeheight.bmp") << QString("negativeheight.bmp")
+ << QByteArray("bmp") << QSize(127, 64)
+ << QString("");
+ QTest::newRow("font.bmp") << QString("font.bmp")
+ << QByteArray("bmp") << QSize(240, 8)
+ << QString("");
+ QTest::newRow("noclearcode.bmp") << QString("noclearcode.bmp")
+ << QByteArray("bmp") << QSize(29, 18)
+ << QString("");
+ QTest::newRow("colorful.bmp") << QString("colorful.bmp")
+ << QByteArray("bmp") << QSize(320, 200)
+ << QString("");
+ QTest::newRow("16bpp.bmp") << QString("16bpp.bmp")
+ << QByteArray("bmp") << QSize(320, 240)
+ << QString("");
+ QTest::newRow("crash-signed-char.bmp") << QString("crash-signed-char.bmp")
+ << QByteArray("bmp") << QSize(360, 280)
+ << QString("");
+ QTest::newRow("4bpp-rle.bmp") << QString("4bpp-rle.bmp")
+ << QByteArray("bmp") << QSize(640, 480)
+ << QString("");
+ QTest::newRow("test32bfv4.bmp") << QString("test32bfv4.bmp")
+ << QByteArray("bmp") << QSize(373, 156)
+ << QString("");
+ QTest::newRow("test32v5.bmp") << QString("test32v5.bmp")
+ << QByteArray("bmp") << QSize(373, 156)
+ << QString("");
+ QTest::newRow("corrupt.gif") << QString("corrupt.gif")
+ << QByteArray("gif") << QSize(0, 0)
+ << QString("");
+ QTest::newRow("trolltech.gif") << QString("trolltech.gif")
+ << QByteArray("gif") << QSize(128, 64)
+ << QString("");
+ QTest::newRow("noclearcode.gif") << QString("noclearcode.gif")
+ << QByteArray("gif") << QSize(29, 18)
+ << QString("");
+ QTest::newRow("earth.gif") << QString("earth.gif")
+ << QByteArray("gif") << QSize(320, 200)
+ << QString("");
+ QTest::newRow("bat1.gif") << QString("bat1.gif")
+ << QByteArray("gif") << QSize(32, 32)
+ << QString("");
+ QTest::newRow("bat2.gif") << QString("bat2.gif")
+ << QByteArray("gif") << QSize(32, 32)
+ << QString("");
+ QTest::newRow("corrupt.jpg") << QString("corrupt.jpg")
+ << QByteArray("jpg") << QSize(0, 0)
+ << QString("JPEG datastream contains no image");
+ QTest::newRow("beavis.jpg") << QString("beavis.jpg")
+ << QByteArray("jpg") << QSize(350, 350)
+ << QString("");
+ QTest::newRow("YCbCr_cmyk.jpg") << QString("YCbCr_cmyk.jpg")
+ << QByteArray("jpg") << QSize(75, 50)
+ << QString("");
+ QTest::newRow("YCbCr_rgb.jpg") << QString("YCbCr_rgb.jpg")
+ << QByteArray("jpg") << QSize(75, 50)
+ << QString("");
+ QTest::newRow("qtbug13653-no_eoi.jpg") << QString("qtbug13653-no_eoi.jpg")
+ << QByteArray("jpg") << QSize(240, 180)
+ << QString("");
+ QTest::newRow("corrupt.mng") << QString("corrupt.mng")
+ << QByteArray("mng") << QSize(0, 0)
+ << QString("MNG error 901: Application signalled I/O error; chunk IHDR; subcode 0:0");
+ QTest::newRow("fire.mng") << QString("fire.mng")
+ << QByteArray("mng") << QSize(30, 60)
+ << QString("");
+ QTest::newRow("ball.mng") << QString("ball.mng")
+ << QByteArray("mng") << QSize(32, 32)
+ << QString("");
+ QTest::newRow("rect.svg") << QString("rect.svg")
+ << QByteArray("svg") << QSize(105, 137)
+ << QString("");
+ QTest::newRow("rect.svgz") << QString("rect.svgz")
+ << QByteArray("svgz") << QSize(105, 137)
+ << QString("");
+ QTest::newRow("corrupt.svg") << QString("corrupt.svg")
+ << QByteArray("svg") << QSize(0, 0)
+ << QString("");
+ QTest::newRow("corrupt.svgz") << QString("corrupt.svgz")
+ << QByteArray("svgz") << QSize(0, 0)
+ << QString("");
+ QTest::newRow("image.pbm") << QString("image.pbm")
+ << QByteArray("pbm") << QSize(16, 6)
+ << QString("");
+ QTest::newRow("image.pgm") << QString("image.pgm")
+ << QByteArray("pgm") << QSize(24, 7)
+ << QString("");
+ QTest::newRow("corrupt.png") << QString("corrupt.png")
+ << QByteArray("png") << QSize(0, 0)
+ << QString("");
+ QTest::newRow("away.png") << QString("away.png")
+ << QByteArray("png") << QSize(16, 16)
+ << QString("");
+ QTest::newRow("image.png") << QString("image.png")
+ << QByteArray("png") << QSize(22, 22)
+ << QString("");
+ QTest::newRow("kollada.png") << QString("kollada.png")
+ << QByteArray("png") << QSize(436, 160)
+ << QString("");
+ QTest::newRow("black.png") << QString("black.png")
+ << QByteArray("png") << QSize(48, 48)
+ << QString("");
+ QTest::newRow("YCbCr_cmyk.png") << QString("YCbCr_cmyk.png")
+ << QByteArray("png") << QSize(75, 50)
+ << QString("");
+ QTest::newRow("teapot.ppm") << QString("teapot.ppm")
+ << QByteArray("ppm") << QSize(256, 256)
+ << QString("");
+ QTest::newRow("image.ppm") << QString("image.ppm")
+ << QByteArray("ppm") << QSize(4, 4)
+ << QString("");
+ QTest::newRow("runners.ppm") << QString("runners.ppm")
+ << QByteArray("ppm") << QSize(400, 400)
+ << QString("");
+ QTest::newRow("test.ppm") << QString("test.ppm")
+ << QByteArray("ppm") << QSize(10, 10)
+ << QString("");
+ QTest::newRow("gnus.xbm") << QString("gnus.xbm")
+ << QByteArray("xbm") << QSize(271, 273)
+ << QString("");
+ QTest::newRow("corrupt-colors.xpm") << QString("corrupt-colors.xpm")
+ << QByteArray("xpm") << QSize(0, 0)
+ << QString("QImage: XPM color specification is missing: bla9an.n#x");
+ QTest::newRow("corrupt-pixels.xpm") << QString("corrupt-pixels.xpm")
+ << QByteArray("xpm") << QSize(0, 0)
+ << QString("QImage: XPM pixels missing on image line 3");
+ QTest::newRow("corrupt-pixel-count.xpm") << QString("corrupt-pixel-count.xpm")
+ << QByteArray("xpm") << QSize(0, 0)
+ << QString("");
+ QTest::newRow("marble.xpm") << QString("marble.xpm")
+ << QByteArray("xpm") << QSize(240, 240)
+ << QString("");
+ QTest::newRow("test.xpm") << QString("test.xpm")
+ << QByteArray("xpm") << QSize(256, 256)
+ << QString("");
+ QTest::newRow("black.xpm") << QString("black.xpm")
+ << QByteArray("xpm") << QSize(48, 48)
+ << QString("");
+ QTest::newRow("namedcolors.xpm") << QString("namedcolors.xpm")
+ << QByteArray("xpm") << QSize(8, 8)
+ << QString("");
+ QTest::newRow("nontransparent.xpm") << QString("nontransparent.xpm")
+ << QByteArray("xpm") << QSize(8, 8)
+ << QString("");
+ QTest::newRow("transparent.xpm") << QString("transparent.xpm")
+ << QByteArray("xpm") << QSize(8, 8)
+ << QString("");
+}
+
+void tst_QImageReader::readFromResources()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+ QFETCH(QSize, size);
+ QFETCH(QString, message);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ for (int i = 0; i < 2; ++i) {
+ QString file = i ? (":/images/" + fileName) : (prefix + fileName);
+ {
+ // suppress warnings if we expect them
+ if (!message.isEmpty()) {
+ for (int j = 0; j < 5; ++j)
+ QTest::ignoreMessage(QtWarningMsg, message.toLatin1());
+ }
+
+ // 1) full filename, no format
+ QImageReader reader(file);
+ QImage image = reader.read();
+ if (size.isNull())
+ QVERIFY(image.isNull());
+ else
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.size(), size);
+ }
+ {
+ // 2) full filename, with format
+ QImageReader reader(file, format);
+ QImage image = reader.read();
+ if (size.isNull())
+ QVERIFY(image.isNull());
+ else
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.size(), size);
+ }
+ {
+ // 3) full filename, with uppercase format
+ QImageReader reader(file, format.toUpper());
+ QImage image = reader.read();
+ if (size.isNull())
+ QVERIFY(image.isNull());
+ else
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.size(), size);
+ }
+ {
+ // 4) chopped filename, with format
+ QImageReader reader(file.left(file.lastIndexOf(QLatin1Char('.'))), format);
+ QImage image = reader.read();
+ if (size.isNull())
+ QVERIFY(image.isNull());
+ else
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.size(), size);
+ }
+ {
+ // 5) chopped filename, with uppercase format
+ QImageReader reader(file.left(file.lastIndexOf(QLatin1Char('.'))), format.toUpper());
+ QImage image = reader.read();
+ if (size.isNull())
+ QVERIFY(image.isNull());
+ else
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.size(), size);
+ }
+ }
+
+ // Check that the results are identical
+ if (!message.isEmpty()) {
+ QTest::ignoreMessage(QtWarningMsg, message.toLatin1());
+ QTest::ignoreMessage(QtWarningMsg, message.toLatin1());
+ }
+ QCOMPARE(QImageReader(prefix + fileName).read(), QImageReader(":/images/" + fileName).read());
+}
+
+void tst_QImageReader::readCorruptImage_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<bool>("shouldFail");
+ QTest::addColumn<QString>("message");
+ QTest::addColumn<QByteArray>("format");
+ QTest::newRow("corrupt jpeg") << QString("corrupt.jpg") << true
+ << QString("JPEG datastream contains no image")
+ << QByteArray("jpeg");
+ QTest::newRow("corrupt gif") << QString("corrupt.gif") << true << QString("") << QByteArray("gif");
+ QTest::newRow("corrupt mng") << QString("corrupt.mng") << true
+ << QString("MNG error 901: Application signalled I/O error; chunk IHDR; subcode 0:0")
+ << QByteArray("mng");
+ QTest::newRow("corrupt png") << QString("corrupt.png") << true << QString("") << QByteArray("png");
+ QTest::newRow("corrupt bmp") << QString("corrupt.bmp") << true << QString("") << QByteArray("bmp");
+ QTest::newRow("corrupt xpm (colors)") << QString("corrupt-colors.xpm") << true
+ << QString("QImage: XPM color specification is missing: bla9an.n#x")
+ << QByteArray("xpm");
+ QTest::newRow("corrupt xpm (pixels)") << QString("corrupt-pixels.xpm") << true
+ << QString("QImage: XPM pixels missing on image line 3")
+ << QByteArray("xpm");
+ QTest::newRow("corrupt xbm") << QString("corrupt.xbm") << false << QString("") << QByteArray("xbm");
+ QTest::newRow("corrupt tiff") << QString("corrupt-data.tif") << true << QString("") << QByteArray("tiff");
+ QTest::newRow("corrupt svg") << QString("corrupt.svg") << true << QString("") << QByteArray("svg");
+ QTest::newRow("corrupt svgz") << QString("corrupt.svgz") << true << QString("") << QByteArray("svgz");
+}
+
+void tst_QImageReader::readCorruptImage()
+{
+ QFETCH(QString, fileName);
+ QFETCH(bool, shouldFail);
+ QFETCH(QString, message);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ if (!message.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, message.toLatin1());
+ QImageReader reader(prefix + fileName);
+ QVERIFY(reader.canRead());
+ QCOMPARE(reader.read().isNull(), shouldFail);
+}
+
+void tst_QImageReader::readCorruptBmp()
+{
+ QCOMPARE(QImage(prefix + "tst7.bmp").convertToFormat(QImage::Format_ARGB32_Premultiplied), QImage(prefix + "tst7.png").convertToFormat(QImage::Format_ARGB32_Premultiplied));
+}
+
+void tst_QImageReader::supportsOption_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QIntList>("options");
+
+ QTest::newRow("png") << QString("black.png")
+ << (QIntList() << QImageIOHandler::Gamma
+ << QImageIOHandler::Description
+ << QImageIOHandler::Quality
+ << QImageIOHandler::Size);
+}
+
+void tst_QImageReader::supportsOption()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QIntList, options);
+
+ QSet<QImageIOHandler::ImageOption> allOptions;
+ allOptions << QImageIOHandler::Size
+ << QImageIOHandler::ClipRect
+ << QImageIOHandler::Description
+ << QImageIOHandler::ScaledClipRect
+ << QImageIOHandler::ScaledSize
+ << QImageIOHandler::CompressionRatio
+ << QImageIOHandler::Gamma
+ << QImageIOHandler::Quality
+ << QImageIOHandler::Name
+ << QImageIOHandler::SubType
+ << QImageIOHandler::IncrementalReading
+ << QImageIOHandler::Endianness
+ << QImageIOHandler::Animation
+ << QImageIOHandler::BackgroundColor;
+
+ QImageReader reader(prefix + fileName);
+ for (int i = 0; i < options.size(); ++i) {
+ QVERIFY(reader.supportsOption(QImageIOHandler::ImageOption(options.at(i))));
+ allOptions.remove(QImageIOHandler::ImageOption(options.at(i)));
+ }
+
+ foreach (QImageIOHandler::ImageOption option, allOptions)
+ QVERIFY(!reader.supportsOption(option));
+}
+
+void tst_QImageReader::tiffCompression_data()
+{
+ QTest::addColumn<QString>("uncompressedFile");
+ QTest::addColumn<QString>("compressedFile");
+
+ QTest::newRow("TIFF: adobedeflate") << "rgba_nocompression_littleendian.tif"
+ << "rgba_adobedeflate_littleendian.tif";
+ QTest::newRow("TIFF: lzw") << "rgba_nocompression_littleendian.tif"
+ << "rgba_lzw_littleendian.tif";
+ QTest::newRow("TIFF: packbits") << "rgba_nocompression_littleendian.tif"
+ << "rgba_packbits_littleendian.tif";
+ QTest::newRow("TIFF: zipdeflate") << "rgba_nocompression_littleendian.tif"
+ << "rgba_zipdeflate_littleendian.tif";
+}
+
+void tst_QImageReader::tiffCompression()
+{
+ QFETCH(QString, uncompressedFile);
+ QFETCH(QString, compressedFile);
+
+ SKIP_IF_UNSUPPORTED("tiff");
+
+ QImage uncompressedImage(prefix + uncompressedFile);
+ QImage compressedImage(prefix + compressedFile);
+
+ QCOMPARE(uncompressedImage, compressedImage);
+}
+
+void tst_QImageReader::tiffEndianness()
+{
+ SKIP_IF_UNSUPPORTED("tiff");
+
+ QImage littleEndian(prefix + "rgba_nocompression_littleendian.tif");
+ QImage bigEndian(prefix + "rgba_nocompression_bigendian.tif");
+
+ QCOMPARE(littleEndian, bigEndian);
+}
+
+void tst_QImageReader::tiffOrientation_data()
+{
+ QTest::addColumn<QString>("expected");
+ QTest::addColumn<QString>("oriented");
+ QTest::newRow("Indexed TIFF, orientation1") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_1.tiff";
+ QTest::newRow("Indexed TIFF, orientation2") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_2.tiff";
+ QTest::newRow("Indexed TIFF, orientation3") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_3.tiff";
+ QTest::newRow("Indexed TIFF, orientation4") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_4.tiff";
+ QTest::newRow("Indexed TIFF, orientation5") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_5.tiff";
+ QTest::newRow("Indexed TIFF, orientation6") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_6.tiff";
+ QTest::newRow("Indexed TIFF, orientation7") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_7.tiff";
+ QTest::newRow("Indexed TIFF, orientation8") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_8.tiff";
+
+ QTest::newRow("Mono TIFF, orientation1") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_1.tiff";
+ QTest::newRow("Mono TIFF, orientation2") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_2.tiff";
+ QTest::newRow("Mono TIFF, orientation3") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_3.tiff";
+ QTest::newRow("Mono TIFF, orientation4") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_4.tiff";
+ QTest::newRow("Mono TIFF, orientation5") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_5.tiff";
+ QTest::newRow("Mono TIFF, orientation6") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_6.tiff";
+ QTest::newRow("Mono TIFF, orientation7") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_7.tiff";
+ QTest::newRow("Mono TIFF, orientation8") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_8.tiff";
+
+ QTest::newRow("RGB TIFF, orientation1") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_1.tiff";
+ QTest::newRow("RGB TIFF, orientation2") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_2.tiff";
+ QTest::newRow("RGB TIFF, orientation3") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_3.tiff";
+ QTest::newRow("RGB TIFF, orientation4") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_4.tiff";
+ QTest::newRow("RGB TIFF, orientation5") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_5.tiff";
+ QTest::newRow("RGB TIFF, orientation6") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_6.tiff";
+ QTest::newRow("RGB TIFF, orientation7") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_7.tiff";
+ QTest::newRow("RGB TIFF, orientation8") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_8.tiff";
+}
+
+void tst_QImageReader::tiffOrientation()
+{
+ QFETCH(QString, expected);
+ QFETCH(QString, oriented);
+
+ SKIP_IF_UNSUPPORTED("tiff");
+
+ QImage expectedImage(prefix + expected);
+ QImage orientedImage(prefix + oriented);
+ QCOMPARE(expectedImage, orientedImage);
+}
+
+void tst_QImageReader::tiffGrayscale()
+{
+ SKIP_IF_UNSUPPORTED("tiff");
+
+ QImage actualImage(prefix + "grayscale.tif");
+ QImage expectedImage(prefix + "grayscale-ref.tif");
+
+ QCOMPARE(expectedImage, actualImage.convertToFormat(expectedImage.format()));
+}
+
+void tst_QImageReader::dotsPerMeter_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("expectedDotsPerMeterX");
+ QTest::addColumn<int>("expectedDotsPerMeterY");
+ QTest::addColumn<QByteArray>("format");
+ QTest::newRow("TIFF: 72 dpi") << ("rgba_nocompression_littleendian.tif") << qRound(72 * (100 / 2.54)) << qRound(72 * (100 / 2.54)) << QByteArray("tiff");
+ QTest::newRow("TIFF: 100 dpi") << ("image_100dpi.tif") << qRound(100 * (100 / 2.54)) << qRound(100 * (100 / 2.54)) << QByteArray("tiff");
+}
+
+void tst_QImageReader::dotsPerMeter()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, expectedDotsPerMeterX);
+ QFETCH(int, expectedDotsPerMeterY);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImage image(prefix + fileName);
+
+ QCOMPARE(image.dotsPerMeterX(), expectedDotsPerMeterX);
+ QCOMPARE(image.dotsPerMeterY(), expectedDotsPerMeterY);
+}
+
+void tst_QImageReader::physicalDpi_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("expectedPhysicalDpiX");
+ QTest::addColumn<int>("expectedPhysicalDpiY");
+ QTest::addColumn<QByteArray>("format");
+ QTest::newRow("TIFF: 72 dpi") << "rgba_nocompression_littleendian.tif" << 72 << 72 << QByteArray("tiff");
+ QTest::newRow("TIFF: 100 dpi") << "image_100dpi.tif" << 100 << 100 << QByteArray("tiff");
+}
+
+void tst_QImageReader::physicalDpi()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, expectedPhysicalDpiX);
+ QFETCH(int, expectedPhysicalDpiY);
+ QFETCH(QByteArray, format);
+
+ SKIP_IF_UNSUPPORTED(format);
+
+ QImage image(prefix + fileName);
+
+ QCOMPARE(image.physicalDpiX(), expectedPhysicalDpiX);
+ QCOMPARE(image.physicalDpiY(), expectedPhysicalDpiY);
+}
+
+void tst_QImageReader::autoDetectImageFormat()
+{
+ // Assume PNG is supported :-)
+ {
+ // Disables file name extension probing
+ QImageReader reader(prefix + "kollada");
+ reader.setAutoDetectImageFormat(false);
+ QVERIFY(!reader.canRead());
+ QVERIFY(reader.read().isNull());
+ reader.setAutoDetectImageFormat(true);
+ QVERIFY(reader.canRead());
+ QVERIFY(!reader.read().isNull());
+ }
+ {
+ // Disables detection based on suffix
+ QImageReader reader(prefix + "kollada.png");
+ reader.setAutoDetectImageFormat(false);
+ QVERIFY(!reader.canRead());
+ QVERIFY(reader.read().isNull());
+ reader.setAutoDetectImageFormat(true);
+ QVERIFY(reader.canRead());
+ QVERIFY(!reader.read().isNull());
+ }
+ {
+ // Disables detection based on content
+ QImageReader reader(prefix + "kollada-noext");
+ reader.setAutoDetectImageFormat(false);
+ QVERIFY(!reader.canRead());
+ QVERIFY(reader.read().isNull());
+ reader.setAutoDetectImageFormat(true);
+ QVERIFY(reader.canRead());
+ QVERIFY(!reader.read().isNull());
+ }
+
+ if (QImageReader::supportedImageFormats().contains("jpeg")) {
+ QImageReader io(prefix + "YCbCr_rgb.jpg");
+ io.setAutoDetectImageFormat(false);
+ // This should fail since no format string is given
+ QImage image;
+ QVERIFY(!io.read(&image));
+ }
+ if (QImageReader::supportedImageFormats().contains("jpeg")) {
+ QImageReader io(prefix + "YCbCr_rgb.jpg", "jpg");
+ io.setAutoDetectImageFormat(false);
+ QImage image;
+ QVERIFY(io.read(&image));
+ }
+ {
+ QImageReader io(prefix + "tst7.png");
+ io.setAutoDetectImageFormat(false);
+ // This should fail since no format string is given
+ QImage image;
+ QVERIFY(!io.read(&image));
+ }
+ {
+ QImageReader io(prefix + "tst7.png", "png");
+ io.setAutoDetectImageFormat(false);
+ QImage image;
+ QVERIFY(io.read(&image));
+ }
+}
+
+void tst_QImageReader::fileNameProbing()
+{
+ QString name("doesnotexist.png");
+ QImageReader r;
+ r.setFileName(name); // non-existing / non-readable file
+ QCOMPARE(r.fileName(), name);
+
+ r.size();
+ QCOMPARE(r.fileName(), name);
+ r.read();
+ QCOMPARE(r.fileName(), name);
+}
+
+void tst_QImageReader::pixelCompareWithBaseline_data()
+{
+ QTest::addColumn<QString>("fileName");
+
+ QTest::newRow("floppy (16px,32px - 16 colors)") << "35floppy.ico";
+ QTest::newRow("semitransparent") << "semitransparent.ico";
+ QTest::newRow("slightlybrokenBMPHeader") << "kde_favicon.ico";
+ QTest::newRow("sightlybrokenIconHeader") << "connect.ico";
+}
+
+void tst_QImageReader::pixelCompareWithBaseline()
+{
+ QFETCH(QString, fileName);
+
+ static int enteredCount = 0; // Used for better error diagnostics if something fails. We
+ static int loadFailCount = 0; // don't know if the reason load() fails is that the plugin
+ // does not exist or because of a bug in the plugin. But if at
+ // least one file succeeded we know that the plugin was built.
+ // The other failures are then real failures.
+ QImage icoImg;
+ const QString inputFileName(QString::fromAscii("images/%1").arg(fileName));
+ QFileInfo fi(inputFileName);
+
+ ++enteredCount;
+ // might fail if the plugin does not exist, which is ok.
+ if (icoImg.load(inputFileName)) {
+ icoImg = icoImg.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ const QString baselineFileName(QString::fromAscii("baseline/%1.png").arg(fi.baseName()));
+#if 0
+ icoImg.save(baselineFileName);
+#else
+ QImage baseImg;
+ QVERIFY(baseImg.load(baselineFileName));
+ baseImg = baseImg.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ QCOMPARE(int(baseImg.format()), int(icoImg.format()));
+ QCOMPARE(baseImg, icoImg);
+#endif
+ } else {
+ ++loadFailCount;
+ if (enteredCount != loadFailCount) {
+ QFAIL("Plugin is built, but some did not load properly");
+ } else {
+ qWarning("loading failed, check if ico plugin is built");
+ }
+ }
+}
+
+
+void tst_QImageReader::testIgnoresFormatAndExtension_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QString>("extension");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("black.png") << "black" << "png" << "png";
+ QTest::newRow("black.xpm") << "black" << "xpm" << "xpm";
+ QTest::newRow("colorful.bmp") << "colorful" << "bmp" << "bmp";
+ QTest::newRow("image.ppm") << "image" << "ppm" << "ppm";
+ QTest::newRow("image.pbm") << "image" << "pbm" << "pbm";
+ QTest::newRow("image.pgm") << "image" << "pgm" << "pgm";
+
+ QTest::newRow("bat1.gif") << "bat1" << "gif" << "gif";
+
+ QTest::newRow("beavis.jpg") << "beavis" << "jpg" << "jpeg";
+
+ QTest::newRow("fire.mng") << "fire" << "mng" << "mng";
+
+ QTest::newRow("image_100dpi.tif") << "image_100dpi" << "tif" << "tiff";
+
+ QTest::newRow("rect.svg") << "rect" << "svg" << "svg";
+ QTest::newRow("rect.svgz") << "rect" << "svgz" << "svgz";
+}
+
+
+void tst_QImageReader::testIgnoresFormatAndExtension()
+{
+ QFETCH(QString, name);
+ QFETCH(QString, extension);
+ QFETCH(QString, expected);
+
+ SKIP_IF_UNSUPPORTED(expected.toLatin1());
+
+ QList<QByteArray> formats = QImageReader::supportedImageFormats();
+ QString fileNameBase = prefix + name + ".";
+
+ foreach (const QByteArray &f, formats) {
+ if (f == extension)
+ continue;
+ QFile tmp(QDir::tempPath() + "/" + name + "_" + expected + "." + f);
+
+ QVERIFY(QFile::copy(fileNameBase + extension, QFileInfo(tmp).absoluteFilePath()));
+
+ QString format;
+ QImage image;
+ {
+ // image reader needs to be scoped for the remove() to work..
+ QImageReader r;
+ r.setFileName(QFileInfo(tmp).absoluteFilePath());
+ r.setDecideFormatFromContent(true);
+ format = r.format();
+ r.read(&image);
+ }
+
+ tmp.remove();
+
+ QVERIFY(!image.isNull());
+ QCOMPARE(format, expected);
+ }
+}
+
+
+void tst_QImageReader::saveFormat_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+
+ QTest::newRow("Format_Mono") << QImage::Format_Mono;
+ QTest::newRow("Format_MonoLSB") << QImage::Format_MonoLSB;
+ QTest::newRow("Format_Indexed8") << QImage::Format_Indexed8;
+ QTest::newRow("Format_RGB32") << QImage::Format_RGB32;
+ QTest::newRow("Format_ARGB32") << QImage::Format_ARGB32;
+ QTest::newRow("Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("Format_RGB16") << QImage::Format_RGB16;
+ QTest::newRow("Format_ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied;
+ QTest::newRow("Format_RGB666") << QImage::Format_RGB666;
+ QTest::newRow("Format_ARGB6666_Premultiplied") << QImage::Format_ARGB6666_Premultiplied;
+ QTest::newRow("Format_RGB555") << QImage::Format_RGB555;
+ QTest::newRow("Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied;
+ QTest::newRow("Format_RGB888") << QImage::Format_RGB888;
+ QTest::newRow("Format_RGB444") << QImage::Format_RGB444;
+ QTest::newRow("Format_ARGB4444_Premultiplied") << QImage::Format_ARGB4444_Premultiplied;
+}
+
+void tst_QImageReader::saveFormat()
+{
+ QFETCH(QImage::Format, format);
+
+ QImage orig(":/images/kollada.png");
+
+ QImage converted = orig.convertToFormat(format);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QVERIFY(converted.save(&buf, "png"));
+ buf.close();
+ QImage stored = QImage::fromData(buf.buffer(), "png");
+
+ stored = stored.convertToFormat(QImage::Format_ARGB32);
+ converted = converted.convertToFormat(QImage::Format_ARGB32);
+ QCOMPARE(stored, converted);
+}
+
+
+void tst_QImageReader::readText_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QString>("key");
+ QTest::addColumn<QString>("text");
+
+ QTest::newRow("png, tEXt before img") << "txts.png" << "Title" << "PNG";
+ QTest::newRow("png, zTXt before img") << "txts.png" << "Comment" << "Some compressed text.";
+ QTest::newRow("png, tEXt after img") << "txts.png" << "Disclaimer" << "For testing only.";
+ QTest::newRow("png, zTXt after img") << "txts.png" << "Description" << "Rendered by Persistence of Vision (tm) Ray Tracer";
+}
+
+
+void tst_QImageReader::readText()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QString, key);
+ QFETCH(QString, text);
+
+ QImage img(prefix + fileName);
+ QVERIFY(img.textKeys().contains(key));
+ QCOMPARE(img.text(key), text);
+}
+
+
+void tst_QImageReader::preserveTexts_data()
+{
+ QTest::addColumn<QString>("text");
+
+ QTest::newRow("Simple") << "simpletext";
+ QTest::newRow("Whitespace") << " A text with whitespace ";
+ QTest::newRow("Newline") << "A text\nwith newlines\n";
+ QTest::newRow("Double newlines") << "A text\n\nwith double newlines\n\n";
+ QTest::newRow("Long") << QString("A rather long text, at least after many repetitions. ").repeated(100);
+ QString latin1set;
+ int c;
+ for(c = 0x20; c <= 0x7e; c++)
+ latin1set.append(QLatin1Char(c));
+ for(c = 0xa0; c <= 0xff; c++)
+ latin1set.append(QLatin1Char(c));
+ QTest::newRow("All Latin1 chars") << latin1set;
+
+#if 0
+ // Depends on iTXt support in libpng
+ QTest::newRow("Multibyte string") << QString::fromUtf8("\341\233\222\341\233\226\341\232\251\341\232\271\341\232\242\341\233\232\341\232\240");
+#endif
+}
+
+
+void tst_QImageReader::preserveTexts()
+{
+ QFETCH(QString, text);
+ QString key("testkey");
+ QString key2("testkey2");
+ QString text2("Some other text.");
+ QString key3("testkey3");
+ QString text3("Some more other text.");
+
+ QImage img(":/images/kollada.png");
+ img.setText(key, text);
+ img.setText(key2, text2);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QVERIFY(img.save(&buf, "png"));
+ buf.close();
+ QImage stored = QImage::fromData(buf.buffer(), "png");
+ QCOMPARE(stored.text(key), text);
+ QCOMPARE(stored.text(key2), text2);
+
+ QImage img2(":/images/kollada.png");
+ img2.setText(key3, text3);
+ QBuffer buf2;
+ QImageWriter w(&buf2, "png");
+ w.setText(key, text);
+ w.setText(key2, text2);
+ QVERIFY(w.write(img2));
+ buf2.close();
+ QImageReader r(&buf2, "png");
+ QCOMPARE(r.text(key), text.simplified());
+ QCOMPARE(r.text(key2), text2.simplified());
+ QCOMPARE(r.text(key3), text3.simplified());
+}
+
+
+QTEST_MAIN(tst_QImageReader)
+#include "tst_qimagereader.moc"
diff --git a/tests/auto/gui/image/qimagewriter/.gitignore b/tests/auto/gui/image/qimagewriter/.gitignore
new file mode 100644
index 0000000000..9355bcd1bf
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/.gitignore
@@ -0,0 +1 @@
+tst_qimagewriter
diff --git a/tests/auto/gui/image/qimagewriter/images/YCbCr_cmyk.jpg b/tests/auto/gui/image/qimagewriter/images/YCbCr_cmyk.jpg
new file mode 100644
index 0000000000..b8aa9ea609
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/YCbCr_cmyk.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/YCbCr_rgb.jpg b/tests/auto/gui/image/qimagewriter/images/YCbCr_rgb.jpg
new file mode 100644
index 0000000000..8771224cb5
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/YCbCr_rgb.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/beavis.jpg b/tests/auto/gui/image/qimagewriter/images/beavis.jpg
new file mode 100644
index 0000000000..d55504779b
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/beavis.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/colorful.bmp b/tests/auto/gui/image/qimagewriter/images/colorful.bmp
new file mode 100644
index 0000000000..8ea6f4acd7
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/colorful.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/earth.gif b/tests/auto/gui/image/qimagewriter/images/earth.gif
new file mode 100644
index 0000000000..2c229eb110
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/earth.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/font.bmp b/tests/auto/gui/image/qimagewriter/images/font.bmp
new file mode 100644
index 0000000000..28b8c66924
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/font.bmp
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/gnus.xbm b/tests/auto/gui/image/qimagewriter/images/gnus.xbm
new file mode 100644
index 0000000000..58d1ac845a
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/gnus.xbm
@@ -0,0 +1,622 @@
+#define noname_width 271
+#define noname_height 273
+static char noname_bits[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfa,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x49,0xe0,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x97,0xaa,0x8a,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x57,0x2a,0x41,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa9,0x52,0x16,0xfe,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4a,0x49,0x05,
+ 0xf9,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x95,0xaa,0x58,0xf4,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xa5,0x54,0x26,0xe1,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x54,0x49,0x49,0xe4,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x2a,0xa5,
+ 0x2a,0xd1,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0xd5,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0x52,0x95,0x54,0xc4,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,
+ 0x24,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x57,0x29,0xa9,0x92,0x11,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x57,0xd5,0xfa,0xff,0xff,0xab,0xea,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x4a,0x55,0x2a,0x41,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x25,0x29,0xe5,0xff,0xff,0x95,0xa4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa7,0xa4,
+ 0x24,0xa5,0x14,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4a,0xa5,0xd4,0xff,
+ 0x3f,0x52,0xa9,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x29,0x55,0x55,0x55,0x41,0x7e,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xa9,0x54,0xea,0xff,0xdf,0x2a,0x55,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x4a,0x49,0x12,0x7e,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x55,0xa5,0x92,0xff,0x23,0xa5,0x4a,0xd6,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa5,0xa4,0x94,0xaa,0x42,
+ 0x7d,0xff,0xff,0xff,0xff,0xff,0xff,0x9f,0x4a,0x2a,0xa9,0xff,0xad,0x92,0x24,
+ 0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2a,
+ 0x95,0x52,0x52,0x29,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x52,0x49,0x55,
+ 0xfe,0x91,0x54,0x55,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x49,0x29,0x55,0x25,0x85,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0x95,0xaa,0x92,0x7e,0x55,0x55,0xa9,0x4a,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2a,0x50,0x95,0xaa,0x24,0x7e,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x57,0x2a,0x95,0x54,0x79,0x95,0x92,0x92,0x94,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xb9,0x62,0x29,0x49,
+ 0x85,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x49,0x49,0x95,0xba,0xa4,0x54,
+ 0xaa,0x52,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,
+ 0x1a,0xf8,0xa7,0xaa,0x22,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x52,
+ 0x2a,0x75,0x55,0xa5,0x24,0xa5,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xbf,0x5a,0xfd,0x57,0x92,0x94,0x7e,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x4a,0x4a,0x55,0x49,0x89,0x92,0x94,0xaa,0x94,0xf4,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x1a,0xfc,0x2f,0x55,0x05,0x7c,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x55,0xa9,0x4a,0x55,0x2a,0x55,0x55,0x55,0x55,0xe5,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x4e,0xfd,0x5f,
+ 0x29,0xa5,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0xa4,0x54,0x52,0x4a,0x55,0xa9,
+ 0xa4,0x24,0xa5,0x94,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x2f,0x1d,0xfe,0x3f,0x95,0x04,0x7c,0xff,0xfd,0xff,0xff,0xff,0x3f,0x49,0xa5,
+ 0x54,0xa9,0xa4,0x92,0x4a,0x49,0x4a,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xaf,0x44,0xfe,0x5f,0xa9,0x52,0x7d,0xff,0xe5,0xff,0xff,
+ 0xff,0x5f,0x55,0x92,0x2a,0x95,0x52,0x4a,0x52,0xaa,0x52,0x4a,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x16,0xff,0xbf,0x4a,0x05,0x7c,
+ 0xff,0xd9,0xff,0xff,0xff,0x5f,0x95,0x42,0xa5,0x52,0x95,0xaa,0xaa,0xaa,0x94,
+ 0x54,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x43,0xfe,
+ 0xbf,0x54,0x52,0x7d,0x7f,0x25,0xff,0xff,0xff,0xa7,0xa4,0x28,0x92,0x54,0x4a,
+ 0xa5,0x4a,0x92,0xaa,0x4a,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xab,0x12,0xfe,0x7f,0xa5,0x02,0x7c,0x7f,0x55,0xfd,0xff,0xff,0x95,0x2a,
+ 0x82,0x54,0xa5,0x54,0x2a,0xa9,0x2a,0xa5,0x52,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x27,0x4b,0xff,0xff,0x4a,0x29,0x7d,0xff,0x92,0xfe,
+ 0xff,0xff,0x55,0x92,0x20,0xa8,0x94,0x2a,0xa5,0x94,0x52,0x29,0xa9,0xf4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x01,0xff,0x7f,0x52,0x42,
+ 0x7c,0xff,0x25,0xf9,0xff,0x7f,0xaa,0x02,0x8a,0x40,0x29,0x49,0x09,0x41,0x4a,
+ 0x55,0x25,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x57,
+ 0xff,0xff,0x95,0x12,0x7d,0xff,0xa9,0xfa,0xff,0x7f,0x25,0xa9,0x20,0x2a,0xa5,
+ 0xaa,0x42,0x92,0x54,0x92,0x54,0x95,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xaf,0x83,0xff,0xff,0xa9,0x42,0x7e,0xff,0xaa,0xf4,0xff,0xaf,0x54,
+ 0x01,0x82,0x80,0xaa,0x54,0x14,0x08,0xa2,0xaa,0x4a,0xd2,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xef,0xcf,0xd7,0xff,0xff,0x52,0x12,0x7f,0xff,0x4a,
+ 0xea,0xff,0x57,0x92,0xaa,0x28,0x24,0x29,0x25,0x81,0x82,0x08,0x49,0x52,0x55,
+ 0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xdf,0xef,0xe7,0xff,0xff,0x2a,
+ 0x05,0x7e,0xff,0x55,0xd5,0xff,0xa5,0x2a,0x00,0x8e,0x10,0x4a,0x89,0x24,0x28,
+ 0xa0,0xaa,0x2a,0x49,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xe7,0xff,
+ 0xef,0xff,0xff,0xa5,0x50,0x7e,0xff,0x25,0xe5,0xff,0x2a,0xa5,0x52,0x7f,0x85,
+ 0x54,0x35,0x08,0x82,0x0a,0x55,0x95,0xaa,0xfc,0xff,0xff,0xff,0xcf,0xff,0xff,
+ 0xff,0xff,0xd7,0xff,0xff,0xff,0x7f,0x52,0x85,0x7e,0xff,0xab,0x94,0x1e,0x55,
+ 0x2a,0xc8,0xff,0x10,0x90,0x92,0xa0,0x08,0x20,0x24,0x52,0x25,0xfd,0xff,0xff,
+ 0xff,0xef,0xff,0xff,0xff,0xff,0xe9,0xff,0xff,0xff,0xff,0x94,0x10,0x7e,0xff,
+ 0x93,0xaa,0x6a,0x49,0x49,0xf2,0xff,0x85,0x52,0x09,0x0a,0xa2,0x4a,0x92,0x29,
+ 0xa9,0xf2,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0x7f,
+ 0x55,0x25,0x7f,0xff,0x55,0x49,0x49,0x95,0x0a,0xf9,0xff,0x17,0x48,0x26,0x50,
+ 0x08,0x00,0xa9,0x4a,0x95,0xfa,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xf2,
+ 0xff,0xff,0xff,0xff,0x92,0x80,0x7e,0xff,0xa7,0x54,0xaa,0xa4,0x52,0xfc,0xff,
+ 0xaf,0x42,0x89,0xfa,0xbf,0x54,0x20,0xa9,0xa4,0xd4,0xff,0xff,0xff,0xcb,0xff,
+ 0xff,0xff,0xff,0xf5,0xff,0xff,0xff,0xff,0x54,0x29,0x7f,0xff,0x4b,0xa5,0x92,
+ 0x2a,0x01,0xff,0xff,0x1f,0xa8,0x22,0xff,0xff,0x01,0xa5,0x2a,0x55,0xa9,0xff,
+ 0xff,0xff,0xd4,0xff,0xff,0xff,0x7f,0xfa,0xff,0xff,0xff,0x7f,0xa5,0x04,0x7f,
+ 0xff,0x57,0x2a,0x55,0xa9,0x54,0xfe,0xff,0x3f,0x05,0x89,0xff,0xff,0x5f,0x48,
+ 0x92,0x2a,0x95,0xff,0xff,0xff,0xea,0xff,0xff,0xff,0xff,0xd2,0xff,0xff,0xff,
+ 0x7f,0x2a,0x91,0x7f,0xff,0xa9,0x54,0x4a,0x52,0x02,0xff,0xff,0xff,0x50,0xd1,
+ 0xff,0xff,0x1f,0x81,0xaa,0xa4,0x52,0xfe,0xff,0x3f,0xe9,0xff,0xff,0xff,0x7f,
+ 0x1d,0xff,0xff,0xff,0xff,0x54,0x41,0x7f,0xff,0x93,0x92,0x52,0x95,0xc8,0xff,
+ 0xff,0xff,0x8b,0xc4,0xff,0xff,0x7f,0x24,0xa5,0x2a,0x49,0xf9,0xff,0x7f,0xd5,
+ 0xff,0xff,0xff,0xbf,0x4a,0xff,0xff,0xff,0xff,0x4a,0x14,0x7f,0xff,0x28,0xa5,
+ 0x94,0x2a,0xa0,0xff,0xff,0x7f,0x22,0xf0,0xff,0xff,0x7f,0x12,0x94,0xa4,0xaa,
+ 0xea,0xff,0xaf,0xea,0xff,0xff,0xff,0x5f,0x8e,0xff,0xff,0xff,0x7f,0xa9,0x40,
+ 0x7f,0xff,0x48,0x55,0x55,0x12,0xca,0xff,0xff,0xff,0x0a,0xf5,0xff,0xff,0xff,
+ 0x80,0x52,0x95,0x54,0xaa,0xfe,0x55,0xc4,0xff,0xff,0xff,0x5f,0xa5,0xff,0xff,
+ 0xff,0xff,0x94,0x14,0x7f,0xff,0x52,0x2a,0xa9,0x4a,0xe1,0xff,0xff,0xbf,0x24,
+ 0xf0,0xff,0xff,0xff,0x0b,0x28,0xa9,0x92,0x24,0x55,0x49,0xe5,0xd7,0xff,0xff,
+ 0xa7,0x8a,0xff,0xff,0xff,0x7f,0xa5,0xc0,0x7f,0xff,0x50,0x49,0x95,0x04,0xf8,
+ 0xff,0xff,0x5f,0x1f,0xfd,0xff,0xff,0xff,0x47,0x45,0x55,0xaa,0xaa,0x4a,0xaa,
+ 0xea,0xaf,0xff,0xff,0x2b,0xc3,0xff,0xff,0xff,0x7f,0x55,0x94,0x7f,0x7f,0x4a,
+ 0x55,0x52,0x51,0xfe,0xff,0xff,0x5f,0x4e,0xf8,0xff,0xff,0xff,0x1f,0x50,0x92,
+ 0x52,0x49,0xa9,0x92,0xe4,0xd3,0xff,0xff,0x4b,0xd5,0xff,0xff,0xff,0xff,0x94,
+ 0xc0,0x7f,0x3f,0xa0,0xa4,0xaa,0x04,0xfe,0xff,0xff,0xa7,0x1d,0xfd,0xff,0xff,
+ 0xff,0x9f,0x84,0xaa,0x4a,0xaa,0x24,0x55,0xf2,0x2b,0xff,0x7f,0xa9,0xc1,0xff,
+ 0xff,0xff,0x7f,0x4a,0x95,0x7f,0xbf,0x2a,0x95,0x24,0x50,0xff,0xff,0xff,0x97,
+ 0x5e,0xfe,0xff,0xff,0xff,0x3f,0x92,0x24,0x95,0x92,0xaa,0xa4,0xf2,0xcb,0xff,
+ 0x5f,0xd5,0xe5,0xff,0xff,0xff,0xff,0x52,0x80,0x7f,0x3f,0xa0,0x52,0x15,0x85,
+ 0xff,0xff,0xff,0xd7,0x38,0xfe,0xff,0xff,0xff,0xff,0x20,0xaa,0x52,0x55,0x55,
+ 0x55,0xf9,0x29,0xfd,0xab,0xa4,0xf0,0xff,0xff,0xff,0x7f,0x29,0xa9,0x7f,0xff,
+ 0x42,0x25,0x49,0xe8,0xff,0xff,0xff,0x69,0x7a,0xff,0xff,0xff,0xff,0xff,0x82,
+ 0x52,0xaa,0x24,0x89,0x4a,0xf8,0x55,0x2a,0x49,0x95,0xf5,0xff,0xff,0xff,0xbf,
+ 0x2a,0xc4,0x7f,0x7f,0x90,0x54,0x15,0xe2,0xff,0xff,0xff,0x25,0xbc,0xff,0xff,
+ 0xff,0xff,0xff,0x29,0x48,0x49,0xaa,0xaa,0xa4,0xfa,0x95,0x92,0x54,0x52,0xf0,
+ 0xff,0xff,0xff,0xbf,0x4a,0xd1,0x7f,0xff,0x05,0xaa,0x40,0xf8,0xff,0xff,0x7f,
+ 0xaa,0xfc,0xff,0xff,0xff,0xff,0xff,0x43,0xa9,0xaa,0x4a,0x52,0xa9,0xf8,0xa4,
+ 0xaa,0x52,0x95,0xfc,0xff,0xff,0xff,0x7f,0x52,0xc0,0x7f,0xff,0xa1,0x00,0x24,
+ 0xfa,0xff,0xff,0xff,0x0a,0xfe,0xff,0xff,0xff,0xff,0xff,0x17,0x92,0x24,0xa5,
+ 0x2a,0x55,0xfe,0xaa,0xa4,0x2a,0x29,0xf9,0xff,0xff,0xff,0xbf,0x2a,0xea,0x7f,
+ 0xff,0x05,0x92,0x90,0xfc,0xff,0xff,0xbf,0xa4,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0xa0,0xaa,0x54,0x49,0x25,0x7c,0x49,0x95,0xa4,0x12,0xfc,0xff,0xff,0xff,
+ 0x7f,0x8a,0xe0,0x7f,0xff,0xa3,0x04,0x05,0xfe,0xff,0xff,0xbf,0x06,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x49,0x95,0x52,0xaa,0x12,0x7f,0x55,0x52,0x55,0x0a,
+ 0xfd,0xff,0xff,0xff,0x3f,0x29,0xe8,0x7f,0xff,0x0f,0x50,0x50,0xff,0xff,0xff,
+ 0x5f,0xca,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x04,0xa9,0x4a,0x25,0x45,0x3e,
+ 0xa9,0x2a,0xa9,0xa2,0xfc,0xff,0xff,0xff,0x7f,0x55,0xe1,0x7f,0xff,0x27,0x05,
+ 0xc4,0xff,0xff,0xff,0x9f,0x91,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x41,0x4a,
+ 0x29,0xa9,0x12,0x5e,0x95,0x94,0x4a,0x0a,0xfe,0xff,0xff,0xff,0xbf,0x12,0xf4,
+ 0x7f,0xff,0x8f,0x50,0xf1,0xff,0xff,0xff,0xa7,0xc2,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x14,0x92,0xaa,0x4a,0xa2,0xbf,0xa4,0x52,0x95,0x22,0xff,0xff,0xff,
+ 0xff,0x3f,0x45,0xf2,0x7f,0xff,0x3f,0x04,0xf4,0xff,0xff,0xff,0xd7,0xe8,0xff,
+ 0xff,0xff,0xff,0x5f,0xff,0xff,0x83,0xa8,0x94,0x54,0x09,0x2f,0x55,0x4a,0x52,
+ 0x49,0xff,0xff,0xff,0xff,0x5f,0x99,0xf0,0x7f,0xff,0x7f,0x51,0xfc,0xff,0xff,
+ 0xff,0x6b,0xf1,0xff,0xff,0xff,0xff,0x5f,0xfd,0xff,0x2b,0x2a,0xa9,0x12,0x20,
+ 0x5f,0xa9,0xaa,0x54,0x00,0xff,0xff,0xff,0xff,0x5f,0x15,0xf2,0x7f,0xff,0xff,
+ 0x8f,0xff,0xff,0xff,0xff,0x2b,0xfc,0xff,0xff,0xff,0xff,0x2f,0xfd,0xff,0x87,
+ 0xa0,0x4a,0xaa,0x8a,0x9f,0x4a,0x52,0x15,0xa9,0xff,0xff,0xff,0xff,0x5f,0x8a,
+ 0xfc,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x94,0xf8,0xff,0xff,0xff,0xff,
+ 0x57,0xf2,0xff,0x2f,0x82,0x52,0x05,0xd0,0x2f,0x95,0x4a,0x49,0x84,0xff,0xff,
+ 0xff,0xff,0xbf,0x24,0xf8,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x12,0xfd,
+ 0xff,0xff,0xff,0xff,0x4b,0xd5,0xff,0x9f,0x28,0x54,0x48,0xc5,0xbf,0x52,0x55,
+ 0x0a,0xe1,0xff,0xff,0xff,0xff,0x9f,0x4a,0xfa,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1a,0xfe,0xff,0xff,0xff,0xff,0x57,0xa9,0xff,0x3f,0x82,0x00,0x21,
+ 0xf0,0x5f,0x2a,0x49,0x21,0xc4,0xff,0xff,0xff,0xff,0xaf,0x1a,0xfd,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x85,0xff,0xff,0xff,0xff,0xff,0x29,0xa5,0xff,
+ 0xff,0x24,0x52,0x88,0xfc,0xbf,0x92,0x2a,0x09,0xf1,0xff,0xff,0xff,0xff,0x9f,
+ 0x4c,0xfc,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x15,0xff,0xff,0xff,0x7f,
+ 0xff,0xa5,0x4a,0xff,0xff,0x90,0x08,0x01,0xfe,0x3f,0x55,0x52,0x24,0xf4,0xff,
+ 0xff,0xff,0xff,0xaf,0x02,0xfd,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xc6,
+ 0xff,0xff,0xff,0xbf,0xfe,0x95,0x54,0xff,0xff,0x05,0x42,0xa8,0xfe,0xbf,0xa4,
+ 0x2a,0x41,0xf9,0xff,0xff,0xff,0xff,0x5f,0x55,0xfc,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x4f,0xd0,0xff,0xff,0xff,0xbf,0x7c,0xaa,0x92,0xfc,0xff,0x53,0x08,
+ 0x01,0xff,0x1f,0x4a,0x01,0x04,0xfc,0xff,0xff,0xff,0xff,0x27,0x05,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xc5,0xff,0xff,0xff,0x4f,0xbf,0x52,0xaa,
+ 0xfe,0xff,0x07,0x42,0xea,0xff,0xbf,0x50,0x54,0x51,0xff,0xff,0xff,0xff,0xff,
+ 0x97,0x56,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xf0,0xff,0xff,0xff,
+ 0x2f,0x7f,0xa5,0x54,0xfd,0xff,0x3f,0x09,0xe0,0xff,0x1f,0x02,0x01,0x04,0xff,
+ 0xff,0xff,0xff,0xff,0xaf,0x02,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,
+ 0xf5,0xff,0xff,0xff,0xab,0x9f,0x94,0x92,0xfc,0xff,0xff,0x40,0xfd,0xff,0x9f,
+ 0x48,0x48,0xa1,0xff,0xff,0xff,0xff,0xff,0xa7,0x56,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x6b,0xf8,0xff,0xff,0xff,0xa4,0x5f,0xa9,0x2a,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x22,0x21,0xc4,0xff,0xff,0xff,0xff,0xff,0x2f,0x03,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0xfa,0xff,0xff,0x7f,0xd5,0x2f,0xa5,
+ 0xa4,0xfa,0xff,0xff,0xff,0xff,0xff,0xbf,0x08,0x08,0xf9,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0x4a,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x94,0xfc,0xff,0xff,
+ 0x7f,0x69,0xac,0x2a,0x55,0xf9,0xff,0xff,0xff,0xff,0xff,0x7f,0xa2,0x22,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0x53,0x21,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x15,0xfe,0xff,0xff,0x9f,0x2a,0x95,0x94,0x92,0xf4,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x08,0x88,0xfe,0xff,0xff,0xff,0xff,0xff,0x57,0x8b,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xa9,0xfe,0xff,0xff,0x5f,0x52,0xbc,0x52,0x55,0xf5,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xa1,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x7f,0x0d,0xff,0xff,0xff,0x57,0x15,0x3f,
+ 0x55,0x49,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xc8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xd7,0x89,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xbf,0xd6,0xff,0xff,
+ 0xff,0x4b,0x45,0x3f,0x49,0xaa,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xf9,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xc9,0xe2,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x81,0xff,0xff,0xff,0x29,0x11,0x5f,0x28,0x55,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0xc8,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0x5f,0xd6,0xff,0xff,0x7f,0xaa,0xc2,0x0f,0x55,0x49,0xea,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa5,
+ 0xe2,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x9f,0xe1,0xff,0xff,0xbf,0x4a,0xd1,
+ 0x5f,0x48,0xa5,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xe9,0xe0,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x27,0xf4,0xff,
+ 0xff,0xbf,0x94,0xc4,0x07,0x91,0x2a,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xca,0xea,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0xf1,0xff,0xff,0x9f,0x52,0xe0,0x4b,0x44,0x52,0xe9,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6a,0xe0,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0x4b,0xfc,0xff,0xff,0xab,0x2a,0xf5,0x0f,0x51,0xa5,
+ 0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x69,0xe5,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x55,0xf8,0xff,0xff,0x95,0x14,
+ 0xf0,0x5f,0x84,0x54,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x75,0xf0,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x13,0xfd,
+ 0xff,0xff,0xa5,0x42,0xf9,0x7f,0x91,0x4a,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xb2,0xfa,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0x54,0xfe,0xff,0x7f,0x52,0x12,0xfa,0xff,0x20,0xa5,0xe4,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x34,0xf8,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0x25,0xff,0xff,0xaf,0xaa,0x48,0xfc,0xff,0x0b,
+ 0x29,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xb5,0xf8,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x52,0xff,0xff,0x2f,0x49,
+ 0x02,0xfe,0xff,0x43,0xaa,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x3a,0xfa,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0x4a,
+ 0xff,0xff,0xa5,0x2a,0xa9,0xff,0xff,0x17,0x25,0xe9,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x9a,0xfc,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0x2a,0xff,0x7f,0x95,0x54,0x80,0xff,0xff,0x07,0xa9,0xea,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x1d,0xfc,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0x3f,0xa9,0xfe,0x7f,0xa9,0x12,0xe5,0xff,0xff,
+ 0x5f,0x4a,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x5f,0xad,0xfe,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0x95,0xea,0x97,0x54,
+ 0x4a,0xf0,0xff,0xff,0x1f,0xa8,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x5f,0x0e,0xfe,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,
+ 0x52,0x55,0xa9,0x92,0x02,0xfd,0xff,0xff,0x5f,0x53,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x5e,0xfe,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xbf,0x2a,0x49,0x4a,0x55,0x49,0xfc,0xff,0xff,0x3f,0x94,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0x0f,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4f,0xa5,0xaa,0x92,0xa4,0x20,0xff,0xff,
+ 0xff,0xbf,0xa4,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x5f,0x57,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,0x52,0x52,0xaa,
+ 0x2a,0x0a,0xff,0xff,0xff,0x7f,0x54,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x07,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xa7,0x94,0x4a,0x55,0x4a,0xa0,0xff,0xff,0xff,0xff,0xa8,0xfa,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x57,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0x2f,0x55,0xa9,0x92,0x12,0xe9,0xff,0xff,0xff,0x7f,0x24,
+ 0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,
+ 0x87,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0xa5,0x4a,0xaa,0x44,0xf4,0xff,
+ 0xff,0xff,0xff,0x55,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0xab,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xab,0x94,0xa4,
+ 0x92,0x12,0xf9,0xff,0xff,0xff,0xff,0xa8,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xab,0x83,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0x47,0xa9,0x2a,0x55,0x40,0xfc,0xff,0xff,0xff,0xff,0x25,0xf5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xe7,0xff,0xff,0xff,0xff,0xff,0xd7,0x97,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0x33,0x55,0xa9,0x24,0x15,0xfe,0xff,0xff,0xff,0xff,
+ 0x95,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,
+ 0x93,0xc3,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0x25,0xa5,0x2a,0x40,0xff,
+ 0xff,0xff,0xff,0xff,0xa9,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xff,
+ 0xff,0xff,0xff,0xff,0xe7,0xd5,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4b,0x92,
+ 0x54,0x92,0xd4,0xff,0xff,0xff,0xff,0xff,0x55,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xe9,0xff,0xff,0xff,0xff,0xff,0xd5,0xc1,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0x97,0xaa,0x4a,0x05,0xe2,0xff,0xff,0xff,0xff,0xff,0x25,0xf1,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xfd,0xff,0xff,0xff,0xff,0xd5,0xea,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0x55,0x25,0xa1,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0x95,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe8,0xfa,0xff,0xff,0xff,
+ 0xff,0xea,0xe0,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xa7,0x24,0x59,0x04,0xfa,
+ 0xff,0xff,0xff,0xff,0xff,0xa9,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe2,
+ 0xfd,0xff,0xff,0xff,0xff,0xc9,0xe9,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4f,
+ 0x52,0x05,0xa1,0xfc,0xff,0xff,0xff,0xff,0xff,0xa5,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x70,0xf9,0xff,0xff,0xff,0xff,0x74,0xe2,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0x47,0x95,0x92,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xe2,0xfa,0xff,0xff,0xff,0xff,0x72,0xe8,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x97,0xaa,0x20,0xd0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x55,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xb8,0xfc,0xff,0xff,
+ 0xff,0xff,0xea,0xe2,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x07,0x04,0x82,0xc2,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x29,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x71,0xfd,0xff,0xff,0xff,0x7f,0x2a,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0x4f,0x91,0x28,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x54,0xfe,0xff,0xff,0xff,0x7f,0x75,0xf2,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0x27,0x44,0x82,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x29,
+ 0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0xb8,0xfc,0xff,0xff,0xff,0xbf,0x14,
+ 0xf1,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x0f,0x11,0x20,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x55,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x9a,0xfe,0xff,
+ 0xff,0xff,0x7f,0x5a,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,0x40,0x85,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x09,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0x2d,0xfd,0xff,0xff,0xff,0x9f,0x12,0xf9,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0x3f,0x14,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0xa6,0xfe,0xff,0xff,0xff,0x5f,0x4d,0xfa,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0x40,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x09,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0x4b,0xfe,0xff,0xff,0xff,0xbf,
+ 0x2c,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x43,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x57,0xff,
+ 0xff,0xff,0xff,0x5f,0x0a,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x89,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xd5,0xa9,0xff,0xff,0xff,0xff,0xaf,0x5a,0xfc,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa3,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x81,0x95,0xff,0xff,0xff,0xff,0x9f,0x06,0xfd,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xc9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xca,0xa5,0xff,0xff,0xff,0xff,
+ 0x2f,0x95,0xfc,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xea,
+ 0xff,0xff,0xff,0xff,0xaf,0x26,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xf5,0xf4,0xff,0xff,0xff,0xff,0xaf,0x86,0xfe,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc1,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x70,0xe5,0xff,0xff,0xff,0xff,0x4f,0x2e,0xfe,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xb2,0xfa,0xff,0xff,0xff,
+ 0xff,0x57,0x83,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xf3,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x78,
+ 0xf2,0xff,0xff,0xff,0xff,0xa7,0x22,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x5f,0x5d,0xfd,0xff,0xff,0xff,0xff,0x97,0x87,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x3c,0xfd,0xff,0xff,0xff,0xff,0x53,0xa3,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xac,0xfe,0xff,0xff,
+ 0xff,0xff,0x57,0x95,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,
+ 0x9e,0xfe,0xff,0xff,0xff,0xff,0x97,0x81,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x57,0xfe,0xff,0xff,0xff,0xff,0xa9,0xa5,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0xaf,0xff,0xff,0xff,0xff,0xff,0x4b,
+ 0x89,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0x93,0xff,0xff,
+ 0xff,0xff,0xff,0x95,0xa2,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x83,0xab,0xff,0xff,0xff,0xff,0xff,0xd3,0xc8,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,
+ 0xff,0xff,0xff,0xff,0xe9,0xa5,0xff,0xff,0xff,0xff,0xff,0xa5,0xe1,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xd5,0xff,0xff,0xff,0xff,0xff,
+ 0xd5,0xc8,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xea,0xea,0xff,
+ 0xff,0xff,0xff,0xff,0x14,0xc1,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xff,0xff,
+ 0xff,0xe0,0xe4,0xff,0xff,0xff,0xff,0xff,0x65,0xe8,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,
+ 0xff,0xff,0xff,0xff,0x3f,0x72,0xe9,0xff,0xff,0xff,0xff,0xff,0x6a,0xe1,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xbf,0xb8,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0x52,0xea,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xff,0x1f,0x7a,0xf5,
+ 0xff,0xff,0xff,0xff,0x7f,0x2a,0xe0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,
+ 0xff,0x8f,0x58,0xfa,0xff,0xff,0xff,0xff,0x7f,0x25,0xf5,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xb5,0xff,0xff,0xdf,0xff,0x57,0x5e,0xfd,0xff,0xff,0xff,0xff,0xff,0x34,0xe0,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xca,0xff,0xff,0x8f,0xff,0x07,0xac,0xfc,0xff,0xff,0xff,
+ 0xff,0x7f,0x2a,0xf5,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd4,0xff,0xff,0x57,0xff,0x2b,0x2d,
+ 0xfd,0xff,0xff,0xff,0xff,0xff,0xb2,0xf0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd2,0xff,0xff,
+ 0x07,0xff,0x43,0x4a,0xff,0xff,0xff,0xff,0xff,0xbf,0x2a,0xf8,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0xc5,0xff,0xff,0x2b,0xfe,0x08,0xab,0xfe,0xff,0xff,0xff,0xff,0x7f,0xaa,
+ 0xf2,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0xea,0xff,0xff,0x83,0x36,0x20,0x55,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x15,0xf0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0xc2,0xff,0xff,0x48,0x4a,0x85,
+ 0x49,0xff,0xff,0xff,0xff,0xff,0x7f,0x59,0xfa,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0xf5,0xff,
+ 0x7f,0x10,0x29,0x50,0xa5,0xff,0xff,0xff,0xff,0xff,0x3f,0x15,0xf9,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0xe4,0xff,0x7f,0x05,0x95,0x42,0xd5,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x35,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xab,0xea,0xff,0xbf,0xa0,0x24,0xa8,0xd4,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x19,0xf9,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x27,0xe5,0xff,0x3f,0x92,0xaa,
+ 0x50,0xe9,0xff,0xff,0xff,0xff,0xff,0x9f,0x4a,0xfc,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa9,0xe2,
+ 0xff,0x9f,0xa0,0xaa,0x2a,0xf5,0xff,0xff,0xff,0xff,0xff,0x5f,0x1a,0xf9,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x95,0xf8,0xff,0x5f,0x4a,0x92,0x4a,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xbf,0x4a,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x52,0xf2,0xff,0x1f,0x20,0x49,0xa5,0xfa,0xff,
+ 0xff,0xff,0xff,0xff,0x5f,0x1a,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaa,0xf8,0xff,0x47,0xa9,
+ 0x2a,0x29,0xf9,0xff,0xff,0xff,0xff,0xff,0xbf,0x0a,0xfc,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x49,
+ 0xf2,0xff,0x17,0x92,0xaa,0xaa,0xfe,0xff,0xff,0xff,0xff,0xff,0x9f,0xac,0xfe,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x9f,0x2a,0xf8,0xff,0x43,0xa8,0x24,0x25,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0x0a,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x94,0xfa,0xff,0x91,0x54,0xaa,0x52,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x2f,0x4d,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0x45,0xfc,0xff,0x03,
+ 0x92,0x52,0xaa,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x06,0xfc,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,
+ 0x12,0xfe,0xff,0x50,0xaa,0x2a,0x95,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0xa5,
+ 0xfe,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x44,0xff,0xff,0x0a,0x25,0xa5,0xa4,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x97,0x06,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0x15,0xff,0xff,0x40,0xa9,0x92,0xea,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x55,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xa1,0xff,0x7f,
+ 0x92,0x4a,0xaa,0xd4,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x06,0xfc,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x95,0x8a,0xff,0x3f,0x84,0x54,0xa9,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,
+ 0x25,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x52,0xe0,0xff,0xbf,0x50,0xa9,0x4a,0xf2,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x8e,0xfe,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xa9,0xea,0xff,0x3f,0x24,0x95,0x54,
+ 0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x23,0xfe,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x4a,0xf0,0xff,
+ 0x9f,0x50,0x69,0x49,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x8b,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xa5,0xf4,0xff,0x0f,0x2d,0x75,0xaa,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xaf,0x03,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9f,0x14,0xfa,0xff,0x2f,0xa8,0xfa,0x25,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x97,0xd7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xaa,0xfc,0xff,0x0f,0x4d,0xfd,
+ 0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0x83,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x12,0xfc,
+ 0xff,0x27,0x92,0xfe,0xcb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0x0a,0xff,0xff,0x83,0x56,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xef,0xc7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xab,0x24,0xff,0xff,0x2b,0xaa,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xe7,0xef,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x45,0xff,0xff,0x05,0x95,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0x82,
+ 0xff,0xff,0x51,0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xa9,0xe8,0xff,0xff,0x85,0xca,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x52,0xc1,0xff,0xff,0x90,0xd5,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x4d,0xe8,0xff,0xff,0xa5,
+ 0xe4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x51,
+ 0xf2,0xff,0x7f,0x40,0xd5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x95,0xf8,0xff,0x7f,0xa9,0xea,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x15,0xfa,0xff,0x3f,0xa4,0xf4,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xa4,0xfc,0xff,0x7f,
+ 0x71,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,
+ 0x15,0xfe,0xff,0x3f,0x94,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x0a,0xff,0xff,0x1f,0x79,0xf2,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0xa4,0xff,0xff,0x5f,0x8c,0xfa,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x53,0x82,0xff,0xff,
+ 0x1f,0x5c,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xa4,0x92,0xff,0xff,0xbf,0x56,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9a,0xc4,0xff,0xff,0x0f,0x2e,0xfd,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa2,0xf0,0xff,0xff,0xaf,0xa7,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x55,0xe4,0xff,
+ 0xff,0x0f,0x57,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xbf,0x54,0xf2,0xff,0xff,0x9f,0x4b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9f,0x92,0xf8,0xff,0xff,0xc7,0xab,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x15,0xfe,0xff,0xff,0x97,0xd7,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa7,0x94,0xfc,
+ 0xff,0xff,0xc7,0xe3,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x2f,0x05,0xfe,0xff,0xff,0xcf,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x53,0xa9,0xff,0xff,0xff,0xd3,0xeb,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x05,0xff,0xff,0xff,0xe3,
+ 0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x54,0xc2,
+ 0xff,0xff,0xff,0xeb,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x95,0xc8,0xff,0xff,0xff,0xf3,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xa5,0xd2,0xff,0xff,0xff,0xff,0xf5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xaa,0xe0,0xff,0xff,0xff,
+ 0xff,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x49,
+ 0xf8,0xff,0xff,0xff,0xff,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x9f,0x2a,0xf5,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x4a,0xf8,0xff,0xff,0xff,0xff,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x14,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,
+ 0x4a,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xab,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0x52,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x53,0x85,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x54,0xa2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x4a,0xc9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xa5,0xe0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x94,0xe4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x5f,0x55,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0x12,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x54,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x0a,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x53,0x45,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x97,0x14,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x45,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x54,0x82,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x4a,0xe9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x52,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x55,0xe8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x24,
+ 0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x55,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x24,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x15,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,
+ 0x49,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x2f,0x95,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x01,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0xd5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x57,0x81,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x97,0xd4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xe0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x93,0xf4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x57,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x2b,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x89,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x05,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x49,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x89,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xe9,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x9f,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x6f,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x9f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f};
diff --git a/tests/auto/gui/image/qimagewriter/images/kollada.png b/tests/auto/gui/image/qimagewriter/images/kollada.png
new file mode 100644
index 0000000000..2abd4bb763
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/kollada.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/marble.xpm b/tests/auto/gui/image/qimagewriter/images/marble.xpm
new file mode 100644
index 0000000000..e59830bbe9
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/marble.xpm
@@ -0,0 +1,329 @@
+/* XPM */
+static char *dummy[]={
+"240 240 86 2",
+"#t c #959595",
+"#r c #9a9a9a",
+"#l c #9b9b9b",
+"#e c #9c9c9c",
+"#f c #9d9d9d",
+"#n c #9e9e9e",
+"#q c #9f9f9f",
+"#j c #a0a0a0",
+"#k c #a1a1a1",
+"## c #a2a2a2",
+"#g c #a3a3a3",
+"#s c #a4a4a4",
+"#d c #a5a5a5",
+"#b c #a6a6a6",
+"#p c #a7a7a7",
+".8 c #a8a8a8",
+"#o c #aaaaaa",
+".5 c #ababab",
+"#a c #acacac",
+".6 c #adadad",
+".9 c #aeaeae",
+".7 c #afafaf",
+"#i c #b0b0b0",
+"#. c #b1b1b1",
+"#h c #b2b2b2",
+".4 c #b3b3b3",
+"#c c #b4b4b4",
+".3 c #b5b5b5",
+".U c #b6b6b6",
+".O c #b7b7b7",
+".1 c #b8b8b8",
+".V c #b9b9b9",
+".2 c #bababa",
+".W c #bbbbbb",
+".X c #bcbcbc",
+".Z c #bdbdbd",
+".L c #bebebe",
+".Y c #bfbfbf",
+".N c #c0c0c0",
+".R c #c1c1c1",
+".M c #c2c2c2",
+".P c #c3c3c3",
+".S c #c4c4c4",
+".Q c #c5c5c5",
+".T c #c6c6c6",
+".H c #c7c7c7",
+".E c #c8c8c8",
+".K c #c9c9c9",
+".F c #cacaca",
+".I c #cbcbcb",
+".J c #cccccc",
+".B c #cdcdcd",
+".G c #cecece",
+".z c #cfcfcf",
+".D c #d0d0d0",
+".A c #d1d1d1",
+".C c #d2d2d2",
+".o c #d3d3d3",
+".y c #d4d4d4",
+".v c #d5d5d5",
+".n c #d6d6d6",
+".u c #d7d7d7",
+".w c #d8d8d8",
+".p c #d9d9d9",
+".m c #dadada",
+".h c #dbdbdb",
+".s c #dcdcdc",
+".g c #dddddd",
+".x c #dedede",
+".i c #dfdfdf",
+".f c #e0e0e0",
+".q c #e1e1e1",
+"Qt c #e2e2e2",
+".d c #e3e3e3",
+".# c #e4e4e4",
+".c c #e5e5e5",
+".r c #e6e6e6",
+".a c #e7e7e7",
+".b c #e8e8e8",
+".l c #e9e9e9",
+".e c #eaeaea",
+".t c #ebebeb",
+".j c #ececec",
+".k c #eeeeee",
+".0 c #f0f0f0",
+"#m c #f2f2f2",
+"Qt.#.a.a.a.b.c.d.e.e.a.b.a.c.c.b.c.c.cQt.f.f.g.h.g.h.g.h.f.i.i.iQtQtQtQtQt.cQtQtQt.i.f.f.fQt.d.c.a.a.a.a.a.a.a.a.a.b.a.a.a.c.a.c.e.e.e.e.e.e.j.e.j.j.j.j.j.j.k.j.k.j.k.j.j.k.j.j.e.e.e.e.l.a.a.a.#.c.#.c.a.a.a.e.e.e.l.e.e.l.e.e.e.e.e.e.e.e.e.e.j.e.j.j.j.e.j.e.e.e.l.e.e.l.e.e.l.e.e.l.e.e.l.e.l.e.l.e.l.e.l.e.c.c.#.#QtQt.m.g.n.o.p.i.i.m.i.#.#.#.#.#QtQt.qQt.#.#.#.#.#.#.#.#.a.a.a.a.a.a.r.a.a.r.a.r.a.r.a.r.a.r.a.a.#.c.c.c.r.a.r.l.a.a.a.a.e.e.l.a.a.a.c.c.r.#.s.h.h.p.n.h.f.i.gQt.#.d.d.f",
+".h.g.c.a.a.a.r.c.e.a.b.c.c.a.c.c.r.cQtQt.f.i.g.h.h.h.p.g.g.g.g.i.iQtQtQtQtQtQtQt.f.iQt.q.fQtQt.d.l.a.l.a.l.a.l.a.b.a.b.a.r.a.r.a.e.l.j.l.j.l.e.e.t.e.j.e.j.j.j.e.j.k.j.j.k.j.j.k.e.e.l.e.e.a.l.a.#.c.#.c.a.l.a.e.e.l.e.e.l.e.e.l.e.e.e.e.e.e.e.b.j.e.j.j.e.j.e.j.e.l.e.e.l.e.l.e.l.b.l.e.e.l.e.e.e.l.b.l.b.l.b.l.#.aQt.c.i.f.i.m.p.u.h.i.i.qQtQt.q.#.r.#Qt.#QtQtQt.#.#.#.c.c.#.c.r.l.r.l.a.r.a.l.#.a.r.a.r.a.r.a.r.a.r.c.r.c.a.c.r.a.r.a.c.a.c.a.l.e.e.a.b.cQt.c.qQt.i.m.p.v.p.m.f.sQtQt.q.cQt.q",
+".v.h.i.f.a.r.a.b.a.b.a.c.a.r.c.c.c.cQtQt.f.f.g.h.u.u.u.p.u.h.g.hQtQtQtQtQtQtQtQt.i.fQt.fQt.d.c.c.a.a.a.a.a.a.a.a.a.r.a.c.a.c.a.c.e.e.e.e.e.e.j.e.j.l.j.j.j.j.k.j.k.e.j.j.j.j.j.e.e.e.e.e.l.a.a.r.cQt.c.c.a.a.b.a.l.e.l.e.e.l.e.l.e.b.e.e.b.e.e.e.e.j.j.j.e.j.e.t.e.l.e.l.e.b.l.e.b.a.e.b.l.e.b.l.b.a.e.a.e.a.e.a.a.a.#QtQtQt.i.g.p.p.pQtQt.#Qt.q.#.a.r.#.#Qt.#Qt.a.r.c.r.a.r.a.r.a.a.a.r.a.a.r.a.#.r.a.r.a.r.a.r.a.r.a.a.c.c.#.a.a.a.a.a.r.a.a.a.e.e.l.a.a.c.c.c.a.i.i.p.p.u.h.m.i.f.i.c.c.c.d.f",
+".h.h.m.f.cQt.b.b.a.c.a.c.c.c.d.d.fQtQtQt.f.i.g.g.v.u.p.v.p.u.h.h.i.g.i.m.gQtQtQt.s.qQtQtQt.c.#.c.a.a.e.a.l.b.l.a.b.a.b.a.r.a.r.a.e.e.t.e.t.e.l.e.l.j.e.e.j.e.j.j.j.j.k.j.k.j.j.k.e.e.e.e.l.a.l.a.d.#.#.c.a.a.l.a.e.l.e.e.l.e.l.e.e.e.e.e.e.e.b.e.e.j.e.e.j.b.j.e.b.e.l.b.e.l.e.e.l.e.l.l.b.l.l.e.l.b.e.l.b.l.b.e.b.a.#.c.qQt.q.f.u.g.i.i.qQt.#.s.a.r.a.c.c.#.c.c.#.c.#.c.#.a.c.a.a.r.l.a.l.r.a.r.r.a.r.a.r.a.r.a.r.a.r.c.r.a.c.a.a.l.r.l.a.l.b.a.e.l.e.b.aQt.cQtQtQt.s.g.v.u.w.f.gQt.#.cQt.c.f.q",
+".h.v.h.g.d.d.a.a.r.a.c.r.c.c.cQt.d.f.f.f.f.i.m.g.g.h.u.p.p.u.u.h.i.i.s.i.i.i.i.i.fQt.iQt.#.c.a.c.a.a.a.a.a.a.a.a.a.r.a.c.aQt.a.c.e.l.e.e.e.e.j.j.j.l.j.e.j.k.j.j.k.e.k.e.j.j.j.e.e.e.e.l.e.a.a.r.#.c.#.c.a.a.b.a.e.b.l.e.b.l.e.b.l.l.b.l.l.b.l.l.e.e.t.j.e.l.e.j.l.e.l.e.l.e.l.e.#.e.#.e.a.e.e.l.a.l.a.b.a.e.a.l.b.l.a.c.#.gQt.i.g.g.s.iQt.#.#Qt.r.a.r.a.c.c.c.c.l.a.l.a.l.r.a.r.a.l.a.r.a.a.a.a.r.a.r.a.r.r.a.r.a.r.a.a.c.c.#.a.a.a.a.a.a.b.a.b.l.e.b.a.a.c.cQtQt.i.i.m.p.w.i.f.d.#Qt.c.c.c.d.d",
+".x.h.v.w.hQt.c.bQt.c.a.c.c.dQt.d.f.g.f.i.fQt.f.s.f.g.g.g.u.h.p.h.u.g.h.g.h.f.g.g.qQtQt.c.#.c.#.c.a.a.a.a.l.a.l.a.b.a.c.b.c.r.a.b.l.e.j.e.j.l.e.e.j.j.j.j.j.e.k.e.k.j.j.k.j.k.j.k.e.e.e.e.l.a.a.a.c.i.#.c.a.a.a.b.l.e.l.e.l.e.e.l.e.e.l.e.e.l.e.e.l.e.e.e.j.l.b.l.e.l.b.l.r.l.b.e.l.e.l.e.l.b.a.b.e.b.l.e.l.e.l.b.l.b.l.#.c.#QtQt.m.i.f.iQtQtQt.q.#.a.r.c.a.a.b.e.a.a.a.a.a.l.a.l.a.a.l.a.l.a.l.a.r.r.a.r.a.a.r.a.r.a.r.c.r.a.c.a.l.l.l.l.b.a.a.b.e.e.l.a.#.cQt.c.c.f.s.g.m.m.f.fQt.f.c.b.a.r.r.d",
+".f.g.n.v.n.x.q.d.c.c.d.dQt.d.fQt.f.fQt.gQtQtQtQtQtQt.f.f.f.g.m.h.h.p.u.v.p.h.g.iQtQt.#Qt.c.a.c.c.a.l.a.l.b.a.a.a.b.a.r.aQt.c.a.b.b.l.e.l.e.e.j.e.t.e.j.e.j.j.k.j.j.j.j.e.k.e.j.j.e.e.e.l.e.a.l.rQt.#.c.c.a.a.a.a.e.e.e.l.e.l.e.e.l.l.l.l.l.e.l.l.e.j.e.j.l.b.l.e.b.l.b.l.e.l.a.b.a.b.a.e.#.e.l.l.a.e.#.e.#.e.a.e.l.e.a.a.q.#.fQt.f.gQt.iQtQtQtQt.#.#.r.a.a.b.e.b.l.l.e.l.e.l.a.l.a.a.a.a.a.a.a.a.a.r.a.r.a.r.a.r.a.r.a.a.c.c.c.a.l.e.l.a.a.a.b.l.e.b.a.a.c.c.c.q.d.g.f.m.g.sQt.c.dQt.c.#.b.r.c.r",
+".f.f.g.o.y.s.f.q.c.c.d.#.f.dQt.q.f.f.fQtQtQtQtQtQt.q.dQt.f.f.x.g.p.u.p.u.u.h.p.h.iQt.#.#.c.#.c.l.a.a.a.a.l.a.l.a.b.a.c.a.cQt.c.a.l.e.j.e.j.e.l.e.j.e.j.e.j.j.j.j.j.k.j.k.j.k.j.j.e.e.e.e.l.a.a.aQtQt.#.c.a.l.a.a.b.l.e.b.l.e.b.l.l.b.e.l.b.l.l.b.l.j.e.j.e.l.e.l.a.e.l.b.a.b.e.l.e.l.b.l.e.l.b.l.b.e.l.e.l.b.l.r.l.b.l.#.c.#.qQt.gQt.fQt.qQt.qQt.dQt.a.a.a.e.e.e.l.a.l.l.a.e.l.e.e.a.l.a.l.a.l.a.r.a.r.a.r.a.r.a.r.a.r.c.r.c.a.a.l.a.a.b.a.e.b.b.#.l.e.a.#.cQt.d.d.f.s.m.iQtQt.cQtQt.a.b.#.b.c.#",
+".b.i.f.x.w.z.A.pQt.d.g.x.g.g.h.g.f.d.dQt.dQt.c.c.#.c.#Qt.iQt.s.x.u.y.z.B.C.y.g.g.#QtQt.c.#.a.a.c.a.l.b.l.a.a.a.a.#.c.c.c.c.d.c.c.b.a.a.a.a.a.e.a.l.l.l.l.l.l.e.l.j.e.j.e.e.e.e.j.j.j.l.e.a.a.c.c.iQtQt.#.a.#.b.e.a.a.a.a.b.a.a.a.l.a.l.#.l.l.l.l.l.b.l.b.l.b.l.b.l.b.a.a.#.qQtQt.c.a.c.aQt.a.#.a.b.l.r.l.b.l.e.l.l.a.a.#.q.dQt.g.i.sQtQt.i.c.a.a.#.r.r.a.a.b.b.b.b.a.b.a.b.a.a.e.l.l.l.e.l.a.a.a.r.a.a.r.a.r.a.a.a.a.l.a.b.l.b.b.b.l.a.a.a.a.a.a.e.#.a.#.a.#.a.#.q.i.d.i.i.d.c.c.r.b.r.b.c.r.#.c",
+".b.c.f.f.p.A.o.v.dQt.q.x.g.w.f.i.f.d.d.c.c.c.a.c.#.c.#.cQtQtQt.i.p.n.z.D.B.C.o.u.i.iQt.i.#.c.c.c.c.c.#.c.c.c.c.c.c.#.#.i.#.d.c.c.a.a.a.b.l.b.a.a.l.l.l.b.l.l.e.e.e.j.j.j.j.j.e.j.e.j.l.e.a.c.c.cQtQt.c.c.c.a.a.b.a.a.b.a.a.a.b.a.e.l.l.l.l.e.l.l.b.a.l.r.l.a.l.r.b.l.#.aQt.c.#Qt.a.a.#.a.a.a.c.a.b.e.l.b.e.a.b.a.b.l.#.#.cQt.i.f.g.f.x.fQt.c.c.r.r.r.#.a.a.a.e.b.a.a.a.a.a.b.a.e.l.l.l.l.l.l.a.l.r.#.a.r.a.a.a.l.a.l.b.a.e.b.e.e.a.a.b.a.a.b.#.a.a.a.#.a.#.a.#.a.c.qQt.i.dQt.c.#.b.b.#.b.r.c.c.b",
+".b.aQt.f.m.h.o.o.m.s.g.s.h.g.sQt.dQt.c.c.c.c.c.c.a.c.c.c.#.dQt.g.i.h.y.A.C.v.v.p.m.g.g.f.f.fQt.#.c.c.a.c.#.c.#.c.#QtQtQtQt.#.c.c.a.a.a.l.a.l.l.l.l.l.l.l.l.l.e.l.e.e.e.l.e.l.e.l.e.e.e.#.b.aQt.c.i.f.q.c.a.c.b.b.a.#.a.b.#.a.a.#.l.e.l.b.l.l.b.l.l.l.b.l.b.l.l.l.r.a.#.q.#.c.i.c.#.c.a.c.#.a.#.a.a.l.b.l.l.b.l.e.l.a.aQt.#Qt.f.g.i.iQtQt.i.#.a.a.r.r.#.r.a.c.b.b.a.b.a.b.a.a.e.e.l.l.e.l.l.a.a.a.a.r.a.#.r.a.a.a.l.a.a.e.e.l.b.l.a.a.a.a.b.a.a.a.#.l.#.a.#.a.#.a.q.d.i.i.cQt.c.c.b.b.b.b.c.b.#.a",
+".aQtQt.f.x.g.u.o.o.p.o.u.n.g.f.c.c.d.c.c.a.r.a.b.a.a.#.c.cQtQt.d.q.s.h.v.u.v.u.u.p.p.p.g.m.g.g.fQt.#Qt.#.#.c.#Qt.i.q.gQt.iQt.c.c.a.a.a.a.a.a.a.a.a.r.#.a.l.e.a.b.l.e.l.e.l.b.l.e.e.t.e.a.c.c.dQtQtQt.#.c.c.b.a.b.a.b.a.a.a.b.a.b.a.a.a.a.#.a.r.a.#.r.a.r.a.r.#.aQt.#Qt.c.#.c.#Qt.a.a.a.r.a.a.r.a.a.#.aQt.a.c.a.c.a.#.#.#.c.q.f.f.s.f.sQtQt.c.aQt.a.r.#.a.a.b.a.a.e.a.a.e.a.e.e.e.e.l.l.a.e.a.l.a.r.a.r.a.a.a.a.b.e.l.e.e.e.b.e.b.b.a.b.#.a.a.#.a.b.#.c.cQt.c.q.c.q.#.f.c.f.c.a.c.b.#.a.a.#.b.c.b",
+".d.d.dQt.s.s.h.w.v.z.o.v.h.i.f.#.c.c.c.c.c.a.b.a.a.b.a.c.c.f.dQtQt.q.m.h.h.u.p.p.h.w.p.h.h.g.g.g.gQt.iQtQtQtQtQt.i.i.iQtQtQt.#.c.#.a.a.b.l.a.a.a.a.l.r.l.#.a.l.a.#.b.e.a.b.a.e.e.l.e.a.a.c.c.d.dQtQt.c.#.#.c.b.l.b.a.#.a.#.a.a.#.a.#.a.a.r.a.#.a.a.a.#.a.#.a.a.aQt.qQt.#Qt.#Qt.c.#.c.a.c.aQt.a.#.c.a.a.b.a.#.a.#.a.a.c.iQt.f.f.f.i.iQt.iQt.#.a.a.a.a.r.a.c.a.a.b.a.b.l.e.e.e.a.e.l.e.b.a.b.a.b.a.a.#.r.a.a.b.c.a.a.e.e.a.e.l.b.l.a.a.a.b.a.a.r.aQt.a.c.q.c.q.cQt.#QtQtQtQtQt.cQt.b.a.r.b.c.c.c.c",
+".g.d.g.f.h.m.h.u.z.E.F.B.n.h.fQt.c.c.c.b.a.r.a.b.b.a.b.a.c.c.c.d.s.i.g.m.h.g.h.w.h.g.h.m.h.g.m.x.i.i.i.i.f.s.i.s.h.s.g.iQtQt.i.c.r.a.a.r.a.a.a.r.#.a.a.a.a.a.b.a.b.a.l.b.l.a.a.a.b.e.a.r.c.cQtQtQt.q.#.c.r.a.b.b.a.a.a.b.aQt.a.c.r.c.r.#Qt.#.a.cQt.#.#.c.#.#Qt.#.iQt.d.qQt.#.c.#.a.r.a.#.a.b.a.a.cQt.cQt.c.c.c.c.c.qQt.#.d.i.f.g.i.g.q.fQt.c.a.c.a.a.a.a.#.a.a.a.b.a.a.e.a.e.a.a.e.e.l.e.a.a.c.r.r.a.a.a.c.a.b.b.l.l.a.b.a.b.e.b.a.b.a.aQt.a.#.a.c.c.cQt.c.f.#.c.i.#QtQtQt.r.c.aQt.c.d.#.fQt.f.d",
+".x.q.x.x.h.p.w.v.G.H.E.I.C.o.g.x.c.c.c.b.a.a.e.e.a.e.b.b.b.c.c.c.f.f.f.f.f.f.g.i.h.h.g.h.g.g.f.iQt.f.g.g.g.m.g.m.g.h.i.iQt.i.#.#.c.#.q.c.#.#.c.q.#.r.a.a.c.a.a.b.a.b.a.b.a.b.a.a.e.a.#.c.c.dQt.dQtQt.c.c.a.c.b.a.b.a.a.a.a.b.a.#.c.q.cQt.#Qt.#.#.c.q.c.q.c.q.c.q.f.f.iQt.c.i.a.q.a.c.a.c.aQt.aQt.c.c.c.c.cQt.cQt.#.a.#.i.f.f.f.g.s.iQt.iQt.#.c.#.a.a.a.a.a.c.a.r.a.e.a.e.e.a.b.l.e.e.e.b.e.b.b.#.a.a.cQt.b.c.b.b.l.a.e.a.l.b.a.b.#.a.#.a.a.a.c.aQt.c.i.#.i.c.f.#Qt.#.f.c.cQt.cQtQt.d.i.fQt.q.f.f",
+".s.w.h.p.h.n.v.o.p.A.F.J.I.B.o.h.c.a.c.b.a.b.a.a.b.e.b.e.a.r.c.c.x.i.f.iQtQt.f.f.p.p.h.h.w.i.i.f.i.i.f.i.f.i.f.g.g.p.m.g.i.q.d.#.i.c.#.c.#.c.#.#.r.a.q.a.a.#.r.a.a.a.e.a.a.a.b.a.#.a.c.c.cQt.d.dQtQt.#.cQt.a.a.e.a.r.a.b.a.a.c.a.q.c.#.q.#Qt.#Qt.q.#Qt.#.c.qQtQt.g.g.dQtQt.#.#.c.a.a.#.a.r.a.a.a.c.cQt.cQt.c.c.c.c.#QtQt.f.f.m.x.g.f.q.fQt.c.c.a.a.a.a.a.a.r.#.a.a.a.a.e.a.e.a.a.e.e.e.b.e.a.b.b.a.a.a.c.a.b.l.b.a.l.a.b.a.b.e.b.a.a.r.aQt.b.#.aQt.#.f.fQt.iQtQtQtQtQtQtQt.cQt.c.fQt.f.h.x.x.h.s",
+".h.u.v.u.v.u.h.gQt.f.n.o.B.B.D.B.h.fQt.c.a.a.b.a.e.l.e.e.a.c.c.f.#.cQt.#.fQt.i.f.q.i.s.p.h.g.p.p.s.i.i.i.i.g.f.i.iQtQtQt.i.i.s.iQtQt.#Qt.#.i.#.i.a.#.r.r.a.r.l.l.a.a.a.#.a.a.a.a.#.c.#.c.#Qt.#.#.iQt.c.c.a.b.b.e.l.e.l.#.b.c.b.c.dQt.iQt.f.i.s.g.s.s.i.s.i.m.sQt.f.iQt.q.c.#.a.bQt.d.c.#.a.a.#.a.#.#.c.#QtQt.i.f.q.#Qt.i.i.g.i.g.x.s.q.iQt.q.#.#.#.a.a.a.a.a.l.a.c.r.c.c.c.c.c.b.e.l.a.l.a.b.c.aQt.a.a.a.c.a.b.b.l.a.a.a.a.cQt.c.c.c.i.d.dQt.dQt.cQt.#QtQtQtQt.d.#.a.cQt.cQt.d.d.g.f.x.h.w.u.u.v",
+".u.p.h.h.p.m.g.x.q.f.g.u.C.B.z.o.v.fQt.c.l.a.a.a.e.e.b.l.b.c.c.c.c.cQt.c.d.d.fQt.x.i.g.g.p.u.p.u.h.i.i.g.s.i.i.f.s.f.q.f.iQt.i.f.q.g.q.i.qQt.f.q.r.r.r.#.#.a.a.a.a.a.a.c.aQt.c.q.c.#.#Qt.#.#.c.#Qt.c.#.a.c.a.l.b.b.l.e.b.a.#.c.a.q.cQtQtQtQt.i.m.i.p.m.g.u.w.m.s.m.g.fQt.qQt.#.#.q.#.q.c.#.a.a.#.c.q.c.q.cQt.cQt.q.r.iQt.g.i.x.gQt.iQt.qQt.#.#.c.a.a.#.a.l.a.a.l.c.c.c.c.c.c.a.c.l.e.b.a.b.c.a.c.r.a.#.a.a.#.a.b.b.a.b.a.r.a.c.c.c.c.cQt.c.i.c.i.c.c.q.dQtQt.fQtQt.#Qt.#.d.i.d.i.i.g.m.g.n.v.u.p",
+".h.h.m.g.g.f.fQt.#Qt.g.g.y.B.B.v.h.h.f.c.c.a.b.a.e.l.e.a.a.b.c.c.#.c.c.qQtQt.xQt.i.g.g.w.h.p.v.p.p.h.h.g.i.i.s.i.i.fQtQt.q.f.iQt.i.s.i.m.i.s.i.s.q.iQt.#Qt.#.i.#.c.c.c.c.#.c.#.c.#.c.#.#.c.#.#.cQt.i.c.c.a.r.b.e.a.e.l.a.a.r.a.r.c.q.#.iQt.i.q.s.i.h.n.o.z.A.z.v.w.g.m.f.f.d.g.dQt.dQt.c.c.c.#.c.#Qt.#.c.#QtQtQt.#.iQtQt.i.i.m.i.s.xQt.iQt.q.c.#.a.#.a.a.#.a.#.aQt.cQt.cQt.c.c.c.#.a.a.a.a.c.c.c.r.a.a.c.a.c.e.b.a.#.a.c.#.c.c.c.fQt.fQt.dQt.fQtQt.#Qt.c.i.cQt.dQt.dQt.fQt.dQt.f.h.g.g.g.v.h.n.v",
+".f.f.f.fQtQt.d.d.b.c.f.f.p.C.A.v.h.v.i.c.a.c.a.r.e.e.c.b.c.a.b.a.a.#.#.c.cQtQt.d.m.f.g.h.h.p.u.u.o.u.u.g.g.i.fQt.s.i.s.fQtQtQtQt.i.f.g.g.g.g.m.g.i.s.i.xQtQtQtQt.#.c.q.c.#.c.c.#.c.#Qt.c.c.c.c.qQt.c.#.c.c.a.b.a.b.l.b.b.a.aQt.a.a.q.cQtQtQt.x.f.u.p.o.z.J.K.B.A.p.v.n.w.w.x.g.h.f.g.d.i.d.iQt.c.iQt.#.iQtQt.iQt.iQtQt.s.x.s.x.gQt.f.qQt.f.#.#.c.c.#.a.a.a.a.a.a.c.c.c.dQt.dQt.c.a.aQt.a.a.q.c.#.#.a.a.a.a.r.a.b.a.a.a.b.c.c.cQtQt.cQt.c.i.cQt.d.q.cQt.c.#.f.d.q.d.i.d.fQt.f.g.f.s.g.g.m.h.h.g.h",
+"QtQt.#.f.c.c.c.c.a.cQt.d.x.v.v.u.p.w.f.c.#.c.a.c.a.a.b.a.b.a.a.b.a.a.a.c.#.d.#Qt.f.f.i.g.g.h.u.u.y.u.u.h.m.i.s.f.i.i.iQt.x.f.q.fQt.i.f.i.m.g.i.g.s.i.s.i.i.g.fQt.d.#QtQt.iQt.i.c.#.c.#.c.q.c.#.cQtQt.c.#.#.a.b.a.e.a.e.a.a.r.a.c.qQt.#.iQt.q.f.s.A.A.z.B.F.B.o.v.n.v.v.v.v.v.v.v.x.w.g.h.x.g.f.g.f.g.f.f.g.f.dQt.f.s.i.s.i.m.i.m.g.q.gQt.i.#.f.#.q.c.q.a.c.#.c.#.c.cQt.c.c.c.c.c.q.a.#.c.c.c.#Qt.a.rQt.a.c.#.b.b.#.aQt.cQt.c.dQt.fQt.fQt.dQt.fQtQt.c.r.fQtQtQt.d.gQtQt.i.f.gQt.g.f.f.g.f.f.f.f.f",
+".c.c.c.b.b.b.b.b.b.a.a.cQt.x.v.A.p.p.iQt.c.c.c.c.c.c.a.r.a.a.b.a.a.a.c.aQt.#.d.qQtQt.f.i.i.g.m.p.v.u.u.p.p.g.g.i.g.i.i.fQtQtQtQt.s.i.gQtQtQtQt.i.i.q.f.i.f.q.g.i.i.gQt.f.#.d.#.d.c.q.c.#.c.q.c.#.iQt.q.c.cQt.b.a.b.e.#.a.#.cQt.c.cQt.g.iQt.s.i.m.z.A.z.B.B.z.v.p.h.w.h.n.p.v.A.I.I.B.A.v.h.h.w.h.h.h.m.x.x.f.i.f.s.g.m.x.m.g.g.g.q.f.sQtQt.#Qt.d.c.r.cQt.#.c.#.cQt.c.c.c.cQt.c.c.a.r.q.#.#.iQtQt.q.a.#Qt.a.r.a.b.c.a.a.b.a.c.i.cQt.fQt.c.i.cQt.c.q.cQt.#.dQtQt.fQt.f.x.d.d.f.d.d.i.d.c.c.c.c.a.c",
+".a.b.b.l.e.b.j.e.b.e.e.a.cQt.g.o.v.g.g.x.#.c.c.c.r.c.c.a.b.a.e.e.#.a.a.a.a.c.c.c.#.cQtQt.fQt.i.g.p.u.p.p.w.p.w.h.i.i.i.i.s.f.q.fQt.qQt.q.gQtQt.i.#.#Qt.#QtQtQt.i.i.g.f.sQt.i.#.c.i.d.c.c.dQt.d.iQt.f.#.c.c.c.a.r.l.l.e.a.c.c.c.c.g.f.f.m.g.m.w.v.o.v.o.B.B.B.u.u.m.x.w.g.w.p.z.B.L.M.F.A.A.o.y.A.o.o.p.h.w.h.w.n.h.w.g.w.g.s.g.f.s.f.i.i.d.fQtQt.#.c.#.c.#.c.q.c.c.c.c.c.c.c.c.c.#.#.c.#.fQtQtQt.r.#.a.#.cQt.b.b.#.a.c.aQt.c.dQt.dQt.d.i.d.i.d.i.c.q.c.c.q.i.d.i.f.gQtQtQt.c.a.#.r.b.b.#.b.b.j.e",
+".e.b.e.e.j.j.e.j.b.e.e.#.c.d.x.p.v.h.m.wQt.c.c.d.c.a.c.a.e.a.e.l.l.a.a.c.a.#.c.#.#.c.#.#.iQt.f.q.g.h.u.h.p.h.u.u.s.i.s.f.i.iQtQt.iQt.iQtQt.#QtQt.x.#Qt.#.#.#QtQtQtQtQt.g.f.g.f.g.dQtQt.f.#.f.#.dQt.i.d.q.cQt.a.b.a.a.#.a.#.cQt.c.f.m.g.w.w.p.A.z.v.u.A.B.z.o.p.w.g.m.h.w.w.n.o.o.N.H.I.D.F.F.N.O.N.P.I.A.v.h.n.h.m.h.u.g.w.g.m.i.s.f.gQt.i.dQt.dQtQtQt.#Qt.#.c.q.c.c.c.cQt.c.c.c.#.#Qt.qQt.gQt.i.#.#.#.#.c.c.a.c.c.a.r.a.c.c.c.i.cQtQt.d.i.dQt.d.q.cQt.c.fQt.iQt.g.d.dQt.a.a.b.l.e.r.e.e.b.e.e.k",
+".e.e.e.e.e.j.j.j.e.e.b.b.c.d.q.g.u.z.J.D.p.g.c.l.c.b.c.b.a.a.e.e.c.c.a.c.q.c.c.#.c.#.c.#.c.#Qt.#.i.q.i.m.p.v.u.v.u.h.h.i.m.i.i.f.qQtQtQt.xQt.i.#.r.#.#.c.a.a.c.bQt.c.c.c.c.c.qQt.i.g.iQt.f.d.g.f.gQtQt.c.c.a.#.a.b.a.#.c.d.d.f.x.m.p.o.z.B.z.z.o.A.v.v.v.v.u.n.h.h.h.m.m.h.v.z.B.Q.R.F.A.v.z.z.F.B.B.B.F.I.I.J.B.B.z.A.w.p.m.x.g.g.p.g.m.i.iQt.f.#QtQtQtQt.cQtQt.cQt.c.c.c.c.c.cQt.cQt.#Qt.f.g.f.c.c.c.c.a.#.cQt.a.c.c.cQt.c.c.cQt.#Qt.cQtQt.fQt.q.#Qt.x.h.g.dQt.c.aQt.a.b.#.a.b.e.e.e.e.e.e.e.e",
+".j.b.e.j.e.j.e.j.j.e.e.b.c.d.q.q.h.v.D.B.z.n.i.c.c.a.c.a.b.a.b.l.a.#.c.#.c.c.q.c.c.c.#.c.c.#.d.#Qt.i.i.h.p.u.y.A.p.h.w.i.f.iQtQt.xQt.qQt.#Qt.#Qt.r.#.r.#.c.a.#.c.c.cQt.cQt.c.cQtQt.f.f.f.g.f.g.i.h.g.f.i.dQt.c.c.c.c.dQt.g.f.h.m.m.m.u.A.z.o.A.v.v.v.p.v.p.u.h.w.f.g.x.m.w.n.B.I.M.S.E.A.z.z.y.z.o.o.o.v.z.B.E.E.P.Q.T.F.I.o.o.p.u.p.u.g.w.x.gQtQt.c.#.c.iQt.c.q.dQt.cQt.c.cQt.c.c.qQt.#Qt.g.f.f.qQt.cQt.c.c.c.c.c.rQt.c.c.cQt.c.cQt.c.c.i.c.i.d.qQt.f.g.x.q.f.c.c.#.b.a.b.a.b.r.b.e.b.e.b.e.e.e",
+".e.j.e.k.e.j.j.j.j.k.e.a.r.c.d.q.q.m.v.C.A.u.gQt.c.cQt.c.a.a.a.a.c.c.a.c.#.c.c.#.c.q.c.c.q.c.#QtQt.f.i.m.g.v.u.A.p.u.h.i.m.iQt.fQtQtQt.xQt.#Qt.#.q.a.r.c.a.a.c.b.cQt.#.c.a.c.a.c.c.cQtQt.d.g.g.g.w.w.h.fQt.d.i.d.g.g.s.h.m.w.h.w.i.m.v.o.u.o.v.u.u.h.u.h.u.p.n.h.p.h.m.x.w.u.B.F.M.M.F.C.z.o.u.o.u.u.h.p.u.o.A.z.E.M.N.R.E.E.K.K.I.B.o.u.h.g.x.x.g.iQt.iQt.dQtQtQt.qQtQtQt.#Qt.i.#Qt.i.dQt.g.f.g.c.d.q.c.cQt.cQt.cQt.c.cQt.c.c.#Qt.rQtQtQt.d.i.d.#.i.g.fQt.d.dQt.a.b.a.r.a.r.a.e.e.e.e.e.e.e.e.e",
+".e.j.j.e.e.j.e.j.e.e.e.b.c.r.c.dQt.i.g.w.v.o.h.x.c.c.c.c.b.c.b.a.a.c.c.#.c.c.#.c.#.c.#.c.#.c.cQtQtQt.i.i.g.p.v.o.u.p.h.g.i.i.gQt.x.#.i.#QtQt.qQt.a.rQt.a.a.c.a.c.a.a.a.a.a.#.a.aQt.c.c.fQt.dQt.f.x.x.x.h.g.f.g.h.u.n.g.g.g.g.m.g.m.m.p.o.u.v.o.u.w.p.w.w.h.w.m.h.h.x.w.g.n.o.B.Q.U.Q.D.o.C.o.u.v.w.w.u.g.w.h.h.v.v.z.C.B.I.I.E.N.N.Q.I.A.A.v.p.m.i.i.g.f.i.sQt.i.qQt.q.i.f.f.fQt.d.iQt.#.f.g.i.g.c.i.c.f.cQt.c.c.c.c.c.c.c.cQt.c.c.c.#QtQtQtQt.fQt.i.f.i.dQt.c.c.b.#.b.a.b.a.b.e.a.b.b.e.r.e.b.e",
+".j.e.e.k.e.k.e.j.k.e.e.e.b.c.c.r.iQt.m.h.w.v.n.u.d.f.c.c.c.#.c.aQt.#.c.c.q.c.c.q.c.q.c.c.#Qt.#QtQtQt.f.s.i.m.p.p.u.p.u.g.m.i.f.qQtQtQtQt.i.#Qt.#.r.#.r.a.a.#.r.a.b.a.bQt.a.c.b.#.a.a.c.c.cQtQt.f.f.g.g.f.x.h.g.w.w.h.g.h.x.h.g.g.i.p.v.A.o.o.A.A.u.w.w.g.w.g.p.m.s.w.p.w.n.o.I.T.V.N.D.o.v.v.h.v.g.i.w.h.u.h.w.h.p.g.u.p.w.u.v.A.Q.T.E.P.F.I.z.u.m.g.g.i.m.g.g.i.g.f.f.f.f.f.f.m.f.g.f.g.f.g.x.gQtQtQtQtQt.c.q.cQt.c.q.c.q.c.c.c.#.q.c.f.c.iQt.i.f.gQt.iQt.a.b.#.b.e.b.b.b.e.e.e.e.e.e.e.e.e.e.e",
+".e.k.e.k.k.k.j.e.e.e.e.b.l.b.b.b.c.d.f.w.p.n.v.v.cQt.c.c.c.c.a.r.#.c.c.#.c.#.c.cQt.cQt.c.q.cQtQtQt.iQt.f.g.i.g.m.u.p.u.h.m.i.s.f.i.q.i.dQt.#Qt.#.c.r.c.a.c.a.a.c.l.b.e.l.e.b.l.b.a.c.aQt.a.c.d.#.dQt.dQtQt.g.x.h.h.w.w.w.u.g.w.g.m.h.o.z.v.A.z.z.w.u.w.w.m.h.s.w.p.n.w.p.v.z.F.P.W.P.F.v.o.v.h.p.m.h.g.h.g.w.p.n.i.m.m.m.m.h.h.m.A.A.z.B.Q.Q.P.M.F.K.o.v.p.w.p.u.g.g.g.s.g.m.g.w.x.m.m.g.g.m.g.gQt.i.c.f.#Qt.dQt.c.#.cQt.c.cQt.#.c.cQtQt.i.f.i.d.m.f.i.cQt.a.#.b.a.b.a.e.a.b.a.e.e.e.e.e.e.e.e.e",
+".e.j.k.j.j.j.e.k.e.e.e.e.e.e.e.l.rQtQt.f.h.g.p.v.d.dQt.f.c.c.c.a.c.#Qt.c.#.c.#.c.q.c.q.cQt.#.i.c.qQt.g.q.s.f.s.s.p.p.u.g.m.g.f.q.q.i.qQt.iQt.#.i.r.#.r.a.#.a.c.a.b.a.l.r.l.e.l.b.l.b.a.c.aQt.c.i.cQt.cQt.dQt.dQt.s.s.g.p.w.u.p.u.v.o.z.B.B.A.B.H.v.u.w.h.w.h.w.p.h.n.n.o.o.B.I.E.L.X.E.o.o.u.w.h.w.g.w.h.g.s.h.w.h.m.s.m.h.h.g.g.o.u.w.u.o.J.M.Y.L.N.N.H.B.z.o.u.w.w.g.h.m.h.w.p.w.h.w.w.g.m.g.i.f.iQt.f.#QtQtQt.cQt.cQtQtQt.c.cQt.rQt.c.iQt.g.i.x.g.d.#.l.r.a.b.b.e.e.b.e.e.e.b.e.e.e.e.e.e.e.e",
+".j.e.k.k.k.k.j.e.e.e.e.e.b.e.b.e.d.d.f.f.f.w.p.p.dQt.d.c.c.c.c.c.q.c.c.#.c.cQt.#.c.c.#.c.#.f.#Qt.dQt.f.g.f.s.s.m.h.u.p.u.m.m.s.g.q.f.xQt.qQt.#Qt.a.r.a.c.a.c.a.r.l.e.l.e.l.e.e.a.e.a.a.a.b.c.a.cQt.a.a.a.c.dQt.d.a.rQt.s.g.w.v.A.z.z.F.F.D.B.E.Q.C.v.v.n.w.p.w.n.n.n.D.A.G.B.F.P.Y.W.T.C.v.v.p.w.g.x.h.w.h.w.h.h.y.u.n.x.x.h.h.h.s.w.u.v.A.A.z.B.K.N.L.N.H.Q.B.o.u.u.u.w.p.w.p.u.h.v.w.w.w.m.s.g.iQt.f.#.f.c.c.i.cQtQt.d.q.cQt.cQt.c.q.d.iQt.f.f.m.x.q.a.b.e.b.#.l.e.l.e.l.b.e.l.e.e.e.e.e.e.e.e",
+".k.k.e.j.e.j.e.j.j.j.e.e.e.e.b.e.c.d.dQt.x.x.x.h.h.i.d.c.r.r.r.b.c.c.c.cQt.c.c.c.cQt.cQt.c.c.cQt.i.iQt.i.f.s.f.m.g.m.g.m.h.h.p.gQt.i.qQt.q.r.q.r.b.l.b.r.a.a.q.#.#.a.a.a.a.a.a.l.b.l.b.a.cQt.c.c.#.cQt.cQt.c.#.c.#QtQtQt.i.f.g.m.v.z.I.H.I.I.Q.U.K.J.A.y.y.n.y.y.z.z.B.B.F.I.K.T.M.Z.X.G.u.o.v.u.h.u.g.h.h.v.w.v.w.m.g.h.m.h.x.g.h.m.w.v.w.v.w.u.o.o.A.I.K.N.Z.U.I.z.n.v.h.w.m.u.o.n.w.g.m.f.s.g.i.i.c.f.cQt.cQt.dQtQtQt.c.i.c.q.#QtQt.i.f.g.f.m.cQt.r.c.c.bQt.b.b.r.e.b.e.l.e.e.j.j.j.k.j.k.k.k",
+".k.0.j.k.e.j.e.j.e.k.e.e.e.b.l.b.c.dQt.q.f.f.f.f.m.i.g.d.c.r.a.b.c.c.c.c.c.c.c.c.c.c.c.c.cQt.c.c.#.iQt.i.i.g.h.i.m.g.p.g.w.g.w.h.s.iQtQtQt.#.#.#.r.l.r.#.r.a.#.c.a.a.a.b.a.l.#.a.b.l.b.a.a.a.cQt.a.q.c.c.c.c.c.c.c.c.q.dQt.f.f.f.g.h.o.z.B.B.S.1.O.Y.P.K.A.A.K.P.Q.H.B.B.I.I.Q.K.M.W.W.I.v.o.p.v.w.h.h.u.p.v.p.v.w.h.m.h.m.h.h.g.m.m.h.m.w.w.w.w.n.u.n.o.o.B.B.K.Z.Z.P.Q.H.z.z.z.A.B.A.n.u.w.h.m.f.gQt.i.cQt.r.c.f.#.f.#.dQtQt.f.c.qQt.iQt.s.f.g.rQt.c.#.c.#.c.r.#.a.e.a.b.b.e.e.j.k.j.j.k.k.0.k",
+".k.j.k.j.k.k.b.j.j.j.e.e.e.e.b.e.c.c.d.q.d.g.f.f.g.g.f.f.d.d.c.c.cQt.c.c.c.c.cQt.cQt.c.cQt.c.c.q.c.q.#.iQt.i.f.g.s.i.s.g.p.g.p.g.m.i.s.i.i.q.i.#.#.r.r.r.a.a.#.c.l.a.a.r.a.a.a.l.b.l.b.a.b.c.#.c.c.#.cQt.c.#.cQt.c.c.cQtQtQt.i.d.s.i.m.v.v.o.z.Q.2.3.2.Z.N.L.Z.U.Y.T.F.F.Q.Q.R.N.S.Y.U.R.B.v.u.o.u.v.v.u.v.u.v.n.m.m.m.x.h.h.g.h.h.m.m.h.m.h.m.m.m.m.w.w.n.n.o.o.z.z.H.N.L.L.L.W.H.S.I.A.u.v.v.u.m.h.f.gQt.f.cQtQt.f.f.i.iQt.fQt.f.#.dQt.f.f.f.g.a.b.r.b.r.b.#.b.a.e.r.e.b.e.e.b.e.e.e.e.k.j.j.j",
+".k.k.e.k.j.k.e.j.e.k.e.e.e.e.l.b.c.a.c.cQt.d.d.f.i.s.g.x.f.dQt.c.c.c.c.cQt.c.c.c.a.a.#.a.a.a.a.c.i.#QtQt.iQt.s.f.s.f.s.i.g.i.g.m.g.g.s.i.i.iQt.q.#.#.c.r.#.r.a.#.a.l.#.l.a.l.a.a.e.l.e.a.a.a.r.a.a.a.#.a.a.b.a.b.a.aQt.c.cQt.d.i.f.i.f.m.h.w.v.z.Y.M.M.2.4.5.6.O.1.L.N.T.N.R.Z.Z.N.W.7.L.I.o.u.A.o.p.o.v.v.w.p.p.m.x.m.g.g.g.g.x.g.g.i.g.i.i.g.s.s.h.g.m.h.m.p.h.n.o.o.A.I.E.T.N.M.Z.M.I.B.z.A.v.w.h.m.f.g.f.d.f.f.i.g.f.g.q.i.d.#.f.d.i.dQt.fQt.r.b.l.r.l.b.e.r.b.b.b.e.a.b.e.l.b.l.b.j.e.k.j.k",
+".k.j.k.j.e.j.e.j.j.j.e.e.e.e.b.e.a.b.a.c.c.cQt.dQt.f.g.s.xQt.#.c.c.c.c.c.c.c.c.c.a.a.c.aQt.a.#.a.c.q.c.#QtQt.iQt.iQtQt.i.i.g.i.g.i.m.f.i.g.i.g.i.#.#.#.c.#.#.a.a.#.a.a.a.a.#.a.a.l.e.e.#.a.r.a.c.#.a.a.a.#.b.#.b.r.a.b.aQt.c.c.cQt.#.i.g.m.w.u.C.M.T.H.E.Z.4.4.4.U.4.U.U.2.N.N.R.2.U.8.V.Q.z.v.B.u.v.u.w.p.w.s.m.g.g.g.i.g.f.f.i.x.x.f.x.f.x.x.f.q.q.f.s.i.g.i.g.s.g.m.w.n.v.o.B.K.N.1.Z.N.P.F.C.o.v.h.x.f.g.gQt.g.f.g.g.f.g.f.i.d.i.cQt.cQt.c.a.e.b.e.e.b.e.b.e.e.a.e.r.e.e.b.e.l.e.l.b.e.e.e.e",
+".j.j.e.k.e.e.e.e.j.j.e.e.e.e.e.e.e.b.e.a.b.c.a.c.cQt.i.h.g.fQtQt.c.cQt.c.c.c.c.c.b.e.l.b.l.e.a.a.#.a.q.c.qQt.qQt.#.q.iQtQtQt.i.f.qQt.x.f.i.i.g.i.i.f.i.#.c.q.a.r.l.a.l.a.l.a.l.a.b.e.l.b.a.#.c.a.b.l.a.b.a.e.b.e.l.e.r.e.b.r.aQt.#.i.i.f.m.m.v.n.z.F.Q.H.E.Q.L.N.1.4.6.6.9.U.U.U.3#.##.V.F.B.o.A.o.u.n.g.h.x.g.x.g.i.d.i.f.f.fQtQtQtQtQtQtQtQtQtQtQtQt.qQtQtQtQt.#.#.q.w.m.v.v.z.B.S.Y.Q.F.Q.Q.Q.I.A.v.h.m.x.x.g.g.g.f.g.f.g.f.g.q.f.dQt.c.b.a.r.e.r.e.r.e.e.e.e.b.b.b.l.e.e.e.e.l.#.l.b.e.e.e.j",
+".k.k.k.j.e.e.e.e.j.j.e.e.e.b.e.b.e.l.e.e.e.a.b.cQtQt.f.g.h.gQtQt.c.c.c.c.c.a.c.c.l.b.b.a.e.#.e.b.r.#.r.c.#Qt.cQtQt.#.c.q.iQtQtQt.q.#.#.xQt.i.i.iQtQtQtQt.#.c.r.a.a.a.a.a.a.a.a.a.l.l.b.a.a.r.a.c.l.l.b.l.e.r.l.r.j.e.l.b.a.aQt.cQt.i.i.g.m.h.w.w.v.B.K.I.B.B.F.B.M.L.1.9#..9#a.9.6#b##.V.E.I.A.C.n.w.h.h.f.i.g.f.i.f.i.f.fQtQt.r.r.#Qt.#.#Qt.#.rQtQtQtQt.fQt.rQtQtQtQt.w.s.g.m.m.D.I.A.v.w.A.H.Q.F.H.I.v.h.w.m.f.h.m.h.g.f.g.f.g.d.i.c.cQt.b.e.b.e.b.e.e.b.e.b.e.b.a.e.r.b.#.b.r.a.a.a.a.a.b.e.l",
+".j.k.e.k.e.e.b.e.j.k.e.e.e.e.e.e.e.j.e.l.e.r.a.a.cQt.x.h.u.g.f.i.c.c.c.c.c.c.c.c.b.l.l.e.l.e.l.l.r.#.#.#.c.#.q.c.q.a.q.cQt.i.c.i.#.qQt.q.i.qQt.i.i.f.i.f.q.#.a.#.l.r.b.a.l.#.l.a.b.a.e.a.a.aQt.c.b.a.e.a.e.l.b.e.e.b.#.e.b.#.bQt.c.i.f.g.x.m.n.n.o.o.o.o.v.B.I.B.E.Q.M.Z.1#c#c.4#d#e#f.V.K.F.A.o.u.w.h.g.i.dQt.c.i.i.fQt.cQtQtQt.r.b.r.b.r.r.r.r.#.r.#.r.r.r.r.r.f.f.i.g.m.h.m.v.h.C.o.w.n.u.v.n.E.N.M.z.n.h.m.m.m.h.g.g.g.g.g.f.f.dQt.c.#.a.#.e.b.e.e.b.e.b.e.b.b.e.b.l.e.e.l.e.l.a.a.#.a.a.b.b",
+".e.e.e.e.e.e.e.e.e.j.j.j.k.j.j.e.e.e.e.e.b.a.b.b.dQt.f.i.w.h.u.h.fQt.q.a.#.a.a.c.e.a.b.a.b.a.b.b.#.a.#.a.#.a.#.a.rQt.r.c.#.a.a.#.r.#.#.aQt.#QtQtQtQtQtQtQtQtQtQt.r.a.r.r.a.r.a.#.l.l.b.a.c.c.d.d.#.l.b.l.b.a.b.l.b.l.b.#.a.c.#.c.c.i.i.g.h.g.m.m.w.D.v.o.o.A.A.A.B.K.P.Q.T.Y.W.W.6#g#g#c.R.P.E.D.m.h.g.x.q.f.q.gQtQtQtQt.#.#.rQt.b.r.r.r.b.r.a.r.b.e.b.b.b.b.b.b.fQt.g.f.f.g.f.h.m.m.m.m.g.h.h.h.o.o.J.Q.Q.B.z.o.v.u.w.w.h.m.x.h.#.#.a.r.b.r.b.e.r.#.r.a.b.e.e.j.j.e.j.b.e.r.b.r.b.l.e.a.e.l.e.l",
+".e.e.e.e.e.e.e.e.e.k.j.j.j.j.j.j.e.e.e.e.e.b.e.b.cQt.g.i.p.p.v.p.fQt.c.c.a.#.b.c.l.b.l.e.l.e.l.l.a.b.a.a.#.a.#.a.#.a.#.a.r.#.a.a.l.a.#.r.c.q.c.#Qt.iQt.i.f.i.fQt.r.#.a.a.a.a.r.r.l.l.r.a.cQt.dQt.a.a.e.a.e.l.e.l.b.b.a.#.b.#.c.a.fQt.i.f.g.f.h.h.m.w.n.n.v.y.o.A.o.B.Q.R.R.P.R.Y#h.9#i.L.P.R.E.J.v.w.i.x.#.x.f.d.#Qt.#.cQtQt.r.#.#.a.#.a.r.b.r.r.b.b.j.b.e.b.#.b.cQt.f.x.g.f.x.f.m.m.m.g.g.g.h.f.p.w.v.A.B.I.Q.Q.z.z.v.p.w.w.p.h.aQt.e.r.e.e.b.r.b.c.b.r.e.e.e.b.j.j.j.e.e.e.e.b.l.b.l.b.l.b.e.e",
+".j.e.j.k.j.k.j.k.j.e.k.j.j.k.e.k.e.e.e.b.l.b.a.b.c.i.f.f.h.A.C.v.m.fQt.a.a.a.c.a.b.a.e.#.e.#.e.b.l.a.#.l.#.a.a.#.a.a.#.a.#.a.a.#.#.a.a.#.a.c.cQtQt.f.q.fQt.i.f.f.#.#.#.q.#.#.c.#.#.r.#.#.c.c.d.d.#.l.#.l.b.a.e.#.e.e.a.b.#.cQtQtQt.i.g.g.g.s.g.g.h.w.n.v.y.n.A.A.B.B.Q.N.Y.H.Q.Z#h.2.P.K.K.Q.H.B.o.o.h.p.s.x.#.r.#.a.#.rQt.b.r.r.b.r.b.r.b.r.b.#.b.e.e.b.j.b.b.b.#.c.f.g.f.g.fQt.g.s.f.g.f.f.g.x.f.g.x.w.v.o.A.I.Q.Q.B.o.y.h.x.gQt.a.#.b.r.e.r.bQtQt.b.#.e.b.j.j.j.e.j.e.e.b.e.e.b.l.b.l.e.j.l.j",
+".k.j.k.j.j.j.k.e.j.k.j.k.e.k.j.j.e.e.e.e.b.b.e.a.c.c.f.m.u.o.C.D.g.fQt.#.a.#.a.c.e.l.e.l.e.l.e.a.l.e.#.a.l.#.l.a.b.l.e.l.e.b.l.e.l.b.l.e.c.#.c.c.iQtQt.gQt.g.f.gQt.iQtQtQt.iQt.i.#.q.#.cQt.#.f.c.a.#.a.b.l.b.l.e.l.r.a.r.aQt.aQt.d.g.f.g.f.g.g.g.h.w.n.n.v.y.A.z.H.Q.P.P.N.R.Z.O.O.Q.J.A.G.y.D.z.z.A.o.h.h.q.#.bQtQtQt.b.r.r.r.bQt.r.r.b.#.b.r.b.b.k.e.j.e.b.j.e.r.#Qt.f.f.g.f.f.f.g.g.f.f.g.d.x.f.g.g.x.w.w.h.v.Q.F.K.B.o.n.h.q.dQt.dQt.c.f.a.r.c.c.r.b.e.e.b.e.b.k.e.k.e.k.j.e.e.e.e.e.e.j.j.j",
+".j.j.j.j.j.j.j.j.k.e.j.j.j.j.j.j.e.e.e.a.e.b.a.r.bQtQt.x.h.o.C.C.w.i.f.#.a.a.aQt.e.#.e.#.e.#.e.b.l.e.l.#.a.a.b.l.e.e.b.e.l.e.e.b.e.e.e.b.b.a.b.a.c.c.#.dQtQt.fQt.fQt.f.s.f.i.g.i.#Qt.qQt.dQtQt.c.#.a.b.a.l.b.l.r.e.b.a.a.#.cQt.c.i.f.g.g.f.g.h.i.h.g.w.w.p.n.A.K.F.P.N.M.N.U#i.O.P.G.o.v.h.h.w.n.I.z.A.p.x.s.x.f.x.cQt.#.c.r.b.b.b.r.c.r.b.r.b.b.e.j.e.k.j.e.b.e.bQtQtQtQt.d.f.g.i.i.c.f.i.d.f.f.c.f.f.h.h.w.m.n.o.A.o.o.o.C.n.w.g.g.q.f.c.#.r.b.c.r.e.e.b.e.e.e.j.b.k.b.k.j.0.0.j.j.j.j.e.j.j.k",
+".k.j.j.j.k.j.j.k.j.j.k.j.j.e.k.j.e.e.e.e.a.b.b.a.b.d.f.f.h.u.o.v.p.h.f.d.c.#.a.b.l.e.l.e.l.e.l.a.e.#.e.a.#.l.e.l.e.b.l.e.e.b.e.l.j.b.l.e.l.b.b.#.a.#.c.#.#.c.c.iQt.iQt.s.f.s.f.sQt.i.d.#.i.c.cQt.a.#.a.#.l.b.l.e.l.b.b.#.aQt.aQtQt.g.g.f.m.f.w.x.m.p.w.w.o.A.B.K.K.M.Z.U.9#j.8.Z.A.v.w.s.s.s.h.u.v.D.z.A.o.w.s.x.g.x.q.d.r.r.r.b.r.r.b.r.b.r.b.r.j.e.k.k.e.j.e.e.r.bQt.#.#Qt.c.f.i.d.i.f.c.fQt.d.f.f.x.g.x.h.h.n.u.u.h.w.x.n.o.y.o.w.w.x.dQt.c.#Qt.b.r.e.e.e.e.b.e.k.e.j.k.0.e.0.j.e.e.k.e.k.e.k",
+".j.0.j.0.j.k.k.j.k.e.k.e.j.j.e.e.e.e.e.b.b.#.b.b.a.fQtQt.h.g.h.h.p.h.gQt.#.a.a.a.b.a.b.a.b.a.b.l.e.l.e.#.a.e.#.e.b.l.e.e.l.j.j.e.j.j.e.b.e.b.a.e.e.l.e.l.a.#.c.cQt.fQtQtQt.iQt.s.f.i.iQt.d.i.cQt.a.#.a.l.#.a.#.a.r.a.#.a.r.cQt.c.g.f.g.f.h.m.w.w.w.n.n.n.A.I.I.K.T.N.2.9#k#l#i.Q.p.w.sQt.f.x.h.h.f.h.D.E.F.z.y.n.m.p.x.q.x.r.r.#.b.b.r.b.r.b.r.b.k.e.k.e.k.e.b.j.r.b.#.c.#.#Qt.#.cQtQt.cQt.cQtQt.f.d.d.g.f.h.h.h.m.f.g.f.m.g.p.n.n.n.w.h.g.xQtQt.c.r.b.e.b.b.e.e.b.k.b.k.k.0.0#m.k.k.k.j.j.k.j.k",
+".j.j.k.j.j.k.j.j.j.k.j.b.j.j.e.j.e.b.e.e.b.a.b.a.r.d.d.d.f.g.g.m.u.p.iQt.c.#.a.b.l.e.l.e.l.e.l.e.#.e.#.a.#.l.e.l.e.b.j.e.j.b.j.e.j.b.j.e.l.e.r.e.e.b.l.b.e.a.e.#.#.#.#.q.#QtQt.i.i.s.f.f.i.d.f.c.#.l.a.#.a.a.a.#.a.b.bQt.aQt.aQt.f.g.f.h.i.p.h.w.w.n.v.D.A.J.B.z.Z.M.N#h#n#b.N.z.p.n.s.#.#.x.s.gQt.g.u.z.B.K.F.E.y.y.p.p.x.q.#.r.r.b.r.b.b.r.b.e.e.k.k.k.b.k.e.b.l.r.#QtQt.c.r.cQtQt.c.f.c.#.#Qt.q.d.x.x.h.p.x.h.q.#.i.f.g.w.s.w.s.p.p.w.p.f.d.#.cQt.b.r.e.e.b.k.e.j.j.0.0.e#m#m.k.j.j.j.k.e.j.j",
+".k.j.k.k.k.j.k.k.j.k.k.k.j.k.e.j.j.e.e.e.e.e.a.r.a.aQtQt.g.x.h.h.f.s.f.gQt.d.c.c.b.e.b.b.b.a.b.b.a.e.l.e.e.e.#.e.l.l.l.b.l.l.e.b.e.e.e.b.e.l.e.l.e.l.e.l.e.b.a.c.a.#.a.c.a.#.c.c.iQt.i.iQtQt.qQt.b.#.b.#.b.r.a.b.b.l.r.aQt.c.c.c.g.i.s.m.w.w.n.o.w.C.C.A.B.A.I.z.Z.P.N.4.5.O.G.p.s.g.f.s.#Qt.#.#.f.x.g.p.u.v.C.J.Y.E.C.u.s.g.q.f.b.#.e.r.e.b.b.e.r.j.e.j.j.b.j.eQt.cQtQtQtQt.cQt.a.#.cQt.cQt.cQt.f.g.i.g.dQtQt.cQtQtQtQtQt.g.g.g.g.s.h.g.m.n.w.xQt.a.e.b.#.e.e.e.e.j.e.k.0.0.0.e.0.k.e.0.k.0.k.0",
+".j.k.j.k.j.k.k.j.k.j.j.j.k.j.j.e.j.j.e.e.b.a.b.e.a.c.c.d.f.f.x.x.i.i.iQtQt.c.c.c.e.e.a.b.a.b.r.c.#.l.b.l.r.l.l.b.e.b.l.e.l.b.l.l.e.l.b.l.e.e.b.e.e.j.l.b.e.a.a.#.a.r.a.#.a.c.#.a.i.#Qt.iQt.iQt.i.a.#.a.r.a.a.#.a.b.b.e.#.cQtQt.d.s.g.i.h.h.v.n.o.v.v.D.D.A.G.z.K.P.Y.N.U.6.Y.D.n.s.s.f.#.f.#.f.rQt.f.f.g.x.p.n.n.B.B.z.A.y.w.h.q.cQt.c.b.r.b.r.e.b.j.b.j.b.j.e.rQt.cQt.cQt.cQt.c.#.bQt.cQt.c.f.d.f.g.dQt.f.dQt.cQt.c.q.d.f.g.f.g.f.g.f.g.m.D.n.wQt.cQt.e.b.b.e.e.e.k.0.k.k.e.k.0.e.0.k.0.k.e.k.k",
+".k.e.j.k.j.k.j.j.j.j.j.e.e.e.k.e.j.b.e.e.b.b.a.b.#.cQtQt.f.d.f.g.f.f.iQt.g.#.d.d.l.r.e.a.bQt.a.c.#.e.l.e.l.e.a.l.l.e.b.l.e.l.b.e.b.e.e.e.b.l.e.l.e.e.l.e.l.e.a.a.a.a.#.c.a.#.a.c.cQt.dQt.cQt.dQt.c.r.a.a.r.a.b.#.a.#.aQt.c.f.d.f.g.i.i.h.w.u.n.n.C.C.o.D.o.B.I.z.K.P.N.4#h.P.y.w.s.f.f.#.#.#.#QtQt.c.f.d.f.f.x.p.u.h.o.A.B.A.u.u.g.q.f.d.#.b.r.e.b.r.e.b.r.b.r.bQtQt.cQt.cQt.cQt.cQt.cQt.c.f.d.f.f.gQt.x.f.cQt.#.#.bQt.cQt.d.f.f.g.g.g.x.m.o.o.v.f.iQt.c.#.e.l.b.j.j.e.k.0.k.k.k.k.k.e.k.k.0.k.e",
+".k.j.k.j.k.e.k.j.k.j.k.e.k.e.e.e.k.e.e.e.e.#.e.b.c.c.c.cQtQt.d.d.iQt.fQt.f.dQt.q.a.b.a.r.a.c.c.a.a.l.b.l.r.l.b.e.b.l.l.l.b.e.l.l.e.l.b.e.l.e.b.e.j.l.e.e.l.e.a.b.a.b.a.b.a.c.a.aQt.c.#.fQtQtQtQt.cQt.c.#.a.r.a.b.a.#.cQt.d.f.f.x.i.g.m.g.h.n.v.v.n.o.D.o.D.A.G.I.K.Q.M.1.3.P.o.w.x.fQtQt.#Qt.r.#.b.r.#.rQt.f.g.f.x.h.p.y.A.B.A.D.w.s.x.x.d.c.r.b.r.b.e.r.b.r.bQt.cQt.cQt.cQt.c.cQtQtQt.dQt.d.i.d.f.f.i.dQt.cQt.r.#.b.r.cQtQtQt.x.m.m.w.w.w.w.v.w.g.i.iQt.c.#.b.a.b.k.e.k.e.k.j.k.e.0.k.0.e.k.0.0",
+".j.j.e.j.j.k.j.j.j.j.j.e.e.j.e.e.e.j.e.b.e.b.a.bQt.c.c.c.cQt.dQtQtQt.f.f.f.fQtQt.cQt.c.c.cQt.cQt.a.b.l.e.l.e.a.l.e.b.l.e.l.b.l.b.e.e.l.b.e.e.e.e.e.e.l.j.e.b.a.a.#.a.a.#.a.#.aQt.c.cQt.cQt.cQt.cQt.aQt.a.c.a.#.cQt.c.c.fQt.fQt.g.h.m.h.w.u.v.y.D.v.o.o.D.o.o.A.G.I.K.H.N.3.Y.y.h.sQt.f.#.#.r.#.r.r.b.r.a.rQt.c.iQt.d.x.x.n.o.D.B.y.o.n.g.q.f.cQt.r.b.r.b.c.bQt.r.iQtQtQtQt.cQt.c.i.cQt.fQt.dQt.fQt.fQt.d.f.cQt.c.r.aQtQt.d.f.x.i.w.n.C.C.w.m.g.f.f.i.x.q.c.c.b.b.e.e.e.j.j.j.j.k.k.k.e.k.0.k.0.k",
+".k.j.k.j.k.e.k.e.j.k.e.j.j.b.e.j.b.e.e.b.e.l.b.l.c.cQt.c.c.c.c.c.d.fQtQt.fQt.f.gQt.d.c.cQt.c.c.a.e.#.a.#.a.b.l.b.l.e.l.b.l.e.l.e.l.b.e.e.b.l.e.e.j.j.j.e.l.e.a.a.b.a.b.c.a.r.a.a.bQt.a.cQt.cQt.cQt.c.cQt.cQt.cQt.aQt.d.iQt.g.x.h.u.n.p.w.n.u.o.D.n.o.D.o.D.o.C.o.I.I.I.Z.1.P.w.v.fQt.f.#Qt.#Qt.r.l.r.a.r.#.cQt.c.#Qt.d.g.s.h.y.v.z.A.o.v.g.x.q.gQt.c.#.c.#.c.rQtQt.i.i.c.fQt.q.d.q.dQtQt.f.f.f.f.f.f.f.dQt.c.#.c.c.#.d.f.d.g.x.h.x.w.o.w.o.m.m.g.f.g.g.g.iQt.c.#.e.b.e.e.j.e.e.e.e.k.j.k.e.j.e.k",
+".e.k.e.k.e.k.j.j.k.e.k.e.e.j.e.e.e.j.b.e.b.r.a.rQt.c.cQt.cQt.cQtQt.#.d.iQt.s.i.i.iQt.i.#.c.r.#.a.l.a.#.e.a.e.a.e.b.l.e.l.b.l.b.l.e.e.l.e.e.e.j.e.j.e.j.e.e.l.b.a.a.a.a.#.a.#.a.a.b.aQt.c.#.cQt.cQt.dQt.r.c.cQt.c.#Qt.i.f.g.x.m.h.v.u.n.n.v.o.D.v.o.C.o.v.n.v.D.o.B.z.H.M.W.K.v.h.x.f.f.#Qt.r.#.r.#.a.r.b.#Qt.cQt.c.c.f.d.g.q.h.x.o.o.v.v.u.n.w.h.f.cQt.cQt.cQt.fQt.iQtQt.i.#Qt.i.cQtQtQt.#.d.f.fQt.fQt.dQt.dQt.#.iQt.g.f.g.f.g.m.x.h.h.m.m.h.g.g.g.f.g.g.g.fQt.a.r.e.r.e.b.j.j.j.j.e.k.j.k.j.k.j",
+".b.k.e.j.k.e.k.j.k.j.k.j.j.j.e.e.e.b.l.r.l.b.a.bQtQt.c.c.c.c.a.a.fQt.fQt.i.f.f.g.g.f.dQt.q.c.a.#.a.b.a.a.#.l.b.l.l.l.b.l.e.l.e.l.b.e.b.l.b.j.e.e.j.t.e.e.l.e.#.a.b.#.b.a.r.a.c.#.bQt.a.#.cQt.cQt.cQt.c.cQt.cQt.c.iQt.g.i.g.g.w.g.o.o.v.u.v.D.o.o.A.y.C.n.n.n.n.D.A.I.H.P.Y.I.w.h.s.fQt.fQt.#.c.#Qt.b.r.cQt.cQt.aQt.cQt.cQt.c.f.f.u.u.h.v.A.o.o.p.g.g.i.q.f.f.f.f.iQt.iQt.#.i.c.#Qt.q.#QtQt.i.f.g.f.d.i.dQt.rQt.c.g.h.m.h.m.h.h.w.n.w.w.h.gQt.dQt.d.d.f.c.f.iQt.c.#.r.a.b.e.b.e.b.k.j.k.0.e.k.e.k",
+".j.k.j.k.j.b.e.e.e.j.j.b.e.r.e.b.r.a.a.r.a.#.r.a.q.c.#.c.#.qQtQtQt.iQtQt.iQt.sQt.g.p.h.iQt.i.a.e.a.a.b.l.e.e.l.b.e.e.e.b.e.b.e.e.l.e.e.e.e.e.j.e.j.j.e.j.e.j.e.e.e.e.e.r.a.bQt.c.e.a.r.c.#.a.#.a.#Qt.cQt.i.d.i.f.i.g.f.g.s.x.m.w.w.h.w.w.v.n.v.n.v.w.o.w.n.m.v.w.C.v.B.Z.1.Q.o.p.h.gQt.r.r.b.r.e.b.#.e.r.b.#.#Qt.d.fQt.d.g.d.gQt.g.g.x.n.o.A.z.K.z.v.u.v.p.s.s.i.f.q.q.d.dQt.d.i.dQtQt.d.i.d.qQt.iQtQt.i.f.g.f.s.s.g.s.g.f.g.d.f.cQt.c.c.rQt.r.r.b.r.a.b.b.e.b.b.b.b.r.b.e.b.e.j.j.e.0.k.k.0.k.0",
+".j.e.j.e.e.e.e.j.j.k.e.e.l.e.b.e.a.r.a.a.r.a.r.a.#.c.#Qt.#.d.#.i.#Qt.#Qt.fQtQt.s.i.g.p.s.iQt.#.bQt.c.a.#.a.#.e.l.e.b.l.e.l.e.l.b.e.b.l.b.e.e.e.e.e.e.e.j.l.e.a.a.e.b.e.e.a.b.a.c.a.r.a.#.b.#.bQt.#.a.q.c.i.f.f.f.i.i.g.s.x.m.m.m.w.u.m.w.v.v.o.o.w.n.w.h.h.h.p.n.w.o.A.S.Z.Z.H.y.h.x.fQt.r.r.e.r.b.b.a.r.a.#.a.rQt.d.i.d.i.d.i.d.g.f.g.g.h.u.A.z.J.B.A.v.w.s.p.s.f.x.f.g.d.i.dQt.i.f.g.g.f.f.f.xQtQt.g.f.g.f.g.q.#Qt.#.dQt.c.d.d.c.rQt.r.r.r.b.r.a.e.r.e.b.e.b.e.r.e.e.b.b.e.e.b.0.k.e.0.e.k.e.k",
+".j.k.0.e.j.e.e.b.j.e.b.e.e.e.a.b.#.a.a.c.a.c.a.aQt.c.cQt.cQt.c.c.#Qt.#.c.q.cQtQtQt.s.u.g.iQtQt.cQt.c.a.a.#.a.b.l.b.e.b.e.b.e.e.l.e.e.e.l.e.e.e.e.j.j.e.j.e.l.a.a.b.l.b.a.aQt.cQt.c.a.#.cQt.#Qt.c.qQt.c.q.i.d.g.g.g.g.f.g.g.m.x.m.p.m.m.w.w.v.n.w.n.h.h.h.h.h.h.h.g.u.o.I.M.1.Z.Q.h.w.gQt.#.r.r.r.b.a.r.#.b.#.c.fQt.fQt.d.i.dQt.d.i.d.f.f.m.s.n.u.A.J.J.B.A.u.h.p.w.x.g.x.f.f.f.g.i.q.f.f.fQt.fQt.g.i.s.m.h.f.q.f.#Qt.cQt.a.r.a.b.r.b.b.e.e.e.b.e.b.e.e.e.e.e.e.e.j.b.j.e.j.j.e.j.k.k.0.k.k.0.k.0",
+".j.e.j.e.j.b.j.e.e.e.l.e.r.a.b.a.a.a.a.#.a.a.#.a.c.#.c.a.c.a.a.#.a.aQt.a.c.c.cQtQt.f.m.g.s.f.dQt.c.c.#.a.a.#.e.a.e.#.e.l.e.l.e.b.l.b.e.b.e.l.e.e.l.b.l.l.b.e.r.a.e.a.a.#.c.c.c.c.cQt.d.#.cQt.d.q.c.q.c.fQt.i.i.gQt.g.s.g.f.g.m.h.m.x.m.g.m.p.w.h.h.p.h.h.x.g.h.h.x.h.u.A.I.L.Y.N.D.n.x.fQtQt.r.#.a.r.#.b.#Qt.rQt.d.i.d.i.dQt.fQtQtQt.c.g.f.g.g.w.u.v.z.z.z.v.o.v.w.g.w.g.w.g.m.x.g.f.m.i.g.f.i.f.g.m.g.f.x.i.d.d.a.a.a.a.b.a.r.r.e.e.b.e.r.e.b.e.e.e.b.e.e.b.e.b.j.e.e.j.b.j.b.e.0.e.k.e.0.k.e.k",
+".j.j.j.e.j.e.l.e.b.l.e.b.a.a.b.a.a.#.a.a.a.a.a.a.b.a.b.#.b.b.a.b.b.e.b.aQt.c.c.c.c.q.i.i.f.fQt.d.f.c.cQt.a.a.e.b.e.e.e.b.e.b.e.e.e.l.e.l.b.e.b.e.j.j.l.b.l.l.a.a.a.#.a.c.aQt.c.c.qQt.#.iQt.iQt.#.f.d.i.c.fQt.i.i.i.i.f.g.g.x.h.h.s.g.g.f.h.m.h.h.h.g.g.x.f.x.g.g.x.h.p.y.A.B.E.N.K.y.h.q.i.fQt.r.#.b.#.bQt.c.f.c.fQt.dQt.d.q.dQt.#.cQt.c.i.g.g.s.u.v.h.h.p.n.A.z.n.v.p.w.p.h.h.n.h.m.g.g.f.x.g.g.w.h.g.fQt.c.d.c.a.b.b.b.a.b.b.b.b.e.e.e.e.e.b.j.e.j.e.e.b.e.e.e.e.b.j.b.e.e.j.e.e.k.0.k.0.k.0.k",
+".j.j.e.e.j.e.e.e.l.e.l.a.a.a.c.c.b.e.l.e.e.b.l.b.b.b.e.e.e.e.b.b.b.e.b.e.r.b.b.#.a.c.c.f.m.g.h.dQt.i.c.c.a.#.a.l.e.l.b.l.e.l.e.l.b.e.b.e.e.e.l.e.t.b.l.e.a.b.b.a.a.a.a.a.#.c.#Qt.cQt.d.iQt.#.iQt.dQt.i.f.#Qt.q.i.d.f.i.f.g.g.g.x.g.f.g.g.h.g.x.g.x.h.q.g.x.g.q.x.g.x.h.n.u.y.A.Q.R.K.n.g.f.fQtQt.#.#.rQt.dQt.rQtQt.d.i.fQt.dQt.f.cQt.d.x.d.g.g.f.m.h.w.x.g.p.w.u.v.u.o.o.z.A.A.v.v.u.p.m.g.m.x.m.i.fQt.c.c.c.b.c.e.b.e.e.b.e.b.e.e.b.e.e.b.j.e.b.e.k.b.j.j.j.j.k.e.0.k.0.k.0.e.k.0.k.k.k.e.k.e.k",
+".j.e.j.e.e.e.b.l.b.l.a.a.a.c.a.#.e.e.b.e.e.e.b.e.l.e.e.e.l.e.l.e.e.e.e.b.e.b.b.b.e.#.cQt.f.h.x.x.f.dQtQt.c.c.aQt.e.b.e.e.b.e.b.e.l.e.l.e.b.l.b.e.b.j.l.b.l.l.a.#.a.r.a.q.c.#.cQtQtQt.iQt.fQtQtQt.i.d.i.cQt.#Qt.qQtQtQt.f.f.f.g.g.g.i.i.i.x.d.f.g.f.f.f.x.d.f.f.g.g.f.g.s.h.w.o.G.Q.H.A.w.x.d.d.f.bQtQt.rQt.c.f.rQt.fQt.d.#.fQt.d.f.d.f.d.d.g.f.f.q.q.x.h.m.s.h.s.p.w.v.o.o.B.B.B.v.o.v.u.h.g.f.fQtQt.c.c.a.b.e.r.l.e.l.b.e.j.j.e.j.j.j.e.j.j.e.k.j.b.k.e.e.j.e.e.k.k.e.k.e.k.0.k.e.k.e.0.k.0.k.0",
+".j.e.e.j.j.e.e.e.l.l.a.#.a.a.a.c.b.e.e.b.b.e.e.e.e.e.b.e.e.b.e.b.j.b.e.j.e.b.b.r.e.b.cQt.f.g.x.hQt.i.d.c.c.cQt.a.b.e.r.l.b.l.e.l.e.b.e.b.e.e.e.e.t.e.e.l.b.e.a.a.a.a.r.c.#.#.d.#.iQtQtQtQt.iQt.iQt.dQt.f.#Qt.a.#.c.cQt.i.f.g.g.f.i.f.fQt.f.f.d.f.d.f.d.i.c.f.d.f.i.g.g.x.s.A.C.n.T.H.K.y.x.cQt.x.#.#.cQt.d.#.c.f.d.i.d.i.dQt.d.i.d.q.f.d.f.qQt.d.fQt.f.q.x.h.s.p.u.v.v.v.A.C.o.D.z.y.o.v.w.i.g.f.#Qt.q.a.a.l.e.j.e.e.e.j.e.j.b.e.k.e.j.j.j.b.k.b.j.k.e.k.e.k.e.k.e.k.0.k.0.k.e.k.0.k.0.e.k.k.e.k",
+".0.e.k.e.j.b.e.b.a.b.l.e.e.#.e.l.e.b.e.e.e.j.k.j.k.j.j.j.k.j.j.k.e.e.j.b.e.b.e.b.c.f.c.#Qt.h.v.y.x.gQt.i.cQt.c.c.#.q.a.a.l.b.b.e.b.l.e.l.e.b.l.b.e.b.l.b.e.b.e.e.b.l.a.a.bQt.a.cQtQtQtQtQt.fQt.f.dQt.cQt.cQt.c.#.#Qt.r.#.c.f.q.x.f.f.d.f.d.f.f.dQt.cQt.c.f.d.g.q.f.g.x.g.h.p.n.y.J.H.L.N.z.p.h.d.f.g.f.fQt.f.d.d.f.c.q.a.#.r.b.#.q.i.dQt.fQt.g.q.cQt.d.d.f.h.s.p.p.h.u.v.v.o.A.A.w.m.g.f.fQt.d.c.r.r.b.b.b.b.b.b.k.j.k.j.k.j.k.k.j.k.j.b.k.k.e.k.k.e.e.j.e.b.j.e.k.e.0.e.0.k.0.e.k.j.k.j.k.e.0.k",
+".e.j.e.b.e.e.b.b.l.e.l.b.l.e.l.e.j.j.e.j.e.e.e.j.e.j.k.k.j.k.j.k.e.e.e.e.e.e.e.e.b.c.dQtQt.w.y.C.h.m.i.f.dQt.d.d.q.#.a.#.l.b.l.b.a.e.b.e.b.l.e.e.l.e.e.e.l.e.l.b.a.l.b.#.c.a.r.a.f.iQtQt.iQtQt.i.c.#Qt.c.cQt.b.#.b.#.#.rQt.r.f.f.i.f.cQt.i.c.f.cQtQt.f.d.f.q.i.q.g.q.f.x.g.p.n.y.B.F.N.1.E.o.s.h.g.f.g.f.f.f.f.cQtQt.cQt.cQt.c.#Qt.fQt.d.g.g.f.f.g.f.g.x.h.s.h.h.u.v.y.o.z.C.o.v.i.g.fQt.i.c.c.c.r.b.b.b.b.b.b.b.k.e.j.k.e.k.j.j.j.j.j.k.e.j.e.k.e.k.k.b.j.j.e.j.e.k.0.k.k.e.k.0.k.e.k.e.j.j.k.j",
+".e.e.e.e.e.#.a.#.e.l.b.l.e.e.e.j.e.e.j.e.b.k.e.e.k.j.e.e.k.b.k.j.b.k.e.j.b.j.e.b.b.cQt.#Qt.p.v.J.p.h.w.g.m.f.xQt.#.q.#.a.c.e.#.a.b.e.l.e.e.b.e.b.e.b.l.b.e.e.b.e.l.b.l.b.a.a.c.a.c.#.#.#.#.#.#.#.cQt.c.c.#.b.r.b.r.b.b.rQtQt.c.f.d.f.c.#.cQt.cQt.rQt.cQt.d.f.q.xQt.x.g.q.h.p.y.y.I.H.Y.3.N.I.o.p.g.i.g.gQt.f.d.dQtQtQt.c.f.c.f.d.iQt.iQt.g.x.g.i.h.g.h.h.w.p.n.p.B.D.z.A.v.w.h.g.iQtQt.dQt.c.c.c.e.e.e.j.e.e.e.e.b.k.j.j.j.j.e.k.e.e.e.e.e.j.k.e.0.k.j.k.j.b.e.e.k.e.k.e.k.j.k.e.j.k.j.k.e.b.e.b",
+".c.#.aQt.a.c.a.c.b.e.e.e.b.l.e.e.k.e.j.k.k.k.e.k.j.j.k.k.j.k.j.j.k.j.k.j.k.j.k.k.e.#.aQt.s.h.y.C.v.n.A.u.p.g.g.s.#QtQt.c.#.a.b.#.b.b.e.b.l.e.l.e.l.e.e.l.b.e.l.e.e.l.b.l.b.#.b.c.q.c.c.c.c.c.cQt.c.c.aQt.a.r.a.b.b.r.r.b.b.#Qt.r.fQt.cQt.dQt.#Qt.dQt.d.#.d.d.x.d.f.x.f.g.h.p.n.A.F.T.N.Z.Z.M.B.u.x.m.x.f.g.d.i.c.f.#.fQt.f.d.x.g.i.s.f.s.g.s.g.m.p.h.n.v.o.v.z.D.B.B.o.u.h.g.fQt.dQt.cQt.c.b.b.b.e.j.b.e.j.b.j.e.j.e.e.e.e.j.e.e.e.e.e.j.e.e.b.j.0.e.j.e.k.j.j.e.b.j.e.e.j.b.j.e.e.e.e.b.e.e.b.e",
+".a.a.a.a.a.#.a.a.e.l.b.l.e.e.j.j.b.k.k.j.e.k.e.k.e.k.k.e.k.k.e.k.j.k.b.k.j.k.j.k.e.e.eQt.f.p.v.v.n.A.C.z.y.u.g.i.iQt.#.#.c.a.#.b.e.l.e.e.b.e.b.e.e.b.l.e.e.e.b.e.b.l.b.l.e.a.a.a.c.c.#.a.a.#.a.a.a.#.a.b.a.r.e.r.l.b.b.r.b.#.rQt.c.#.c.rQt.rQt.rQt.r.cQt.d.f.d.f.h.f.x.f.p.h.y.z.M.M.Q.Q.M.2.N.z.h.w.g.h.f.f.dQtQtQtQt.g.f.g.f.g.m.g.w.h.w.p.w.h.u.o.o.z.o.z.o.B.v.v.p.w.fQt.d.#Qt.#.c.a.b.#.b.b.b.e.e.e.e.e.j.e.b.e.b.e.k.e.e.e.b.e.b.e.e.e.j.e.e.k.e.e.e.b.b.e.e.b.e.b.e.b.e.b.b.b.a.e.a.b.a.a",
+".c.aQt.e.#.e.e.e.b.e.e.k.e.e.j.j.k.j.k.e.k.0.k.0.k.k.k.k.e.k.k.0.e.k.k.k.k.e.0.k.k.b.e.c.f.v.C.D.o.y.z.C.y.u.p.sQt.#.iQtQt.c.a.b.#.e.b.e.l.e.l.b.l.e.e.b.l.b.l.e.t.e.l.e.a.b.b.a.q.a.a.c.a.c.a.c.a.c.e.a.b.b.b.e.r.e.b.b.r.r.#.#Qt.cQt.rQt.dQt.c.f.cQt.r.d.f.q.f.x.h.g.h.h.n.A.z.Q.M.E.K.F.3.O.K.v.w.s.h.f.i.c.f.c.g.d.g.f.m.h.w.u.v.o.v.A.A.A.o.o.A.o.v.v.u.v.u.h.w.g.fQt.cQt.a.c.c.a.b.b.e.e.e.j.e.k.e.k.e.b.j.e.e.j.e.b.e.b.e.e.l.e.e.b.e.b.j.e.e.b.e.#.b.aQt.a.#.b.#.r.#.r.#.a.a.a.#.a.c.a.a",
+".b.e.e.e.e.e.b.j.e.e.j.e.e.k.e.e.k.k.k.0.0.e.0.k.e.0.e.0.0.0.e.0.k.0.e.0.0.k.0.k.0.j.e.b.i.h.A.D.o.y.A.C.z.u.h.q.gQt.i.#.dQt.c.c.e.b.l.e.b.e.e.e.e.b.l.e.e.e.e.b.e.e.l.b.l.l.l.b.a.c.a.a.a.a.a.#.e.b.l.r.e.e.b.b.e.e.b.e.r.b.r.cQt.#.cQt.rQt.r.c.#.cQt.c.f.q.g.q.m.s.h.w.w.o.A.I.Q.F.I.I.F.N.1.Y.B.v.h.w.f.x.i.d.f.f.g.f.m.h.u.u.B.z.J.B.J.D.B.z.o.u.v.h.g.m.g.g.g.i.sQtQt.a.l.eQt.a.b.a.b.e.j.b.k.e.e.k.b.k.e.e.b.e.b.e.e.e.j.e.r.e.r.e.e.e.b.e.#.b.a.c.c.d.f.d.aQt.c.aQt.a.c.#.c.cQt.c.cQt.c.b",
+".b.b.b.k.b.k.0.e.j.j.j.e.k.b.j.j.0.e.0.k.0.k.e.0.0.0.0.0.e.0#m.e.k.0.k.0.k.0.k.0.k.e.j.eQt.g.o.C.o.v.z.C.v.u.i.sQtQt.d.qQt.c.c.c.b.e.e.l.e.l.b.l.b.l.e.e.b.l.b.e.t.e.j.l.e.r.l.b.a.a.#.b.a.#.b.a.l.e.l.e.l.b.e.e.e.k.r.e.r.bQt.r.rQtQt.r.c.f.c.#.dQt.c.f.f.q.f.g.s.g.w.x.n.o.z.K.Q.B.I.K.I.I.Y.V.K.A.p.h.g.f.f.iQt.g.g.m.w.w.v.o.F.E.F.E.F.B.B.D.w.m.g.h.g.x.m.x.iQt.c.a.a.e.a.b.a.a.b.b.e.e.e.j.b.j.j.j.j.j.e.b.e.e.e.e.e.b.e.b.e.a.e.b.b.r.b.r.c.c.d.f.d.f.d.f.b.b.#.b.aQt.a.cQt.c.c.c.c.b.c.c",
+".k.k.e.k.k.k.e.k.k.e.k.e.k.k.k.e.k.k.0.k.0.k.0.k.e.0.0.0.0.k.0.0.0.k.0.e.0.k.e.0.k.k.k.j.a.x.A.z.u.u.h.h.n.h.m.gQtQtQt.c.a.r.e.b.a.e.b.e.b.e.e.e.e.e.b.l.e.e.l.e.b.j.b.l.e.l.a.a.#.a.a.a.a.b.a.a.l.#.e.b.l.b.e.r.e.j.b.k.#.bQt.d.f.cQt.fQt.d.i.f.fQt.x.f.f.g.f.g.n.h.w.p.o.B.E.R.Q.F.B.z.K.I.E.R.U.M.v.w.p.g.q.x.i.x.f.w.h.z.D.E.2.Q.B.v.w.p.u.s.h.f.f.f.g.f.fQt.f.iQt.#.c.q.c.a.a.a.a.a.b.a.a.a.e.e.b.l.e.b.l.e.a.#.cQtQt.dQtQt.dQt.#.c.qQt.q.c.c.#.c.a.c.c.c.#.e.b.e.e.r.e.b.e.b.b.e.b.e.b.e.b",
+".k.e.k.0.e.k.0.e.k.j.j.k.j.e.0.k.0.e.k.e.0.k.e.0.k.k.e.k.0.k.0.k.e.0.k.0.k.0.0.k.k.e.j.e.b.i.u.B.p.p.h.p.h.g.i.xQt.q.dQt.a.#.a.e.b.l.e.l.e.l.b.l.b.e.l.e.b.e.b.e.j.l.l.b.e.e.a.b.a.b.a.b.a.a.a.b.l.l.l.a.e.#.e.b.b.b.j.e.b.r.c.d.c.i.d.i.d.g.f.f.g.f.g.f.g.m.x.m.p.u.n.v.o.I.T.R.E.B.A.z.z.B.E.P.L.Z.A.w.m.f.h.h.g.g.w.h.o.B.E.T.H.F.y.w.h.p.i.x.f.f.iQt.f.gQt.fQt.c.i.c.c.a.a.aQt.a.#.a.a.#.a.#.a.a.aQt.a.c.aQt.a.a.a.c.q.#.d.i.#.#Qt.qQtQtQt.i.c.cQt.c.c.#.c.c.#.e.a.b.l.e.l.e.b.e.e.e.e.e.e.e",
+".k.k.k.k.0.k.k.k.j.e.k.e.k.0.k.e.k.k.0.0.k.e.0.k.e.0.k.0.e.0.k.0.0.k.0.k.0.k.k.0.j.b.k.e.aQt.g.y.u.h.u.h.g.x.f.f.iQt.d.c.a.b.e.e.l.e.b.e.b.e.l.e.e.l.b.e.l.e.l.e.b.j.e.l.l.e.#.a.#.a.a.a.r.a.a.b.b.l.b.l.e.b.e.b.j.r.j.r.b.bQt.d.i.d.i.d.i.f.g.d.g.f.g.x.h.g.w.h.w.p.w.o.z.F.P.N.z.o.u.A.A.z.B.I.M.Z.I.n.x.h.h.x.w.h.v.o.B.F.E.E.z.u.h.g.f.i.q.sQt.dQt.dQtQt.dQt.d.c.c.c.c.a.a.a.a.b.c.#.c.b.a.a.cQt.c.c.cQt.c.c.a.#.a.a.c.c.i.d.cQt.c.c.cQt.c.c.b.b.b.b.r.b.b.b.e.e.b.e.e.b.e.e.e.b.e.b.j.b.e.j",
+".0.e.0.e.k.e.0.e.j.k.j.0.k.e.k.0.e.k.k.e.0.k.k.0.k.e.k.k.0.k.0.k.0.e.k.0.e.0.0.e.k.j.k.b.eQt.s.h.p.h.g.g.m.i.g.i.d.#.i.c.a.b.a.b.e.b.e.e.l.e.e.l.b.e.e.b.e.e.b.e.t.b.t.e.e.e.a.b.a.a.b.a.a.b.a.a.l.a.e.a.b.e.#.e.r.b.b.e.r.c.f.q.i.q.dQt.f.f.gQt.x.h.x.h.x.s.s.w.p.w.u.o.B.F.T.S.o.v.n.n.y.y.z.B.P.2.H.o.w.g.p.w.u.o.y.B.F.B.B.C.g.h.f.q.d.d.d.d.c.d.i.dQt.c.c.c.cQt.a.c.a.#.e.e.#.a.a.b.a.a.bQt.c.c.c.a.c.a.cQt.e.l.b.a.#.c.a.a.e.b.e.b.b.b.e.e.b.e.b.e.e.e.b.e.e.e.e.j.e.j.e.j.b.j.e.j.j.e.k.j",
+".k.k.k.k.0.k.k.0.e.k.e.k.k.0.k.j.k.0.e.k.k.e.0.e.k.0.k.e.0.k.0.k.0.k.0.k.0.k.0.k.k.e.k.e.e.rQt.s.g.m.g.g.f.i.f.i.#.d.c.c.a.b.e.e.l.e.l.b.e.b.e.e.l.e.l.e.l.b.l.e.e.j.e.b.l.e.a.a.#.b.a.a.a.a.a.e.l.l.b.l.l.b.e.b.e.b.e.b.aQtQt.gQt.fQt.fQt.g.f.f.x.f.m.f.x.w.s.h.w.n.v.o.B.E.H.F.v.v.w.w.n.o.A.H.2.Z.I.o.w.h.h.o.z.B.z.B.C.v.u.p.f.iQt.#.a.r.cQt.aQt.a.c.b.b.aQt.b.a.b.b.e.e.e.e.e.e.b.l.e.e.b.l.a.b.#.a.a.b.a.a.b.b.e.b.e.r.e.b.l.b.l.e.l.e.b.l.e.e.e.e.b.e.e.e.e.j.b.k.b.k.b.k.e.j.e.j.e.j.e.j",
+".0.e.0.k.e.0.e.k.j.0.k.0.e.k.e.k.e.k.0.k.j.k.k.0.k.e.0.k.0.k.0.e.k.0.k.0.k.0.k.0.k.k.j.j.e.#.a.#.g.i.i.sQt.iQtQtQt.#.c.a.#.b.l.b.e.b.e.e.e.e.l.b.e.b.e.b.e.e.e.e.e.j.j.j.l.e.#.b.a.a.a.a.b.#.b.a.l.l.e.l.b.b.l.r.e.b.e.r.a.i.f.gQt.fQt.d.i.qQt.f.g.f.g.x.g.x.h.g.n.h.o.o.B.E.I.B.v.o.n.u.n.D.z.K.X.Z.B.o.u.w.z.J.J.B.A.u.w.h.m.iQtQt.c.a.b.a.a.r.b.a.b.a.r.a.b.b.l.b.e.e.b.e.e.j.b.l.l.e.e.l.l.l.b.e.l.e.b.l.e.e.a.e.e.b.e.j.j.j.k.j.e.k.e.j.j.k.b.k.b.k.e.j.j.e.k.e.k.j.k.j.k.k.k.e.k.k.k.j.j.k",
+".k.k.k.e.0.k.k.0.e.k.e.0.k.0.k.j.0.e.k.e.k.e.0.k.j.k.k.e.0.k.0.0.0.e.0.k.e.0.k.e.0.k.k.e.j.b.l.b.i.qQtQtQtQtQtQt.#.d.c.c.b.e.e.e.l.e.l.b.e.e.e.e.l.e.l.e.e.j.e.t.e.j.e.e.e.l.a.a.#.b.a.b.a.a.a.b.l.l.e.l.e.a.b.b.b.b.b.aQt.i.f.g.dQtQt.g.dQt.f.g.f.g.f.g.f.m.x.w.h.v.A.z.I.F.B.C.n.y.n.n.u.A.K.I.W.W.I.v.o.z.K.F.o.u.h.g.f.f.d.f.d.cQt.a.b.a.r.c.r.e.b.b.b.e.b.a.b.b.e.e.e.j.e.j.l.e.b.l.b.l.b.e.l.l.b.l.e.l.b.l.e.e.e.j.j.e.k.j.e.0.k.0.k.e.0.k.0.j.k.e.k.e.k.k.k.k.k.e.k.e.0.e.j.k.0.e.j.e.k.k",
+".0.e.0.k.k.0.e.k.j.0.k.k.0.e.k.e.k.k.k.j.j.k.k.e.k.e.0.k.0.e.0.k.k.0.k.0.0.k.0.0.j.k.e.j.e.b.l.lQt.iQtQt.#QtQt.qQt.cQt.a.a.b.e.e.e.b.e.e.j.l.j.e.e.e.b.j.e.l.e.e.j.e.e.t.b.e.a.b.a.a.a.a.#.b.a.a.l.b.e.a.b.e.b.e.c.#.aQt.#.i.f.g.#.d.i.d.i.dQt.f.iQt.i.f.g.f.m.g.n.v.A.D.I.E.I.o.p.u.n.n.y.A.z.K.N.V.E.B.I.H.E.z.h.h.w.i.f.c.a.bQt.c.a.b.a.b.b.c.a.b.b.l.b.l.b.e.b.l.b.e.j.j.j.e.e.l.e.l.e.l.e.l.e.j.e.j.e.j.j.j.b.e.e.j.k.k.e.0.0.k.0.e.0.0.0.e.k.e.k.0.k.0.k.0.e.0.e.k.0.k.k.0.k.j.e.k.j.k.j.j",
+".j.k.j.e.0.k.0.0.k.0.e.k.k.k.0.k.e.j.j.j.e.j.j.k.j.k.j.e.0.k.0.k.0.k.0.e.k.0.k.0.k.e.k.j.j.e.e.b.e.#Qt.q.fQtQt.c.c.#.c.bQt.l.b.#.e.e.e.e.e.b.e.e.b.a.e.a.b.e.e.e.j.j.j.e.e.e.b.l.aQt.a.b.a.a.a.r.e.l.l.b.l.a.#.a.b.#.aQt.c.d.gQtQt.f.#.f.cQt.cQt.d.g.f.h.x.p.h.p.n.u.o.F.P.T.I.o.n.o.n.u.C.z.B.K.Q.2.V.M.E.F.z.p.f.i.d.dQt.c.cQt.b.#.b.e.e.a.b.a.e.b.l.r.e.r.e.e.e.e.e.j.e.j.j.j.e.e.b.e.j.e.e.b.j.b.j.k.j.e.j.j.0.k.0.k.0.k.0.k.e.k.e.k.k.e.k.0.k.j.e.k.e.k.e.k.k.j.k.k.j.e.k.j.j.k.k.j.k.e.k.k",
+".k.e.k.k.k.e.k.0.e.k.k.0.e.k.e.k.j.j.k.j.k.e.j.j.k.e.0.k.k.0.k.0.0.e.k.0.k.0.e.k.0.0.0.k.e.k.e.j.e.a.c.#.qQtQt.c.c.c.a.c.b.a.b.e.e.e.j.e.e.j.e.e.e.e.e.k.e.j.j.e.0.e.j.j.e.l.e.b.a.b.#.a.a.b.a.a.l.e.e.a.e.l.b.a.#.a.#.c.f.f.f.g.d.#.f.c.q.cQt.fQt.g.f.m.x.s.w.p.u.v.B.F.E.E.B.A.f.h.n.o.o.A.o.A.2.2.N.K.B.z.n.g.qQtQt.d.d.c.c.c.a.b.b.l.b.b.l.r.b.b.b.e.a.e.#.e.e.e.l.e.k.b.j.e.e.j.e.l.b.e.j.e.k.k.e.k.e.k.j.k.k.0.k.0.e.0.k.0.0.0.k.0.k.0.k.k.e.k.k.0.k.j.0.k.k.j.k.e.k.j.j.j.e.e.k.b.j.j.j.j",
+".j.j.k.e.0.k.0.k.k.0.e.k.k.0.k.k.e.j.j.e.j.j.j.e.0.k.0.k.0.k.e.0.k.0.0.k.0.k.0.0.k.k.k.j.k.e.e.j.e.a.a.cQt.#.c.#.c.a.c.a.a.b.e.e.j.k.e.k.k.j.k.j.e.k.j.e.k.k.k.k.j.j.k.e.j.b.e.e.#.c.a.a.#.a.a.b.e.b.l.b.l.b.a.#.l.#.aQt.d.g.g.i.fQt.d.i.dQt.fQt.f.g.f.h.g.w.p.n.w.v.B.E.E.F.B.v.g.m.m.w.u.o.J.F.1.Z.F.B.u.h.f.f.i.d.d.c.c.#.c.b.r.e.e.e.b.e.e.e.l.b.e.e.r.e.e.e.e.e.j.e.j.e.k.b.j.e.e.j.e.e.e.j.j.k.e.k.j.k.e.e.0.k.e.0.k.0.k.0.k.k.e.k.0.e.k.e.k.j.e.0.e.k.e.k.e.k.j.e.k.j.k.e.k.k.b.j.j.e.e.k",
+".j.k.e.0.k.k.e.0.e.k.0.j.k.e.k.e.j.j.k.j.e.j.j.k.e.0.k.0.e.0.k.0.k.0.k.0.k.0.k.0.0.e.k.j.k.b.e.j.e.e.a.a.c.c.#.c.#.c.b.a.b.b.l.b.j.j.j.j.j.j.e.j.j.b.e.j.e.j.j.e.e.k.e.j.e.b.e.b.a.a.a.b.a.b.a.#.e.l.l.b.l.l.b.a.#.a.#.cQt.g.f.gQt.f.iQt.fQt.i.d.g.f.g.x.h.p.p.p.u.v.z.E.M.E.A.p.v.n.u.u.z.E.Y.V.Z.F.o.u.g.f.dQt.d.d.c.#.c.b.b.a.e.e.a.e.b.e.b.e.r.e.e.e.e.l.b.e.e.j.e.e.j.j.e.j.e.j.e.b.l.j.e.e.e.k.e.k.b.j.k.k.k.0.0.0.k.0.0.0.e.0.0.0.k.0.k.0.j.e.k.k.0.k.0.k.k.j.j.j.j.b.j.b.k.j.e.k.e.j.j.j",
+".j.k.j.k.e.0.k.k.k.0.e.k.j.j.0.k.j.b.j.e.k.e.e.j.k.k.e.k.0.k.e.k.e.0.k.e.0.k.e.0.k.0.k.j.k.e.j.e.e.k.e.j.a.a.c.c.c.a.c.a.b.a.e.b.j.e.k.e.j.b.j.e.e.k.k.j.e.e.e.k.e.j.e.b.e.e.a.b.#.a.#.a.a.a.a.a.e.e.b.l.b.a.a.#.l.#QtQt.d.g.f.s.g.f.f.g.f.g.f.g.f.g.f.h.h.w.p.n.w.o.B.E.H.F.B.v.A.o.B.B.Q.Y.N.P.F.v.p.g.f.i.cQt.aQt.b.a.b.a.b.e.e.j.b.e.e.l.e.j.e.e.a.b.b.e.e.b.j.e.k.e.j.e.k.e.b.e.e.j.e.e.j.e.k.j.k.j.k.k.e.k.0.k.k.0.k.0.0.0.0.k.k.e.0.0.e.k.k.0.k.e.k.e.k.j.e.j.j.j.j.j.j.j.e.j.e.j.e.j.e.j",
+".e.k.e.j.k.e.k.j.e.k.j.e.k.e.k.e.j.k.j.j.j.j.j.k.e.k.0.k.e.k.0.k.0.k.0.0.k.0.k.0.j.e.k.b.k.e.j.e.j.e.j.e.e.a.c.#.#.c.a.r.a.e.b.e.e.e.l.e.e.e.l.e.b.e.e.b.e.e.e.e.e.e.e.e.e.a.e.b.a.c.a.a.b.a.r.a.e.l.l.e.l.a.#.a.#.a.r.cQt.f.g.g.g.g.f.g.f.g.f.g.f.g.f.h.m.p.n.n.p.z.H.Q.T.K.K.Q.L.N.P.N.T.E.I.o.u.m.f.f.d.c.c.r.c.r.b.b.b.e.e.e.j.e.e.j.e.j.b.e.b.e.e.e.e.e.l.e.j.e.e.j.j.j.b.j.e.j.l.e.e.b.j.e.k.e.j.j.j.j.k.e.k.0.e.0.0.e.k.0.k.0.0.0.k.k.0.k.j.e.0.k.j.k.e.k.e.k.b.j.b.k.b.j.j.j.e.e.e.k.e.j",
+".j.k.j.k.j.j.k.e.k.j.k.j.j.k.k.k.e.e.e.e.e.e.j.j.k.0.e.k.0.k.e.0.k.e.k.e.k.e.k.0.e.k.j.j.k.b.e.e.e.j.k.e.k.e.c.#.c.a.a.a.b.a.b.a.a.a.a.a.aQt.a.c.a.a.#.a.a.a.e.l.e.b.e.b.a.r.b.a.#.b.#.c.a.a.a.a.e.b.l.r.l.#.a.#.l.q.a.f.f.g.f.g.f.g.f.g.f.g.f.g.f.g.x.m.s.n.h.o.v.B.E.L.N.N.N.R.3.O.M.B.A.p.h.x.sQtQt.i.d.c.b.b.b.b.b.b.e.e.b.k.j.k.j.j.e.j.j.j.b.l.b.e.b.b.b.e.j.j.j.j.b.j.j.j.e.e.b.j.e.j.e.k.j.j.j.e.k.k.j.k.0.k.0.k.0.0.0.e.0.k.e.k.0.e.k.e.k.j.j.e.j.j.k.0.e.e.k.e.k.e.k.b.e.b.e.e.e.j.b.k",
+".k.e.k.e.k.e.j.j.k.j.e.k.e.k.e.k.j.j.j.j.k.e.j.k.e.k.0.e.k.0.k.0.k.0.k.0.k.0.k.k.j.k.e.e.k.e.j.j.e.j.k.0.k.e.a.#.c.c.a.r.a.b.#.b.a.#.cQt.c.c.cQt.r.#.#.r.#.a.a.a.e.b.e.e.e.a.b.b.a.c.a.#.a.#.b.a.e.l.e.l.e.l.a.#.a.#.rQt.d.f.f.s.g.f.f.g.f.f.g.f.g.f.m.h.g.n.n.n.A.z.T.W.9#a.V.T.K.J.B.v.g.q.f.d.q.#Qt.c.c.f.c.#.r.e.e.e.b.e.k.k.j.j.e.j.j.j.b.j.b.e.b.e.l.e.e.e.e.k.j.e.k.e.j.e.e.j.e.e.e.e.j.b.k.j.k.k.k.j.k.j.0.k.0.k.0.k.k.0.k.0.0.e.k.k.0.k.k.e.j.k.k.e.j.e.e.k.e.e.j.e.e.j.b.e.e.j.b.k.e.k",
+".j.j.j.e.j.j.e.k.j.e.j.j.j.j.k.j.k.j.k.j.j.j.k.j.0.k.k.j.k.j.e.e.e.j.e.e.b.l.j.e.e.j.k.j.e.j.e.e.e.e.l.e.b.e.e.e.a.#.c.a.#QtQtQt.#.#.cQtQt.iQtQt.#.#.#.#.#.#.#.a.c.a.cQt.a.c.a.c.#.a.b.a.b.a.a.#.e.l.r.l.r.l.#.l.#.a.q.cQtQt.f.i.dQtQt.cQtQt.cQt.x.g.g.x.g.w.p.o.B.M.U.4.1.N.I.z.D.v.h.x.gQt.q.d.cQt.b.e.e.e.b.e.e.j.e.j.j.j.j.j.e.k.k.e.j.e.j.e.e.e.b.b.r.e.b.e.j.j.j.e.j.k.j.e.j.e.t.j.j.k.k.k.e.k.j.k.j.k.k.j.k.j.k.j.e.k.j.k.k.0.k.0.k.e.0.e.j.k.e.e.e.k.k.e.e.j.j.e.e.e.b.e.e.e.e.j.e.e.b.e",
+".j.j.e.e.e.e.j.j.j.j.j.j.k.j.j.j.e.j.j.e.j.k.j.j.0.j.0.j.e.e.k.e.j.e.e.l.t.e.e.j.k.k.j.j.e.e.b.e.l.b.e.e.e.j.b.e.a.c.r.c.#.cQtQt.#.c.#Qt.i.fQtQt.#.c.#.c.#.c.#.c.aQt.a.c.b.c.b.c.b.a.a.a.a.a.b.a.#.e.l.e.l.e.a.a.#Qt.c.q.c.iQt.gQt.cQtQt.cQt.cQt.q.g.q.g.g.g.y.A.E.Z.4.W.P.Q.o.n.u.w.x.f.d.f.d.f.b.r.e.b.b.e.j.e.b.j.e.e.k.b.k.e.k.j.j.j.e.e.j.e.e.e.e.l.e.a.e.e.e.k.j.k.j.j.j.j.j.e.j.b.e.k.e.k.j.k.k.j.k.j.k.j.k.k.j.k.k.j.j.j.0.e.k.k.e.k.j.k.e.e.b.e.b.e.b.e.k.b.j.b.l.b.e.r.l.b.e.e.b.l.e.e",
+".j.e.j.j.j.e.k.j.e.e.e.k.j.j.k.j.k.j.k.j.k.j.j.0.j.e.0.j.k.j.e.j.e.j.e.e.e.l.e.e.e.e.e.l.b.e.l.e.l.l.l.b.e.e.e.j.a.r.a.c.c.#.f.#.c.q.#QtQtQtQt.i.#.c.q.c.#.c.q.#.r.a.r.a.c.#.c.a.#.a.b.a.b.a.#.a.e.l.r.l.r.a.#.#.c.qQtQt.i.gQt.gQt.f.cQt.cQt.cQt.g.f.g.g.x.w.A.I.T.W.2.E.B.A.v.m.h.m.f.iQt.f.d.d.b.b.e.j.e.j.j.k.j.e.j.e.k.e.k.e.k.j.k.b.j.j.e.j.e.b.b.b.b.b.a.e.e.e.e.e.e.b.e.e.e.e.e.j.k.j.k.k.e.k.j.k.k.k.j.k.k.j.k.k.j.k.e.k.k.0.k.e.0.j.e.k.b.e.e.b.e.e.b.e.j.j.j.e.e.e.a.e.b.l.e.b.l.e.b.e",
+".j.e.j.e.j.j.j.k.j.j.k.j.j.k.e.j.j.j.j.j.j.e.j.j.0.0.k.j.j.e.e.e.j.b.j.j.j.e.l.e.l.j.l.e.l.e.l.b.l.r.e.b.e.e.j.j.a.#.a.c.a.a.c.c.#.#.cQtQtQtQtQt.c.#.c.#.a.c.c.c.a.c.a.c.a.r.a.r.a.b.a.a.#.a.c.a.c.#.a.a.a.a.cQt.#QtQt.i.f.f.g.g.f.i.fQt.f.d.i.d.f.f.g.m.w.w.B.E.Z.L.P.B.v.v.w.h.f.gQt.d.d.d.c.c.e.b.e.b.e.j.k.j.k.j.j.j.e.j.j.j.e.j.k.e.e.b.e.e.a.b.a.b.a.b.b.a.e.e.e.b.e.e.e.j.l.e.j.e.e.k.e.k.j.k.k.j.k.j.k.k.j.k.k.j.j.j.j.j.k.e.j.k.j.k.e.j.e.b.e.b.e.b.e.e.j.e.e.b.l.b.e.r.e.e.l.e.e.e.l.e",
+".j.j.j.e.j.e.k.j.b.j.j.j.e.j.k.j.k.e.k.j.k.j.k.j.j.k.k.j.k.j.j.j.e.j.l.b.j.l.j.e.b.l.b.l.b.l.a.a.l.e.l.e.e.e.e.j.l.a.a.a.a.a.c.c.c.#.c.#.iQtQtQt.c.c.#.c.c.#.c.c.a.#.a.b.a.c.a.c.a.#.a.b.c.#.a.#.a.a.c.#.cQt.c.q.d.iQt.g.f.g.g.g.gQt.g.i.d.i.x.f.f.f.g.h.u.A.F.N.6.W.H.o.o.w.m.gQtQt.fQt.i.cQt.r.e.b.e.j.e.e.k.e.j.j.b.k.e.k.e.k.k.e.k.e.k.e.j.e.#.a.a.#.a.a.#.a.e.b.l.e.e.e.e.b.e.l.j.e.k.e.k.k.e.k.j.k.k.j.k.j.k.j.k.j.e.k.j.k.e.0.k.e.k.e.k.j.b.e.e.b.e.e.b.e.b.e.j.e.e.l.b.l.e.b.e.b.l.b.e.e",
+".j.e.j.e.e.k.j.j.j.k.j.k.j.k.j.j.j.j.j.j.j.j.e.j.0.e.0.j.e.e.j.e.j.e.j.j.e.j.l.b.l.l.l.l.l.r.a.#.e.l.e.e.e.e.k.e.l.a.a.a.a.a.a.a.a.c.#Qt.cQt.iQt.c.q.c.c.q.c.a.c.a.c.a.r.a.bQt.b.a.b.a.#.a.a.b.cQt.cQt.c.c.#Qt.d.q.d.i.g.g.g.m.h.g.f.x.f.x.d.gQt.x.h.h.g.o.F.V#i.U.H.v.v.v.g.g.f.i.#.d.c.c.b.a.r.e.e.e.k.b.k.k.k.j.j.k.j.j.j.e.e.j.k.e.e.e.j.e.j.a.b.c.cQt.c.a.c.e.e.e.e.e.e.e.e.e.e.j.e.e.e.j.j.k.j.k.k.e.k.j.k.k.k.j.k.j.k.e.k.k.k.k.j.j.k.e.j.b.e.b.e.e.b.e.b.j.e.b.l.b.e.b.b.b.e.l.e.e.e.l.e",
+".j.e.j.k.j.e.j.k.j.e.j.j.j.j.k.e.k.j.k.e.k.j.k.j.k.k.k.j.k.j.b.j.e.e.e.j.e.e.l.l.t.b.l.#.r.#.r.a.l.b.l.e.b.e.e.e.e.e.a.a.c.b.a.c.a.a.#.c.#QtQtQt.c.c.c.c.c.c.c.c.a.r.a.a.b.c.a.c.a.a.a.c.aQt.a.a.c.c.c.cQt.cQtQt.i.g.f.g.m.f.h.m.g.g.f.g.f.g.g.f.s.w.u.n.I.W.6#c.B.A.w.h.m.g.x.q.#Qt.c.#.a.e.b.e.e.b.j.j.j.k.e.0.j.j.e.k.k.e.k.j.k.j.k.e.b.j.e.b.a.a.q.c.#.c.#.a.b.a.b.a.r.a.a.b.l.e.l.e.j.e.e.k.e.k.j.k.j.k.e.k.j.k.j.j.j.j.e.k.e.k.e.k.e.j.k.e.e.b.e.b.e.e.b.e.e.b.l.e.e.l.b.l.e.b.e.b.l.b.e.b",
+".j.e.e.e.e.j.e.e.j.j.k.j.k.e.j.j.j.j.j.j.j.j.j.j.0.j.0.j.j.j.j.j.l.e.j.l.j.e.e.b.l.r.l.l.a.r.#.r.b.l.e.e.e.b.e.j.l.e.a.b.a.a.r.a.a.c.c.#.cQtQtQt.c.c.c.c.a.c.a.cQt.a.a.r.a.a.r.a.r.a.b.a.r.a.a.aQt.cQt.c.c.#.f.c.i.f.g.m.h.m.m.w.h.p.g.s.g.x.s.g.x.p.n.v.E#.#i.N.G.z.n.m.g.hQt.qQt.#.c.a.a.#.e.r.e.e.e.j.e.k.0.0.j.j.e.e.k.j.j.j.k.e.k.e.k.e.e.e.a.c.a.#Qt.r.c.a.b.a.r.b.a.b.b.#.e.l.e.e.k.b.e.k.k.j.k.k.j.e.k.j.k.k.j.k.e.j.k.j.0.k.j.k.j.k.e.j.r.e.b.e.e.b.j.e.b.j.b.e.b.e.r.e.r.l.b.l.e.e.l.e",
+".e.e.e.e.e.j.j.j.e.b.e.e.j.j.j.j.0.0.e.0.k.k.j.k.b.j.j.j.j.e.j.e.j.j.e.e.e.j.l.j.t.b.r.q.#.c.c.b.b.l.e.b.e.e.j.e.b.e.l.#.b.a.a.b.r.a.r.dQtQt.#.c.#.c.c.a.c.a.b.a.a.a.a.l.a.b.a.b.c.#.c.#.c.c.c.c.fQtQt.iQtQtQt.s.i.g.g.g.h.w.o.o.m.g.f.h.g.x.x.h.p.w.C.S.V.U.N.K.v.w.m.h.g.f.f.d.#Qt.a.a.b.e.a.e.e.k.e.k.j.k.e.e.k.k.k.k.j.j.k.j.e.j.e.e.l.e.a.b.#.c.#.#QtQtQtQt.b.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.j.k.j.j.j.k.e.j.e.j.k.e.j.j.e.e.e.j.e.j.e.e.e.b.e.e.e.b.e.b.e.b.t.e.l.b.l.e.b.l.a.#.a.a.#.a.#.a",
+".e.e.b.e.e.b.e.j.j.e.k.b.e.e.e.b.k.e.k.k.j.k.j.j.t.e.e.e.j.e.e.e.j.j.j.e.j.e.j.e.t.l.r.#.#.c.a.a.l.b.j.e.j.e.j.e.e.l.e.b.a.a.r.a.a.r.c.#Qt.i.d.#.c.#.c.#.c.c.b.a.a.l.a.a.a.a.b.b.#.c.cQt.#.c.#.qQt.iQt.fQt.f.iQt.f.s.f.g.x.w.n.z.o.p.h.x.h.w.w.n.v.o.K.N#..U.Q.o.v.w.m.h.f.g.d.d.c.#.#.a.a.e.b.b.k.e.k.j.j.j.k.k.0.0.k.e.k.k.j.k.e.j.e.j.e.b.a.a.a.a.#.cQt.iQtQt.e.a.r.l.e.e.b.e.e.e.b.e.e.e.e.e.j.j.e.k.e.j.k.e.k.b.j.k.j.k.j.e.j.j.j.e.j.j.t.e.e.l.e.l.e.e.t.e.b.t.b.j.e.b.t.e.b.a.l.#.e.e.l.e",
+".a.b.l.l.e.e.e.e.e.e.e.e.e.e.e.e.k.k.j.k.e.k.j.e.j.e.e.j.e.j.e.j.j.e.j.j.j.e.e.e.e.l.#.r.#Qt.a.r.l.e.l.b.e.b.e.e.b.l.e.a.a.r.a.a.q.a.#.cQtQt.#.cQt.#.c.#.c.a.a.a.a.r.#.l.b.a.b.a.#.c.a.c.cQt.c.cQt.#Qt.qQt.qQtQt.qQt.i.g.g.m.n.v.u.w.w.w.n.h.y.o.B.H.3#..W.E.A.n.u.w.m.f.g.d.dQt.r.a.a.b.b.l.e.e.j.j.j.e.k.k.b.k.k.k.0.k.j.k.e.e.j.j.e.l.e.l.e.a.a.a.a.c.c.#.d.#.r.e.b.e.b.l.b.e.a.e.b.e.e.e.e.e.j.k.j.k.j.k.e.j.e.k.j.e.k.e.e.b.e.e.b.e.b.e.b.e.l.e.e.j.l.b.e.b.l.e.b.l.e.b.e.b.a.l.b.l.e.b.l.b",
+".l.l.e.l.b.l.b.l.b.l.r.l.e.b.e.e.e.j.e.e.k.j.j.j.e.j.e.t.e.e.l.j.e.j.j.e.j.j.e.t.l.l.r.q.#.a.a.b.l.b.l.e.e.e.k.e.e.a.b.a.a.c.a.b.r.#.cQtQtQt.#.cQt.#Qt.c.#.c.c.c.l.a.l.a.a.a.b.b.b.c.a.r.a.c.cQt.c.cQtQt.#.d.#Qt.q.c.f.i.g.h.v.z.o.v.o.n.v.v.o.A.N.4.8#i.T.o.p.n.w.m.f.gQt.f.c.c.#.c.b.l.b.e.b.e.k.j.k.k.j.j.k.j.j.0.k.j.k.j.j.e.j.j.j.j.j.e.e.e.a.l.a.q.c.#.iQt.e.b.l.r.e.b.e.e.e.b.l.e.e.e.e.e.j.j.e.k.e.j.k.b.j.e.k.j.k.e.j.j.b.e.e.e.e.e.l.e.e.b.e.b.e.e.l.e.b.e.b.b.e.r.l.b.#.a.c.#.c.a.c.a",
+".a.#.a.a.a.a.r.a.a.a.a.a.a.a.a.#.l.b.e.e.e.e.j.e.j.b.j.e.j.e.j.j.e.j.j.j.j.j.e.j.b.r.r.#.a.a.e.b.l.e.l.b.l.b.e.e.b.l.e.a.b.#.r.c.a.#QtQt.f.d.c.#Qt.#Qt.cQt.c.#.c.a.a.a.a.b.a.b.b.a.b.r.b.b.b.b.a.c.c.c.cQt.cQt.c.f.#Qt.f.f.w.v.A.A.z.z.B.B.B.Q.S#i.U.W.N.E.A.n.x.s.g.f.f.d.cQt.c.a.e.b.b.e.e.j.j.e.j.j.e.j.k.e.k.e.0.k.k.j.e.b.j.e.e.e.j.l.e.e.e.a.b.a.r.c.i.d.#.r.e.b.e.a.e.b.e.b.e.b.e.e.e.e.e.j.k.j.j.k.j.e.k.e.j.j.j.e.j.j.e.e.l.e.e.l.b.b.b.l.e.l.e.e.b.e.b.a.#.a.b.l.a.r.a.a.a.a.a.a.#.a.a",
+".a.a.a.a.a.a.a.#.r.l.r.l.r.#.r.r.#.c.#.a.a.e.e.e.e.j.e.j.e.j.e.j.j.j.j.e.j.e.j.l.a.r.q.r.a.#.l.j.l.b.l.e.e.j.e.e.e.l.e.a.a.c.a.a.c.cQt.f.fQtQt.c.#Qt.#Qt.c.#.c.#.l.a.l.a.c.a.b.a.e.b.a.e.l.b.#.b.a.aQt.c.c.c.c.cQt.c.f.f.g.n.A.F.B.B.B.C.I.E.1.U.W.L.N.H.H.o.w.h.f.gQt.i.cQt.a.a.e.#.e.l.e.k.b.e.k.j.k.e.j.k.e.k.0.k.0.k.b.j.j.e.j.j.j.j.e.e.l.e.e.e.a.a.c.#.dQt.b.e.#.e.r.e.e.l.b.e.e.e.e.e.e.e.j.j.e.k.e.k.j.k.j.k.j.j.k.b.j.e.e.e.e.b.b.e.a.e.e.e.b.l.b.e.l.e.#.b.a.r.a.r.a.#.cQt.cQt.c.cQt.c",
+".a.#.r.a.#.r.a.r.a.#.r.#.r.r.r.#.#.#.#.a.#.a.e.l.e.l.j.b.t.e.e.e.j.e.j.e.j.b.j.e.a.#.#.#.r.a.e.e.e.l.e.b.j.e.j.b.e.e.b.a.a.b.cQt.r.cQt.f.f.fQt.c.#.#QtQt.#.d.#.c.c.#.c.c.a.c.r.c.b.e.b.e.b.l.b.e.b.#.a.a.#.a.a.#.dQt.x.q.w.u.z.F.F.I.B.K.N.W.4.W.H.M.M.M.I.A.n.p.s.i.f.fQtQt.c.#.b.e.e.b.j.b.k.0.e.k.j.k.j.j.j.j.k.0.e.k.k.e.e.j.e.j.e.j.e.e.e.e.b.e.b.b.r.cQt.c.#.a.e.b.l.e.b.e.b.e.a.e.e.e.e.e.j.k.j.j.k.j.e.k.e.j.j.j.k.j.k.j.b.a.b.e.a.b.b.a.b.l.e.e.l.b.#.a.c.r.a.b.a.b.a.#.c.c.c.c.c.c.c.c",
+".#.r.a.r.l.r.#.r.#.r.r.r.r.r.#.r.x.q.q.#.r.#.l.b.l.b.j.e.j.e.t.e.j.j.b.j.e.t.e.e.a.r.#.q.#.#.l.j.l.b.l.e.j.e.j.e.e.l.e.a.#.cQt.c.#QtQt.f.i.fQt.c.#Qt.#Qt.#Qt.c.#.a.#.a.c.c.c.c.r.a.e.a.e.a.b.b.a.b.a.b.b.b.r.b.c.d.f.q.h.h.A.B.F.M.H.E.P.3.5.4.P.Q.Q.Q.Q.Q.J.A.u.g.gQtQt.c.aQt.c.b.e.b.e.k.e.k.k.k.b.j.j.j.k.j.k.0.k.0.k.j.k.k.b.j.j.j.l.e.l.e.a.e.b.l.b.a.cQt.c.a.r.a.r.e.r.e.b.e.e.e.e.e.e.e.e.e.k.e.k.e.j.k.j.k.j.k.j.e.k.e.j.e.e.e.b.e.l.e.a.e.r.b.b.r.a.#.b.#.b.a.b.#.b.#.a.c.cQt.cQt.cQt.c",
+".e.l.b.e.b.e.e.e.l.l.b.l.b.a.r.aQt.iQtQt.i.#.#.#.l.l.l.e.l.e.e.e.e.k.l.j.e.e.l.l.#.d.q.r.a.l.b.b.e.j.e.j.j.b.e.r.l.e.b.c.c.d.c.d.#QtQt.i.g.g.iQt.c.#Qt.f.fQtQt.#.#.c.c.a.a.b.e.e.b.b.b.b.b.b.r.b.c.r.c.f.d.d.c.xQt.qQt.h.n.C.P.2.2.L.2#i#o.4.M.Q.P.E.M.T.F.A.w.m.f.f.g.d.f.c.r.b.l.b.e.r.e.r.l.e.b.k.k.j.e.j.j.b.k.j.k.e.k.j.k.j.e.e.e.e.e.e.e.e.b.e.b.a.r.c.a.c.r.a.b.a.b.a.e.a.e.b.b.e.e.e.e.e.e.e.e.e.e.j.j.e.e.k.e.k.j.j.k.j.j.j.e.j.e.e.b.e.e.l.e.b.e.b.e.b.l.b.r.e.b.e.b.eQt.a.b.a.b.e.b.e",
+".r.b.b.e.a.b.b.e.l.b.l.l.l.a.a.#.#.#.qQt.#.#.c.#.l.b.l.b.e.r.e.e.k.j.j.b.j.l.b.l.r.r.r.a.#.l.b.e.k.b.e.b.j.b.e.b.b.l.a.c.c.dQt.f.#Qt.f.f.h.g.gQt.r.c.#.f.iQt.#Qt.c.#.c.a.a.b.l.b.b.b.b.b.b.b.b.b.cQt.c.d.d.d.d.d.gQt.d.g.h.D.N.6.6#h#h#i.3.M.E.B.B.I.E.K.B.A.u.m.m.f.gQt.dQt.b.a.b.b.a.e.a.e.r.e.e.k.j.j.k.j.k.j.k.e.k.j.k.j.k.k.b.e.b.e.b.e.b.b.l.e.e.e.a.c.#.c.a.b.a.r.l.b.a.b.e.e.e.e.e.e.e.e.e.e.e.e.e.j.e.e.k.j.j.k.e.k.e.j.k.j.k.e.k.j.e.j.e.b.e.b.a.b.a.e.r.e.a.b.a.e.#.e.#.a.b.e.b.a.b.b",
+".e.e.l.b.e.e.l.e.b.l.l.r.lQt.a.a.a.a.r.#.#.#.#.r.#.l.a.e.l.b.e.e.e.e.j.e.j.l.e.#.r.q.#.a.a.b.a.e.b.e.j.e.e.e.b.b.c.cQtQt.i.d.f.q.qQt.i.f.i.g.gQt.#QtQt.f.i.fQtQt.#.c.c.c.a.c.b.e.b.b.b.b.b.b.b.rQt.b.cQt.c.d.f.q.g.s.w.v.A.D.R.1#k#o#h.W.H.B.o.B.A.o.z.z.B.z.o.p.w.h.m.f.gQt.d.#.a.b.r.e.b.l.e.e.j.k.e.k.e.k.j.k.j.k.j.k.k.k.j.k.e.e.e.e.e.e.e.e.e.r.e.b.b.a.c.a.r.a.b.a.b.b.e.e.e.b.e.e.e.e.e.e.e.e.e.e.e.j.j.e.j.j.j.j.k.j.k.j.e.k.j.j.j.k.e.j.e.b.e.e.e.e.e.e.a.e.b.e.b.b.b.e.a.b.e.a.b.e.a.e",
+".e.e.b.e.b.e.b.e.l.l.e.l.e.a.a.#.a.c.a.#.c.a.c.c.l.l.e.l.b.a.b.e.j.j.l.e.l.e.b.a.r.c.r.#.a.b.b.e.e.e.e.e.b.b.b.#.cQtQt.dQt.q.f.f.cQtQtQt.f.i.g.fQtQtQt.fQtQtQtQt.c.#.#.c.c.a.b.b.a.b.b.b.b.b.a.b.l.b.c.d.f.d.f.g.u.n.h.u.o.B.N.9#i.2.Q.F.B.v.o.v.v.v.o.o.A.B.z.v.p.u.g.g.iQt.#.c.r.a.a.a.r.b.a.b.e.b.e.k.b.j.j.j.k.j.k.k.j.k.j.k.e.e.e.e.e.e.e.e.e.e.e.e.a.r.a.b.b.#.b.#.e.a.#.b.l.e.e.e.e.e.e.e.e.e.e.e.e.j.j.e.j.k.j.k.e.j.j.j.k.j.e.k.e.k.j.k.e.e.e.l.b.e.b.e.e.e.b.e.e.e.l.e.b.e.r.e.#.e.r.e",
+".e.e.b.e.e.e.b.e.e.e.b.e.b.b.a.b.a.a.a.c.a.a.#.a.#.l.r.l.e.b.e.a.b.l.e.b.l.e.a.a.q.r.#.a.a.e.e.b.b.e.b.e.r.rQt.rQt.d.d.i.d.d.i.q.c.#QtQtQt.f.i.x.iQtQtQtQt.fQt.g.#.c.c.c.a.c.b.e.b.e.a.e.a.e.b.b.aQt.#QtQt.i.m.g.p.h.u.z.B.Q.W.U.H.F.z.v.v.p.w.p.w.w.h.v.z.B.B.C.m.g.i.fQtQt.c.#.a.a.#.a.a.a.e.a.e.j.j.e.k.k.e.k.k.k.j.k.j.k.k.j.k.j.j.k.j.j.e.j.e.e.e.l.b.b.b.a.a.b.a.b.b.b.e.b.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.k.e.j.j.j.k.j.j.j.j.k.j.j.k.e.j.e.e.b.e.b.e.e.b.b.l.b.e.a.e.b.b.l.b.e.e.e.b.l.e",
+".e.b.l.b.e.a.e.b.j.e.e.b.e.#.b.#.a.a.#.a.a.a.a.a.l.l.e.l.e.l.r.e.l.b.l.l.e.a.#.a.c.rQt.a.#.b.b.e.b.e.b.a.r.a.c.a.d.iQt.d.dQt.d.d.c.c.c.qQt.f.f.g.h.g.f.iQtQt.i.xQtQtQt.c.c.c.c.c.a.a.a.a.b.c.aQt.c.dQt.f.x.g.h.h.u.z.K.M.Y.Q.F.D.o.o.u.h.p.m.p.x.p.w.w.h.v.z.B.D.x.g.f.iQt.f.cQt.c.r.a.r.a.b.a.a.j.e.j.e.j.j.j.j.k.j.k.j.k.k.j.k.j.k.j.j.k.j.k.j.e.e.e.b.a.b.a.b.r.a.r.a.b.l.b.l.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.j.j.k.j.k.j.e.k.j.k.e.j.j.j.j.j.e.e.e.e.b.e.b.l.e.e.e.e.b.e.e.e.e.b.e.e.a.b.b.e",
+".e.e.e.e.b.e.e.e.b.l.e.b.a.b.b.a.b.a.a.a.a.#.a.a.b.a.e.b.a.e.b.e.l.e.l.b.a.a.c.c.#.#.#.a.#.e.b.r.b.#.b.#.c.cQt.c.c.c.cQt.c.c.#.c.c.cQt.c.#.i.g.x.h.g.gQtQt.f.g.h.#Qt.c.d.c.c.r.c.r.c.c.c.c.c.c.c.d.f.f.f.u.o.y.z.Q.Q.S.J.J.C.o.v.h.p.w.x.h.x.q.g.s.w.w.w.v.A.C.B.i.g.fQt.d.a.a.b.a.a.a.a.a.a.a.a.e.b.l.e.e.e.e.j.j.k.k.k.j.k.j.k.j.j.k.j.j.k.j.j.e.e.e.e.b.r.a.b.a.b.a.e.a.e.b.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.k.e.k.e.j.j.j.k.e.j.k.j.k.j.k.j.e.e.e.b.l.e.e.e.r.e.b.e.b.e.b.e.b.l.b.b.b.l.b.e",
+".r.b.#.e.b.e.b.l.e.e.e.b.b.b.a.r.a.a.a.b.a.a.b.a.l.l.l.l.b.a.b.b.l.b.a.e.a.aQt.c.r.q.cQt.c.#.r.b.a.#.a.cQt.a.c.c.cQt.c.c.c.a.a.#.d.c.c.c.#.f.g.h.g.h.iQtQt.i.h.gQtQtQt.d.c.c.c.r.c.c.c.cQt.c.c.i.x.g.x.w.y.E.R.S.A.z.z.G.n.u.p.p.g.g.w.g.f.x.f.x.s.p.w.h.m.A.J.D.g.f.d.f.c.r.b.e.#.c.aQt.a.a.a.a.e.l.e.e.l.e.l.e.k.j.k.j.k.j.k.k.k.j.k.j.k.j.j.k.e.e.e.a.b.a.b.b.b.#.b.b.b.e.b.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.j.k.j.j.k.j.k.j.j.k.e.k.e.j.j.j.e.e.e.e.b.e.b.e.e.l.b.e.e.l.b.e.e.e.e.a.e.b.b.e",
+".e.e.e.e.b.l.b.e.l.e.l.l.e.l.b.l.e.e.l.b.l.e.b.a.b.e.b.e.e.e.e.b.b.b.r.e.b.e.b.b.#.d.iQt.dQt.d.fQt.cQt.a.r.r.a.r.a.#.a.#.cQt.c.c.a.#.c.c.fQt.f.f.q.q.i.f.f.fQt.d.iQt.#.#.#.a.b.b.c.d.d.d.d.q.q.q.p.h.v.B.S.Z.E.o.w.g.m.f.m.i.h.i.g.fQt.g.f.f.g.f.g.g.p.w.o.o.z.J.gQt.a.b.r.b.c.c.a.a.a.a.b.a.b.l.j.j.j.j.j.k.k.j.k.j.k.k.j.k.k.j.k.j.k.k.j.k.k.j.j.k.e.e.e.b.a.b.#.a.a.l.b.e.j.j.e.e.l.e.e.e.j.e.e.e.j.e.j.e.j.e.j.e.e.e.e.e.e.e.j.j.j.j.k.k.j.k.e.j.e.j.e.b.l.j.b.e.b.l.b.e.b.l.b.e.e.b.l.l.l.e",
+".e.l.b.l.e.e.l.e.b.l.b.e.e.l.e.l.e.l.e.l.b.l.c.a.b.a.b.b.l.r.l.b.#.a.a.a.b.b.#.b.iQt.iQt.i.f.d.c.c.a.c.#.a.b.a.b.#.b.b.b.c.c.b.b.c.aQt.c.d.f.d.f.s.g.g.i.g.i.gQt.p.h.fQt.d.d.d.d.r.c.d.g.f.s.w.g.g.v.J.R.M.F.o.p.i.m.i.i.f.f.f.fQt.xQt.q.i.dQt.g.f.g.w.n.p.o.B.A.g.dQt.r.a.r.b.rQt.a.r.a.a.b.a.a.e.e.j.j.e.k.j.k.e.k.j.k.k.j.k.j.k.k.j.k.k.j.k.k.k.j.e.e.e.a.b.a.a.l.b.l.e.e.e.k.l.j.e.j.l.j.e.j.t.e.j.e.j.e.j.e.j.e.j.j.j.j.j.e.j.j.e.k.e.j.j.j.j.j.k.j.e.e.j.e.e.e.e.e.b.e.e.e.j.j.l.l.b.e.b.l",
+".e.e.e.e.e.e.b.b.l.e.l.e.b.l.r.l.b.l.e.l.a.a.#.c.c.#.c.aQt.c.c.c.cQt.cQt.c.c.cQt.#Qt.c.f.cQt.cQt.b.b.b.e.b.b.b.e.b.l.r.a.e.b.a.b.#.a.c.c.c.dQt.f.g.h.w.h.h.g.h.i.v.p.h.h.i.f.x.x.i.q.f.g.h.h.u.o.o.z.F.B.J.v.s.h.f.f.f.f.i.f.i.f.d.dQt.fQt.f.g.d.g.f.p.h.n.A.D.J.s.f.c.b.#.b.a.c.a.a.a.a.b.a.l.b.j.e.j.e.k.j.k.k.k.j.k.j.k.k.j.k.j.k.k.j.k.k.j.k.j.e.e.e.e.b.a.b.a.a.a.e.j.e.j.j.e.e.l.j.e.j.e.j.e.e.e.j.e.j.e.j.e.j.e.e.e.e.j.e.j.j.j.j.k.k.j.k.e.j.j.j.j.e.b.e.e.e.e.b.e.b.e.b.l.e.e.l.e.l.e.e",
+".b.e.e.b.e.e.a.e.a.a.a.a.a.a.a.a.l.e.c.#.c.b.c.b.c.c.d.f.d.d.d.f.#.d.#Qt.#Qt.iQt.q.c.q.a.c.#.r.b.e.e.e.b.e.e.b.e.b.e.e.e.b.a.r.b.a.a.a.cQt.f.d.f.m.p.v.u.v.h.h.h.o.u.h.h.f.g.f.h.x.m.h.h.v.y.J.F.J.C.y.n.h.x.x.q.i.fQtQt.dQt.dQt.cQt.f.f.i.qQt.f.f.g.s.w.n.C.B.J.w.f.i.c.a.#.b.c.aQt.b.a.l.b.a.a.j.e.j.e.j.k.j.k.j.k.k.k.j.k.k.j.k.k.j.k.j.k.j.k.j.k.e.e.r.e.b.l.a.l.a.e.l.e.k.j.e.j.e.j.e.j.e.j.l.e.j.e.j.e.j.e.j.e.j.j.j.e.j.e.j.j.e.j.e.j.j.k.e.k.j.j.k.e.j.e.e.e.e.e.e.e.l.b.e.l.b.e.l.e.l.e",
+".a.a.a.a.a.a.a.#.b.a.#.b.a.a.#.c.#.aQt.c.c.c.c.c.c.c.f.#QtQtQt.cQt.qQtQtQt.#Qt.c.cQt.c.b.#.b.r.r.e.e.b.e.j.e.j.e.e.e.e.e.#.b.a.b.a.r.c.c.dQt.d.g.h.h.o.o.v.u.v.v.y.u.h.m.i.g.w.g.h.u.o.z.J.J.G.A.u.p.p.h.h.f.d.r.f.d.f.dQt.dQt.d.d.dQt.f.d.gQt.g.f.g.w.s.n.A.z.F.p.i.d.d.b.a.cQt.b.a.a.a.b.a.e.a.e.b.l.e.e.e.j.e.k.j.k.j.k.j.k.k.j.k.k.j.k.k.j.k.j.e.e.e.e.b.a.r.a.a.a.j.e.e.j.k.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.e.j.e.j.e.j.j.j.k.j.k.k.j.k.j.j.j.j.e.e.e.e.e.e.e.e.r.e.b.a.a.a.a.a.a.b.a",
+".b.a.a.a.#.b.a.aQt.c.a.c.a.c.c.c.b.c.c.cQt.d.i.d.i.dQt.dQt.dQtQt.c.c.c.cQt.cQt.c.#.a.a.#.b.b.b.e.k.e.j.k.e.k.e.k.e.t.b.e.b.b.a.r.a.a.a.c.d.f.f.f.x.p.u.A.C.v.v.A.v.A.u.h.h.v.v.C.F.F.F.J.J.y.u.u.g.g.g.i.gQtQt.d.i.dQtQt.d.d.d.i.dQt.d.i.f.d.f.d.f.g.x.w.p.A.J.F.p.wQt.f.c.r.c.c.a.#.a.b.#.a.a.a.e.l.e.e.e.e.e.j.j.k.k.j.k.k.j.k.j.k.j.k.k.j.k.k.j.k.e.e.e.l.b.e.a.l.a.e.e.e.j.j.e.j.e.j.e.j.e.j.e.j.e.e.e.e.j.e.j.e.j.e.j.e.j.e.j.j.e.k.e.k.e.k.e.j.j.j.j.k.e.e.e.e.e.b.l.e.e.e.a.b.a.a.r.a.a.a",
+".a.a.a.a.a.a.#.a.c.cQt.cQt.cQt.c.c.c.fQt.f.fQt.f.c.q.c.#.#.#.#.c.a.r.a.b.a.b.a.b.e.b.e.b.e.b.e.b.k.0.k.0.k.k.0.k.j.e.e.j.l.b.e.b.aQt.c.c.dQtQt.x.g.g.v.v.v.v.z.z.E.K.J.F.B.B.T.P.2.S.J.C.u.w.h.i.m.g.f.g.c.cQt.i.d.d.f.d.d.c.d.d.d.d.g.dQt.fQt.g.d.g.x.n.p.A.J.F.v.p.f.d.c.a.aQt.a.a.c.#.a.b.a.b.a.a.b.e.e.b.j.e.k.j.k.k.j.k.k.j.k.k.j.k.j.k.j.k.j.e.e.e.e.b.a.b.#.a.b.j.l.e.k.j.e.j.e.j.e.j.e.j.e.j.e.t.e.j.e.j.j.e.j.e.j.e.j.e.j.j.j.j.j.k.k.j.k.j.j.e.j.j.j.e.e.b.e.e.b.b.e.b.#.a.a.b.a.a.b.a",
+".l.a.l.a.#.a.a.aQt.c.c.c.c.c.c.c.fQt.dQt.d.i.dQt.#.c.a.a.a.a.a.c.b.b.e.e.b.e.b.e.b.e.e.e.b.b.j.b.0.e.0.e.0.e.0.e.j.e.j.e.e.b.a.b.a.a.c.c.d.i.d.f.f.g.h.o.v.v.y.z.Z.Y.R.R.R.Y.U#c.H.F.C.v.u.g.h.x.f.f.dQtQtQt.#.#.d.d.d.d.r.c.r.dQt.dQt.d.dQt.dQt.dQt.h.s.w.o.B.J.z.v.h.i.c.#.a.c.a.#.a.a.a.a.a.l.b.l.a.b.e.b.b.j.j.k.k.j.k.j.k.k.j.k.j.k.k.j.k.k.j.k.e.e.e.b.r.l.a.l.a.e.e.e.j.k.e.j.e.j.e.j.e.j.e.j.e.e.e.e.j.e.j.j.e.j.e.j.e.j.j.e.j.e.k.e.k.e.k.e.j.e.j.j.e.j.e.a.e.b.e.l.e.e.a.b.#.a.a.a.#.a",
+".c.q.a.c.a.#.q.cQtQt.iQt.#.iQtQtQt.iQtQt.#.c.cQt.b.l.r.e.b.b.b.e.e.b.j.e.j.e.e.e.k.j.e.k.k.e.k.e.k.k.k.k.k.k.k.k.k.j.j.b.b.a.b.b.a.#.a.q.cQt.d.i.i.s.w.u.o.n.h.o.M.M.2#c.8#p.U.S.A.y.u.w.h.x.x.g.f.f.d.d.c.c.c.cQt.cQt.#.dQt.d.f.c.q.c.cQt.c.cQt.c.i.f.x.m.p.y.A.z.C.o.h.d.r.c.#.c.c.b.a.b.c.c.d.a.a.b.a.e.e.e.e.j.j.j.k.j.k.j.j.e.e.e.e.e.e.e.e.e.l.e.#.a.a.c.c.a.a.a.a.e.e.e.e.j.e.j.e.e.e.e.e.j.e.j.j.j.j.e.e.j.e.j.e.j.e.j.e.j.j.j.j.j.j.j.j.e.e.e.e.e.e.e.e.e.e.e.e.e.b.a.b.l.e.a.b.a.r.a.c",
+".#.c.c.q.c.c.#.c.qQt.#.fQt.d.#.iQtQtQt.q.cQt.c.c.b.e.b.e.e.e.e.b.k.e.k.b.j.b.k.b.0.e.0.k.0.k.e.k.0.e.0.e.0.e.0.e.j.e.e.e.l.r.c.c.b.a.a.cQt.f.f.g.m.h.h.v.B.F.F.E#i#o.8#c.P.H.F.Q.C.A.v.h.g.s.x.xQtQt.d.iQt.c.c.cQtQt.f.#.d.f.d.d.a.a.a.a.c.c.c.cQt.d.d.g.x.w.u.y.z.z.o.u.hQt.f.d.#.f.c.#.a.c.cQt.l.a.a.a.e.e.e.e.k.j.k.j.k.k.j.0.e.e.e.e.e.e.e.e.e.e.e.a.a.c.b.c.#.a.c.e.e.e.e.e.e.e.e.e.j.j.j.j.e.e.j.e.e.e.j.e.j.e.j.e.j.e.j.e.j.j.e.j.e.j.e.j.e.e.e.e.e.e.e.e.e.b.e.e.b.a.b.r.l.b.a.aQt.a.c.c",
+".c.q.c.#.c.q.c.#Qt.dQt.#.d.iQtQtQt.q.c.c.c.c.b.l.b.a.e.b.j.e.j.j.e.b.j.e.j.j.j.j.k.k.k.e.k.k.0.k.e.k.k.k.k.k.k.k.j.j.b.b.a.c.a.c.a.aQt.c.f.f.g.x.g.v.B.F.P.V#o#q#o.1.S.F.A.v.y.v.A.u.u.u.h.g.x.f.f.dQt.d.dQt.c.c.#.#.c.#.c.c.c.c.c.a.c.c.b.r.b.a.c.fQt.f.h.g.n.p.A.B.z.A.p.x.f.f.dQt.#.c.a.c.c.d.a.a.b.a.e.e.e.e.j.0.j.k.j.k.j.j.e.e.e.e.e.e.e.e.j.l.e.e.a.b.a.c.a.a.b.e.a.e.e.e.e.t.e.j.e.e.e.j.e.l.j.e.j.j.e.j.e.j.e.j.e.j.e.j.j.j.j.j.j.j.j.j.e.e.e.e.e.e.e.e.e.j.b.e.e.b.l.b.a.a.a.r.a.c.c.c",
+"QtQtQt.iQtQtQt.fQt.q.d.i.#Qt.c.i.c.#.cQt.c.e.a.b.e.e.e.e.e.e.e.j.j.j.j.b.k.j.j.j.0.e.k.0.e.k.e.k.k.j.e.e.k.b.j.j.e.e.l.e.bQt.dQt.r.#.d.g.q.h.s.n.o.F.Z.1#i#d#r#r.Y.B.v.u.u.u.h.g.h.u.v.u.h.h.h.xQtQt.d.iQt.c.c.cQt.#.c.c.c.c.d.#.a.a.#.b.e.a.b.#.c.a.f.d.x.x.x.p.v.C.z.z.v.v.p.w.f.gQt.c.#.c.a.c.a.a.a.e.e.e.e.e.j.j.k.j.k.j.k.j.j.j.k.j.j.k.j.j.e.j.l.e.b.a.a.b.a.a.c.e.e.e.e.e.l.e.e.e.j.j.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.e.e.e.e.e.e.e.e.e.e.l.e.e.a.b.b.a.b.a.c.cQt.c.c",
+"Qt.xQt.f.f.g.f.f.g.fQt.iQt.dQtQt.c.q.c.a.b.b.b.e.e.r.e.e.j.e.e.e.b.j.e.j.e.b.j.b.k.0.k.k.0.k.0.e.e.e.j.e.b.k.j.e.e.b.b.a.b.c.r.d.d.f.x.x.s.n.o.B.N.4.9#o#j#f.6.X.D.z.p.h.hQtQtQt.g.h.o.y.v.p.x.f.f.d.dQt.d.c.a.c.r.a.#.a.c.a.b.a.b.a.b.a.b.b.b.b.a.c.c.d.d.f.x.x.p.v.u.o.y.v.o.y.h.h.f.#.c.c.c.c.a.a.b.e.l.e.e.e.k.e.j.j.j.e.k.j.j.j.e.j.e.e.j.j.e.e.e.a.a.b.a.b.a.l.b.l.b.e.e.e.j.e.j.j.e.e.j.j.e.j.e.j.e.j.e.e.j.e.j.e.j.e.j.e.j.j.j.j.j.j.j.j.e.e.e.e.e.e.e.b.e.b.e.b.b.a.e.#.a.cQt.c.c.c.d.d",
+".f.f.f.g.f.f.g.iQtQt.gQtQt.qQt.q.c.c.c.a.b.e.e.e.e.e.e.e.e.j.r.e.j.j.j.e.e.k.e.k.e.k.0.e.k.e.k.k.e.j.b.j.e.j.e.b.e.e.b.b.#.d.d.f.q.x.x.w.v.I.M#c.U#i#p.8#a.U.P.D.z.v.v.g.fQtQtQt.h.h.p.A.v.p.g.x.fQt.dQt.f.c.c.c.#.#.a.a.c.#.b.a.e.e.e.e.b.e.e.b.r.b.#.a.f.d.d.f.x.h.h.n.u.o.C.B.u.p.fQtQt.c.cQt.a.a.a.b.e.e.e.e.j.j.k.j.k.j.j.k.e.e.e.e.e.e.e.e.e.j.l.b.a.a.b.a.a.a.c.e.e.e.e.e.j.e.j.e.j.e.j.j.j.j.j.e.j.e.t.e.e.j.e.j.e.j.e.j.j.e.j.e.j.e.j.e.e.e.e.e.e.e.b.e.e.l.e.e.e.b.a.b.r.a.cQt.c.d.fQt",
+".x.m.x.g.x.g.f.x.iQtQt.d.#.d.c.c.c.a.r.b.b.e.j.e.e.b.e.b.e.e.j.e.b.j.b.e.j.b.e.j.k.0.e.k.0.k.0.e.j.b.b.e.b.j.e.j.e.a.a.c.d.f.d.f.h.s.v.B.Q.Z.1#h.2#i.9.U.Q.B.v.h.y.o.g.i.fQt.d.f.d.i.p.y.z.v.m.x.i.dQt.dQt.c.c.c.r.a.a.a.a.b.a.e.b.b.e.e.e.e.e.e.r.a.r.r.c.b.d.d.x.x.x.g.v.o.D.J.D.A.gQt.i.#.c.c.a.a.b.l.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.l.e.a.#.b.c.a.b.l.a.e.b.j.e.k.e.j.e.j.e.j.e.e.e.j.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.j.j.j.j.j.j.e.e.e.e.e.e.b.e.l.b.e.e.r.l.b.e.aQt.c.cQt.d.iQt.f",
+".x.f.g.f.h.f.f.f.cQt.c.#.f.#Qt.d.a.c.e.b.e.e.e.b.e.b.e.e.j.e.b.e.j.j.e.k.e.k.e.k.e.k.0.k.k.e.k.e.j.b.e.e.e.e.b.b.b.b.bQt.d.d.g.q.n.u.A.N.4#o.3.L.6#c.2.T.D.p.x.g.g.p.u.g.f.q.f.q.d.f.g.y.A.A.w.f.f.dQtQt.d.c.c.c.r.#.l.a.#.a.e.b.e.e.e.e.j.b.e.e.r.r.r.bQt.rQt.r.q.f.f.p.h.v.z.D.J.C.u.iQt.c.c.b.#.a.a.b.e.e.e.e.e.e.e.e.j.e.e.e.e.e.e.e.e.e.e.e.j.j.e.b.a.a.a.b.a.a.a.e.e.e.k.e.j.e.j.e.j.e.j.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.j.e.j.e.j.e.j.j.e.e.e.e.e.b.e.b.l.b.e.e.e.b.a.eQt.d.i.d.i.f.f.g",
+"Qt.fQt.dQt.cQt.d.#.a.#.a.a.a.a.b.a.a.a.a.b.a.b.a.e.l.e.e.b.e.k.b.e.b.j.b.e.b.j.b.e.l.b.e.e.b.r.e.e.r.r.c.f.d.c.#.b.b.d.d.h.h.h.v.F.N#i#j#d#h.2.1.Z.J.A.h.h.m.x.xQt.h.p.u.p.fQt.c.#.d.i.g.o.C.C.v.f.i.d.c.l.#.aQt.c.a.a.a.b.l.e.l.e.j.k.k.e.e.j.e.e.e.e.e.e.b.b.b.b.r.d.x.w.h.o.C.F.K.D.h.gQt.q.aQt.c.c.a.a.b.b.c.e.e.j.e.j.e.e.e.j.j.j.j.j.j.j.j.b.l.a.a.c.b.c.b.l.e.e.e.e.j.k.j.j.j.j.j.k.j.k.j.j.j.j.j.j.j.j.j.e.j.e.j.e.e.e.e.j.e.j.e.j.j.j.e.j.e.e.l.a.a.a.r.a.c.c.cQt.f.d.f.g.i.f.f.f.f.s.f",
+"Qt.d.i.c.cQt.c.c.a.a.a.a.a.l.a.a.a.a.r.a.a.#.a.a.l.b.l.e.j.e.e.e.j.b.j.b.j.b.j.b.j.j.e.b.b.r.b.r.e.r.c.f.d.d.r.r.d.f.d.f.g.v.B.S#c#s#t#t#g#h.V.S.J.y.u.u.w.h.g.x.i.m.p.v.h.g.d.c.c.#.f.g.y.z.B.v.f.fQtQt.a.b.a.b.c.c.b.a.a.b.e.e.e.e.j.j.j.e.j.r.e.b.e.r.e.b.#.c.#.c.f.f.g.n.v.o.G.F.z.v.h.fQt.#.c.#.c.a.c.a.b.b.e.j.e.j.j.j.j.e.j.j.j.j.j.j.e.j.e.e.e.c.b.a.c.a.e.t.l.j.e.j.j.j.j.k.e.k.e.j.e.k.e.j.e.j.e.j.e.j.j.e.j.e.j.j.j.e.j.j.j.b.j.e.e.j.e.l.b.e.a.r.c.aQt.c.c.i.dQt.gQtQtQt.iQt.iQtQtQt",
+".a.a.a.a.#.a.a.#.a.#.a.#.a.#.a.a.a.b.a.a.b.a.b.a.e.e.e.e.e.b.e.e.b.e.b.e.b.e.b.e.e.j.e.e.r.e.r.e.#.c.d.q.x.x.x.w.q.x.h.v.z.F.S.H.X#i#p#o.O.N.E.D.v.u.u.v.h.h.x.h.i.g.g.p.h.g.g.d.c.q.f.x.w.C.z.z.g.gQt.c.aQt.b.aQt.a.c.a.a.e.l.e.e.k.j.k.e.e.j.j.e.e.e.e.e.b.b.b.b.c.dQt.x.h.u.v.J.G.B.v.p.w.g.f.#.c.c.a.b.a.e.l.e.e.j.e.j.j.j.j.e.e.e.e.e.j.e.j.b.l.a.a.c.b.c.b.l.l.e.e.j.e.e.k.j.j.k.j.k.j.k.j.j.j.j.j.j.j.j.j.e.j.e.j.e.e.j.e.e.e.l.e.e.l.b.l.e.e.l.a.a.a.c.#.c.cQt.cQt.d.d.d.f.c.d.c.d.cQt.c",
+".b.b.b.b.b.b.b.b.c.a.c.a.a.a.a.b.a.c.aQt.c.c.#.c.a.a.#.a.b.b.r.b.j.e.e.e.e.e.e.e.b.e.b.r.r.r.#.d.q.i.m.w.w.h.g.x.p.o.J.Q.M.F.B.C.C.D.F.I.G.D.C.u.z.v.u.p.h.h.g.g.f.m.g.h.g.g.fQt.#.dQt.f.g.o.C.G.h.g.f.q.#.c.b.c.c.r.a.r.a.l.e.e.j.e.e.j.j.e.e.j.e.b.e.j.b.b.r.bQt.c.f.f.h.g.h.h.D.z.o.v.o.v.u.hQtQt.c.a.a.a.e.e.e.e.l.e.e.e.b.e.j.j.e.j.e.e.j.e.e.e.b.a.b.a.c.a.e.t.e.j.e.e.e.j.j.j.k.e.j.j.j.j.j.e.j.e.j.e.j.e.j.e.j.e.j.j.e.j.t.e.e.j.e.l.e.e.l.b.a.a.bQt.c.c.c.a.f.d.f.d.i.c.r.b.#.b.#.b.r.r",
+".e.e.l.e.b.l.b.e.l.b.b.b.b.b.a.r.a.r.a.c.b.a.r.a.a.b.a.b.a.b.r.r.b.e.b.b.r.r.b.r.b.r.c.f.f.x.x.h.m.h.p.v.A.o.A.z.E.F.F.F.z.y.v.u.u.v.v.C.z.v.p.p.A.u.h.u.h.g.h.h.f.f.i.g.g.m.g.fQt.iQt.g.g.v.G.z.o.p.iQtQt.cQt.c.c.a.c.a.b.b.l.e.b.j.j.k.e.e.j.e.b.j.e.e.e.r.b.b.c.a.cQt.f.x.m.h.p.v.v.v.v.o.v.v.f.iQt.c.a.b.e.e.b.l.b.e.a.e.l.e.b.l.e.l.e.e.l.e.l.b.a.b.a.a.c.c.l.e.e.j.e.e.e.e.j.j.j.k.j.j.k.j.j.j.j.j.j.j.j.j.e.j.e.j.e.e.e.e.e.l.e.l.a.a.a.a.a.a.a.r.c.c.c.c.c.c.c.a.c.a.cQt.e.b.e.b.e.r.e.e",
+".e.b.e.b.e.e.e.e.b.#.e.a.b.a.e.b.aQt.b.c.a.c.a.r.#.c.a.b.r.c.r.c.c.c.c.a.c.a.c.a.d.g.f.h.h.n.p.o.v.z.K.E.Q.L.W.L.F.J.C.v.u.u.y.p.v.p.u.v.n.h.g.h.g.g.g.g.g.m.x.g.g.f.f.g.p.g.g.gQtQt.d.d.g.h.y.G.y.u.w.iQtQt.c.r.cQt.b.a.a.l.e.e.e.j.b.k.j.j.e.j.e.e.e.j.e.b.r.b.c.c.c.fQt.f.x.x.m.p.h.o.p.v.o.o.g.i.f.d.c.c.b.b.a.b.a.b.a.b.b.a.e.e.e.b.l.b.e.b.e.e.b.a.a.r.a.c.j.l.j.e.j.e.e.e.e.k.e.k.e.k.e.j.e.j.e.j.e.j.e.j.j.e.e.e.j.l.j.l.e.e.e.b.a.r.a.b.#.b.c.aQt.c.c.d.d.f.rQt.r.#.b.r.e.b.e.b.e.e.b.e",
+".r.r.b.r.b.r.b.b.b.b.a.b.a.b.a.b.c.c.c.cQt.c.c.c.c.c.c.c.c.d.f.d.f.q.x.q.g.q.f.x.g.n.p.o.A.D.I.E.T.U#a.8.7.U.P.C.v.u.v.p.p.g.p.p.h.g.w.g.g.f.f.x.iQtQt.s.i.fQtQt.f.f.f.q.i.g.g.hQtQt.c.cQt.s.u.o.C.A.h.sQt.f.c.rQt.c.a.#.b.e.j.l.e.e.j.k.k.b.j.e.e.j.e.e.e.b.r.b.aQt.c.#.d.f.f.f.f.x.x.h.o.v.v.o.u.n.g.f.f.c.c.c.a.c.b.c.a.a.b.b.e.l.e.e.e.e.l.e.l.b.a.a.b.a.c.c.l.e.j.e.j.e.e.e.k.j.k.j.j.k.j.j.j.j.j.j.j.j.j.j.e.l.j.e.e.e.e.e.l.e.a.a.e.a.a.a.a.c.b.c.c.c.c.c.f.d.r.a.b.b.a.r.e.b.b.b.b.b.b.b",
+".b.a.#.b.b.r.r.c.r.l.b.e.b.l.r.e.c.c.c.c.c.cQt.c.cQt.c.r.c.f.d.d.x.f.x.x.x.h.x.h.u.o.z.F.T.W.1#i.1.8#i.X.R.P.T.C.u.u.p.p.h.g.g.g.x.h.g.fQt.f.f.fQt.#.dQtQtQt.#Qt.q.f.f.f.i.g.g.w.i.f.i.c.f.g.n.A.y.y.v.g.s.d.c.c.c.c.c.a.a.e.l.e.e.e.j.e.k.e.e.j.j.b.j.e.b.b.b.b.c.#.cQt.d.d.g.q.d.i.x.w.p.p.v.v.o.v.h.g.q.c.d.d.b.c.a.c.b.a.b.a.e.b.e.a.e.a.e.b.e.e.a.b.a.r.a.c.j.l.e.j.e.e.e.e.k.e.j.j.j.j.j.e.j.j.e.j.e.j.e.j.e.e.e.l.e.t.e.l.b.a.l.b.a.a.b.a.b.c.#.c.c.c.c.c.r.r.c.rQt.b.r.e.a.#.b.#.a.b.a.b",
+".e.b.e.l.b.l.b.e.a.cQt.c.c.c.cQtQtQt.iQtQt.dQt.d.x.x.f.gQtQt.q.#.h.p.n.p.o.o.I.E.Q.Y.W.W.Z.N.E.J.I.Y#a.1.L.N.C.g.g.g.g.f.i.f.s.f.i.#.iQt.c.q.c.c.c.c.a.cQt.#Qt.q.#.q.#.#.cQtQtQt.g.gQt.d.dQt.s.g.n.n.y.o.h.f.d.#.c.a.a.b.l.e.e.j.b.e.e.e.e.e.b.e.b.e.e.e.b.e.b.l.b.b.a.b.#.c.c.d.iQtQt.f.x.m.h.w.o.v.z.o.n.u.p.hQt.c.a.a.l.b.c.d.e.l.e.e.e.e.e.l.a.a.a.a.a.b.b.b.j.e.j.j.j.j.j.j.j.j.j.j.j.j.j.j.k.e.k.j.j.k.j.j.j.j.j.j.e.e.l.b.r.a.a.a.c.r.c.d.#.a.a.a.#.c.c.c.cQt.c.c.cQt.c.c.#.b.e.e.e.b.e.b",
+".b.j.l.b.e.b.b.eQt.a.c.cQt.c.c.d.c.c.c.d.d.d.d.cQt.d.f.f.m.h.p.u.A.C.D.F.E.P.2#c.M.Q.F.B.z.o.z.D.T.O#d.U.R.F.p.f.g.iQtQtQtQtQtQt.cQt.dQt.#.c.c.c.c.#.c.c.#.c.#.d.a.#.c.#.c.iQtQt.iQtQt.c.f.d.f.m.y.o.y.n.p.m.d.d.#.#.a.a.b.e.e.e.b.e.b.e.r.e.b.e.e.e.e.e.e.e.b.e.a.b.b.b.b.c.d.c.c.#.d.f.i.x.g.h.v.o.v.o.o.y.o.u.f.f.c.a.a.c.c.c.e.e.a.e.b.l.b.e.r.a.l.a.b.c.e.a.e.j.j.e.j.e.j.e.j.e.j.e.j.e.j.e.j.k.j.j.j.j.j.j.j.j.j.j.j.e.a.l.a.#.a.a.c.c.c.r.a.#.r.c.c.dQt.fQt.d.#.f.#QtQt.d.a.b.e.b.b.b.e.b",
+".e.b.e.e.b.a.r.b.e.a.r.a.c.cQt.c.#.c.c.d.x.x.s.s.x.i.u.v.C.B.E.K.1.2.X.Y.S.H.Q.Q.o.v.u.p.p.n.o.z.R#o#q#h.F.v.hQtQtQtQtQtQtQt.c.c.c.cQt.c.c.c.c.c.b.b.a.c.c.c.c.#.a.a.#.c.c.c.c.#.i.f.i.d.cQtQt.i.p.u.n.v.p.x.g.d.a.a.b.a.a.e.b.e.e.e.e.e.l.e.e.e.#.e.e.e.e.e.e.e.e.a.a.b.a.r.r.c.c.c.f.d.f.f.h.x.g.h.h.u.v.o.y.z.p.iQt.c.c.c.a.r.l.e.e.e.l.e.e.e.a.a.a.a.a.a.b.b.j.l.e.e.e.e.e.e.e.e.j.e.j.e.e.e.e.e.e.e.e.e.e.e.j.e.e.l.e.a.b.a.a.l.a.a.rQt.c.d.#.d.#Qt.dQt.fQt.iQt.iQt.#.f.#.q.b.r.e.b.e.r.e.r",
+".b.b.r.b.r.r.b.b.#.b.a.bQt.d.d.cQt.d.f.x.h.p.v.C.u.A.C.J.H.P.M.N.T.T.I.z.y.u.v.p.f.f.x.m.w.h.v.z.2#p#i.2.B.h.x.dQtQtQt.c.c.c.c.c.a.c.a.c.b.c.a.a.e.a.b.b.a.#Qt.c.a.a.a.#.a.#.c.cQt.dQt.iQtQt.gQt.g.m.p.h.g.g.s.d.c.c.a.b.a.b.b.e.e.e.e.b.b.e.e.e.e.e.e.e.e.e.e.b.e.e.r.e.a.b.b.b.c.c.cQt.f.f.x.x.f.g.g.m.h.v.v.C.v.n.g.fQt.c.a.l.b.c.a.c.b.c.a.c.l.a.l.a.b.a.e.a.e.e.t.e.t.e.t.e.t.e.l.e.e.e.t.e.e.e.e.e.e.e.e.e.e.e.e.e.a.b.a.a.a.c.#.a.#.cQtQt.f.f.f.g.g.g.f.f.iQt.#.i.dQtQtQt.b.c.b.r.r.e.b.b",
+".c.#.c.cQt.d.f.dQt.d.i.d.dQt.x.f.g.p.v.y.B.Q.M.X.2.2.Q.K.C.u.p.h.p.p.h.g.x.f.q.f.x.q.dQt.f.w.o.B#.#..S.D.hQtQt.cQtQt.#.c.a.b.e.b.b.r.b.a.r.e.b.r.e.e.e.a.#.r.#.c.a.a.b.a.b.c.c.c.#Qt.fQtQt.gQtQt.f.i.g.i.i.g.m.iQt.#.c.a.b.l.b.a.e.e.b.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.a.b.l.b.a.b.b.c.c.d.d.x.f.d.#.g.g.h.p.v.o.z.o.p.xQt.#.a.a.a.b.a.b.a.b.a.a.a.r.a.a.a.r.b.b.e.e.e.e.e.e.e.e.e.e.e.l.e.e.e.e.e.e.e.e.e.b.e.a.e.l.a.r.a.c.c.c.c.#.cQtQtQtQtQt.x.f.h.g.x.m.x.x.f.f.xQtQt.dQt.dQt.d.c.d.f.dQt.#",
+".d.d.f.d.d.q.f.q.m.g.g.g.g.h.h.n.C.z.F.S.Y.N.L.L.G.D.v.p.h.i.fQt.g.f.f.x.d.dQt.#.f.g.q.i.f.p.C.E#..X.z.h.fQt.f.c.b.c.a.b.r.e.e.e.e.l.e.e.e.e.e.e.e.b.e.e.b.c.a.c.a.b.a.c.c.c.a.c.c.iQt.g.iQtQt.d.i.f.i.i.i.g.i.gQt.c.c.c.a.b.e.b.e.e.e.e.a.e.e.e.e.e.e.e.e.e.e.e.b.e.e.e.#.b.b.b.e.a.r.b.c.d.d.dQtQt.d.f.h.g.p.u.o.C.o.p.gQt.c.a.b.c.a.r.a.c.b.c.l.a.l.a.b.a.e.a.e.a.e.a.e.a.e.a.e.a.e.b.a.l.b.l.b.e.b.b.e.b.l.b.b.a.b.c.c.c.c.d.fQtQt.f.g.f.i.i.v.w.w.h.m.g.g.i.g.i.f.f.f.f.g.f.fQt.xQt.d.f.q.f",
+".f.f.g.x.m.g.w.g.u.v.o.o.C.B.C.C.H.F.F.D.y.u.p.g.x.f.f.d.c.c.c.c.c.c.d.#.r.c.d.f.q.f.g.x.u.z.F.R.2.F.u.f.#.b.c.#.a.b.b.e.e.e.b.j.e.e.r.e.a.e.b.e.e.j.e.e.b.e.c.r.e.e.r.b.b.b.b.c.r.d.f.i.g.g.d.cQt.i.i.g.i.i.h.s.c.c.c.c.c.b.a.b.e.b.a.e.b.e.e.e.e.e.e.e.e.e.e.e.e.j.e.e.e.e.l.b.e.e.e.a.bQt.d.d.b.c.d.d.f.x.m.s.o.C.z.v.u.fQt.#.c.c.c.c.c.c.c.c.a.a.a.a.a.a.b.b.e.e.a.b.a.a.e.e.e.a.a.a.b.a.b.e.b.l.b.l.b.a.b.b.c.c.c.c.c.d.dQt.f.f.x.g.p.h.u.h.v.p.m.g.x.g.fQt.g.g.f.i.f.f.i.g.m.g.g.g.w.x.m.s",
+".w.g.w.v.p.n.u.v.B.B.B.F.S.N.H.F.v.v.h.h.x.f.f.d.l.l.e.a.r.#.q.q.d.dQt.f.iQtQtQt.f.x.f.m.h.z.Q.L.E.u.x.c.e.a.e.c.b.e.b.e.e.j.j.e.b.l.e.e.j.e.e.e.j.e.e.j.a.b.c.a.b.e.a.e.a.b.a.b.c.#.f.m.i.fQt.f.c.d.s.i.i.i.i.g.#.c.c.b.a.b.e.b.a.e.e.e.e.e.e.e.e.e.e.b.e.e.e.e.e.e.b.e.b.e.e.b.j.b.e.b.b.c.d.d.r.c.f.d.d.g.x.g.u.C.z.C.o.h.fQt.b.c.a.c.b.c.a.c.l.a.l.a.b.a.b.a.e.e.l.a.e.a.e.e.a.l.b.a.a.a.l.a.a.e.b.b.a.e.b.l.c.c.c.d.d.dQt.f.f.h.g.n.u.A.v.o.g.g.g.f.iQtQt.i.i.h.i.m.i.m.g.m.u.p.v.p.v.u.n.u",
+".C.A.v.h.w.u.z.A.F.M.S.H.z.u.g.f.iQtQt.i.c.c.a.c.e.r.l.b.a.b.b.b.b.a.#.b.c.c.f.q.i.d.h.h.o.I.E.J.x.gQt.cQt.b.#.e.b.j.e.k.j.k.j.k.e.e.b.l.b.e.e.e.b.e.e.#.a.a.#.a.a.a.#.a.a.e.r.a.aQtQtQt.f.x.f.fQt.i.f.s.f.f.g.m.i.c.b.e.b.a.a.r.b.e.e.e.e.e.e.e.e.e.e.e.k.e.e.e.e.e.e.e.e.e.e.e.b.e.l.r.a.b.b.a.c.a.c.c.cQt.d.iQt.p.v.o.o.v.h.i.d.d.c.c.c.c.c.b.a.l.e.e.b.e.e.e.e.e.e.a.a.b.a.c.a.a.c.a.r.a.r.c.c.c.c.c.c.c.c.cQt.c.fQt.f.i.n.u.C.z.C.v.u.h.g.s.m.f.d.qQt.f.x.g.u.p.p.h.h.p.p.u.w.v.u.v.v.y.C.A",
+".C.v.v.v.o.o.z.A.W.Z.Q.B.u.g.m.fQt.iQt.#.c.a.c.a.b.a.b.e.b.a.b.a.l.r.a.bQt.d.d.d.c.g.g.n.v.Q.H.C.gQt.f.c.c.a.b.e.j.j.j.j.k.e.k.j.b.l.e.e.e.b.j.e.l.b.e.b.a.b.c.a.l.a.a.a.a.b.a.e.a.c.#.f.f.g.f.f.iQt.s.f.i.g.g.x.uQt.a.e.e.e.l.a.e.b.e.j.e.j.e.j.e.j.e.k.j.k.e.j.e.e.e.b.e.j.b.e.e.b.e.a.b.b.a.b.r.c.c.c.c.fQt.d.s.g.o.v.A.o.v.hQt.d.c.c.c.a.c.c.l.a.a.l.e.e.e.b.l.e.l.e.a.c.a.b.a.a.b.c.c.c.c.c.a.r.a.a.c.cQt.c.d.d.f.x.g.w.u.o.C.y.y.v.g.h.x.f.x.f.#.d.iQt.x.h.m.h.m.h.h.h.u.h.p.p.v.v.A.v.A.C",
+".o.u.v.o.A.y.C.F.2.Y.F.p.g.f.fQtQtQt.cQt.a.c.r.b.b.e.b.b.a.b.e.b.b.a.#.b.c.c.f.qQt.h.m.h.B.N.J.uQtQt.c.c.#.b.b.l.b.k.b.k.e.k.e.b.e.e.b.l.e.l.e.b.e.e.e.a.a.c.a.a.#.a.a.b.#.b.b.a.#.aQt.f.f.f.f.fQtQt.f.q.g.i.i.m.n.hQt.a.b.b.e.e.e.j.e.e.b.e.j.e.e.e.j.k.k.k.k.b.j.e.j.e.e.e.e.j.e.e.e.b.a.b.b.b.a.cQt.c.cQt.dQtQt.g.h.v.v.A.p.g.d.d.c.c.r.c.c.a.a.a.b.a.r.a.b.b.a.a.a.c.b.c.c.c.c.c.a.c.a.c.c.c.a.a.#.c.c.#QtQt.n.p.n.v.u.v.u.v.p.u.h.g.f.f.f.d.s.f.g.f.f.f.w.h.g.i.g.i.w.h.p.h.v.u.u.u.o.v.o.C",
+".v.v.u.o.v.v.F.R.B.B.y.p.g.fQt.c.#.#.c.a.a.b.e.e.e.e.e.e.e.e.b.e.e.r.a.aQt.d.d.f.f.h.p.o.S.Q.o.g.i.c.c.c.a.e.e.e.j.j.e.k.j.k.j.k.e.l.e.e.e.b.e.l.e.b.e.#.b.c.#.a.a.a.a.a.a.b.a.e.aQt.#.dQt.fQtQt.#Qt.i.f.f.f.x.x.o.p.i.#.c.a.r.e.e.b.e.e.j.e.j.e.j.e.j.e.k.e.k.e.e.b.e.j.e.j.e.e.b.e.#.e.e.b.l.b.c.a.c.c.c.dQt.fQt.g.i.p.v.v.u.h.q.f.dQt.c.c.c.c.a.a.a.b.a.b.b.e.c.#.r.c.c.c.c.d.a.#.#.c.i.fQtQtQtQtQt.g.g.g.w.h.B.D.z.v.o.p.u.p.i.iQtQtQtQt.#.i.f.f.f.s.g.h.g.g.h.x.h.h.g.h.u.p.u.u.v.o.v.v.o.v",
+".p.w.o.y.z.B.F.E.p.p.h.g.f.i.d.c.c.a.a.a.r.e.e.b.e.e.b.e.e.e.e.e.r.a.#.c.c.d.d.f.g.w.p.B.M.F.h.x.c.#Qt.a.b.l.e.j.e.j.e.e.k.b.j.b.e.b.e.b.l.e.e.b.e.#.e.a.a.a.a.c.#.a.a.r.a.#.b.a.a.cQt.i.f.f.#.cQt.#Qt.#.g.f.s.g.p.u.p.i.c.c.b.e.r.b.b.b.b.r.b.b.e.e.e.j.k.e.e.j.j.e.e.b.e.e.b.e.e.e.e.b.l.b.b.b.a.b.c.cQt.d.#.dQtQt.x.m.u.o.v.n.f.qQt.d.f.c.c.r.c.c.c.c.c.c.c.c.c.c.c.c.d.i.dQt.c.dQt.i.f.f.g.w.h.h.u.u.o.o.z.D.z.C.o.u.p.h.f.fQtQtQtQt.gQt.c.c.f.f.x.g.p.h.h.g.x.f.x.g.w.h.u.v.B.C.z.C.A.A.o.A",
+".n.v.v.A.F.H.B.v.g.h.f.f.f.d.c.b.#.a.e.e.e.b.e.j.e.e.j.e.e.b.e.b.e.a.b.#.c.f.x.f.h.w.o.K.R.A.g.q.q.c.c.a.a.e.e.j.e.j.j.e.e.k.j.j.e.l.e.l.e.b.e.l.e.b.b.c.a.#.#.c.a.#.a.a.a.a.b.#.c.qQt.qQtQt.c.a.c.c.c.i.dQt.f.g.p.p.u.hQt.#Qt.e.r.r.b.#.b.b.b.b.e.j.e.j.e.e.j.e.e.e.j.e.j.e.j.e.b.b.e.a.b.a.e.b.aQt.c.c.cQt.d.i.d.f.x.h.h.v.v.v.h.f.q.fQt.c.c.c.a.c.a.c.a.r.c.r.c.d.d.i.d.f.f.qQt.i.f.x.g.g.u.y.v.z.C.z.C.B.C.o.u.p.g.h.f.f.fQt.#Qt.qQtQt.c.#.cQt.f.m.h.h.w.s.m.x.h.h.w.p.v.v.A.B.F.C.B.C.A.v.u",
+".p.u.A.z.F.J.u.g.g.i.f.i.d.c.b.b.l.e.e.e.e.j.e.e.k.e.b.j.e.j.e.j.b.a.#.cQt.d.g.g.h.u.B.H.F.u.h.d.#.c.#.e.b.e.j.j.b.k.e.k.e.e.j.b.e.b.e.e.b.l.e.b.b.l.a.#.a.c.c.q.a.rQt.cQt.a.#.a.c.#.iQt.i.c.a.a.c.cQtQt.d.i.f.f.m.p.h.m.h.fQt.c.r.#.r.a.rQt.b.b.b.j.e.e.e.j.e.j.b.j.e.e.e.e.e.e.e.e.e.r.a.b.b.a.c.b.c.c.c.cQt.d.d.d.g.x.w.u.v.z.x.f.f.q.f.d.dQt.c.#.c.c.c.d.c.dQt.fQtQt.x.h.x.h.x.s.g.n.v.C.z.D.B.B.D.A.v.p.h.g.iQt.fQtQt.dQt.dQt.cQt.c.#Qt.c.#.g.f.h.n.p.v.h.x.h.g.w.u.y.z.z.J.Q.I.J.D.A.A.u.n",
+".y.A.I.H.J.p.g.wQtQtQt.#.c.a.b.b.e.b.j.e.k.e.k.k.j.j.j.j.e.j.b.e.l.r.aQt.c.g.g.x.h.v.F.S.C.p.x.dQt.#.a.l.l.b.e.e.e.k.e.e.j.j.j.j.e.l.b.l.e.e.e.l.r.b.#.c.a.cQt.#.#.c.qQt.cQt.cQt.c.iQt.dQt.c.a.#.c.c.c.cQt.dQt.g.x.m.h.h.p.s.f.i.a.r.b.#.b.r.b.r.e.b.e.j.e.j.e.e.j.e.e.j.b.e.j.b.b.e.b.l.b.a.b.r.a.c.cQt.c.d.fQt.#.d.q.h.g.u.o.B.g.h.x.g.q.i.dQtQtQt.d.d.d.d.d.d.d.fQt.g.f.h.f.x.h.h.n.C.I.F.B.z.v.u.u.p.h.i.x.#.iQt.qQt.d.f.d.d.c.c.c.cQt.fQt.g.f.m.h.n.u.u.w.m.w.h.h.v.J.F.H.H.N.M.E.E.F.B.o.n",
+".J.K.H.G.w.i.fQt.cQt.a.c.b.a.b.e.e.e.e.e.e.j.e.b.k.e.k.j.e.e.e.j.#.a.bQt.d.g.x.w.z.S.z.m.i.f.gQt.q.a.#.b.e.e.e.e.b.e.b.e.e.b.e.e.e.e.e.b.b.a.r.a.#.q.c.q.c.#Qt.#Qt.iQtQt.iQt.dQt.iQt.q.#.c.c.c.c.a.#.cQt.d.#.fQt.f.qQt.d.f.g.u.y.gQtQt.dQt.b.r.e.e.e.j.e.e.e.b.j.e.e.j.e.e.e.b.e.a.a.a.b.e.b.b.b.c.a.c.c.cQt.d.dQtQt.g.g.p.n.v.D.o.p.i.f.#.d.f.x.c.#.f.#Qt.g.f.h.q.g.i.g.v.v.o.C.F.H.H.F.B.v.u.v.f.g.f.g.i.f.fQtQtQt.c.#Qt.c.#.c.#.d.#Qt.dQt.f.f.w.w.iQt.f.m.v.o.v.v.v.u.u.u.u.u.G.A.J.z.E.E.K.I",
+".H.F.J.u.h.fQt.i.a.c.a.a.a.e.e.e.e.e.j.e.e.e.j.e.0.k.j.k.j.e.b.e.b.b.#.c.q.f.m.u.Q.T.v.m.f.#Qt.d.a.a.a.l.b.a.b.e.e.e.l.e.l.e.l.e.b.l.b.a.e.b.a.r.#.#.c.q.c.iQt.i.i.s.i.g.f.g.f.iQt.iQtQt.cQt.c.c.c.#.c.cQt.f.f.d.s.g.iQt.f.i.g.u.f.h.f.i.d.c.b.#.l.b.l.e.e.j.e.e.j.e.e.r.e.b.a.b.a.a.#.a.b.a.b.b.cQt.c.c.c.d.#.d.i.d.f.x.h.u.o.A.A.u.xQt.i.f.x.s.g.i.f.f.f.f.i.g.w.h.u.o.D.J.I.F.C.D.B.C.v.h.h.hQt.qQtQt.iQtQtQtQt.#Qt.c.c.#.cQt.c.#Qt.d.fQt.g.f.i.i.iQt.i.h.o.v.h.g.g.w.h.h.w.h.n.u.y.C.G.H.R.W",
+".K.z.p.gQt.f.#.c.a.a.c.r.b.e.e.e.k.k.j.k.k.k.k.k.k.k.k.j.e.e.e.e.#.b.a.a.d.g.h.n.R.E.p.i.sQt.i.d.a.#.a.b.l.e.l.e.b.l.b.e.b.e.b.e.l.e.l.e.#.a.a.c.q.#.q.c.iQt.i.f.g.s.f.s.g.i.g.d.i.#QtQt.c.c.d.f.aQt.c.q.dQt.f.f.iQt.c.f.c.d.i.h.g.g.m.f.f.#.dQt.e.a.e.r.e.e.e.e.b.e.e.e.a.b.b.a.a.a.a.c.#.b.a.bQt.c.c.d.i.d.dQt.c.#.g.f.m.p.o.v.z.u.g.m.x.x.w.v.h.g.g.h.u.u.o.v.B.D.I.I.D.I.D.C.o.u.p.h.g.g.f.fQt.qQt.fQt.d.#.d.#.c.c.c.#.c.c.c.cQtQtQt.d.f.f.fQtQtQtQt.g.g.u.p.i.f.i.f.i.g.g.h.m.p.w.n.A.C.H.Q",
+".u.h.gQt.fQt.c.a.c.c.a.a.e.e.e.k.k.j.k.j.j.j.j.j.j.k.j.k.j.b.j.e.c.a.bQtQtQt.h.p.S.H.u.g.s.d.#Qt.a.a.a.b.l.r.e.j.e.e.e.e.l.e.l.b.e.l.b.a.c.#.c.cQt.c.#.iQt.g.f.g.i.i.g.s.f.gQt.d.q.i.#.c.c.c.f.d.c.c.fQt.fQt.g.f.dQtQt.b.r.d.f.g.w.p.h.w.g.g.fQt.c.#.a.b.a.j.b.e.e.e.e.a.r.a.c.c.c.c.c.c.c.c.r.cQt.d.#.d.d.f.f.q.i.dQt.f.h.g.v.v.z.v.u.h.g.p.v.o.u.v.u.A.C.D.B.J.z.F.z.z.z.v.u.p.p.m.i.i.f.fQt.i.d.#.i.c.c.#.c.cQt.c.r.c.a.c.c.c.#.cQt.f.f.i.f.fQt.dQt.f.f.x.x.x.iQt.i.f.i.f.g.i.f.s.g.g.h.u.y.y",
+".i.fQtQtQt.q.a.l.b.#.e.e.b.e.k.j.j.k.j.k.k.j.k.j.k.j.e.e.e.e.b.bQt.cQt.c.d.f.h.w.B.M.z.h.fQt.i.d.#.a.a.e.l.e.e.j.b.l.b.e.e.b.e.l.l.#.a.a.a.#.c.q.#QtQt.i.f.x.f.f.s.g.i.g.f.iQt.fQtQt.#.c.c.c.d.c.qQt.#.i.d.g.f.g.cQt.r.c.#.d.d.x.h.h.p.h.p.g.g.i.c.c.a.b.b.b.e.j.e.e.a.b.a.aQt.c.qQt.c.c.#.fQt.d.d.d.f.f.f.q.g.f.dQt.g.x.m.h.h.o.z.y.A.u.o.v.v.z.B.z.B.D.z.z.y.C.o.u.p.p.g.m.i.g.f.qQt.iQt.iQt.d.c.c.c.c.c.c.c.c.a.c.a.c.a.c.a.a.fQt.i.d.i.d.fQt.d.f.fQt.f.m.fQt.#QtQtQtQtQtQt.fQt.#Qt.s.g.g.h.i",
+".dQt.c.c.a.a.a.e.a.b.b.e.e.k.e.k.j.j.j.j.j.j.k.j.k.e.j.b.e.b.r.r.r.c.c.#.f.f.w.v.T.P.z.h.f.dQt.c.a.a.a.l.e.e.e.e.e.e.l.b.e.l.e.b.l.a.a.r.#.c.q.d.#QtQt.iQt.f.g.f.g.i.s.g.i.g.dQt.iQtQt.#QtQt.f.dQt.#Qt.d.iQt.g.f.g.d.cQt.c.d.g.i.w.g.g.g.g.p.w.h.i.d.c.a.b.e.e.e.b.#.e.bQt.c.#.cQtQtQt.g.dQt.d.d.g.f.f.q.f.x.x.x.f.g.x.g.h.h.v.v.J.F.F.J.C.z.B.D.B.D.G.C.A.y.u.u.h.s.i.sQtQt.iQtQt.iQt.dQt.d.c.d.#.c.a.c.#.c.b.a.c.a.r.#.r.aQt.c.#Qt.c.f.fQtQt.f.q.d.f.g.f.f.fQt.c.#.cQtQtQt.f.i.f.gQtQtQt.xQtQt",
+".c.c.c.a.a.e.l.b.e.e.e.b.e.j.k.j.k.k.j.k.k.j.k.j.k.e.e.j.b.b.b.c.cQt.c.fQt.x.n.z.W.Z.C.g.fQt.i.c.a.#.a.e.e.e.b.j.e.b.e.e.l.b.e.e.r.#.r.a.#.#QtQt.i.iQtQt.g.f.f.g.i.g.i.g.f.s.f.gQt.#QtQt.d.#.fQtQt.c.i.c.i.q.g.f.g.f.f.d.f.f.g.m.x.x.g.x.m.g.h.u.f.d.f.c.b.b.b.b.a.b.aQt.a.c.f.dQt.iQtQtQt.dQtQt.q.f.x.f.h.x.x.s.p.s.g.w.p.o.v.o.B.T.Q.F.F.D.y.A.u.u.v.u.v.u.u.p.m.i.i.i.f.f.d.dQt.#.cQt.d.d.d.d.b.b.b.b.b.b.a.b.b.b.a.b.a.b.b.bQt.c.iQt.d.qQt.f.dQt.f.f.x.hQt.c.q.cQt.dQt.f.f.f.f.f.fQtQt.c.a.c",
+".a.b.b.b.l.b.e.l.e.e.e.e.j.e.j.k.j.j.j.k.e.k.e.k.e.j.e.e.b.b.b.r.f.c.dQt.d.w.o.K#h.Z.v.h.fQt.d.c.r.a.a.b.l.e.l.e.e.l.j.e.j.e.l.b.a.r.#.a.q.#.i.#.iQtQt.g.f.g.f.f.s.i.g.i.i.f.gQtQt.iQt.q.fQt.d.f.c.q.c.f.d.i.f.g.h.f.g.f.f.h.s.g.x.p.g.h.x.g.g.g.g.gQt.c.b.e.e.e.a.r.c.c.c.d.c.f.i.i.f.f.f.f.g.f.x.f.h.x.s.h.p.h.x.p.p.u.u.v.A.o.E.F.H.I.A.z.u.u.p.u.v.h.p.g.w.h.i.s.g.x.x.s.q.q.d.#.d.c.d.d.d.d.a.b.b.l.e.l.e.r.l.e.e.e.b.#.b.#.cQt.#.qQtQt.f.f.f.f.x.f.x.f.d.a.c.cQt.d.f.gQt.f.h.g.i.f.c.c.b.e",
+".e.b.e.e.b.e.e.e.b.e.e.j.k.k.k.e.j.j.j.j.k.j.e.e.e.e.e.e.b.a.b.a.c.a.f.g.h.v.B#i#h.K.uQt.iQtQt.q.a.a.l.a.e.e.e.b.l.b.l.l.b.l.e.l.l.l.a.a.#.c.#Qt.q.iQtQt.q.s.q.s.i.s.i.g.i.s.f.f.q.c.c.c.i.cQt.cQt.iQt.#.c.f.g.x.w.w.h.n.p.v.m.h.o.v.u.u.y.s.p.x.u.v.u.m.f.d.f.#.d.c.d.f.d.g.f.i.s.f.i.q.f.f.i.g.s.h.h.p.p.u.v.y.z.C.o.C.o.o.z.A.u.v.p.u.h.h.h.w.i.s.x.s.g.m.i.i.iQt.qQt.#Qt.fQt.b.#.b.#.a.r.b.b.e.a.e.b.b.e.b.l.e.l.b.a.a.a.c.a.d.#.d.i.f.f.fQt.f.f.i.f.xQtQt.c.a.#.a.cQt.f.f.f.gQtQtQt.#.a.#.a",
+".b.l.b.e.b.l.b.e.e.j.e.e.k.e.k.k.j.k.j.k.e.j.e.e.b.e.e.b.a.b.#.bQt.#.dQt.w.v.F#h.M.J.h.qQtQtQt.f.l.a.a.l.e.l.e.e.e.l.b.e.l.e.l.b.l.b.a.#.c.q.cQt.i.q.qQt.xQt.sQt.s.i.sQt.i.f.g.f.q.c.q.c.f.cQt.c.f.c.#QtQt.q.q.p.m.u.m.w.m.p.w.p.o.v.v.h.n.n.h.p.p.p.w.m.f.i.d.dQt.f.dQt.i.f.i.i.m.g.g.g.h.h.w.u.u.u.v.A.D.B.E.G.z.z.y.v.p.p.p.p.h.w.g.g.h.m.g.gQt.f.i.g.i.g.i.g.#.iQtQt.q.d.#.d.#.b.a.b.a.b.l.a.b.b.b.e.e.e.e.b.e.l.e.a.a.c.b.cQt.cQtQt.dQt.f.f.i.f.f.s.fQt.iQt.a.a.a.#.dQt.f.f.fQtQt.#.c.a.b.a",
+".e.e.e.e.b.e.e.e.e.j.e.e.k.j.k.e.k.j.j.j.k.j.e.e.e.b.e.l.r.b.b.c.iQt.g.x.w.z.F.2.B.v.h.i.iQtQt.d.r.a.l.a.a.e.b.a.l.e.l.l.b.l.e.l.a.r.a.#.#.#.qQtQtQt.i.q.f.sQt.i.i.f.q.g.q.g.f.fQt.i.dQt.i.d.d.f.c.f.f.i.g.x.w.w.v.o.o.v.v.n.o.y.o.v.v.o.v.p.n.m.u.v.A.v.v.w.g.f.qQt.i.i.i.m.g.p.v.o.v.v.o.C.C.B.F.F.z.E.P.N.R.P.u.v.u.h.m.g.m.x.g.f.f.g.f.fQt.gQt.g.f.g.f.f.g.f.#.c.q.c.cQt.c.c.#.b.#.b.#.b.b.r.l.e.e.e.b.b.e.e.b.l.e.a.b.a.a.b.#.cQt.dQtQt.f.f.m.g.f.f.i.iQt.c.c.a.c.c.iQt.f.g.fQtQt.c.c.a.a.a",
+".b.e.r.l.e.e.b.e.e.e.k.e.k.e.k.k.e.j.j.k.j.j.e.e.e.l.e.b.b.a.b.c.#.i.f.h.p.F.Q.P.C.p.g.iQtQt.cQt.r.c.a.l.a.a.e.e.b.a.b.a.e.a.b.a.#.aQt.#.#.d.#Qt.i.q.f.i.iQt.s.s.f.q.g.i.g.f.g.f.iQtQt.fQt.f.d.d.f.f.i.h.h.w.y.A.z.z.B.A.A.A.o.v.z.B.K.F.I.z.C.A.C.z.o.z.z.o.v.p.i.h.p.h.A.v.z.B.I.z.F.F.z.I.F.E.H.F.B.F.Q.Q.Q.I.g.g.s.i.f.g.f.fQt.qQt.#.#.i.#.d.#QtQtQt.s.gQtQt.c.q.cQt.c.c.#.c.b.a.b.a.b.a.b.a.e.e.b.l.e.b.l.b.l.e.e.#.a.a.r.a.c.c.c.iQt.q.i.f.i.g.f.sQtQtQt.#.#.c.#.cQt.d.fQt.fQtQt.c.c.a.a.b",
+".e.e.e.e.b.e.e.e.k.k.j.k.k.k.j.j.j.k.j.j.k.j.e.e.b.e.b.a.e.aQt.a.dQtQt.h.h.Q.Z.H.u.h.h.iQt.#Qt.#.c.#.a.a.b.a.b.a.a.b.a.a.#.a.a.a.c.a.#.c.#.iQt.d.qQt.i.i.i.s.i.i.g.s.f.f.f.g.f.g.#.d.i.dQt.q.g.f.f.f.h.h.v.A.B.F.P.L.Z.L.T.E.E.K.T.P.Z.L.N.P.L.P.P.T.E.T.E.I.I.I.J.B.J.J.B.E.I.T.B.I.I.D.F.I.F.B.o.v.v.o.v.u.u.h.sQt.fQtQt.dQt.f.c.c.cQt.c.c.cQt.cQtQt.fQt.dQtQt.#.c.q.c.c.c.r.c.#.e.r.e.r.e.e.e.r.e.e.b.e.e.e.e.e.l.e.a.b.c.a.c.c.c.#.qQt.d.fQt.x.g.f.fQtQtQt.c.#.c.c.c.#.i.dQtQtQtQt.c.r.a.e.a",
+".e.e.b.b.e.e.e.e.k.e.k.j.j.j.j.k.j.0.j.k.e.j.e.e.e.e.e.a.b.b.cQt.#.d.g.g.o.F.Z.I.h.h.g.iQtQtQtQt.c.#.c.c.a.a.b.b.a.a.a.b.c.aQt.a.#Qt.#.f.#.d.#.iQt.i.s.i.g.i.x.s.i.f.s.f.g.f.g.qQt.i.dQt.d.fQt.xQt.m.h.A.B.Q.Y.W.1#c#i#c.1.X.X.Y.R.X.R.L.R.N.V.1.W.Z.P.S.T.T.P.L.Q.H.E.E.J.K.J.J.A.v.C.A.v.v.v.v.g.i.m.i.m.i.g.f.#QtQt.f.cQt.a.c.a.#.a.a.a.#.a.a.c.c.c.cQt.cQt.c.cQt.c.c.#.b.r.b.#.b.e.a.e.a.r.e.l.e.a.e.b.e.b.l.b.e.e.a.a.#.c.b.#.c.cQt.dQt.f.f.i.f.q.fQtQtQt.cQt.c.#.c.c.cQtQtQtQtQt.c.c.a.a.a",
+".e.e.l.e.e.e.e.e.j.k.j.k.k.j.k.e.j.j.k.j.k.j.e.e.e.r.e.b.#.b.a.c.c.g.f.w.u.I.Z.B.g.m.g.i.f.q.#.#.#.c.c.c.c.b.a.r.a.b.a.a.#.b.a.aQt.#.c.#Qt.i.f.f.f.g.f.g.g.g.m.g.g.s.f.g.f.g.f.iQt.f.g.d.i.q.f.g.m.u.z.F.M.L.2.U.N.2.N.N.Q.H.E.F.F.E.F.F.E.H.Q.M.I.B.B.z.C.z.B.F.F.F.B.o.A.o.u.v.h.p.w.g.h.h.h.x.g.f.f.g.f.g.f.i.d.dQt.d.d.c.rQt.c.c.b.b.b.cQt.b.a.r.a.a.a.a.a.aQt.r.#.a.r.c.r.r.e.b.l.b.e.e.e.l.r.e.e.e.e.b.e.e.l.e.l.b.a.r.a.c.c.c.iQt.f.f.fQt.f.f.f.gQtQt.iQt.#.c.c.c.#QtQt.cQtQt.i.c.c.l.b.l",
+".e.b.e.e.e.e.e.e.e.k.j.j.j.k.e.e.j.k.j.j.k.e.e.e.e.e.b.a.e.b.cQtQt.f.x.n.o.J.P.z.x.g.g.iQt.q.#.#Qt.c.#.a.c.a.b.b.a.a.a.a.a.c.#.c.#.c.#.i.cQt.f.g.i.i.m.g.s.g.m.g.x.m.f.g.f.g.g.q.f.g.f.g.f.g.x.x.p.v.J.Q.N.X.X.X.S.H.K.C.J.B.z.z.o.y.z.C.J.D.A.C.v.u.o.u.v.p.p.A.C.o.v.v.h.g.h.f.p.h.x.h.x.f.i.f.f.g.q.q.f.q.d.d.fQtQt.c.d.r.c.b.a.cQt.bQt.c.cQt.a.b.a.b.r.b.r.aQt.cQt.cQt.c.r.a.r.l.r.e.b.l.b.e.b.e.#.b.e.a.e.r.e.l.e.#.a.c.b.a.c.#.dQt.dQt.f.f.f.s.f.qQtQtQtQt.d.f.#.c.c.c.c.#QtQtQt.#.c.a.a.b",
+".e.t.j.j.j.j.0.j.k.j.j.k.j.j.k.j.k.j.k.j.j.k.j.e.e.e.b.e.e.b.#.b.f.g.f.f.m.B.H.I.A.g.xQtQt.cQtQt.a.r.r.a.a.a.a.aQt.cQt.r.c.c.c.cQtQtQt.d.i.f.f.x.g.w.g.g.m.i.g.i.i.s.s.x.m.h.m.m.i.q.i.s.i.m.u.w.C.D.H.P.R.P.K.D.A.o.A.z.o.v.v.v.n.u.o.o.B.o.o.p.m.h.n.h.v.h.w.h.o.n.u.f.x.x.fQt.dQt.fQt.d.i.q.d.d.d.c.f.c.d.c.d.#Qt.#Qt.c.c.c.b.r.a.b.a.b.a.b.b.aQt.c.c.c.a.c.c.#.a.#.a.#.a.a.#.a.a.a.#.l.e.l.l.r.e.b.e.e.e.e.e.l.b.e.e.e.a.#.a.#.q.#QtQt.xQtQt.#.c.#.cQt.iQtQt.q.c.cQt.c.#.c.cQt.#.#.c.r.c.l.a",
+".l.j.e.j.j.k.k.k.j.j.j.j.e.k.e.k.j.j.k.e.k.e.j.k.e.e.e.j.b.c.b.rQt.d.d.g.w.B.Q.N.u.g.iQtQt.#QtQt.r.a.a.#.#.c.q.c.c.a.c.a.c.aQt.c.#.c.qQt.f.f.f.h.h.g.g.m.g.g.h.w.s.w.u.n.h.n.h.h.g.u.p.n.u.v.o.C.B.J.B.B.B.D.z.v.n.u.v.h.v.h.m.h.p.w.p.v.o.o.u.p.g.g.m.x.g.h.g.h.v.u.m.f.q.g.d.iQt.dQt.fQt.dQt.i.c.f.d.d.d.f.d.f.#Qt.#.c.c.c.#.c.b.a.b.#.b.#.b.#.c.cQt.cQt.c.a.c.b.a.a.#.l.a.b.a.b.a.b.a.l.e.#.e.b.l.r.l.r.e.b.e.l.e.l.l.e.a.b.a.#.#.#.iQtQt.xQt.q.#.cQtQtQtQtQt.dQt.c.#Qt.c.#.c.qQt.a.#.c.c.a.a",
+".l.l.e.j.j.j.k.j.k.j.j.k.j.j.k.j.j.j.j.k.j.k.j.k.e.k.e.e.e.r.r.r.i.c.f.f.w.D.M.U.v.h.fQtQt.cQt.d.r.a.rQt.#.c.#.c.#.c.#.a.#.a.a.aQt.#.cQt.g.f.h.i.p.u.p.h.h.w.n.u.h.v.A.C.B.B.A.o.C.D.A.C.C.G.B.J.z.C.y.v.u.p.h.g.m.g.x.m.g.g.g.h.i.g.g.w.h.p.w.g.g.f.f.i.g.f.f.f.p.h.i.f.g.dQt.#.d.dQt.d.dQt.d.dQtQt.c.i.#Qt.cQt.#Qt.#.iQt.f.c.c.#.a.a.a.a.a.a.a.a.c.c.c.a.a.r.a.a.#.l.a.r.a.a.#.a.#.a.#.e.b.l.e.#.e.b.e.e.e.b.e.b.l.e.e.b.a.a.a.#.#.#QtQtQtQtQt.#.c.q.#QtQtQtQt.#QtQt.c.c.c.dQt.#Qt.#.c.r.c.l.a",
+".l.b.l.e.j.j.j.j.j.k.e.k.e.k.e.j.k.j.j.j.e.j.j.j.b.e.j.e.b.r.bQt.c.c.i.x.o.E.L#h.o.p.g.i.iQtQtQtQt.#QtQtQt.iQt.i.c.c.c.c.c.cQt.c.#QtQt.i.f.g.g.g.u.h.v.h.v.v.v.v.A.D.B.E.E.F.I.I.B.B.D.B.D.I.G.E.u.v.u.w.w.i.g.f.g.f.g.f.f.g.fQt.f.g.f.i.x.m.x.g.f.f.gQt.f.iQt.i.q.x.i.i.#Qt.i.cQt.fQt.d.i.d.q.d.cQt.cQt.d.fQt.d.iQt.i.c.#.cQtQt.cQt.cQt.cQt.c.#.a.cQt.cQt.c.#.c.l.e.#.a.b.a.b.a.l.a.b.a.l.l.b.l.b.e.a.b.b.a.e.b.l.b.e.l.e.a.a.a.#.a.#.#Qt.iQtQt.#.#.c.#.fQtQt.i.#Qt.c.c.#.c.#.#Qt.#.#.c.#.c.a.a",
+".a.a.e.e.e.e.e.j.j.j.b.j.k.j.k.j.e.k.j.k.j.k.j.e.k.e.e.e.e.rQt.cQt.i.g.s.A.N.1.2.v.u.g.sQtQt.fQtQt.iQtQtQt.f.d.f.d.i.d.i.d.dQt.f.c.#.i.i.m.h.p.u.u.y.v.A.o.z.B.A.F.I.I.F.I.B.o.v.A.u.y.v.A.v.A.v.h.h.w.g.f.gQt.iQt.#.iQt.iQt.q.dQtQt.iQt.g.f.f.s.f.f.f.iQtQt.c.qQt.f.x.f.sQtQt.c.i.cQt.c.c.c.c.c.#.c.#Qt.#.#.#.qQt.qQtQt.iQt.f.d.#.c.#.c.c.#.c.#.cQt.c.c.c.b.c.c.b.l.e.a.#.a.a.#.a.#.a.a.#.e.b.l.r.e.b.e.a.b.b.e.l.l.e.l.e.a.r.a.a.r.#.#.#QtQtQt.c.#.#.d.#QtQtQt.d.#.c.c.c.cQt.cQt.#.#.#.a.c.l.a",
+".a.l.a.b.l.j.j.e.k.j.j.j.e.k.e.j.j.j.j.j.j.e.k.j.e.e.j.b.b.b.c.#.#.f.h.w.z.R.M.F.o.p.g.f.qQt.fQtQtQt.q.f.f.f.g.f.iQtQtQtQt.f.i.fQt.i.x.g.p.u.o.C.C.D.J.I.F.E.E.J.B.z.z.o.v.u.h.h.i.i.m.g.g.m.g.g.w.g.gQt.i.d.#.dQt.qQt.#.c.#Qt.c.iQt.d.#.#.f.i.x.g.g.fQt.d.q.#.c.iQt.g.i.s.i.g.f.c.c.c.c.c.cQt.c.cQtQt.c.#.f.cQt.#QtQt.iQtQtQt.#.#.#.#.#.#.#.#.#.c.c.cQt.c.cQt.c.e.l.b.a.r.b.a.b.a.l.#.l.#.l.e.l.b.b.a.b.b.e.l.b.l.b.l.e.b.a.a.a.l.a.c.#Qt.#.d.#.#Qt.#QtQtQtQtQt.cQtQt.c.#.cQt.#Qt.qQt.c.#.c.a.a",
+".a.a.l.a.e.e.e.j.k.j.e.j.k.j.j.k.j.k.j.j.k.j.j.j.e.e.e.e.bQt.rQtQt.g.s.A.I.P.H.B.o.p.g.sQtQt.iQtQtQt.i.f.s.x.i.x.s.s.p.s.p.s.s.s.g.g.w.p.o.D.J.z.E.M.P.Q.H.Q.F.B.v.h.h.x.w.f.gQt.g.f.g.f.g.f.f.i.i.f.i.c.c.c.f.qQt.d.fQt.fQt.c.c.d.i.dQtQt.f.x.p.g.h.x.gQtQt.c.q.d.f.x.i.m.g.g.fQt.cQt.c.c.a.c.a.#.#.#.q.#.#.#.qQt.i.#QtQt.iQt.fQtQtQtQt.#.#.#.#Qt.c.c.c.cQt.c.c.b.a.l.#.l.a.#.a.#.a.a.#.a.e.b.l.b.l.b.e.#.e.r.e.l.e.e.l.e.a.a.b.a.a.a.a.c.c.q.c.#.c.#.i.cQt.iQtQtQtQt.#.d.i.cQt.i.#Qt.#.#.a.a.l",
+".l.a.b.a.e.e.e.e.e.j.k.e.j.j.j.j.j.e.k.e.k.e.k.j.e.j.e.b.b.r.f.c.h.w.w.I.P.Q.F.B.u.g.fQtQtQtQtQtQtQt.f.g.g.x.w.g.n.n.p.w.p.h.w.h.m.w.h.o.B.z.E.I.N.L.N.E.F.J.z.v.w.m.x.m.xQtQt.q.q.f.fQt.f.iQtQt.dQt.i.cQt.d.f.i.i.d.#.d.#.d.dQt.f.dQt.c.dQt.f.s.g.w.g.f.dQt.qQt.f.f.i.i.h.h.w.h.c.c.cQt.cQt.r.a.d.q.d.#.d.q.d.#.#Qt.q.iQtQtQtQt.#.i.#Qt.iQt.iQt.cQt.c.q.c.c.c.c.l.e.e.a.a.#.l.e.a.l.#.e.#.l.l.a.b.b.b.b.e.b.e.r.l.b.e.l.e.a.a.a.b.a.a.#.a.#.c.c.c.#.#QtQtQtQtQtQt.cQt.cQt.#.#.cQtQt.#Qt.#.c.a.a",
+".b.a.a.b.a.a.b.a.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.l.a.a.cQt.#.f.h.w.D.E.S.J.z.C.o.u.h.g.m.h.h.h.p.h.g.m.h.v.o.B.B.B.F.F.D.E.F.Q.S.N.S.H.E.H.E.F.F.B.z.A.v.p.w.g.g.i.dQt.fQt.d.d.cQt.c.d.d.d.d.f.dQt.dQt.dQt.fQt.a.#Qt.#Qt.#.#.#.cQt.c.iQt.fQt.iQt.f.s.x.m.f.q.d.f.g.f.g.g.w.h.h.q.g.d.c.cQtQt.c.#.c.c.#.c.c.#.c.q.c.#.c.i.c.q.cQtQt.iQt.#.#Qt.c.#.a.a.#.a.#.b.l.#.l.b.b.e.e.e.b.e.r.e.#.e.r.e.b.l.e.b.a.b.a.b.a.e.l.l.b.e.e.b.l.a.a.a.r.a.c.cQt.#Qt.qQtQtQtQtQtQtQt.iQtQtQt.fQt.sQtQt.#.c.l.a.e",
+".a.r.a.a.b.a.a.b.e.e.e.e.e.e.e.e.r.e.e.e.e.e.e.b.b.eQt.aQtQt.fQt.x.p.I.E.F.z.A.D.G.o.u.h.g.f.h.g.h.g.g.u.u.y.D.F.F.Q.H.I.F.F.Q.M.L.L.E.H.B.F.z.D.A.o.o.u.w.g.m.x.i.i.d.i.d.i.d.i.c.aQt.c.f.d.f.d.dQt.f.d.i.dQt.d.#QtQt.#.#.c.#.c.c.cQt.c.dQt.d.f.g.i.g.g.g.x.g.f.f.g.f.m.h.u.v.hQtQtQtQt.d.d.i.#Qt.c.#.cQt.#.c.c.#.c.i.c.#.c.#.c.q.#.#.#.i.c.i.#.#.a.#.a.#.a.a.#.l.#.e.b.b.e.b.e.b.a.b.b.b.a.b.b.e.r.l.b.e.b.l.b.l.b.e.e.l.e.l.e.a.b.a.a.#.a.c.cQt.#QtQt.#QtQt.i.qQt.iQt.s.f.i.i.gQtQtQt.#.c.a.a",
+".a.a.a.a.a.a.a.a.e.e.e.e.e.e.l.e.l.e.l.e.e.l.e.l.a.a.a.c.c.d.i.d.f.n.I.I.G.y.v.F.B.C.u.g.m.f.f.f.f.h.h.h.u.A.I.P.N.S.E.I.D.B.I.Q.S.Q.E.J.D.C.A.v.v.h.u.g.h.f.f.fQtQtQt.dQt.dQt.d.c.c.cQt.dQtQt.f.iQtQtQtQtQt.fQt.c.#.d.q.d.i.#.c.q.c.qQt.iQt.f.f.i.m.h.n.p.h.h.m.g.g.w.p.v.v.y.o.f.g.f.fQt.d.dQt.c.#.c.#.c.c.#.c.c.#.c.#.c.#.f.#.d.c.i.d.#Qt.#Qt.a.#.rQt.#.q.a.#.#.a.#.a.b.r.b.b.#.a.#.a.a.r.a.#.b.b.a.#.a.r.a.b.l.b.l.e.l.e.e.l.a.a.a.c.a.c.c.c.#Qt.#Qt.iQtQt.q.f.iQtQtQt.i.x.i.fQtQtQt.c.c.c.c",
+".a.a.a.a.a.b.a.a.a.a.a.e.l.e.e.e.a.b.#.a.a.a.a.a.a.aQt.cQt.c.d.#.g.o.E.E.B.u.o.D.B.C.n.g.i.i.i.i.p.h.p.o.D.I.P.X.M.Q.I.I.D.J.I.I.K.F.F.A.z.v.v.u.g.w.g.h.i.f.q.dQtQt.f.#.fQt.fQtQt.d.i.d.i.d.g.d.f.g.f.f.gQtQt.gQt.iQt.iQtQt.f.iQtQtQt.dQt.f.f.g.h.p.u.v.v.v.h.h.h.w.p.p.u.A.y.y.w.g.f.f.i.#.c.c.c.#.cQt.#.c.#Qt.#.c.cQt.#.c.c.c.q.#.c.i.#QtQtQt.q.#.c.#.q.c.q.q.c.aQt.a.#.c.cQt.a.r.a.#.#.a.b.a.#.a.#.b.b.a.b.a.b.e.l.b.e.l.b.e.a.r.a.b.c.r.c.c.#Qt.qQtQtQtQtQtQt.q.f.q.f.i.s.f.i.iQtQt.#.c.#.c",
+".a.a.a.a.l.a.l.a.l.#.l.l.e.l.a.a.l.a.a.a.a.#.a.#.c.c.c.c.c.c.i.d.g.A.E.F.C.p.v.v.D.z.v.w.g.m.i.g.g.p.n.D.E.R.X.2.K.I.G.D.D.I.F.F.F.z.J.C.u.h.n.h.f.m.x.g.gQt.cQtQtQtQt.dQt.dQt.d.#Qt.#QtQt.g.f.f.f.f.g.f.f.f.fQtQt.i.f.i.s.f.xQt.f.f.f.f.g.x.g.x.u.u.o.y.v.v.v.h.u.h.p.w.u.u.v.u.o.g.f.g.f.d.a.cQt.c.#.c.c.#.c.c.#.c.#.c.c.#.c.#.cQt.#Qt.c.i.#.cQtQt.qQt.iQt.iQt.#.#.rQt.aQt.a.cQt.c.c.a.c.#.c.#.a.#.a.a.#.c.a.c.e.b.l.e.l.e.l.e.a.a.a.c.a.c.a.cQt.#QtQt.#Qt.i.i.iQtQtQtQt.i.x.i.g.x.i.fQtQt.c.a",
+".r.a.a.a.a.a.a.a.a.a.a.a.a.a.a.#.a.a.a.a.a.a.c.a.cQt.cQt.cQt.dQt.m.C.G.F.o.v.u.o.D.B.D.o.h.h.h.h.v.v.D.P.2.1.2.2.Q.T.D.A.B.C.F.J.D.G.C.v.u.h.g.x.s.x.s.g.dQtQt.cQt.d.i.d.q.dQt.fQt.i.d.i.f.f.f.s.f.xQt.i.i.f.iQt.s.i.s.f.s.i.f.i.f.i.g.g.g.g.m.g.p.n.n.y.v.u.u.p.h.h.h.h.h.p.p.h.A.u.g.f.f.#.c.c.#.c.#.c.#Qt.c.#.c.q.c.c.#Qt.#.c.#.i.c.i.#Qt.cQt.iQtQtQt.g.i.g.i.q.#Qt.c.c.c.#.cQt.aQtQtQt.cQt.c.#.c.#.a.c.cQt.c.l.l.l.e.e.l.e.e.a.a.b.#.r.a.r.c.#.i.#QtQtQtQtQtQtQt.f.q.f.f.i.i.i.iQtQt.#.c.a.a",
+".a.a.r.a.r.a.r.a.a.a.a.a.a.a.r.a.a.#.r.#.#.#.r.a.c.c.c.c.c.d.i.q.i.o.F.B.A.u.n.o.C.G.z.v.o.v.o.o.J.K.S.2#h#c.X.N.E.F.D.z.o.o.y.A.y.C.o.h.h.g.m.f.g.h.f.f.g.d.cQt.d.q.dQt.dQt.fQtQtQtQtQt.i.i.f.f.f.f.i.g.i.f.f.f.i.f.g.i.g.i.m.i.f.g.f.f.i.x.g.h.h.h.p.v.u.p.u.h.m.x.x.m.g.g.m.g.v.u.u.iQt.d.c.b.c.q.c.c.#.c.#.c.c.c.#.c.c.#.c.c.q.d.#Qt.c.i.#QtQt.g.i.g.i.s.i.gQt.iQt.iQt.iQt.f.cQt.c.aQt.aQt.cQt.a.c.#Qt.c.c.c.b.e.e.l.b.e.l.b.a.a.a.c.a.c.c.a.#Qt.#Qt.iQt.q.fQt.q.qQt.i.i.g.gQt.#.c.a.a.l.l.j",
+".r.l.a.l.a.a.a.a.r.a.r.a.l.a.a.a.r.r.c.r.#.r.#.a.c.c.c.cQt.dQt.g.g.o.E.F.o.o.u.o.D.F.I.B.o.B.I.K.G.K.E.M.S.M.F.B.D.C.v.u.w.u.v.u.A.u.u.h.g.m.f.f.h.g.h.g.q.dQt.r.q.d.fQtQt.dQt.dQtQt.i.fQt.f.g.f.q.f.f.f.fQt.iQt.x.i.i.f.i.f.f.i.f.g.f.i.f.g.x.g.p.p.p.u.p.u.p.h.x.x.f.x.m.g.f.g.o.u.v.gQt.#.cQt.#.c.c.#.c.#Qt.c.#.c.q.c.#.c.q.d.#.cQt.#.iQt.fQt.sQt.i.f.s.f.s.i.i.q.i.#.i.d.iQtQtQtQtQt.cQt.cQt.#.q.#.#.c.#.#.c.l.b.e.l.e.l.e.e.a.b.a.bQt.b.c.r.#Qt.#QtQtQtQtQt.#Qt.fQt.f.f.iQt.#.a.r.r.#.l.e.j",
+".e.e.a.a.a.l.a.l.e.e.e.j.l.e.a.aQt.aQt.c.cQtQt.#.iQtQt.g.f.i.x.g.s.u.G.F.B.z.D.z.M.Q.E.M.Q.F.I.z.A.y.o.v.u.p.h.w.g.m.g.w.g.h.p.n.p.w.g.m.g.f.m.f.g.fQt.d.q.c.cQt.cQt.a.b.a.b.#.b.c.c.cQt.cQtQtQtQt.#.q.#.c.#.c.c.i.#.d.i.dQtQt.iQtQtQt.i.cQt.#.cQt.qQtQt.i.i.g.g.s.i.i.f.f.f.g.f.g.u.z.p.g.f.f.e.dQt.d.fQt.d.dQt.#.d.#Qt.g.f.f.f.q.#.qQtQt.f.x.f.f.i.h.h.u.h.h.h.s.g.i.m.g.g.h.w.i.f.f.f.g.g.i.q.#.#Qt.#.#.c.c.c.a.r.a.a.a.a.e.l.#.a.a.a.a.r.l.r.a.a.qQtQt.f.f.i.i.qQt.i.g.g.gQt.c.r.a.a.e.a.e.e",
+".e.b.e.l.b.a.b.a.e.l.e.l.e.a.b.c.a.a.#.#.d.#.cQt.fQtQt.f.m.g.h.h.n.B.F.H.I.T.Q.Z#i.2.N.H.B.B.C.v.u.u.u.p.h.w.h.g.g.g.m.g.g.h.g.h.w.g.g.g.m.f.m.f.i.g.fQt.f.cQt.a.aQt.a.a.r.a.b.a.cQt.cQt.c.cQt.d.#.c.c.c.c.c.#.cQt.cQt.c.#.#.cQt.c.c.#.cQt.#.dQt.xQtQtQt.g.g.g.g.f.sQt.f.s.f.fQt.i.h.o.v.g.f.f.bQt.fQt.dQt.dQt.f.#.iQt.d.f.g.i.fQt.iQt.f.i.iQt.s.f.g.m.g.m.u.p.w.i.s.s.g.m.m.m.p.m.m.x.h.g.x.xQt.i.iQt.#.i.c.f.d.#.a.r.#.l.a.b.l.a.r.a.r.l.a.a.a.r.a.#QtQt.x.fQtQt.i.g.f.g.g.sQt.#.a.a.a.a.e.b.e",
+".e.l.e.a.b.l.b.l.e.e.b.a.b.a.a.r.c.c.c.qQt.dQtQt.qQt.s.g.h.h.p.p.B.P.2.U.X.N.L.L.S.H.J.C.C.C.y.o.p.h.h.m.g.f.x.f.g.f.f.x.m.x.m.p.p.w.p.m.h.m.f.i.g.fQt.f.cQt.aQt.c.a.r.a.b.a.r.a.c.c.c.cQt.c.c.c.c.#.c.q.c.#Qt.#.cQt.#Qt.fQt.cQt.qQt.d.#.f.#.c.cQtQt.xQtQt.i.x.i.iQtQt.i.f.f.f.fQt.i.h.A.h.g.dQt.dQt.d.i.d.i.dQt.d.#Qt.i.f.f.f.gQtQt.i.#.f.g.f.g.g.g.m.p.u.p.u.p.p.g.h.p.p.h.p.u.y.n.v.u.u.w.s.f.x.i.gQtQtQt.dQt.#.c.#.c.a.a.a.a.a.a.a.a.a.a.#.a.a.a.#.c.#Qt.f.fQt.q.f.m.h.g.f.f.#Qt.c.l.b.l.b.e",
+".e.e.b.a.b.a.a.b.l.e.a.a.a.c.c.c.c.qQtQt.d.f.g.f.fQt.f.f.h.v.o.z.L.2#h#c.L.T.H.I.z.C.y.u.u.h.p.h.g.m.h.g.x.x.f.g.fQt.g.f.f.h.x.m.v.u.w.p.w.h.m.x.g.x.dQtQt.c.a.b.#.b.a.b.#.b.a.b.c.c.c.c.c.c.c.c.c.q.c.c.#.c.c.#.c.cQt.#.c.#.c.c.c.c.c.#.c.c.#.cQtQtQt.i.f.f.f.gQt.iQt.gQt.fQt.gQt.i.g.z.y.w.f.dQt.fQt.dQt.dQt.fQt.i.dQt.f.g.f.f.i.f.d.g.x.x.p.m.u.v.v.z.v.o.y.A.y.n.u.y.y.C.z.z.I.z.z.C.A.v.p.g.m.g.g.s.fQt.i.d.#.q.#.#.c.#.b.a.a.#.a.aQt.a.c.a.a.a.#.c.c.fQt.f.iQt.i.h.g.h.iQt.#.#.c.a.c.a.e.b",
+".a.a.a.l.a.e.a.a.#.a.a.r.#.c.cQtQt.dQt.f.f.f.f.f.s.i.h.u.v.o.B.B.1.W.Q.F.D.z.C.y.A.u.v.p.u.h.h.h.g.x.x.h.x.g.q.f.q.g.f.f.x.x.w.n.v.v.v.h.w.g.h.gQt.f.i.d.cQt.b.a.b.#.b.a.b.e.b.b.c.cQt.c.c.cQt.c.c.c.#.c.c.#.c.c.#.c.c.c.#.c.c.#.c.c.#.c.c.c.c.#Qt.dQt.iQt.f.i.fQtQtQt.i.f.f.f.f.s.f.h.z.z.z.g.x.i.fQt.gQt.fQt.f.f.f.g.i.f.g.h.g.x.w.h.h.m.h.w.p.F.F.E.E.H.I.E.Q.I.F.I.H.I.Q.E.Q.N.S.F.K.B.C.o.p.h.u.g.g.g.g.f.f.i.f.#Qt.c.a.c.a.c.c.c.a.c.a.c.a.#.a.a.c.c.#Qt.f.q.i.g.x.h.g.f.f.#.c.#.a.c.b.b.a",
+".a.b.a.b.a.#.a.b.a.bQt.c.c.c.c.d.f.f.f.g.f.f.x.g.h.v.v.A.D.z.D.B.G.z.v.h.p.g.p.h.h.p.h.h.h.w.g.w.g.m.h.i.x.x.f.g.g.x.x.m.h.w.p.v.o.u.v.p.w.g.g.hQt.i.dQtQt.c.b.#.b.a.b.#.b.a.b.a.c.c.c.c.c.c.c.c.#.c.c.#.c.c.#.c.c.c.#.c.c.c.c.c.#.c.c.c.c.#.c.cQt.#.c.dQtQtQt.fQtQtQt.fQtQtQt.fQt.g.g.y.F.B.v.h.x.h.x.x.x.x.h.f.h.f.h.h.h.w.h.p.w.u.o.A.o.B.z.I.P.R.N.P.R.N.M.L.M.P.T.R.N.N.L.2.1.X.L.E.E.B.C.z.u.p.h.w.g.g.i.gQtQt.i.#.#Qt.a.r.#.b.c.b.a.r.a.c.l.a.l.a.#.d.i.d.s.x.m.u.w.h.h.gQtQt.c.c.c.a.e.b",
+".a.a.#.a.b.a.a.a.a.c.c.dQt.cQt.fQt.f.x.x.g.w.h.w.o.C.z.C.z.o.z.v.h.p.g.m.m.p.g.g.w.p.h.g.h.x.x.g.p.p.h.m.h.h.x.x.m.g.w.p.h.v.u.o.u.n.h.h.h.g.s.gQt.i.d.i.c.c.a.b.#.b.a.b.b.l.r.e.c.a.c.a.c.a.c.a.c.a.c.a.c.a.c.a.a.a.l.a.l.a.l.a.a.a.a.a.a.a.a.a.#.c.c.#.d.dQtQtQt.q.i.iQt.f.g.f.i.g.p.A.F.z.v.o.h.s.w.x.p.h.w.p.w.p.n.n.u.o.o.A.C.z.I.F.J.F.E.E.Q.H.H.H.E.Q.E.H.I.F.F.H.P.P.P.N.N.N.M.S.P.E.B.B.o.v.u.v.p.m.x.m.f.iQt.d.q.c.c.c.b.a.b.r.a.b.b.r.l.e.a.c.c.d.dQt.i.i.h.h.p.w.h.gQt.i.#Qt.c.c.c.b",
+".b.a.b.a.a.a.r.a.r.aQt.dQt.i.dQt.g.h.g.m.h.h.w.p.J.F.I.C.v.u.u.u.h.h.m.f.i.f.h.p.h.h.h.w.h.g.w.g.v.u.w.h.u.h.m.h.n.u.v.u.v.u.u.o.u.u.v.p.w.h.m.h.iQt.d.i.c.c.r.a.b.a.b.#.b.b.a.b.c.c.c.c.c.c.c.c.c.c.#.c.q.#.c.q.a.a.a.a.a.a.a.a.#.a.a.#.a.a.#.a.c.c.c.c.#Qt.fQtQtQtQt.fQt.fQt.fQt.i.v.y.F.C.A.v.n.n.n.p.h.n.p.n.v.o.v.A.z.z.I.B.F.H.H.Q.I.F.B.F.B.J.C.C.C.C.A.y.A.y.y.C.D.B.B.F.Q.P.T.R.S.S.H.B.C.z.v.u.w.h.g.m.q.g.iQt.#.c.c.c.a.b.b.a.b.b.a.b.l.e.#.a.cQt.d.dQt.m.h.w.u.h.h.gQtQtQt.c.c.c.r.c",
+".d.d.d.d.c.c.c.c.iQt.d.q.f.s.s.p.h.h.u.o.o.B.I.I.o.v.p.p.h.h.h.u.g.f.f.f.g.g.f.f.f.g.f.f.g.w.p.h.h.w.u.v.v.z.C.C.A.z.C.A.u.u.u.p.w.p.w.h.x.h.f.fQtQt.fQt.dQt.c.c.b.l.b.a.a.a.b.a.c.a.r.a.c.b.c.a.c.#.c.#.c.c.#.c.c.a.b.a.b.a.a.r.a.c.a.c.c.c.#.d.#.c.#.c.c.c.#.dQtQtQtQtQt.iQtQt.d.q.g.p.y.z.D.v.y.v.y.B.G.T.S.T.E.H.H.P.Q.P.P.P.T.H.F.G.B.D.o.o.p.n.p.w.p.w.h.u.h.h.n.w.h.v.n.u.z.z.F.E.H.E.E.Q.z.F.D.A.C.y.y.v.m.g.fQt.qQtQt.c.f.d.c.cQt.a.b.bQt.b.b.b.a.a.c.b.cQt.h.p.v.v.h.h.q.d.dQt.c.dQt.q",
+"QtQtQt.fQtQt.c.c.c.f.f.h.w.n.s.p.A.z.B.D.z.D.B.D.u.v.h.w.p.w.h.w.i.f.s.x.g.x.x.h.i.g.g.w.u.p.o.v.A.v.A.z.C.z.z.B.A.z.C.v.v.n.u.u.p.w.h.w.i.x.i.f.f.#.dQt.c.c.a.c.l.e.e.a.b.a.a.b.c.c.c.c.c.c.c.c.#.c.#.cQt.cQt.c.c.a.a.b.a.c.b.a.a.a.a.c.#.c.c.c.c.c.c.c.c.c.c.cQtQtQtQtQtQtQtQt.d.f.f.u.u.C.B.v.u.u.o.D.F.I.P.P.F.F.F.E.H.F.K.I.z.D.D.C.C.v.v.v.m.h.g.g.w.g.h.g.s.w.h.h.u.w.h.n.v.A.C.B.D.J.B.z.z.C.C.y.v.u.v.u.p.h.i.i.gQt.dQt.c.c.c.c.b.b.#.b.c.c.a.bQt.c.#.c.qQt.g.h.v.u.w.g.f.fQt.c.c.#.d.f",
+".d.x.d.d.f.q.f.q.f.g.g.g.v.v.z.F.E.K.I.D.A.v.v.v.m.h.h.u.h.g.g.g.h.g.x.f.g.g.g.h.h.w.u.h.v.v.o.o.B.F.z.B.D.z.D.C.v.v.u.v.p.v.s.h.w.h.g.x.x.g.i.gQtQt.i.cQt.c.r.b.e.l.e.a.a.b.a.a.b.a.b.a.b.a.b.a.c.c.c.c.c.#.c.c.a.b.c.a.b.a.b.c.a.#.a.a.c.c.#.c.#.c.#.c.#.c.c.r.c.c.c.c.c.c.c.c.d.cQt.g.p.A.z.C.h.h.u.o.o.B.G.I.D.B.B.B.D.D.C.z.v.o.u.u.w.h.h.h.g.g.m.g.i.g.f.m.g.g.x.w.x.w.h.w.u.p.v.u.u.v.u.u.u.p.w.h.u.h.u.w.p.u.g.w.i.i.f.f.q.c.#Qt.c.a.b.a.f.c.c.c.d.cQt.d.c.i.f.g.w.u.p.p.gQtQt.c.iQt.i.f",
+".d.d.g.q.f.h.x.h.p.o.A.C.E.Z.X.2.S.I.I.o.v.v.o.v.h.h.v.u.v.u.u.h.h.g.h.w.h.n.p.p.v.u.u.v.z.D.B.z.Q.E.H.E.z.B.C.z.v.p.w.h.h.m.x.h.g.g.h.x.g.f.f.fQtQtQt.c.c.b.l.b.l.e.e.a.a.b.c.b.c.a.b.a.b.a.r.a.a.a.a.a.a.a.a.l.a.b.a.b.e.b.a.l.a.a.a.a.a.c.a.c.c.#.c.c.c.r.c.c.c.c.c.#.c.#.c.#.f.dQt.f.g.v.z.o.h.h.h.u.v.v.v.v.z.C.C.C.o.v.o.v.p.p.u.h.h.i.x.i.h.g.x.x.x.h.g.x.x.x.h.g.x.g.x.g.w.h.h.g.g.i.s.i.h.g.x.g.h.x.s.f.p.h.p.p.g.h.g.gQtQt.c.c.cQt.cQtQtQt.f.dQt.i.d.iQtQt.g.g.h.h.v.h.x.f.fQt.i.f.f.x",
+".x.h.x.s.s.p.p.p.D.K.S.V.8#p#i.1.T.B.I.D.o.o.v.o.o.y.o.v.o.v.v.A.h.w.u.h.v.v.v.v.o.v.A.o.C.B.B.F.Q.S.Q.E.F.B.D.B.o.v.h.n.m.s.h.x.x.h.g.f.f.f.gQt.i.#.cQt.a.a.e.e.b.l.e.#.a.a.b.a.b.a.c.b.c.a.b.a.a.a.l.b.l.a.b.a.b.l.e.e.l.e.a.b.l.l.a.#.a.a.#.c.a.#.a.a.a.a.a.l.a.#.a.a.b.a.a.a.d.c.d.q.f.v.C.z.h.v.h.n.h.n.v.p.v.o.v.w.u.u.h.h.w.g.g.i.m.f.f.f.f.g.fQt.fQt.fQt.g.f.f.f.g.f.g.f.g.i.g.f.i.#.d.#.d.i.dQt.dQt.fQt.m.g.w.h.u.p.p.p.i.iQtQt.#.#Qt.#.d.i.#Qt.dQtQtQt.iQt.f.g.g.u.v.v.h.m.x.f.g.h.g.h",
+".w.u.v.v.v.o.A.A.J.R.W#c.8#h.L.T.D.D.D.C.z.u.u.u.o.o.o.o.o.o.o.o.h.p.w.p.h.h.p.u.h.v.u.v.o.o.A.C.F.I.D.F.F.I.I.I.v.o.w.p.w.h.m.h.h.g.f.f.i.fQtQt.c.q.c.a.a.r.e.e.e.e.l.b.a.b.c.a.b.a.e.e.e.e.b.e.e.e.e.e.e.e.e.j.e.j.e.e.e.e.e.e.l.b.l.l.a.a.a.l.a.a.a.a.a.l.a.a.a.b.a.b.a.a.b.a.d.c.c.cQt.h.A.C.u.p.u.h.h.h.h.w.u.h.h.p.h.h.w.g.g.i.m.f.f.fQt.gQtQtQtQtQtQtQtQt.fQt.gQtQtQtQtQt.f.fQt.c.c.c.b.#.c.c.c.q.c.d.fQt.f.g.g.h.h.h.u.h.i.i.sQt.f.fQt.fQt.f.dQt.i.f.g.f.f.g.f.g.g.u.o.C.p.v.h.m.g.h.o.p",
+".D.B.D.B.D.B.J.B.F.Q.E.F.E.B.C.C.o.u.y.v.p.w.h.p.p.p.h.p.h.p.h.p.m.h.g.h.h.w.p.h.m.g.g.w.u.u.v.u.v.u.o.A.C.z.B.B.v.o.A.o.p.w.p.w.g.g.fQt.f.gQt.i.c.#.aQt.e.e.e.a.e.l.e.a.e.a.b.a.e.e.b.l.b.l.e.l.e.e.e.e.e.e.e.e.l.e.l.j.l.e.t.e.l.l.l.l.a.l.a.a.e.l.e.l.e.e.l.e.e.e.e.e.e.e.e.e.f.cQt.b.c.m.v.B.v.o.p.p.h.h.g.g.h.w.h.m.h.m.g.f.i.f.f.f.f.i.qQt.d.d.d.f.d.d.f.d.#.d.#.dQt.dQt.d.#.c.cQt.b.b.c.b.a.#.r.c.#.c.#Qt.f.f.f.i.i.h.g.h.h.h.g.p.m.g.f.f.i.g.f.f.f.i.i.f.x.g.g.m.h.o.D.I.D.o.u.u.o.v.A.D",
+".P.P.E.J.z.C.C.C.v.A.v.u.p.w.p.n.u.u.h.h.g.h.h.w.i.s.i.s.g.g.i.s.g.g.g.m.g.h.h.w.f.f.m.g.w.h.w.p.p.h.n.n.o.A.z.B.A.z.z.B.A.o.v.n.h.m.i.f.g.f.iQt.#Qt.a.a.e.a.b.b.l.b.e.a.e.b.c.a.b.e.l.e.e.e.e.b.j.k.j.j.j.j.j.j.e.j.e.e.j.e.e.e.j.l.e.l.#.a.a.a.l.e.l.e.a.l.b.l.e.e.e.e.e.b.e.e.c.c.bQt.c.x.z.z.z.A.o.v.h.g.w.g.h.g.h.g.i.i.fQt.m.i.i.f.fQtQt.d.i.dQt.dQt.dQt.dQt.cQt.q.c.#.q.c.c.a.b.a.c.r.#.b.l.a.#.a.#.cQt.d.g.q.h.f.m.x.g.h.h.p.p.g.h.g.h.g.f.i.f.s.f.s.x.s.h.m.h.g.w.o.I.G.I.D.A.D.A.D.I.K",
+".K.G.v.u.p.m.g.g.i.i.g.m.g.h.p.h.s.h.i.i.f.g.x.f.f.dQt.dQt.d.d.d.cQt.dQt.d.iQt.d.q.f.d.f.x.h.h.s.s.m.m.p.u.v.v.o.u.o.o.B.I.B.C.A.v.p.w.h.g.qQt.i.c.c.b.#.e.b.e.e.e.e.j.e.j.e.j.k.e.l.e.e.e.e.j.e.j.e.e.j.e.j.e.e.j.l.e.t.e.l.e.l.b.l.e.j.e.j.e.j.e.e.e.l.e.j.e.e.e.e.j.e.e.l.e.e.j.e.a.c.f.f.w.v.E.z.v.h.g.f.f.x.m.x.g.m.x.f.g.iQtQt.iQtQtQtQtQt.d.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.b.r.b.b.b.l.b.b.b.e.e.b.r.d.d.dQt.d.d.d.dQt.dQt.#.gQt.i.g.w.u.v.h.w.h.h.h.u.u.p.p.v.v.v.C.B.Q.R.I.K.I.I.I.C.D.B",
+".E.D.z.p.g.g.f.m.i.g.i.g.g.g.h.h.h.g.i.i.f.f.g.x.dQt.d.i.dQt.c.c.c.cQt.c.c.cQtQt.c.cQt.fQt.f.h.x.i.s.g.m.w.h.v.u.w.p.o.B.z.A.o.v.v.v.p.u.g.s.f.q.c.c.#.b.b.e.j.e.e.j.e.k.e.k.e.j.e.e.e.l.j.j.e.j.e.e.j.e.j.e.j.e.l.j.e.e.j.e.j.e.l.e.e.l.e.l.e.e.e.l.e.e.j.e.j.e.j.l.e.l.j.e.t.e.e.e.a.cQt.f.g.o.Q.J.v.p.g.i.f.x.f.f.f.f.f.i.f.f.gQtQtQtQtQt.iQt.c.c.c.c.c.c.c.c.c.a.c.c.c.r.c.a.a.e.a.l.r.b.a.e.l.e.l.b.a.c.d.d.fQt.d.#.cQt.c.dQtQtQt.f.g.p.p.u.u.v.u.u.y.v.A.y.o.C.A.z.D.E.K.R.I.B.G.B.D.A.o.o",
+".G.B.o.p.g.f.f.g.i.i.f.f.i.g.i.f.q.iQt.f.g.f.f.qQt.i.d.c.c.b.b.b.a.c.c.a.c.a.c.c.a.a.c.c.d.d.f.f.g.f.g.g.w.n.h.n.m.g.u.o.o.v.p.w.u.v.u.h.g.g.s.iQt.c.c.a.r.e.e.b.j.j.k.j.j.b.j.k.l.j.e.j.e.j.e.j.e.l.e.j.e.e.l.e.j.e.l.e.l.e.l.e.e.l.e.e.l.e.j.l.j.e.j.l.e.j.e.t.e.j.j.e.e.e.e.e.j.e.aQt.d.f.g.u.E.D.v.u.h.h.x.f.i.f.i.f.f.f.f.iQtQtQt.iQtQtQtQt.c.a.c.a.c.a.c.a.b.c.b.a.b.a.a.b.b.b.b.b.a.e.b.#.e.e.b.a.a.c.fQt.c.d.c.c.c.c.fQt.cQtQt.g.g.h.p.u.y.A.y.z.z.B.z.J.z.B.B.F.F.T.P.K.B.D.z.o.v.o.v.B",
+".F.z.v.w.i.f.f.f.f.f.g.i.fQt.fQtQtQtQtQt.dQt.dQt.c.c.c.c.c.b.a.bQt.a.a.r.a.b.c.r.a.r.#.c.c.dQt.d.qQtQt.g.g.w.w.h.g.m.g.w.p.w.x.m.u.p.p.w.g.m.f.gQtQtQt.b.a.e.j.e.j.j.j.e.k.e.k.j.e.l.e.e.j.e.j.e.j.e.j.e.j.e.j.e.l.j.e.l.e.e.e.t.b.e.e.j.b.l.e.e.j.e.e.j.e.j.e.j.e.j.e.j.j.j.l.j.e.j.e.c.#Qt.g.h.F.B.z.u.h.g.f.x.fQt.fQt.f.s.f.fQtQtQtQtQtQtQt.c.c.c.c.r.c.c.r.c.a.a.a.b.a.a.r.a.b.l.a.b.a.b.l.b.e.l.a.a.c.c.c.c.c.c.c.c.c.c.c.dQt.g.f.i.w.h.h.p.v.y.v.C.C.C.C.B.C.D.F.K.T.T.S.K.B.z.o.v.o.B.C.B",
+".D.o.p.g.f.f.fQtQt.#QtQtQtQtQtQtQtQtQt.#Qt.d.d.f.#.c.c.a.c.b.a.e.c.bQt.a.b.a.b.c.a.a.c.a.aQt.c.d.i.c.i.f.m.g.x.f.s.f.m.w.m.g.g.i.g.g.w.g.m.g.g.sQt.q.c.c.a.b.e.b.j.j.k.j.j.k.j.k.e.j.e.j.e.j.e.j.e.j.e.j.e.l.e.e.l.e.l.b.e.l.e.e.l.j.l.e.e.j.e.l.j.e.l.e.j.e.j.e.j.e.j.e.e.j.e.e.j.e.b.c.#.dQt.s.C.A.z.u.h.x.x.fQtQtQtQtQtQt.f.f.iQtQtQtQtQt.c.#.c.r.a.a.b.a.a.b.c.b.c.a.r.a.b.a.a.#.b.a.a.a.#.a.a.a.a.#.a.a.a.c.c.c.c.c.b.c.c.cQt.f.f.f.i.g.m.h.u.v.v.y.v.y.z.C.C.z.G.E.P.S.I.E.F.D.z.C.B.B.B.D",
+".o.u.h.g.i.iQtQtQt.dQt.c.cQt.c.q.c.#Qt.c.cQt.c.c.c.#.c.#.c.l.r.b.a.a.b.a.a.a.a.a.b.a.b.a.b.a.a.a.c.#.c.d.f.g.g.h.x.g.x.w.h.s.f.i.g.g.g.f.f.g.f.gQtQt.c.#.r.a.a.e.e.j.j.j.j.j.e.j.e.l.e.l.e.j.e.j.l.e.e.j.e.j.l.j.e.l.e.e.l.b.e.l.e.e.e.j.e.l.e.j.e.e.j.e.j.e.j.e.e.j.e.j.e.e.j.e.e.e.l.aQt.#Qt.f.p.y.A.u.h.i.fQtQtQtQtQtQtQtQtQtQtQtQt.iQtQt.c.#.b.a.r.a.b.a.r.a.e.e.e.a.b.a.a.b.a.b.a.a.b.a.b.a.a.a.a.a.a.a.a.a.c.c.a.c.c.a.c.a.d.dQtQt.f.f.fQt.g.h.g.h.p.u.p.v.o.C.D.T.T.E.F.D.J.I.D.B.C.D.B.C",
+".p.g.fQtQtQtQt.f.cQt.c.c.q.c.a.a.c.c.c.c.c.a.c.r.c.a.c.b.a.b.e.e.a.a.a.b.e.e.b.a.#.a.a.b.l.e.e.e.e.a.bQt.d.g.f.f.x.x.m.g.h.h.f.iQt.iQt.iQt.dQtQtQt.iQtQt.#.b.c.b.e.e.j.k.j.k.j.k.e.j.e.j.e.l.e.e.e.j.l.e.e.e.e.l.e.b.l.e.l.e.l.e.b.l.l.e.l.e.e.j.e.l.e.l.j.e.j.e.j.e.e.e.t.e.l.e.j.e.e.a.a.c.qQt.x.v.u.u.h.f.dQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.c.#.a.b.e.e.b.e.e.e.b.l.e.a.e.a.e.a.l.l.l.l.a.a.a.a.a.#.a.a.a.#.r.a.#.b.a.b.a.b.a.b.c.c.cQt.c.#Qt.#Qt.f.f.m.g.m.g.h.v.C.B.K.E.G.B.z.D.J.F.C.C.C.C.v",
+".g.g.gQt.#QtQt.fQtQt.c.#.c.a.a.l.b.b.c.a.a.a.a.a.a.a.#.c.a.b.e.e.e.a.b.l.e.e.l.a.b.a.e.e.b.l.j.b.e.b.#.c.d.f.x.g.f.h.s.n.w.g.g.d.i.#Qt.#.cQtQtQt.iQtQt.#.c.c.a.a.e.e.j.j.e.k.e.j.e.l.e.l.e.j.e.t.e.l.e.e.l.l.e.l.e.l.e.e.l.e.e.l.l.e.e.l.e.l.e.l.j.e.j.e.e.j.e.l.e.e.t.e.e.e.e.e.e.e.e.#.a.a.#.#.i.g.u.g.fQtQt.a.#Qt.#Qt.#Qt.#QtQt.iQtQtQtQt.#.c.a.a.a.a.a.a.a.a.e.e.e.b.a.b.a.a.e.a.a.a.a.l.#.l.a.r.a.r.a.r.a.a.c.a.c.b.c.a.r.a.a.b.a.a.a.c.c.#.cQtQtQt.f.x.i.h.u.A.D.E.J.C.v.v.C.B.D.C.z.v.y.v",
+".iQtQt.iQtQt.q.d.c.c.c.c.c.c.c.a.a.c.#.r.a.b.a.b.a.b.b.a.e.a.a.a.b.a.e.e.b.l.b.a.e.l.e.l.a.b.a.a.e.b.e.a.a.cQt.s.g.s.m.g.g.f.g.g.dQt.c.cQt.a.c.c.a.cQt.c.c.i.cQt.b.l.e.e.e.l.e.e.j.j.j.e.j.e.j.e.e.j.j.j.j.j.b.e.b.l.e.b.l.e.b.l.b.a.b.l.b.l.e.e.l.l.l.l.j.e.e.e.j.e.e.e.t.e.t.e.e.j.e.e.l.a.#.aQt.i.p.p.h.x.d.#.a.r.c.c.r.c.d.dQtQt.c.iQt.cQt.c.c.b.a.b.a.b.a.a.e.l.e.l.e.l.e.e.l.l.l.e.a.c.c.c.e.e.l.b.l.e.l.e.e.e.e.e.e.b.b.b.a.a.b.a.c.c.c.cQtQt.d.f.g.g.x.g.u.o.u.o.v.p.w.p.w.u.z.C.o.v.p.h",
+".s.f.qQtQtQt.#.c.c.c.cQt.c.c.a.c.c.b.c.a.b.a.r.a.b.a.l.b.a.a.b.a.l.b.a.l.e.e.e.a.j.l.b.e.e.a.b.a.b.e.e.a.#.#QtQt.g.g.m.h.f.g.d.f.cQt.c.#.c.c.cQt.a.a.a.c.#.c.c.d.a.a.a.a.a.e.a.e.e.l.e.l.e.l.e.l.e.b.e.b.b.e.e.b.l.b.l.l.e.l.e.l.e.l.e.e.l.e.e.l.l.l.l.e.l.j.e.e.e.e.j.l.e.e.e.e.j.j.l.e.e.a.r.a.q.i.g.n.g.x.d.r.c.a.a.c.a.c.cQt.cQt.#.d.#.i.c.#.c.b.a.a.b.a.a.r.l.e.b.l.e.e.l.e.l.l.l.a.a.c.a.c.e.l.e.l.e.e.e.l.b.e.e.b.e.b.l.b.e.a.a.b.c.c.c.c.c.dQt.f.f.x.x.w.u.u.v.v.h.h.h.h.m.u.o.o.o.o.p.h",
+".i.i.iQtQtQt.c.#.#.c.c.c.a.r.a.r.#.c.b.a.c.b.a.a.a.b.a.a.e.a.a.a.e.e.e.e.e.l.e.e.j.j.j.l.e.a.a.a.e.e.l.b.a.c.gQt.s.i.m.fQt.d.fQt.f.c.c.#.c.#.c.b.a.a.c.a.c.c.c.c.a.r.a.c.a.c.a.c.a.a.a.a.a.a.a.a.e.l.e.e.l.l.b.l.e.a.e.b.l.e.b.l.b.e.l.e.e.b.l.e.b.l.l.t.e.e.e.e.l.e.l.e.j.j.e.j.e.j.e.j.l.r.a.#Qt.f.m.h.h.f.d.rQt.b.c.c.c.c.r.c.c.#.c.#.d.#.c.#.a.a.a.a.a.a.a.a.l.l.l.l.b.l.l.b.l.l.#.a.a.a.c.c.e.b.l.e.e.l.j.e.e.l.e.e.e.a.b.a.a.b.a.a.c.a.c.c.c.qQt.f.f.x.m.g.u.v.u.h.u.m.g.g.i.m.p.v.u.v.h.g",
+".gQtQtQt.iQt.i.c.c.cQt.cQt.aQt.a.b.a.a.a.b.a.e.b.e.a.l.b.a.a.r.a.l.b.e.l.e.e.j.e.j.j.j.e.j.e.a.e.e.e.b.a.a.#QtQt.g.s.f.i.d.i.c.c.aQt.aQt.a.b.a.b.b.l.r.a.a.b.a.c.c.c.c.c.r.c.c.c.a.c.c.cQt.#.cQt.a.a.a.a.a.c.a.c.l.b.l.l.r.l.b.l.b.l.e.b.l.l.e.l.l.l.b.l.e.l.e.e.e.l.e.e.e.l.j.e.j.j.l.e.e.a.a.a.i.f.h.w.g.f.d.r.a.c.c.b.c.c.c.c.#.cQt.c.#QtQt.d.a.a.a.a.a.b.a.a.e.a.l.a.l.a.l.r.l.a.r.a.a.a.b.a.e.l.e.l.e.e.e.e.l.e.e.l.b.a.c.b.a.b.a.b.c.c.r.c.#.dQt.f.g.x.g.s.u.u.h.w.h.i.x.i.s.f.i.g.m.h.g.g",
+"QtQt.gQt.#.d.d.cQt.c.c.c.c.c.c.a.a.a.b.a.a.a.a.e.l.e.e.l.e.e.l.e.e.l.j.j.j.j.j.j.j.j.j.j.j.e.e.l.j.e.e.a.a.cQt.s.i.g.fQt.i.cQt.f.a.r.#.c.a.r.a.b.e.b.e.e.b.a.b.e.c.a.c.a.c.a.c.a.c.#.c.#.c.c.#.c.#Qt.c.#.aQt.c.q.a.a.#.e.l.e.b.l.e.l.e.l.e.e.l.b.l.l.l.l.e.l.e.e.e.j.e.t.e.e.e.l.j.j.e.e.l.a.#.a.c.i.g.u.g.f.dQt.c.a.c.c.c.c.c.c.d.#.cQtQtQt.iQt.a.#.a.e.a.l.a.l.a.a.a.a.a.a.a.a.a.r.a.a.a.a.a.a.e.e.l.b.e.t.e.j.l.l.j.l.e.a.a.a.l.a.b.a.c.c.c.c.cQt.d.f.f.g.g.w.u.u.h.g.g.g.m.gQtQt.xQt.i.i.m.f",
+"QtQt.#.#.c.c.a.b.a.a.a.a.#.a.a.b.b.l.b.e.e.e.j.e.e.e.e.e.l.b.e.l.j.j.e.e.e.j.e.j.j.j.j.e.j.l.e.e.e.e.e.e.a.qQtQt.g.i.qQt.c.f.cQt.b.#.a.r.a.b.b.e.j.b.e.e.b.e.e.b.b.a.b.b.a.b.a.b.q.c.#.q.#.#Qt.#.f.#.c.#.c.c.#.c.l.r.a.l.r.l.a.l.e.l.b.e.e.l.e.l.l.l.l.l.l.e.b.e.e.l.e.e.j.l.j.e.j.e.t.e.e.b.c.a.cQt.m.h.g.g.#.a.c.r.c.c.a.c.c.d.qQt.c.#.iQtQtQt.r.a.a.a.r.a.a.a.l.a.l.a.r.#.a.a.q.#.a.a.a.e.a.b.l.b.e.l.e.e.l.e.l.e.l.b.l.a.l.a.a.b.a.c.b.c.c.c.c.#.i.f.f.h.h.h.v.p.v.g.m.x.i.x.s.qQtQt.x.f.i.g",
+"QtQt.c.c.cQt.b.b.a.b.a.b.a.a.b.a.e.l.e.l.e.l.e.l.j.j.j.j.e.j.j.b.j.j.t.j.j.j.j.j.k.k.j.j.j.j.j.e.j.e.e.a.a.cQt.g.qQt.i.c.q.cQt.c.#.b.a.#.e.b.l.e.j.j.j.e.j.e.e.e.a.a.b.a.a.b.a.a.a.r.a.a.a.#.r.#QtQt.gQt.gQt.i.f.#.a.l.e.l.e.b.e.l.e.a.l.b.l.e.e.l.l.l.b.e.l.e.e.l.j.e.t.e.e.e.e.j.j.e.e.l.#.a.#.c.d.i.m.w.i.cQt.c.#.c.c.c.d.dQt.cQt.c.#.dQtQt.i.c.r.a.r.#.r.a.r.a.a.#.r.a.r.a.r.a.c.r.a.l.l.b.l.e.l.e.e.l.e.e.b.t.l.t.l.l.a.a.a.b.a.b.a.c.c.c.c.dQt.d.f.g.h.g.w.p.h.g.g.g.i.g.i.g.f.x.iQt.s.h.h",
+".qQtQt.c.c.b.e.a.e.b.#.a.a.b.a.a.e.e.e.e.j.e.j.e.j.j.j.b.j.e.j.l.j.b.j.e.j.j.j.j.k.k.j.j.j.j.j.j.j.e.e.a.a.#QtQtQt.qQt.q.d.c.#.c.#.a.#.b.e.r.e.e.e.j.j.j.k.e.e.e.e.b.l.e.b.l.e.e.a.a.r.a.r.#.a.#Qt.iQtQtQt.qQtQt.#.a.#.a.b.b.l.#.e.l.b.e.l.e.b.l.l.b.l.l.l.e.e.e.e.l.e.e.j.l.j.l.e.e.j.l.e.b.a.a.b.i.f.m.g.gQt.a.c.c.c.c.c.dQt.fQt.c.#.cQtQtQtQt.#.a.r.a.a.r.#.a.l.r.r.a.a.a.r.a.c.#.c.a.#.a.e.e.l.e.e.l.b.l.e.l.l.l.l.l.l.l.a.a.l.a.a.r.a.r.c.c.c.cQt.f.h.g.p.p.p.h.m.g.s.g.f.f.g.iQt.i.q.x.p.h",
+".h.h.f.#.a.a.a.a.a.a.b.a.b.l.j.e.l.e.l.e.j.e.j.e.j.j.j.j.j.j.j.j.e.l.e.l.e.j.e.t.j.j.j.j.0.j.e.j.k.l.a.#Qt.iQtQt.i.i.gQt.i.i.c.c.a.r.a.e.l.l.e.e.e.e.j.j.j.j.j.j.j.j.e.j.l.e.e.l.b.l.e.#.a.r.a.c.r.r.#.q.f.g.g.i.g.dQt.c.c.a.a.b.l.r.l.a.b.a.e.l.a.a.a.a.e.l.a.l.b.l.l.l.l.e.l.l.j.e.j.l.b.l.e.#.j.aQt.x.u.h.f.q.a.#.e.b.l.a.d.d.r.a.#.d.qQtQtQt.r.r.a.r.a.r.a.r.r.a.r.#.r.r.#.r.a.r.a.a.r.l.r.a.a.#.r.l.l.l.l.l.l.l.a.l.a.l.a.a.#.a.a.a.a.a.c.c.#.rQtQt.g.h.p.h.p.g.g.g.x.g.g.f.i.fQt.f.f.m.g.m",
+".h.g.f.#.a.#.a.a.r.a.c.a.a.b.l.e.j.b.e.l.j.e.j.e.j.j.e.j.e.j.e.j.l.e.l.j.e.l.e.e.j.j.j.0.j.j.j.j.j.e.a.#QtQtQt.iQtQt.f.iQt.dQt.c.b.a.e.l.b.l.e.l.e.e.e.j.e.j.e.j.e.j.e.j.e.e.e.e.e.e.l.b.a.c.#.c.a.#.#.#QtQt.f.m.f.gQt.f.cQt.a.#.a.a.a.a.a.a.a.a.a.l.a.l.a.a.e.a.l.l.b.e.l.l.e.l.j.e.j.e.l.l.b.e.j.#.i.x.h.m.fQt.c.c.e.a.aQt.#.d.a.q.c.#QtQtQt.f.#.a.r.r.a.r.a.r.a.r.a.r.r.a.r.r.r.a.#.r.a.a.a.l.r.l.a.l.a.a.l.a.e.a.l.b.l.a.l.l.a.l.a.a.#.a.c.#.r.r.#.i.s.p.u.p.g.w.g.g.s.g.f.iQtQtQt.s.f.i.f.g",
+".h.mQtQt.i.c.#Qt.a.c.b.a.b.l.e.e.l.l.e.e.j.e.j.e.j.j.j.j.j.j.j.j.e.e.e.l.b.j.e.t.j.j.j.e.j.j.j.j.k.a.c.qQtQt.sQt.f.i.g.#.d.i.c.c.l.l.b.a.e.e.l.e.j.e.j.j.j.j.j.j.j.e.l.j.e.l.e.l.e.l.e.a.a.b.c.a.a.aQt.#.iQt.f.f.gQt.dQt.c.c.c.cQt.#Qt.cQt.a.a.#.a.#.a.a.#.l.a.l.l.l.l.l.l.l.b.l.j.e.t.e.e.b.a.c.b.cQt.x.g.w.gQt.c.q.a.#.a.c.cQt.#.#.#QtQtQtQtQt.#.r.a.r.a.r.a.r.a.r.q.a.#.r.c.r.a.a.r.a.r.a.r.a.r.a.r.a.r.l.r.a.l.a.l.a.l.a.l.a.a.a.a.a.a.a.c.a.#.a.iQt.g.g.h.g.p.g.g.g.f.s.f.f.i.f.i.f.i.g.f.g",
+".p.p.mQtQt.#.c.#.r.a.c.#.a.e.b.l.e.e.e.l.j.e.j.e.j.j.e.j.e.j.e.j.l.l.b.e.e.l.e.e.j.e.j.j.j.j.e.j.e.a.#Qt.i.i.q.gQt.s.fQt.i.d.cQt.e.r.l.e.l.b.e.e.e.j.e.j.e.j.e.j.l.j.j.j.e.e.e.e.l.b.l.b.#.c.a.#.l.a.a.a.cQt.g.f.dQtQtQtQt.cQt.cQtQtQt.#Qt.cQt.c.#.a.a.a.a.a.a.a.#.a.a.#.a.a.a.a.e.j.b.e.l.a.a.a.l.q.i.g.m.g.g.i.dQt.#.c.q.cQt.dQtQtQt.iQtQt.iQt.#.#.a.r.a.r.a.r.#.#.a.r.r.a.r.#.a.r.a.#.r.l.a.l.#.l.r.b.l.l.l.l.a.a.a.l.a.l.b.l.l.#.l.a.a.l.c.c.#.#QtQt.f.m.g.x.g.w.i.m.i.f.iQtQt.qQtQtQt.f.i.f",
+".g.i.i.iQtQt.#.c.#.cQt.a.a.e.l.e.e.t.e.e.e.j.e.l.j.j.j.j.j.j.j.j.e.e.l.l.e.e.j.e.e.j.e.e.e.j.e.e.l.#.#Qt.x.i.s.f.s.i.g.#.dQt.a.b.a.l.b.a.e.l.l.e.j.j.b.j.j.j.j.j.j.j.j.j.l.e.l.e.e.e.e.a.a.b.c.a.e.b.a.c.c.dQtQtQt.c.c.cQt.dQt.fQt.fQt.d.#Qt.cQtQt.#Qt.#.a.c.a.c.a.a.#.a.a.l.a.b.l.l.e.l.a.a.cQt.a.#Qt.s.g.w.p.m.fQt.i.c.c.#Qt.gQt.iQtQtQtQtQtQt.#.r.#.a.r.a.r.a.#.q.r.c.r.q.r.r.a.r.a.r.a.a.r.a.r.r.a.r.r.l.l.l.#.l.a.a.e.a.l.l.a.l.a.a.l.a.c.a.#.dQt.i.i.f.f.f.s.i.g.f.iQt.fQt.iQt.i.f.iQt.f.s",
+".s.i.s.h.sQtQt.#.c.a.r.a.a.e.e.l.e.e.l.e.l.e.j.e.j.j.e.j.e.j.e.j.l.e.e.e.e.l.e.j.l.e.e.j.e.e.j.e.l.a.#.q.g.p.g.i.s.f.iQt.q.dQt.b.#.a.e.l.b.e.e.l.j.j.j.j.e.j.e.j.j.j.j.j.e.e.e.e.l.e.l.b.a.c.b.c.l.l.e.#.a.c.i.d.#.c.cQt.c.i.cQtQtQtQt.iQtQt.i.#.a.#.a.#.a.#.c.q.a.a.a.c.aQt.a.r.e.l.e.a.b.#.c.c.cQt.i.g.g.w.p.h.m.gQtQtQt.cQt.fQtQtQtQtQt.#.c.#.r.r.a.r.a.r.a.r.r.#.r.r.a.r.a.#.r.#.a.a.r.a.r.a.l.r.l.a.l.#.a.l.a.a.b.a.a.l.a.e.l.b.l.a.b.l.#.c.c.cQtQtQt.fQt.f.g.i.i.s.q.iQt.xQtQt.#Qt.q.gQtQt",
+".q.i.p.g.g.fQt.#Qt.cQt.a.r.l.e.e.j.e.b.e.j.j.e.e.j.j.j.j.j.j.j.j.e.j.l.j.l.j.e.l.b.l.e.a.a.e.l.a.a.a.q.q.g.h.s.iQtQtQt.c.c.c.c.b.l.b.l.r.l.l.e.e.j.e.j.e.j.j.j.j.j.j.e.j.e.t.b.e.l.b.e.a.a.#.c.a.e.b.b.a.b.c.d.d.a.#.c.cQt.dQt.f.#.q.#.#.c.#.c.#.c.c.#Qt.c.#.c.#.a.c.a.#.#.a.a.c.b.l.#.a.c.c.cQt.#.iQt.f.s.p.p.v.p.g.mQtQt.iQt.f.fQtQtQt.f.#.#.#.a.r.a.r.a.r.a.r.#.#.a.q.r.c.#.#.#.r.r.#.a.r.#.r.#.a.r.a.r.a.l.r.a.l.a.a.l.e.l.e.l.l.a.l.a.a.c.a.#.c.q.dQt.d.i.f.s.i.iQtQtQt.fQt.#.q.#QtQtQtQt.g",
+".d.i.h.w.g.iQt.#.r.a.c.a.a.e.b.l.e.l.e.l.e.e.t.e.j.j.e.j.e.j.e.j.l.e.e.e.e.l.b.e.a.e.e.a.a.e.e.l.a.#.i.q.s.g.i.i.gQt.i.cQt.c.aQt.e.a.e.l.e.e.e.e.j.j.j.e.e.e.j.e.j.j.j.j.e.e.l.e.e.l.e.l.b.c.bQt.e.e.e.a.b.c.f.q.#.c.a.c.i.cQt.d.r.#.q.c.r.#.r.aQt.#.c.c.c.#.c.c.#.a.c.#.#.c.a.a.l.e.a.b.aQt.cQtQt.f.xQt.i.w.h.u.u.w.g.g.iQtQt.q.f.fQtQt.#.c.a.r.a.r.a.r.a.r.#.a.q.r.a.r.a.r.q.#.r.a.a.a.r.a.a.r.a.r.l.#.l.r.l.l.a.a.a.l.a.l.b.l.a.e.e.a.a.l.c.c.c.cQt.c.cQt.dQt.i.i.s.f.xQtQt.i.rQt.c.qQt.gQtQt",
+".#.i.f.g.h.i.fQt.i.#.#.c.r.a.l.l.j.j.j.j.j.j.e.j.e.e.j.e.j.e.j.e.j.j.j.l.j.e.a.a.a.a.a.c.c.c.c.c.r.#.rQt.q.i.g.f.r.a.a.a.a.b.b.a.l.b.l.#.e.l.e.e.e.e.e.j.j.j.k.j.j.j.j.e.e.e.e.b.l.e.l.b.a.a.a.c.a.aQt.a.c.c.c.d.a.a.aQt.#.c.q.a.#.c.#.#.c.#.#.#.a.a.a.l.a.a.a.a.a.a.l.a.a.a.a.#.l.a.a.#.a.a.c.#Qt.qQt.i.g.g.p.w.u.p.u.h.g.mQt.c.q.#.q.#.c.#.#.c.#.c.#.c.#.c.#.#.a.r.#.a.r.r.a.r.r.r.r.r.r.a.r.a.r.r.r.r.a.a.l.a.b.a.l.l.e.l.l.e.a.l.a.e.l.a.a.lQt.a.c.#.cQt.#.d.s.i.i.iQtQt.gQtQt.qQt.fQtQtQtQt",
+"QtQt.i.x.g.g.g.fQtQt.#.#.#.l.e.l.b.j.e.j.e.j.j.j.e.j.e.j.e.j.e.j.j.j.e.e.e.e.e.e.l.a.l.c.r.c.#.c.d.#.#.#QtQtQtQt.a.#.b.a.a.b.a.b.l.l.l.e.e.e.e.e.j.k.j.k.j.j.j.e.k.j.j.e.e.e.e.e.e.b.e.l.b.a.r.a.b.c.b.c.c.c.d.i.c.q.c.r.c.r.c.c.#Qt.#.c.#.#.c.#.a.#.a.#.l.r.b.a.l.a.#.a.a.l.a.a.l.b.l.a.a.a.#.#Qt.iQt.s.g.m.p.h.h.h.p.h.gQtQt.f.#Qt.cQt.#.q.c.#.c.#.a.#.a.#.a.#.c.r.#.r.#.a.#.r.r.#.a.r.#.a.r.#.a.#.#.a.l.a.a.a.a.l.a.e.a.l.b.l.a.a.e.l.e.l.a.a.a.a.a.c.cQtQtQt.i.i.s.f.sQtQtQtQtQtQt.iQtQtQt.f",
+"Qt.f.i.g.g.g.g.iQtQt.q.#.a.a.a.l.e.e.l.e.e.e.e.l.j.e.j.e.j.e.j.j.e.j.l.j.l.e.b.e.a.a.c.c.c.c.cQt.r.#.#.qQtQt.#.d.a.a.a.b.a.e.r.l.#.l.e.l.e.e.e.e.j.j.j.j.k.j.k.j.j.e.e.e.e.b.a.a.a.a.l.a.a.c.cQt.a.#.#.cQt.#QtQt.#.c.c.c.q.c.#Qt.#.#.c.#Qt.#.c.q.a.a.a.a.a.a.a.a.a.a.a.a.#.a.a.a.#.r.a.a.cQt.#QtQtQt.qQt.f.g.g.m.g.s.g.m.iQtQt.i.#Qt.#.q.c.#.#.c.r.a.a.a.a.a.a.a.r.r.c.r.#.r.a.#.r.r.r.#.r.a.a.r.r.a.r.r.a.a.l.a.l.e.l.l.e.l.l.e.a.a.l.a.l.e.a.l.a.a.#.c.r.cQt.c.i.m.i.iQtQt.gQtQt.i.fQtQt.i.g.q",
+".q.i.f.g.m.x.g.g.xQtQt.#.#.a.a.l.e.l.e.e.j.l.j.e.e.j.e.l.j.e.j.j.j.j.j.e.e.e.l.e.c.r.c.#.c.#QtQt.r.#.#.#.c.#.c.c.l.a.l.e.e.a.e.b.l.l.e.b.l.e.e.e.e.k.j.j.e.j.j.j.e.e.e.l.e.a.b.c.a.a.a.c.c.#.cQt.#.#QtQtQt.iQtQt.f.iQtQtQtQtQtQtQtQtQtQtQt.d.#Qt.a.a.r.a.a.r.a.r.#.c.a.a.a.c.a.c.r.a.#.#.a.#Qt.#.#QtQt.gQt.i.i.g.s.g.p.p.gQtQt.#.#.#.d.#.#.c.#.c.a.a.l.a.l.a.l.a.q.a.r.a.r.#.r.#.r.r.r.a.r.a.r.a.a.#.r.#.a.a.a.a.e.a.l.b.l.a.e.a.l.a.a.l.b.l.l.l.a.a.a.c.c.c.#Qt.i.i.g.i.gQt.q.iQtQtQtQtQtQt.f.f",
+".i.i.i.i.g.g.g.hQtQtQtQt.c.#.a.a.l.a.l.a.e.e.e.l.e.e.e.j.e.j.e.e.j.e.e.l.e.e.e.l.c.c.#.c.#QtQtQt.a.#.#.#.c.c.c.#.l.l.e.e.e.e.e.e.#.l.e.l.e.e.e.e.k.j.j.j.k.j.j.k.l.t.l.b.l.a.a.#.c.c.#Qt.#.#.dQtQtQtQt.iQt.f.fQtQtQtQtQt.iQt.iQtQt.iQt.iQt.#Qt.#.#.#.c.#.q.c.#.#.c.#.c.c.#Qt.c.#.#.r.a.#.i.#.iQt.i.qQt.qQt.s.f.i.s.i.m.v.h.gQt.#.c.#.q.#.d.#.#.c.a.#.a.a.a.a.a.a.a.r.#.r.a.r.a.r.r.r.q.r.r.#.r.a.#.r.a.r.a.a.l.a.e.l.a.l.a.e.l.l.a.l.l.a.l.e.a.e.a.l.c.#.c.i.d.i.i.i.i.iQtQt.fQt.i.xQt.qQt.f.i.i",
+".h.g.i.g.s.h.u.pQt.q.iQt.#.c.a.a.a.b.a.b.a.l.b.e.e.j.l.e.l.e.e.e.j.j.e.j.e.l.e.b.r.#.#QtQt.#QtQt.#.#.#.c.a.a.a.b.l.b.l.e.t.e.e.e.e.l.l.e.e.e.e.e.e.k.j.j.j.j.j.j.e.a.e.l.a.l.c.c.c.#.cQtQt.i.fQtQt.iQtQt.f.i.iQt.iQtQtQtQt.iQtQtQt.qQt.qQt.xQt.i.#.q.#.#.#.#.q.#.#.c.c.q.c.#.c.c.r.#.q.#.#QtQtQt.qQtQt.i.iQt.i.iQtQt.g.v.o.g.f.q.c.#.d.#.q.#Qt.#.a.a.a.a.l.l.l.l.r.r.#.a.#.#.#.r.#.r.r.a.r.a.a.r.r.#.r.a.a.a.a.a.e.a.l.a.a.l.a.e.l.e.a.l.a.l.e.l.a.a.c.c.#.c.#Qt.i.g.s.i.g.q.iQt.iQtQtQt.s.i.m.i",
+".h.g.i.g.h.h.p.p.i.fQtQtQt.c.a.a.a.e.a.e.a.e.e.l.e.e.e.j.e.j.l.j.e.j.e.l.e.a.a.a.#Qt.qQtQtQtQtQt.#.c.#.c.l.a.e.e.l.j.j.j.j.j.e.e.l.b.e.l.e.e.e.e.j.j.j.j.k.j.j.k.l.l.l.a.a.a.#.r.#.c.#QtQtQtQt.fQt.q.i.i.s.g.g.gQtQtQtQtQtQtQt.s.q.x.q.q.s.q.i.qQtQt.i.#Qt.#Qt.#.d.qQt.cQt.#Qt.#Qt.#.#.#.i.#QtQt.i.iQt.qQt.i.qQt.g.i.m.p.v.p.h.i.c.#.#.iQt.#.#.c.a.a.a.a.b.a.b.a.c.r.#.r.r.r.a.r.r.r.r.#.a.r.a.a.r.a.#.r.a.#.a.a.l.l.a.a.l.a.e.l.b.l.e.a.l.a.e.l.a.a.a.#Qt.cQtQt.i.i.i.iQtQt.f.q.i.i.i.i.i.f.g.g",
+".g.h.i.x.i.g.p.p.s.iQtQt.c.q.a.a.r.a.a.a.b.a.b.e.l.j.j.e.j.l.e.e.j.j.e.e.e.l.b.b.#.#Qt.#QtQtQtQt.cQt.a.a.a.e.j.e.j.j.e.j.e.k.j.e.l.l.l.j.e.e.e.e.e.k.j.k.e.j.j.j.l.l.a.l.r.c.a.c.cQt.c.cQtQtQt.f.qQtQt.i.i.g.g.gQtQtQt.qQt.sQtQtQtQtQtQtQtQtQtQt.i.#QtQtQt.#Qt.#Qt.#.d.#QtQt.d.#.#.#.q.#Qt.iQtQt.q.i.q.iQt.x.f.xQt.f.g.w.p.u.g.i.#Qt.#QtQt.#Qt.#.a.#.b.a.#.b.a.a.r.a.r.a.r.c.r.#.r.r.#.a.r.#.a.r.#.r.#.r.a.a.a.l.b.a.l.a.#.a.a.l.l.e.l.a.l.a.l.e.a.#.#.c.c.c.#Qt.i.i.sQtQtQt.iQt.qQt.q.i.i.i.g.g",
+"QtQtQtQtQtQt.d.fQtQt.i.iQtQtQtQt.#.c.l.a.l.a.b.e.e.e.e.e.e.e.e.e.t.j.l.l.a.c.cQt.q.q.f.qQt.iQtQt.a.b.a.e.e.e.l.j.j.j.j.j.k.e.e.e.l.l.b.l.l.j.e.e.e.e.b.e.e.e.e.e.e.e.e.l.b.e.a.a.a.b.a.c.c.c.c.c.#.#.gQt.fQt.fQtQtQtQt.iQtQtQtQtQt.iQtQt.iQtQt.i.d.#.q.d.#QtQtQt.q.q.q.q.q.q.q.q.iQtQtQtQtQtQt.iQt.#.dQtQtQt.i.g.i.xQt.s.g.v.p.h.u.gQt.x.#.a.a.#.a.a.a.a.b.a.a.r.a.r.#.a.a.#.r.a.r.#.r.r.a.r.r.a.r.r.a.r.a.r.a.a.r.a.#.a.l.l.l.e.e.l.e.e.e.e.e.l.a.a.a.r.#.#.d.#.f.q.fQt.q.f.fQt.i.qQtQtQtQtQt.c",
+"Qt.#QtQtQt.gQt.d.#.iQtQtQtQtQtQt.c.#.a.a.a.a.a.e.e.e.e.e.e.e.e.e.e.l.e.l.a.c.#.d.q.q.i.qQtQtQtQt.b.c.a.b.l.e.j.e.j.k.j.k.j.e.e.e.l.l.l.l.e.e.e.e.b.e.e.e.e.b.e.b.j.j.e.e.l.e.a.r.a.c.b.c.c.c.c.c.c.cQtQtQtQtQt.fQtQtQtQtQtQtQt.i.fQt.fQtQt.iQtQt.#.d.#Qt.qQt.#.i.q.x.q.qQt.dQt.dQtQtQt.#Qt.qQtQt.#.iQt.q.iQt.iQt.iQt.g.i.w.A.z.u.p.g.s.qQt.q.a.c.a.a.b.a.a.a.a.a.a.a.a.r.a.r.a.#.a.r.a.a.r.a.r.a.r.c.rQt.r.a.a.l.a.l.r.l.l.l.l.l.e.e.e.l.b.e.l.b.a.r.a.a.c.#.c.#Qt.sQtQt.i.f.f.iQt.#.i.qQtQt.c.#",
+".#Qt.#QtQt.c.dQt.r.#.#Qt.qQtQtQt.#.c.#.c.a.a.b.a.e.e.e.e.e.e.l.e.l.#.l.a.c.cQtQt.i.q.iQtQt.q.fQt.a.b.a.e.e.e.j.e.j.j.k.e.e.e.e.b.l.b.l.l.e.l.e.e.e.e.e.e.e.e.e.e.j.e.j.j.e.e.e.e.e.e.a.b.c.a.r.c.#.#QtQtQtQtQtQt.#.c.#.c.c.#.c.#.#.q.#.qQt.#Qt.q.#.#.#.r.aQt.#Qt.#QtQtQt.q.iQtQt.q.d.q.d.#.d.d.q.r.r.r.q.#QtQtQt.s.i.i.m.h.A.z.y.g.p.p.qQtQt.#.a.#.a.a.#.a.a.a.a.a.r.a.a.r.a.r.a.r.#.a.r.a.r.a.r.a.r.r.r.a.r.a.r.a.r.a.a.l.l.l.l.t.l.b.l.l.l.l.l.a.#.r.a.r.c.#.d.q.iQt.qQt.iQt.f.x.qQtQt.#.#.c.#",
+".c.#.#Qt.c.#.c.c.#.c.iQtQt.iQtQtQtQt.#.c.#.c.c.a.c.a.c.a.c.a.b.a.a.r.c.#.cQtQt.i.q.qQt.iQtQt.fQt.c.c.a.b.e.e.e.e.j.k.j.e.e.e.b.l.l.l.l.l.b.e.e.e.e.e.e.e.j.e.e.e.j.j.j.e.j.e.b.e.a.e.b.a.b.c.c.c.d.c.#.f.#.c.c.#.c.c.c.c.#.c.c.c.a.c.c.c.a.c.#.c.r.a.r.a.a.#.#.#.#Qt.#.#.#.#.#.#.r.d.#.r.r.#.r.#.r.q.r.#.#.d.i.d.i.i.m.h.m.u.A.C.g.p.u.i.i.q.i.c.a.a.a.a.a.a.#.a.l.a.a.r.#.a.a.r.#.a.r.a.r.a.r.a.q.r.c.r.#.a.a.a.l.r.b.l.l.l.l.l.e.l.a.l.a.a.l.l.r.l.r.#.c.#.c.#.iQt.i.s.i.f.s.f.i.xQt.#Qt.cQt.c",
+".#.#Qt.cQt.c.c.c.#.c.#.c.#QtQtQtQtQtQtQt.q.c.#.a.c.c.c.c.c.c.c.c.#.c.#.cQtQtQtQt.i.q.s.qQt.q.fQt.b.a.b.e.l.e.j.e.j.j.e.e.e.e.a.b.l.l.l.l.e.l.e.e.j.k.e.k.e.k.j.j.j.j.e.j.j.e.j.e.e.e.l.b.a.a.c.a.c.#QtQt.#.d.#.c.a.a.a.a.a.a.a.a.#.a.#.a.a.#.a.a.b.l.a.#.a.a.#.a.#.#.#.c.#.#.#.#.q.r.r.r.r.r.#.r.r.r.r.q.r.#.#.q.i.i.i.m.g.u.A.C.h.h.h.u.iQtQtQt.#.c.c.c.c.c.c.#.a.r.#.a.r.a.r.a.r.#.a.r.a.r.a.r.a.r.a.r.a.r.a.l.r.a.r.l.l.l.e.l.a.a.a.a.a.l.a.a.l.l.a.r.c.#QtQt.f.x.i.f.i.g.f.i.i.i.i.i.#.c.#.#",
+".a.r.a.#.q.c.#.c.a.a.c.c.c.c.c.d.i.s.qQtQtQt.c.c.#.c.c.#.c.c.#.cQt.#QtQtQt.iQtQtQt.qQt.i.f.i.fQt.b.a.c.e.b.j.e.l.e.e.l.e.a.a.c.a.l.l.b.l.e.e.e.e.j.j.j.j.k.j.j.j.j.j.j.j.j.j.e.j.t.e.e.e.a.b.a.b.#.dQtQt.c.r.a.r.a.a.a.l.l.a.a.a.l.l.l.b.l.l.l.l.l.b.l.e.a.a.a.r.#.a.c.#.c.aQt.c.r.r.r.r.#.r.#.r.r.#.r.a.#.q.#.#.sQt.s.f.s.p.z.G.h.h.h.h.m.iQt.q.c.q.#.#.q.#.#.#.a.r.a.r.l.a.a.r.a.r.r.a.r.a.r.a.r.#.#.c.r.a.r.a.l.l.l.l.l.l.l.l.l.a.r.#.a.a.a.a.l.l.l.a.r.cQtQt.q.i.f.s.i.i.f.m.g.m.iQtQt.#.#.a",
+".r.a.r.c.#.c.a.c.a.l.a.#.a.#.c.#QtQt.iQtQtQtQtQt.#Qt.#Qt.#QtQt.#QtQtQtQtQtQtQtQt.q.i.q.fQt.qQtQt.a.b.a.e.l.e.e.e.l.l.e.l.a.a.a.#.l.l.l.l.e.l.e.e.k.k.j.k.j.j.k.j.k.0.j.j.e.j.j.e.e.e.t.e.a.b.a.cQt.#Qt.#.#.a.a.b.l.e.l.e.e.l.b.l.e.l.l.l.e.l.e.e.j.e.e.e.e.e.b.b.a.a.a.a.a.#.a.a.#.a.a.a.a.a.a.#.a.a.#.c.c.c.c.c.q.#.i.i.i.m.o.n.o.p.h.p.h.i.i.fQtQtQtQt.dQt.c.c.a.r.a.a.r.#.r.a.#.#.a.r.a.r.a.r.a.r.r.r.a.#.a.l.l.l.l.l.l.l.l.l.a.a.l.a.l.r.l.l.l.l.a.r.c.#.#.i.f.i.s.i.f.g.i.m.p.m.i.iQt.c.#.a",
+".r.a.r.a.a.c.#.a.a.a.l.c.c.a.c.c.f.i.f.iQtQt.#QtQtQtQtQtQtQtQtQt.iQtQtQtQtQtQtQt.q.q.q.iQtQtQtQt.c.b.c.a.e.j.e.l.b.l.l.a.a.a.a.c.l.l.l.l.e.j.e.e.j.j.k.j.j.k.k.j.0.k.j.j.j.j.j.j.j.e.e.e.a.a.b.a.c.fQt.c.#.r.l.l.e.l.b.e.e.l.e.e.l.e.e.e.e.e.l.b.j.j.j.j.e.r.e.e.a.a.a.b.a.a.a.a.a.b.a.#.a.a.a.a.r.e.b.b.cQt.cQt.d.#.#.q.f.i.u.n.o.n.h.h.h.m.gQt.cQtQtQtQt.d.#.#.#.a.r.#.a.a.r.a.r.r.a.r.a.r.a.r.a.r.c.r.a.r.r.a.l.l.l.l.e.l.l.a.l.r.a.r.a.l.a.l.l.l.r.a.a.c.cQt.i.i.f.i.s.g.i.g.u.h.gQt.#.#.r.a"};
diff --git a/tests/auto/gui/image/qimagewriter/images/ship63.pbm b/tests/auto/gui/image/qimagewriter/images/ship63.pbm
new file mode 100644
index 0000000000..4da971a2d7
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/ship63.pbm
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/teapot.ppm b/tests/auto/gui/image/qimagewriter/images/teapot.ppm
new file mode 100644
index 0000000000..b8ab85f3a5
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/teapot.ppm
@@ -0,0 +1,31 @@
+P6
+256 256
+255
+\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[7 eOLjQLmSMoTMnSMlRMhPL_9 \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀnSMtVMzYN~[N~[N\N\O€\O€]O€]O€]O€]O€\O€\O}[NyYNtVM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-wXN}[N€]O„^O†_O†`O‡`Oˆ`Oˆ`OˆaO‰aO‰aO‰aO‰aO‰aO‰aOˆaOˆ`O†_Oƒ^O\N \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaMLyYN…_O‰aP‹bPcPŽcPŽdPŽdPdPdPdPdPdPdPdPeP‘eP’eP’eP‘ePdPcP…_OpUM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN…_OdP“fP•gQ–hQ˜hQ˜iQ™iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœjQœjQœjQ›jQœjQ™iQ“fP‡`O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJiQL‹bP—hQkQ¡mR¤nR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦pR¨pS©qSªqS«rS¬rS«rS©qS¤oRœjQ€]O\KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀfOLrUMcPŸlR©qS¯tS²uTµwT·xT¸xT¹yTºyT»zT»zU¼zU¼zU¼zU»zUºyT¸xT¶wT¯tS¡mR‰aOhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àa0 cNLqUM€\O”fQ¦pS²wVºzV¿|VÂ}VÄVÆVÇ€VÉ‚WÌ…[Õeæ w÷³‹êª…Ĉg§qT“fQ{ZNYIK9\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀO1{G#‘JkRMqUMtVN–iS¨v\·€d¹bµzZ±vU°uT®sSªqS¤nRœjQ’eP„^OrUMHh>!T4\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-V5wE"~I#†M%U+¥e7²l:°g2®b*­a(­`(©^(¥])¡^-›]1ŠS,qC$`9 R3G-\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@)J/i>!pA"tD"wF$yH&xH&tE$wE#yG%}M+ƒT4S5mE*Z7!K/B*;'\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‰aO¦oR½{UÇ€VÏ…X<(F-a: e<!h>!j@#k@$h>"d<!c=$hD-fF2[<)K0@);'5$Ë‚VÇ€V¿|U_LKYIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À…_O·xTÉ‚Wó«€ûµ‹Ö’k¼|X×>µf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&c<!b=%jH2_A/I0!<(8&5$”J¥Y’S%8&;'?)E,<:HA=HE?IJAISFJYIKXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À£nRÁ}UܘqÊŠe±vU²e,™V&¥V†C €@ |> y< u: r9 o7 l6
+j5
+h4
+g3
+5$D,K/b; h>"wM1tK.e="a<#cA,U8&E-<(9&.!a0 b1 c1    
+
++3#@)46G<:HMCIXHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀU*´vT¿~X¸{YÃk+›W&‰N$|> u: p8 k5
+f3
+a0 _/ ]. [- I¡\*ª_(‘LkRMmSMmSMnSMnSMD,R3W5mA"|O0|P1j?"c<!a=%Y7"N1F,;'NCJNCJNDJODJODJODJh>!a: X/K%
+g3
+a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d<!yF#O+€N,rC#qB"pB#k?"a: Z7 6ODJPDJPEJQEJQEJREJREJREJRFJSFJSFJSFJSFJe<!X/
+^/ V+Q(L&I$r9  TlRMnSM46G47G47G46G46G46G46G46G36G36G25G25G15G04G/4F.3F
+
+X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?<H@<HA=HC>HG@ILBIREJ[JKcNLjQL§pR±uTºzUÃ~VÈWË‚XÖŽcäsÒŽe¼{V²vT¨pSžkR•gQŒbP†_O‚^O]O€\O€\O€\O€\O€]O]O]O]O]O]O]O]O]O]O]O€\O€\O~\N}[N|ZNxXN•T%H$
+›W&rVMvWNyYNzYN|ZN}[N}[N><H?<H?<H?<H?<H?<H@<H@<H@<HA=HA=HB=HC>HE?IG@IIAIKBIODJSFJWHK—hQŸlR§pR°b(¾i*Én+Ù|7Û|6Ïr,Íq+Êp-Ãl+»g)±b(®sS§pS lRšiQ•gQePcPŠaPˆaO‡`O‡`O†_O†_O…_O…_O…_O…_O…_O…_O…_O„_O„^O„^Oƒ^Oƒ^O‚]O]O€\O~[N{ZN•T%
+
+ 
+@%<-$G?@…pfdNLuWM\NdNL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJvWN‰aP./01„E}[N]O…_Oˆ`O‰aP‹bPŒbPcPcPŽcPdPdPdPeP‘eP’eP’eP“fP“fQ”fQ•gQ•gQ–gQ–hQ—hQ˜hQ™iQšiQ›jQœjQkQkRžlRŸlRžY&¤\'¨^'µ^½bÀcÃeÇi ÄgÀc½b¼a¹`µ^´]¯X¢[' Z'žY&¢mR¡mR¡mR lRŸlRŸlRžkRkQœkQœjQ›jQšjQšiQ™iQ™iQ˜iQ˜hQ—hQ—hQ—hQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘ePdPcP‰aP—O
+ B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6
+ 
+$5 ¬`(¶e)£nRœjQƒ^OJAI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXIK^KKdNLhPLuWM‚]OŒbP”fQeP m6
+†`OŽcP“fQ—hQ˜hQ™iQšiQšjQ›jQ›jQ›jQœjQœjQœjQœkQkQkQkRžkRžkRžkRžlRŸlRŸlRŸlR lR lR lR¡mR¡mR¡mR¡mRºg)³c(²c(±b(­V¿cÂeÅi!Åi!Àd¼bº`¹`·_·_¶^¢Q§]'ª_(­`(¹f)£nR£nR£nR£nR£nR£nR£nR¢nR¢nR¢nR¢nR¢nR¢nR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR¢mR¢mR£nR¢mR¢mR¡mR mRkR—hQˆGa0 ŠbP mRœjQ“fQ‰aP}[NrUMmSM…L$\À\À\À\À\À\À\À\À B B #C, 8&H.Z7 §pR›jQ{ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJ[JK`LKdNLhQLqUM{ZN…_OŽcP–gQ—hQ
+‹bP‘eP–hQšiQ›jQœjQkQkQkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlR lR lR lR mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢nR£nRÀj*ºg)·e)¶d)Âd°XÅgÅhÂe¿c½b½b¾bªU­`(®a(¯a(³c(¾i*¤oR¤oR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¥oR¥oR¤nR¡mR›jQŽQ%Z- œjQ£nRŸlR—hQŽdP…_OuWMpTMnSMkRLa: \À\À\À\À\À\À\À B B&D2 @*S6#G@IPDJ˜hQmSM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ]KKbMLeOLiQLlRMvWN\OˆaO‘eP—hQœjQ•gQ
+!C+E'0F.4F7%8%U/lG.SFJZIK]KKZIKB=H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀREJZJK`LKdNLgPLjQLlRMnSMpTMqUMtWMxXN{ZN~[N]O„^O†`O‰aO‹bPdP•gQ™iQœkQ lR¤nR§pSªrS­sS¯tT²uT´vT¶wT·xT¹yT¹yTºyTºyT¹yT¶xT´vT¬rS¢nR—hQ¿|U¿|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ}UÀ}UÁ}UÁ}UÁ}UÁ}UÂ}UÂ~UÃ~UÃ~VÃ~VÄVÅ€WÆX®a(ŸlRªrS´vT¸yT¼zU¾|UÁ~VÃXÆ‚[Ɇ_΋dÓ‘jÔ“mÔ“nБlÊŒhĆd½_¶{[°vWªsU¦pS¢nRžkRšiQ˜hQ•gQ“fQ‘ePdPŒbP‰aO†_Oƒ^O€\O|ZNxXNsVMpTMnTMmSMjQL€C B)D&/F-3F47G6%>" Y7 kA$YIK]KK^KKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\KKbMLeOLhPLkRLmSMnTMpTMrUMuWNyYN|ZN\N‚]O„_O‡`OŠaPŒbPŽcPeP“fP—hQ›jQžlR¢nR¥oS©qT¬sT¯uU²vU´wV¶xV¸yV¹yUºzU»zU¼{U½{U¾{U¾|U¿|U¿|U¿|U¿|U¾{U½{U¼{U¼zU»zTºyT¹yT¸xTµwT³vT´vT´vT´vT´wT´wTµwT·xT¹yTºzT¼zU½{U¾{U¿|UÀ|UÂ}UÄVÅ€WÇ‚YÉ„\͈_ÑŒdÙ”láuç£|쩂ſt명æ¦ÞŸ{Õ—sËŽl†d¹^³yZ­uW¨qU¤oSŸlRžkRœjQšiQ˜hQ–gQ”fQ‘ePdPcPŠaP‡`O„^O]O}[NyYNuWMpTMoTMmSMkRLgPL&D#.E,3F46G;'<(D"iB(VGJ]KK`LK[JKB>H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRMmSMoTMqUMsVMvXNzYN}[N€\O‚^O…_Oˆ`OŠaPŒcPdP‘eP“fQ•gQ—hQ™iQkR mS¤oT¨rU¬tW°wY´zZ¸}\»]¾€^À^Á‚^‚^Â\Á€ZÁYÁXÁ~WÁ~WÂ~VÂ~VÂ~VÃ~VÃ~UÃ~UÄ~UÄ~UÄUÄUÅVÅVÅVÅVÆVÆ€VÆ€VÇ€WÇWÈ‚XɃZË…[͇^ЊaÓdØ’iÜ—nâtè£zî©ó¯‡ø´û¸‘üº“û¹“÷¶ñ±Œé©…à¡~Ö˜vËmÇf»€`´z[®vX©rU¥pT£oS¢nS lRžkRœkRšjQ˜iQ–hQ”fQ’ePdPcP‹bPˆ`O…_O‚]O~[NzYNvWNpTMoTMnSMkRMhQLo7 ,2F36G99HC+@ ]8 nA"\JK`ML_LKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_OˆaO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRžlR mS£oU§rW¬vZ²{]¹€a¿…fÅŠjËnГqÓ•sÕ–sÕ–rÕ–qÕ”oÓ’mÑjÏgÍŠcˈaɆ^È„\Ç‚[ÆYÅ€XÅ€WÅWÅWÅVÅVÅWÅ€WÆ€WÇXÈ‚YɃ[Ê…\͇_ÏŠaÒeÕ‘hÙ•mÝ™qávä¡zç¤}꧀멃몄騃奀ߠ|Ù›wÓ•rÌmƉh¿„c¸~^²yZ®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRœkR›jQ™iQ—hQ•gQ“fPePŽcP‹bPˆaO…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQL~I#26G99G?<HA*E$ i@$ZIKaMLbML[JK;:H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ]KKbMLeOLhPLjRLlSMnTMpTMrUMuWMxXN{ZN~\N]O„^O†`O‰aO‹bPŽcPdP’eP”fQ–gQ˜hQšiQœkRžlS mT£oU¦rWªuZ¯y]´~aºƒfŠlË’sÔšzÜ¡€ã§†è«‰ë®‹í¯Œí®‹ë¬ˆè¨„ã£~ßžyÚ™tÖ•oÒjÎŒfˈbÈ…_ƃ\ÅZÄ€YÃXÂWÂ~WÂ~WÂ~WÃXÀXÄ€YÅZƃ\Ç…^Ɇ`ˈbÌŠdÍ‹fÎgÎŽiÎŽjÎŽjÍŽjËŒiljgÆd¿ƒaº^¸}]¶|\´{[²yZ°xY®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRkR›jQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aO†_Oƒ^O€\O|ZNxXNtVMpTMnSMmSMjQLgPL99G?<HG-E&b;!YIK`MLdOM`LKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlRºyTÄ~UÊ‚XʃYÄXº{W­tUšW'¢[(—hQ lRcP€\OhQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRLmSMoTMqUMrVMvWNyYN|ZN\N‚]O„_O‡`O‰aPŒbPŽcPdP’fP”gQ–hQ˜iQšjRœkRžlS¡nT¤pU§sW«vZ°z]µb»„gŠlÉ‘sИyØžÞ¤…ã©Šè­ì±ï³‘ﳑ뭊穅⣀ݞzؘtÒ“nÎiɉdÆ…`Â]Á€[¿~Y¾}X½|W½|V¼{V¼{V¼{V¼{V¼{V¼|W¼|W½}X½}Y½~Z½~Z¼~Z»}[º}[º}[º~\º~\º~]º~]¹~]¸~]·}]¶|\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS mRŸlRkR›jQšiQ˜hQ–gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O}[NyYNuWNpTMnTMmSMkRLhPL|H$D>IQ2P+XHK_LLfQOcNLXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À©qSºyTÃ~VΈ`遲ޜv¾€]ªqS–LŽG|> g3
+S)?*%.—hQ—hQ‘eP‡`OuWM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMoTMqUMsVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽdP‘eP“fP•gQ—hQ˜iQšjRœkRŸlS¡nT¤pV§sX«vZ°z^¶b¼…gËmÊ’sјzØŸ€Þ¤…ã©Šè­ê¯ë°ê¯Žè¬‹å¨‡à¤‚Ûž|Ö™wÑ“qÌŽlljgÃ…bÀ‚_½\»}Zº{X¹zW¸yV·yU·xU·xU·xT·xT·xU·xU·xU·yV·yV·yW¸zW¸{X¹{Y¹|Zº}[º}[º}\º~\¹~]¹~]¸}]·|\µ{\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS¡mRŸlRkRœjQšiQ˜hQ–gQ”fQ’ePdPcPŠbP‡`O…_O‚]O~[NzZNvWNrUMoTMmSMlRMiQLeOLJAIJ(h>!]KKfQOgQN_LKD>I\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À™iQ°tS¸yT¼{UÂYÎŒeï­ˆô´Õ—u¶|\ Z'™LˆD |>
+
+ &3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!'
+ %' %$#" ! !$ 
diff --git a/tests/auto/gui/image/qimagewriter/images/teapot.tiff b/tests/auto/gui/image/qimagewriter/images/teapot.tiff
new file mode 100644
index 0000000000..20845c6e32
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/teapot.tiff
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/images/trolltech.gif b/tests/auto/gui/image/qimagewriter/images/trolltech.gif
new file mode 100644
index 0000000000..f674369efc
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/images/trolltech.gif
Binary files differ
diff --git a/tests/auto/gui/image/qimagewriter/qimagewriter.pro b/tests/auto/gui/image/qimagewriter/qimagewriter.pro
new file mode 100644
index 0000000000..0fc40d0f0a
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/qimagewriter.pro
@@ -0,0 +1,25 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qimagewriter.cpp
+MOC_DIR=tmp
+!contains(QT_CONFIG, no-tiff):DEFINES += QTEST_HAVE_TIFF
+win32-msvc:QMAKE_CXXFLAGS -= -Zm200
+win32-msvc:QMAKE_CXXFLAGS += -Zm800
+
+wince*: {
+ addFiles.files = images\\*.*
+ addFiles.path = images
+ DEPLOYMENT += addFiles
+ DEFINES += SRCDIR=\\\".\\\"
+} else:symbian {
+ addFiles.files = images\\*.*
+ addFiles.path = images
+ DEPLOYMENT += addFiles
+ qt_not_deployed {
+ imagePlugins.files = qjpeg.dll qtiff.dll
+ imagePlugins.path = imageformats
+ DEPLOYMENT += imagePlugins
+ }
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
new file mode 100644
index 0000000000..b119763723
--- /dev/null
+++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
@@ -0,0 +1,628 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <QDebug>
+#include <QFile>
+#include <QImage>
+#include <QImageReader>
+#include <QImageWriter>
+#include <QLabel>
+#include <QPainter>
+#include <QSet>
+
+#if defined(Q_OS_SYMBIAN)
+# define SRCDIR ""
+#endif
+typedef QMap<QString, QString> QStringMap;
+typedef QList<int> QIntList;
+Q_DECLARE_METATYPE(QImage)
+Q_DECLARE_METATYPE(QStringMap)
+Q_DECLARE_METATYPE(QIntList)
+Q_DECLARE_METATYPE(QImageWriter::ImageWriterError)
+Q_DECLARE_METATYPE(QIODevice *)
+Q_DECLARE_METATYPE(QImage::Format)
+
+//TESTED_FILES=
+
+class tst_QImageWriter : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QImageWriter();
+ virtual ~tst_QImageWriter();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void writeImage_data();
+ void writeImage();
+ void writeImage2_data();
+ void writeImage2();
+ void supportedFormats();
+
+ void readWriteNonDestructive_data();
+ void readWriteNonDestructive();
+
+#if defined QTEST_HAVE_TIFF
+ void largeTiff();
+#endif
+
+ void writeToInvalidDevice();
+
+ void supportsOption_data();
+ void supportsOption();
+
+ void saveWithNoFormat_data();
+ void saveWithNoFormat();
+
+ void resolution_data();
+ void resolution();
+
+ void saveToTemporaryFile();
+};
+#ifdef Q_OS_SYMBIAN
+static const QLatin1String prefix(SRCDIR "images/");
+#else
+static const QLatin1String prefix(SRCDIR "/images/");
+#endif
+static void initializePadding(QImage *image)
+{
+ int effectiveBytesPerLine = (image->width() * image->depth() + 7) / 8;
+ int paddingBytes = image->bytesPerLine() - effectiveBytesPerLine;
+ if (paddingBytes == 0)
+ return;
+ for (int y = 0; y < image->height(); ++y) {
+ qMemSet(image->scanLine(y) + effectiveBytesPerLine, 0, paddingBytes);
+ }
+}
+
+// Testing get/set functions
+void tst_QImageWriter::getSetCheck()
+{
+ QImageWriter obj1;
+ // QIODevice * QImageWriter::device()
+ // void QImageWriter::setDevice(QIODevice *)
+ QFile *var1 = new QFile;
+ obj1.setDevice(var1);
+
+ QCOMPARE((QIODevice *) var1, obj1.device());
+ // The class should possibly handle a 0-pointer as a device, since
+ // there is a default contructor, so it's "handling" a 0 device by default.
+ // For example: QMovie::setDevice(0) works just fine
+ obj1.setDevice((QIODevice *)0);
+ QCOMPARE((QIODevice *) 0, obj1.device());
+ delete var1;
+
+ // int QImageWriter::quality()
+ // void QImageWriter::setQuality(int)
+ obj1.setQuality(0);
+ QCOMPARE(0, obj1.quality());
+ obj1.setQuality(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.quality());
+ obj1.setQuality(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.quality());
+
+ // int QImageWriter::compression()
+ // void QImageWriter::setCompression(int)
+ obj1.setCompression(0);
+ QCOMPARE(0, obj1.compression());
+ obj1.setCompression(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.compression());
+ obj1.setCompression(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.compression());
+
+ // float QImageWriter::gamma()
+ // void QImageWriter::setGamma(float)
+ obj1.setGamma(0.0f);
+ QCOMPARE(0.0f, obj1.gamma());
+ obj1.setGamma(1.1f);
+ QCOMPARE(1.1f, obj1.gamma());
+}
+
+tst_QImageWriter::tst_QImageWriter()
+{
+}
+
+tst_QImageWriter::~tst_QImageWriter()
+{
+ QDir dir(prefix);
+ QStringList filesToDelete = dir.entryList(QStringList() << "gen-*" , QDir::NoDotAndDotDot | QDir::Files);
+ foreach( QString file, filesToDelete) {
+ QFile::remove(dir.absoluteFilePath(file));
+ }
+
+}
+
+void tst_QImageWriter::init()
+{
+}
+
+void tst_QImageWriter::cleanup()
+{
+}
+
+void tst_QImageWriter::writeImage_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<bool>("lossy");
+ QTest::addColumn<QByteArray>("format");
+
+ QTest::newRow("BMP: colorful") << QString("colorful.bmp") << false << QByteArray("bmp");
+ QTest::newRow("BMP: font") << QString("font.bmp") << false << QByteArray("bmp");
+ QTest::newRow("XPM: marble") << QString("marble.xpm") << false << QByteArray("xpm");
+ QTest::newRow("PNG: kollada") << QString("kollada.png") << false << QByteArray("png");
+ QTest::newRow("PPM: teapot") << QString("teapot.ppm") << false << QByteArray("ppm");
+ QTest::newRow("PBM: ship63") << QString("ship63.pbm") << true << QByteArray("pbm");
+ QTest::newRow("XBM: gnus") << QString("gnus.xbm") << false << QByteArray("xbm");
+ QTest::newRow("JPEG: beavis") << QString("beavis.jpg") << true << QByteArray("jpeg");
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("TIFF: teapot") << QString("teapot.tiff") << false << QByteArray("tiff");
+#endif
+}
+
+void tst_QImageWriter::writeImage()
+{
+ QFETCH(QString, fileName);
+ QFETCH(bool, lossy);
+ QFETCH(QByteArray, format);
+
+ QImage image;
+ {
+ QImageReader reader(prefix + fileName);
+ image = reader.read();
+ QVERIFY2(!image.isNull(), qPrintable(reader.errorString()));
+ }
+ {
+ QImageWriter writer(prefix + "gen-" + fileName, format);
+ QVERIFY(writer.write(image));
+ }
+
+ {
+ // Shouldn't be able to write to read-only file
+ QFile sourceFile(prefix + "gen-" + fileName);
+ QFile::Permissions permissions = sourceFile.permissions();
+ QVERIFY(sourceFile.setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther));
+
+ QImageWriter writer(prefix + "gen-" + fileName, format);
+ QVERIFY(!writer.write(image));
+
+ QVERIFY(sourceFile.setPermissions(permissions));
+ }
+
+ QImage image2;
+ {
+ QImageReader reader(prefix + "gen-" + fileName);
+ image2 = reader.read();
+ QVERIFY(!image2.isNull());
+ }
+ if (!lossy) {
+ QCOMPARE(image, image2);
+ } else {
+ QCOMPARE(image.format(), image2.format());
+ QCOMPARE(image.depth(), image2.depth());
+ }
+}
+
+void tst_QImageWriter::writeImage2_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QByteArray>("format");
+ QTest::addColumn<QImage>("image");
+
+ const QStringList formats = QStringList() << "bmp" << "xpm" << "png"
+ << "ppm"; //<< "jpeg";
+ QImage image0(70, 70, QImage::Format_ARGB32);
+ image0.fill(QColor(Qt::red).rgb());
+
+ QImage::Format imgFormat = QImage::Format_Mono;
+ while (imgFormat != QImage::NImageFormats) {
+ QImage image = image0.convertToFormat(imgFormat);
+ initializePadding(&image);
+ foreach (const QString format, formats) {
+ const QString fileName = QString("solidcolor_%1.%2").arg(imgFormat)
+ .arg(format);
+ QTest::newRow(fileName.toLatin1()) << fileName
+ << format.toLatin1()
+ << image;
+ }
+ imgFormat = QImage::Format(int(imgFormat) + 1);
+ }
+}
+
+#if defined QTEST_HAVE_TIFF
+void tst_QImageWriter::largeTiff()
+{
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
+ QImage img(4096, 2048, QImage::Format_ARGB32);
+
+ QPainter p(&img);
+ img.fill(0x0);
+ p.fillRect(0, 0, 4096, 2048, QBrush(Qt::CrossPattern));
+ p.end();
+
+ QByteArray array;
+ QBuffer writeBuffer(&array);
+ writeBuffer.open(QIODevice::WriteOnly);
+
+ QImageWriter writer(&writeBuffer, "tiff");
+ QVERIFY(writer.write(img));
+
+ writeBuffer.close();
+
+ QBuffer readBuffer(&array);
+ readBuffer.open(QIODevice::ReadOnly);
+
+ QImageReader reader(&readBuffer, "tiff");
+
+ QImage img2 = reader.read();
+ QVERIFY(!img2.isNull());
+
+ QCOMPARE(img, img2);
+#else
+ QWARN("not tested on Symbian/WinCE");
+#endif
+}
+#endif
+
+/*
+ Workaround for the equality operator for indexed formats
+ (which fails if the colortables are different).
+
+ Images must have the same format and size.
+*/
+static bool equalImageContents(const QImage &image1, const QImage &image2)
+{
+ switch (image1.format()) {
+ case QImage::Format_Mono:
+ case QImage::Format_Indexed8:
+ for (int y = 0; y < image1.height(); ++y)
+ for (int x = 0; x < image1.width(); ++x)
+ if (image1.pixel(x, y) != image2.pixel(x, y))
+ return false;
+ return true;
+ default:
+ return (image1 == image2);
+ }
+}
+
+void tst_QImageWriter::writeImage2()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+ QFETCH(QImage, image);
+
+ //we reduce the scope of writer so that it closes the associated file
+ // and QFile::remove can actually work
+ {
+ QImageWriter writer(fileName, format);
+ QVERIFY(writer.write(image));
+ }
+
+ QImage written;
+
+ //we reduce the scope of reader so that it closes the associated file
+ // and QFile::remove can actually work
+ {
+ QImageReader reader(fileName, format);
+ QVERIFY(reader.read(&written));
+ }
+
+ written = written.convertToFormat(image.format());
+ if (!equalImageContents(written, image)) {
+ qDebug() << "image" << image.format() << image.width()
+ << image.height() << image.depth()
+ << hex << image.pixel(0, 0);
+ qDebug() << "written" << written.format() << written.width()
+ << written.height() << written.depth()
+ << hex << written.pixel(0, 0);
+ }
+ QVERIFY(equalImageContents(written, image));
+
+ QVERIFY(QFile::remove(fileName));
+}
+
+void tst_QImageWriter::supportedFormats()
+{
+ QList<QByteArray> formats = QImageWriter::supportedImageFormats();
+ QList<QByteArray> sortedFormats = formats;
+ qSort(sortedFormats);
+
+ // check that the list is sorted
+ QCOMPARE(formats, sortedFormats);
+
+ QSet<QByteArray> formatSet;
+ foreach (QByteArray format, formats)
+ formatSet << format;
+
+ // check that the list does not contain duplicates
+ QCOMPARE(formatSet.size(), formats.size());
+}
+
+void tst_QImageWriter::readWriteNonDestructive_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<QImage::Format>("expectedFormat");
+ QTest::addColumn<bool>("grayscale");
+ QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono << false;
+ QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << false;
+ QTest::newRow("tiff rgb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32 << false;
+ QTest::newRow("tiff grayscale") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << true;
+}
+
+void tst_QImageWriter::readWriteNonDestructive()
+{
+ QFETCH(QImage::Format, format);
+ QFETCH(QImage::Format, expectedFormat);
+ QFETCH(bool, grayscale);
+ QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format);
+
+ if (grayscale) {
+ QVector<QRgb> colors;
+ for (int i = 0; i < 256; ++i)
+ colors << qRgb(i, i, i);
+ image.setColorTable(colors);
+ }
+
+ QVERIFY(image.save(prefix + "gen-readWriteNonDestructive.tiff"));
+
+ QImage image2 = QImage(prefix + "gen-readWriteNonDestructive.tiff");
+ QImage::Format readFormat = image2.format();
+ QCOMPARE(readFormat, expectedFormat);
+ QCOMPARE(image, image2);
+}
+
+void tst_QImageWriter::writeToInvalidDevice()
+{
+ QLatin1String fileName("/these/directories/do/not/exist/001.png");
+ {
+ QImageWriter writer(fileName);
+ QVERIFY(!writer.canWrite());
+ QCOMPARE(writer.error(), QImageWriter::DeviceError);
+ }
+ {
+ QImageWriter writer(fileName);
+ writer.setFormat("png");
+ QVERIFY(!writer.canWrite());
+ QCOMPARE(writer.error(), QImageWriter::DeviceError);
+ }
+ {
+ QImageWriter writer(fileName);
+ QImage im(10, 10, QImage::Format_ARGB32);
+ QVERIFY(!writer.write(im));
+ QCOMPARE(writer.error(), QImageWriter::DeviceError);
+ }
+ {
+ QImageWriter writer(fileName);
+ writer.setFormat("png");
+ QImage im(10, 10, QImage::Format_ARGB32);
+ QVERIFY(!writer.write(im));
+ QCOMPARE(writer.error(), QImageWriter::DeviceError);
+ }
+}
+
+void tst_QImageWriter::supportsOption_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QIntList>("options");
+
+ QTest::newRow("png") << QString("gen-black.png")
+ << (QIntList() << QImageIOHandler::Gamma
+ << QImageIOHandler::Description
+ << QImageIOHandler::Quality
+ << QImageIOHandler::Size);
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("tiff") << QString("gen-black.tiff")
+ << (QIntList() << QImageIOHandler::Size
+ << QImageIOHandler::CompressionRatio);
+#endif
+}
+
+void tst_QImageWriter::supportsOption()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QIntList, options);
+
+ QSet<QImageIOHandler::ImageOption> allOptions;
+ allOptions << QImageIOHandler::Size
+ << QImageIOHandler::ClipRect
+ << QImageIOHandler::Description
+ << QImageIOHandler::ScaledClipRect
+ << QImageIOHandler::ScaledSize
+ << QImageIOHandler::CompressionRatio
+ << QImageIOHandler::Gamma
+ << QImageIOHandler::Quality
+ << QImageIOHandler::Name
+ << QImageIOHandler::SubType
+ << QImageIOHandler::IncrementalReading
+ << QImageIOHandler::Endianness
+ << QImageIOHandler::Animation
+ << QImageIOHandler::BackgroundColor;
+
+ QImageWriter writer(prefix + fileName);
+ for (int i = 0; i < options.size(); ++i) {
+ QVERIFY(writer.supportsOption(QImageIOHandler::ImageOption(options.at(i))));
+ allOptions.remove(QImageIOHandler::ImageOption(options.at(i)));
+ }
+
+ foreach (QImageIOHandler::ImageOption option, allOptions)
+ QVERIFY(!writer.supportsOption(option));
+}
+
+void tst_QImageWriter::saveWithNoFormat_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QByteArray>("format");
+ QTest::addColumn<QImageWriter::ImageWriterError>("error");
+
+ QTest::newRow("garble") << prefix + QString("gen-out.garble") << QByteArray("jpeg") << QImageWriter::UnsupportedFormatError;
+ QTest::newRow("bmp") << prefix + QString("gen-out.bmp") << QByteArray("bmp") << QImageWriter::ImageWriterError(0);
+ QTest::newRow("xbm") << prefix + QString("gen-out.xbm") << QByteArray("xbm") << QImageWriter::ImageWriterError(0);
+ QTest::newRow("xpm") << prefix + QString("gen-out.xpm") << QByteArray("xpm") << QImageWriter::ImageWriterError(0);
+ QTest::newRow("png") << prefix + QString("gen-out.png") << QByteArray("png") << QImageWriter::ImageWriterError(0);
+ QTest::newRow("ppm") << prefix + QString("gen-out.ppm") << QByteArray("ppm") << QImageWriter::ImageWriterError(0);
+ QTest::newRow("pbm") << prefix + QString("gen-out.pbm") << QByteArray("pbm") << QImageWriter::ImageWriterError(0);
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("tiff") << prefix + QString("gen-out.tiff") << QByteArray("tiff") << QImageWriter::ImageWriterError(0);
+#endif
+}
+
+void tst_QImageWriter::saveWithNoFormat()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+ QFETCH(QImageWriter::ImageWriterError, error);
+
+ QImage niceImage(64, 64, QImage::Format_ARGB32);
+ qMemSet(niceImage.bits(), 0, niceImage.byteCount());
+
+ QImageWriter writer(fileName /* , 0 - no format! */);
+ if (error != 0) {
+ QVERIFY(!writer.write(niceImage));
+ QCOMPARE(writer.error(), error);
+ return;
+ }
+
+ QVERIFY2(writer.write(niceImage), qPrintable(writer.errorString()));
+
+ QImageReader reader(fileName);
+ QCOMPARE(reader.format(), format);
+
+ QVERIFY(reader.canRead());
+
+ QImage outImage = reader.read();
+ QVERIFY2(!outImage.isNull(), qPrintable(reader.errorString()));
+}
+
+void tst_QImageWriter::resolution_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<int>("expectedDotsPerMeterX");
+ QTest::addColumn<int>("expectedDotsPerMeterY");
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("TIFF: 100 dpi") << ("image_100dpi.tif") << qRound(100 * (100 / 2.54)) << qRound(100 * (100 / 2.54));
+ QTest::newRow("TIFF: 50 dpi") << ("image_50dpi.tif") << qRound(50 * (100 / 2.54)) << qRound(50 * (100 / 2.54));
+ QTest::newRow("TIFF: 300 dot per meter") << ("image_300dpm.tif") << 300 << 300;
+#endif
+}
+
+void tst_QImageWriter::resolution()
+{
+ QFETCH(QString, filename);
+ QFETCH(int, expectedDotsPerMeterX);
+ QFETCH(int, expectedDotsPerMeterY);
+
+ QImage image(prefix + QLatin1String("colorful.bmp"));
+ image.setDotsPerMeterX(expectedDotsPerMeterX);
+ image.setDotsPerMeterY(expectedDotsPerMeterY);
+ const QString generatedFilepath = prefix + "gen-" + filename;
+ {
+ QImageWriter writer(generatedFilepath);
+ QVERIFY(writer.write(image));
+ }
+ QImageReader reader(generatedFilepath);
+ const QImage generatedImage = reader.read();
+
+ QCOMPARE(expectedDotsPerMeterX, generatedImage.dotsPerMeterX());
+ QCOMPARE(expectedDotsPerMeterY, generatedImage.dotsPerMeterY());
+}
+
+void tst_QImageWriter::saveToTemporaryFile()
+{
+ QImage image(prefix + "kollada.png");
+ QVERIFY(!image.isNull());
+
+ {
+ // 1) Via QImageWriter's API, with a standard temp file name
+ QTemporaryFile file;
+ QVERIFY(file.open());
+ QImageWriter writer(&file, "PNG");
+ if (writer.canWrite())
+ QVERIFY(writer.write(image));
+ else
+ qWarning() << file.errorString();
+#if defined(Q_OS_WINCE)
+ file.reset();
+#endif
+ QCOMPARE(QImage(writer.fileName()), image);
+ }
+ {
+ // 2) Via QImage's API, with a standard temp file name
+ QTemporaryFile file;
+ QVERIFY(file.open());
+ QVERIFY(image.save(&file, "PNG"));
+ file.reset();
+ QImage tmp;
+ QVERIFY(tmp.load(&file, "PNG"));
+ QCOMPARE(tmp, image);
+ }
+ {
+ // 3) Via QImageWriter's API, with a named temp file
+ QTemporaryFile file("tempXXXXXX");
+ QVERIFY(file.open());
+ QImageWriter writer(&file, "PNG");
+ QVERIFY(writer.write(image));
+#if defined(Q_OS_WINCE)
+ file.reset();
+#endif
+ QCOMPARE(QImage(writer.fileName()), image);
+ }
+ {
+ // 4) Via QImage's API, with a named temp file
+ QTemporaryFile file("tempXXXXXX");
+ QVERIFY(file.open());
+ QVERIFY(image.save(&file, "PNG"));
+ file.reset();
+ QImage tmp;
+ QVERIFY(tmp.load(&file, "PNG"));
+ QCOMPARE(tmp, image);
+ }
+}
+
+QTEST_MAIN(tst_QImageWriter)
+#include "tst_qimagewriter.moc"
diff --git a/tests/auto/gui/image/qmovie/.gitignore b/tests/auto/gui/image/qmovie/.gitignore
new file mode 100644
index 0000000000..396e8cbc7d
--- /dev/null
+++ b/tests/auto/gui/image/qmovie/.gitignore
@@ -0,0 +1 @@
+tst_qmovie
diff --git a/tests/auto/gui/image/qmovie/animations/comicsecard.gif b/tests/auto/gui/image/qmovie/animations/comicsecard.gif
new file mode 100644
index 0000000000..f064de065b
--- /dev/null
+++ b/tests/auto/gui/image/qmovie/animations/comicsecard.gif
Binary files differ
diff --git a/tests/auto/gui/image/qmovie/animations/corrupt.gif b/tests/auto/gui/image/qmovie/animations/corrupt.gif
new file mode 100644
index 0000000000..c1545eb0ed
--- /dev/null
+++ b/tests/auto/gui/image/qmovie/animations/corrupt.gif
Binary files differ
diff --git a/tests/auto/gui/image/qmovie/animations/dutch.mng b/tests/auto/gui/image/qmovie/animations/dutch.mng
new file mode 100644
index 0000000000..4917fdee7a
--- /dev/null
+++ b/tests/auto/gui/image/qmovie/animations/dutch.mng
Binary files differ
diff --git a/tests/auto/gui/image/qmovie/animations/trolltech.gif b/tests/auto/gui/image/qmovie/animations/trolltech.gif
new file mode 100644
index 0000000000..df7eb92703
--- /dev/null
+++ b/tests/auto/gui/image/qmovie/animations/trolltech.gif
Binary files differ
diff --git a/tests/auto/gui/image/qmovie/qmovie.pro b/tests/auto/gui/image/qmovie/qmovie.pro
new file mode 100644
index 0000000000..3e085ceeaf
--- /dev/null
+++ b/tests/auto/gui/image/qmovie/qmovie.pro
@@ -0,0 +1,28 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qmovie.cpp
+MOC_DIR=tmp
+
+!contains(QT_CONFIG, no-gif):DEFINES += QTEST_HAVE_GIF
+!contains(QT_CONFIG, no-jpeg):DEFINES += QTEST_HAVE_JPEG
+!contains(QT_CONFIG, no-mng):DEFINES += QTEST_HAVE_MNG
+
+wince*: {
+ addFiles.files = animations\\*
+ addFiles.path = animations
+ DEPLOYMENT += addFiles
+}
+
+RESOURCES += resources.qrc
+
+symbian: {
+ addFiles.files = animations\\*
+ addFiles.path = animations
+ DEPLOYMENT += addFiles
+
+ qt_not_deployed {
+ imagePlugins.files = qjpeg.dll qgif.dll qmng.dll
+ imagePlugins.path = imageformats
+ DEPLOYMENT += imagePlugins
+ }
+}
diff --git a/tests/auto/gui/image/qmovie/resources.qrc b/tests/auto/gui/image/qmovie/resources.qrc
new file mode 100644
index 0000000000..ce459a0e7e
--- /dev/null
+++ b/tests/auto/gui/image/qmovie/resources.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>animations/corrupt.gif</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/gui/image/qmovie/tst_qmovie.cpp b/tests/auto/gui/image/qmovie/tst_qmovie.cpp
new file mode 100644
index 0000000000..15c7f856b1
--- /dev/null
+++ b/tests/auto/gui/image/qmovie/tst_qmovie.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <QIODevice>
+#include <QLabel>
+#include <QMovie>
+
+//TESTED_FILES=
+
+class tst_QMovie : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QMovie();
+ virtual ~tst_QMovie();
+
+public slots:
+ void init();
+ void cleanup();
+
+protected slots:
+ void exitLoopSlot();
+
+private slots:
+ void getSetCheck();
+ void construction();
+ void playMovie_data();
+ void playMovie();
+ void jumpToFrame_data();
+ void jumpToFrame();
+ void changeMovieFile();
+ void infiniteLoop();
+};
+
+// Testing get/set functions
+void tst_QMovie::getSetCheck()
+{
+ QMovie obj1;
+ // QIODevice * QMovie::device()
+ // void QMovie::setDevice(QIODevice *)
+ QFile *var1 = new QFile;
+ obj1.setDevice(var1);
+ QCOMPARE(obj1.device(), (QIODevice *)var1);
+ obj1.setDevice((QIODevice *)0);
+ QCOMPARE(obj1.device(), (QIODevice *)0);
+ delete var1;
+
+ // CacheMode QMovie::cacheMode()
+ // void QMovie::setCacheMode(CacheMode)
+ obj1.setCacheMode(QMovie::CacheMode(QMovie::CacheNone));
+ QCOMPARE(QMovie::CacheMode(QMovie::CacheNone), obj1.cacheMode());
+ obj1.setCacheMode(QMovie::CacheMode(QMovie::CacheAll));
+ QCOMPARE(QMovie::CacheMode(QMovie::CacheAll), obj1.cacheMode());
+
+ // int QMovie::speed()
+ // void QMovie::setSpeed(int)
+ obj1.setSpeed(0);
+ QCOMPARE(0, obj1.speed());
+ obj1.setSpeed(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.speed());
+ obj1.setSpeed(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.speed());
+}
+
+tst_QMovie::tst_QMovie()
+{
+}
+
+tst_QMovie::~tst_QMovie()
+{
+
+}
+
+void tst_QMovie::init()
+{
+}
+
+void tst_QMovie::cleanup()
+{
+}
+
+void tst_QMovie::exitLoopSlot()
+{
+ QTestEventLoop::instance().exitLoop();
+}
+
+void tst_QMovie::construction()
+{
+ QMovie movie;
+ QCOMPARE(movie.device(), (QIODevice *)0);
+ QCOMPARE(movie.fileName(), QString());
+ QCOMPARE(movie.state(), QMovie::NotRunning);
+}
+
+void tst_QMovie::playMovie_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("frameCount");
+#if defined(QTEST_HAVE_MNG) && !defined(Q_OS_WINCE)
+ // Qt/WinCE runs out of memory for this one...
+ QTest::newRow("home") << QString("animations/dutch.mng") << 10;
+#endif
+#ifdef QTEST_HAVE_GIF
+ QTest::newRow("comicsecard") << QString("animations/comicsecard.gif") << 5;
+ QTest::newRow("trolltech") << QString("animations/trolltech.gif") << 34;
+#endif
+}
+
+void tst_QMovie::playMovie()
+{
+ QFETCH(QString, fileName);
+ QFETCH(int, frameCount);
+
+ QMovie movie(fileName);
+
+ QCOMPARE(movie.state(), QMovie::NotRunning);
+ movie.setSpeed(1000);
+ movie.start();
+ QCOMPARE(movie.state(), QMovie::Running);
+ movie.setPaused(true);
+ QCOMPARE(movie.state(), QMovie::Paused);
+ movie.start();
+ QCOMPARE(movie.state(), QMovie::Running);
+ movie.stop();
+ QCOMPARE(movie.state(), QMovie::NotRunning);
+ movie.jumpToFrame(0);
+ QCOMPARE(movie.state(), QMovie::NotRunning);
+ movie.start();
+ QCOMPARE(movie.state(), QMovie::Running);
+
+ connect(&movie, SIGNAL(finished()), this, SLOT(exitLoopSlot()));
+
+ QLabel label;
+ label.setMovie(&movie);
+ label.show();
+
+ QTestEventLoop::instance().enterLoop(20);
+ QVERIFY2(!QTestEventLoop::instance().timeout(),
+ "Timed out while waiting for finished() signal");
+
+ QCOMPARE(movie.state(), QMovie::NotRunning);
+ QCOMPARE(movie.frameCount(), frameCount);
+}
+
+void tst_QMovie::jumpToFrame_data()
+{
+ playMovie_data();
+}
+
+void tst_QMovie::jumpToFrame()
+{
+ QFETCH(QString, fileName);
+ QMovie movie(fileName);
+ movie.start();
+ movie.stop();
+ QVERIFY(movie.jumpToFrame(-1) == false);
+ QVERIFY(movie.currentFrameNumber() == 0);
+}
+
+void tst_QMovie::changeMovieFile()
+{
+ QMovie movie("animations/comicsecard.gif");
+ movie.start();
+ movie.stop();
+ movie.setFileName("animations/trolltech.gif");
+ QVERIFY(movie.currentFrameNumber() == -1);
+}
+
+void tst_QMovie::infiniteLoop()
+{
+ QLabel label;
+ label.show();
+ QMovie *movie = new QMovie(QLatin1String(":animations/corrupt.gif"), QByteArray(), &label);
+ label.setMovie(movie);
+ movie->start();
+
+ QTestEventLoop::instance().enterLoop(1);
+ QTestEventLoop::instance().timeout();
+}
+
+QTEST_MAIN(tst_QMovie)
+#include "tst_qmovie.moc"
diff --git a/tests/auto/gui/image/qpicture/.gitignore b/tests/auto/gui/image/qpicture/.gitignore
new file mode 100644
index 0000000000..0f391ffb80
--- /dev/null
+++ b/tests/auto/gui/image/qpicture/.gitignore
@@ -0,0 +1 @@
+tst_qpicture
diff --git a/tests/auto/gui/image/qpicture/qpicture.pro b/tests/auto/gui/image/qpicture/qpicture.pro
new file mode 100644
index 0000000000..eb96b73487
--- /dev/null
+++ b/tests/auto/gui/image/qpicture/qpicture.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qpicture.cpp
+
+
+
diff --git a/tests/auto/gui/image/qpicture/tst_qpicture.cpp b/tests/auto/gui/image/qpicture/tst_qpicture.cpp
new file mode 100644
index 0000000000..8661a2b2d0
--- /dev/null
+++ b/tests/auto/gui/image/qpicture/tst_qpicture.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qpicture.h>
+#include <qpainter.h>
+#include <qimage.h>
+#include <qdesktopwidget.h>
+#include <qapplication.h>
+#include <limits.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPicture : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPicture();
+
+private slots:
+ void getSetCheck();
+ void devType();
+ void paintingActive();
+ void boundingRect();
+ void swap();
+ void operator_lt_lt();
+
+ void save_restore();
+
+ void boundaryValues_data();
+ void boundaryValues();
+};
+
+// Testing get/set functions
+void tst_QPicture::getSetCheck()
+{
+ QPictureIO obj1;
+ // const QPicture & QPictureIO::picture()
+ // void QPictureIO::setPicture(const QPicture &)
+ // const char * QPictureIO::format()
+ // void QPictureIO::setFormat(const char *)
+ const char var2[] = "PNG";
+ obj1.setFormat(var2);
+ QCOMPARE(var2, obj1.format());
+ obj1.setFormat((char *)0);
+ // The format is stored internally in a QString, so return is always a valid char *
+ QVERIFY(QString(obj1.format()).isEmpty());
+
+ // const char * QPictureIO::parameters()
+ // void QPictureIO::setParameters(const char *)
+ const char var3[] = "Bogus data";
+ obj1.setParameters(var3);
+ QCOMPARE(var3, obj1.parameters());
+ obj1.setParameters((char *)0);
+ // The format is stored internally in a QString, so return is always a valid char *
+ QVERIFY(QString(obj1.parameters()).isEmpty());
+}
+
+tst_QPicture::tst_QPicture()
+{
+}
+
+void tst_QPicture::devType()
+{
+ QPicture p;
+ QCOMPARE( p.devType(), (int)QInternal::Picture );
+}
+
+void tst_QPicture::paintingActive()
+{
+ // actually implemented in QPainter but QPicture is a good
+ // example of an external paint device
+ QPicture p;
+ QVERIFY( !p.paintingActive() );
+ QPainter pt( &p );
+ QVERIFY( p.paintingActive() );
+ pt.end();
+ QVERIFY( !p.paintingActive() );
+}
+
+void tst_QPicture::boundingRect()
+{
+ QPicture p1;
+ // default value
+ QVERIFY( !p1.boundingRect().isValid() );
+
+ QRect r1( 20, 30, 5, 15 );
+ p1.setBoundingRect( r1 );
+ QCOMPARE( p1.boundingRect(), r1 );
+ p1.setBoundingRect(QRect());
+
+ QPainter pt( &p1 );
+ pt.drawLine( 10, 20, 110, 80 );
+ pt.end();
+
+ // assignment and copy constructor
+ QRect r2( 10, 20, 100, 60 );
+ QCOMPARE( p1.boundingRect(), r2 );
+ QPicture p2( p1 );
+ QCOMPARE( p1.boundingRect(), r2 );
+ QPicture p3;
+ p3 = p1;
+ QCOMPARE( p1.boundingRect(), r2 );
+
+ {
+ QPicture p4;
+ QPainter p(&p4);
+ p.drawLine(0, 0, 5, 0);
+ p.drawLine(0, 0, 0, 5);
+ p.end();
+
+ QRect r3(0, 0, 5, 5);
+ QCOMPARE(p4.boundingRect(), r3);
+ }
+}
+
+void tst_QPicture::swap()
+{
+ QPicture p1, p2;
+ QPainter(&p1).drawLine(0, 0, 5, 5);
+ QPainter(&p2).drawLine(0, 3, 3, 0);
+ QCOMPARE(p1.boundingRect(), QRect(0,0,5,5));
+ QCOMPARE(p2.boundingRect(), QRect(0,0,3,3));
+ p1.swap(p2);
+ QCOMPARE(p1.boundingRect(), QRect(0,0,3,3));
+ QCOMPARE(p2.boundingRect(), QRect(0,0,5,5));
+}
+
+// operator<< and operator>>
+void tst_QPicture::operator_lt_lt()
+{
+ // streaming of null pictures
+ {
+ QPicture pic1, pic2;
+ QByteArray ba( 100, 0 );
+ QDataStream str1( &ba, QIODevice::WriteOnly );
+ str1 << pic1;
+ QDataStream str2( &ba, QIODevice::ReadOnly );
+ str2 >> pic2;
+ QVERIFY( pic2.isNull() );
+ }
+
+ // picture with a simple line, checking bitwise equality
+ {
+ QPicture pic1, pic2;
+ QPainter p( &pic1 );
+ p.drawLine( 10, 20, 30, 40 );
+ p.end();
+ QByteArray ba( 10 * pic1.size(), 0 );
+ QDataStream str1( &ba, QIODevice::WriteOnly );
+ str1 << pic1;
+ QDataStream str2( &ba, QIODevice::ReadOnly );
+ str2 >> pic2;
+ QCOMPARE( pic1.size(), pic2.size() );
+ QVERIFY( memcmp( pic1.data(), pic2.data(), pic1.size() ) == 0 );
+ }
+}
+
+static QPointF scalePoint(const QPointF &point, QPaintDevice *sourceDevice, QPaintDevice *destDevice)
+{
+ return QPointF(point.x() * qreal(destDevice->logicalDpiX()) / qreal(sourceDevice->logicalDpiX()),
+ point.y() * qreal(destDevice->logicalDpiY()) / qreal(sourceDevice->logicalDpiY()));
+}
+
+static QRectF scaleRect(const QRectF &rect, QPaintDevice *sourceDevice, QPaintDevice *destDevice)
+{
+ return QRectF(rect.left() * qreal(destDevice->logicalDpiX()) / qreal(sourceDevice->logicalDpiX()),
+ rect.top() * qreal(destDevice->logicalDpiY()) / qreal(sourceDevice->logicalDpiY()),
+ rect.width() * qreal(destDevice->logicalDpiX()) / qreal(sourceDevice->logicalDpiX()),
+ rect.height() * qreal(destDevice->logicalDpiY()) / qreal(sourceDevice->logicalDpiY()));
+}
+
+static void paintStuff(QPainter *p)
+{
+ QPaintDevice *screenDevice = QApplication::desktop();
+ p->drawRect(scaleRect(QRectF(100, 100, 100, 100), screenDevice, p->device()));
+ p->save();
+ p->translate(scalePoint(QPointF(10, 10), screenDevice, p->device()));
+ p->restore();
+ p->drawRect(scaleRect(QRectF(100, 100, 100, 100), screenDevice, p->device()));
+}
+
+/* See task: 41469
+ Problem is that the state is not properly restored if the basestate of
+ the painter is different when the picture data was created compared to
+ the base state of the painter when it is played back.
+ */
+void tst_QPicture::save_restore()
+{
+ QPicture pic;
+ QPainter p;
+ p.begin(&pic);
+ paintStuff(&p);
+ p.end();
+
+ QPixmap pix1(300, 300);
+ pix1.fill(Qt::white);
+ p.begin(&pix1);
+ p.drawPicture(50, 50, pic);
+ p.end();
+
+ QPixmap pix2(300, 300);
+ pix2.fill(Qt::white);
+ p.begin(&pix2);
+ p.translate(50, 50);
+ paintStuff(&p);
+ p.end();
+
+ QVERIFY( pix1.toImage() == pix2.toImage() );
+}
+
+void tst_QPicture::boundaryValues_data()
+{
+ QTest::addColumn<int>("x");
+ QTest::addColumn<int>("y");
+ QTest::newRow("max x") << INT_MAX << 50;
+ QTest::newRow("max y") << 50 << INT_MAX;
+ QTest::newRow("max x and y") << INT_MAX << INT_MAX;
+
+ QTest::newRow("min x") << INT_MIN << 50;
+ QTest::newRow("min y") << 50 << INT_MIN;
+ QTest::newRow("min x and y") << INT_MIN << INT_MIN;
+
+ QTest::newRow("min x, max y") << INT_MIN << INT_MAX;
+ QTest::newRow("max x, min y") << INT_MAX << INT_MIN;
+
+}
+
+void tst_QPicture::boundaryValues()
+{
+ QPicture picture;
+
+ QPainter painter;
+ painter.begin(&picture);
+
+ QFETCH(int, x);
+ QFETCH(int, y);
+ painter.drawPoint(QPoint(x, y));
+
+ painter.end();
+
+
+}
+
+
+QTEST_MAIN(tst_QPicture)
+#include "tst_qpicture.moc"
diff --git a/tests/auto/gui/image/qpixmap/.gitignore b/tests/auto/gui/image/qpixmap/.gitignore
new file mode 100644
index 0000000000..8d4996f365
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/.gitignore
@@ -0,0 +1 @@
+tst_qpixmap
diff --git a/tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img1.png b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img1.png
new file mode 100644
index 0000000000..7991e9fb17
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img1.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img2.png b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img2.png
new file mode 100644
index 0000000000..dca6d97dc3
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img2.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img1.png b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img1.png
new file mode 100644
index 0000000000..31e6e1aaa0
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img1.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img2.png b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img2.png
new file mode 100644
index 0000000000..0d48026898
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img2.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp.ico b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp.ico
new file mode 100644
index 0000000000..dbb55cd4db
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp.ico
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_16x16.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_16x16.png
new file mode 100644
index 0000000000..f23f39818c
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_16x16.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_256x256.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_256x256.png
new file mode 100644
index 0000000000..293f1c5942
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_256x256.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_32x32.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_32x32.png
new file mode 100644
index 0000000000..bfdb1fe035
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_32x32.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_48x48.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_48x48.png
new file mode 100644
index 0000000000..7dd2d13351
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_48x48.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp.ico b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp.ico
new file mode 100644
index 0000000000..4341a3355e
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp.ico
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_16x16.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_16x16.png
new file mode 100644
index 0000000000..e9a995e19e
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_16x16.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_32x32.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_32x32.png
new file mode 100644
index 0000000000..41ef57f94d
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_32x32.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_48x48.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_48x48.png
new file mode 100644
index 0000000000..35d60d138b
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_48x48.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/designer.png b/tests/auto/gui/image/qpixmap/images/designer.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/designer.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png
new file mode 100644
index 0000000000..a4a19249c7
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png
new file mode 100644
index 0000000000..1506af5a7e
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_50_50_100_100.png b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_50_50_100_100.png
new file mode 100644
index 0000000000..8500ab1f5c
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_x_y_w_h.png
new file mode 100644
index 0000000000..2145c6124c
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_-128_dy_0_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_-128_dy_0_x_y_w_h.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_-128_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_50_50_100_100.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_50_50_100_100.png
new file mode 100644
index 0000000000..728ee79153
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_x_y_w_h.png
new file mode 100644
index 0000000000..e9d5850db7
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_-128_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-128_x_y_w_h.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-128_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_50_50_100_100.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_50_50_100_100.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_null.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_null.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_null.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_x_y_w_h.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_10_50_50_100_100.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_10_50_50_100_100.png
new file mode 100644
index 0000000000..7c09b17830
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_10_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_10_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_10_x_y_w_h.png
new file mode 100644
index 0000000000..70a63405e6
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_10_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_128_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_128_x_y_w_h.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_128_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_0_dy_1_null.png b/tests/auto/gui/image/qpixmap/images/dx_0_dy_1_null.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_0_dy_1_null.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_10_dy_0_50_50_100_100.png b/tests/auto/gui/image/qpixmap/images/dx_10_dy_0_50_50_100_100.png
new file mode 100644
index 0000000000..85abadaf98
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_10_dy_0_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_10_dy_0_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_10_dy_0_x_y_w_h.png
new file mode 100644
index 0000000000..3e03450c01
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_10_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_10_dy_10_50_50_100_100.png b/tests/auto/gui/image/qpixmap/images/dx_10_dy_10_50_50_100_100.png
new file mode 100644
index 0000000000..315fbe087a
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_10_dy_10_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_10_dy_10_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_10_dy_10_x_y_w_h.png
new file mode 100644
index 0000000000..d91dc71217
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_10_dy_10_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_128_dy_0_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_128_dy_0_x_y_w_h.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_128_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_128_dy_128_64_64_128_128.png b/tests/auto/gui/image/qpixmap/images/dx_128_dy_128_64_64_128_128.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_128_dy_128_64_64_128_128.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_128_dy_128_x_y_w_h.png b/tests/auto/gui/image/qpixmap/images/dx_128_dy_128_x_y_w_h.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_128_dy_128_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/images/dx_1_dy_0_null.png b/tests/auto/gui/image/qpixmap/images/dx_1_dy_0_null.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/images/dx_1_dy_0_null.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_argb32.png b/tests/auto/gui/image/qpixmap/loadFromData/designer_argb32.png
new file mode 100644
index 0000000000..55d8247cfc
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_argb32.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.gif b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.gif
new file mode 100644
index 0000000000..26a6da33df
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.gif
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.png b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.png
new file mode 100644
index 0000000000..28cd2f06d1
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif
new file mode 100644
index 0000000000..86a3a2e17d
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.gif b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.gif
new file mode 100644
index 0000000000..49ec77b39b
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.gif
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.png b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.png
new file mode 100644
index 0000000000..09735a9752
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif
new file mode 100644
index 0000000000..f813c057d2
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.jpg b/tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.jpg
new file mode 100644
index 0000000000..70f39c2154
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.png b/tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.png
new file mode 100644
index 0000000000..bca471d576
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmap/qpixmap.pro b/tests/auto/gui/image/qpixmap/qpixmap.pro
new file mode 100644
index 0000000000..fe156d547c
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/qpixmap.pro
@@ -0,0 +1,33 @@
+load(qttest_p4)
+
+QT += core-private gui-private widgets widgets-private
+
+SOURCES += tst_qpixmap.cpp
+wince*|symbian: {
+
+ task31722_0.files = convertFromImage/task31722_0/*.png
+ task31722_0.path = convertFromImage/task31722_0
+
+ task31722_1.files = convertFromImage/task31722_1/*.png
+ task31722_1.path = convertFromImage/task31722_1
+
+ icons.files = convertFromToHICON/*
+ icons.path = convertFromToHICON
+
+ loadFromData.files = loadFromData/*
+ loadFromData.path = loadFromData
+
+ DEPLOYMENT += task31722_0 task31722_1 icons loadFromData
+}
+
+wince*: {
+ DEFINES += SRCDIR=\\\".\\\"
+ DEPLOYMENT_PLUGIN += qico
+} else:symbian {
+ LIBS += -lfbscli.dll -lbitgdi.dll -lgdi.dll
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+ win32:LIBS += -lgdi32 -luser32
+}
+
+RESOURCES += qpixmap.qrc
diff --git a/tests/auto/gui/image/qpixmap/qpixmap.qrc b/tests/auto/gui/image/qpixmap/qpixmap.qrc
new file mode 100644
index 0000000000..99fde61a29
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/qpixmap.qrc
@@ -0,0 +1,29 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>images/designer.png</file>
+ <file>images/dx_0_dy_0_50_50_100_100.png</file>
+ <file>images/dx_0_dy_0_null.png</file>
+ <file>images/dx_0_dy_0_x_y_w_h.png</file>
+ <file>images/dx_0_dy_-10_50_50_100_100.png</file>
+ <file>images/dx_0_dy_10_50_50_100_100.png</file>
+ <file>images/dx_0_dy_-10_x_y_w_h.png</file>
+ <file>images/dx_0_dy_10_x_y_w_h.png</file>
+ <file>images/dx_0_dy_-128_x_y_w_h.png</file>
+ <file>images/dx_0_dy_128_x_y_w_h.png</file>
+ <file>images/dx_0_dy_1_null.png</file>
+ <file>images/dx_-10_dy_0_50_50_100_100.png</file>
+ <file>images/dx_10_dy_0_50_50_100_100.png</file>
+ <file>images/dx_-10_dy_0_x_y_w_h.png</file>
+ <file>images/dx_10_dy_0_x_y_w_h.png</file>
+ <file>images/dx_-10_dy_-10_50_50_100_100.png</file>
+ <file>images/dx_10_dy_10_50_50_100_100.png</file>
+ <file>images/dx_-10_dy_-10_x_y_w_h.png</file>
+ <file>images/dx_10_dy_10_x_y_w_h.png</file>
+ <file>images/dx_-128_dy_0_x_y_w_h.png</file>
+ <file>images/dx_128_dy_0_x_y_w_h.png</file>
+ <file>images/dx_128_dy_128_64_64_128_128.png</file>
+ <file>images/dx_-128_dy_-128_x_y_w_h.png</file>
+ <file>images/dx_128_dy_128_x_y_w_h.png</file>
+ <file>images/dx_1_dy_0_null.png</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
new file mode 100644
index 0000000000..38858e5503
--- /dev/null
+++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
@@ -0,0 +1,1787 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qpixmap.h>
+#include <qbitmap.h>
+#include <qimage.h>
+#include <qimagereader.h>
+#include <qmatrix.h>
+#include <qdesktopwidget.h>
+#include <qpaintengine.h>
+#include <qtreewidget.h>
+#include <qsplashscreen.h>
+
+#include <qplatformpixmap_qpa.h>
+#include <private/qdrawhelper_p.h>
+
+#include <QSet>
+
+#ifdef Q_WS_WIN
+#include <windows.h>
+#endif
+
+#ifdef Q_WS_QWS
+#include <qscreen_qws.h>
+#endif
+
+#ifdef Q_OS_SYMBIAN
+#include <e32std.h>
+#include <fbs.h>
+#include <gdi.h>
+#include <bitdev.h>
+#if !defined(QT_NO_OPENVG)
+#include <QtOpenVG/qvg.h>
+#include <QtOpenVG/private/qpixmapdata_vg_p.h>
+#endif
+#endif
+
+#ifdef Q_WS_X11
+#include <QX11Info>
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+#if defined(Q_OS_SYMBIAN)
+# define SRCDIR ""
+#endif
+Q_DECLARE_METATYPE(QImage::Format)
+
+class tst_QPixmap : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPixmap();
+ virtual ~tst_QPixmap();
+
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void swap();
+
+ void fromImage_data();
+ void fromImage();
+
+ void fromUninitializedImage_data();
+ void fromUninitializedImage();
+
+ void convertFromImage_data();
+ void convertFromImage();
+
+ void testMetrics();
+
+ void scroll_data();
+ void scroll();
+
+ void fill_data();
+ void fill();
+ void fill_transparent();
+
+ void createMaskFromColor();
+
+ void mask();
+ void bitmapMask();
+ void setGetMask_data();
+ void setGetMask();
+ void cacheKey();
+ void drawBitmap();
+ void grabWidget();
+ void grabWindow();
+ void isNull();
+ void task_246446();
+
+ void convertFromImageNoDetach();
+ void convertFromImageDetach();
+
+#if defined(Q_WS_WIN)
+ void toWinHBITMAP_data();
+ void toWinHBITMAP();
+ void fromWinHBITMAP_data();
+ void fromWinHBITMAP();
+
+ void toWinHICON_data();
+ void toWinHICON();
+ void fromWinHICON_data();
+ void fromWinHICON();
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+ void fromSymbianCFbsBitmap_data();
+ void fromSymbianCFbsBitmap();
+ void toSymbianCFbsBitmap_data();
+ void toSymbianCFbsBitmap();
+#endif
+
+ void onlyNullPixmapsOutsideGuiThread();
+ void refUnref();
+
+ void copy();
+ void depthOfNullObjects();
+
+ void transformed();
+ void transformed2();
+
+ void fromImage_crash();
+
+ void fromData();
+ void loadFromDataNullValues();
+
+ void loadFromDataImage_data();
+ void loadFromDataImage();
+
+ void fromImageReader_data();
+ void fromImageReader();
+
+ void fromImageReaderAnimatedGif_data();
+ void fromImageReaderAnimatedGif();
+
+ void preserveDepth();
+ void splash_crash();
+
+ void toImageDeepCopy();
+
+ void loadAsBitmapOrPixmap();
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG)
+ void vgImageReadBack();
+#endif
+ void scaled_QTBUG19157();
+};
+
+static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
+{
+ QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32);
+ QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32);
+
+ if (expectedImage.size() != actualImage.size())
+ return false;
+
+ int size = actual.width() * actual.height();
+
+ int threshold = 2;
+#ifdef Q_WS_X11
+ if (QX11Info::appDepth() == 16)
+ threshold = 10;
+#endif
+
+ QRgb *a = (QRgb *)actualImage.bits();
+ QRgb *e = (QRgb *)expectedImage.bits();
+ for (int i = 0; i < size; ++i) {
+ QColor ca(a[i]);
+ QColor ce(e[i]);
+
+ bool result = true;
+
+ if (qAbs(ca.red() - ce.red()) > threshold)
+ result = false;
+ if (qAbs(ca.green() - ce.green()) > threshold)
+ result = false;
+ if (qAbs(ca.blue() - ce.blue()) > threshold)
+ result = false;
+
+ if (!result)
+ return false;
+ }
+
+ return true;
+}
+
+Q_DECLARE_METATYPE(QImage)
+Q_DECLARE_METATYPE(QPixmap)
+Q_DECLARE_METATYPE(QMatrix)
+Q_DECLARE_METATYPE(QBitmap)
+
+tst_QPixmap::tst_QPixmap()
+{
+}
+
+tst_QPixmap::~tst_QPixmap()
+{
+}
+
+void tst_QPixmap::init()
+{
+}
+
+void tst_QPixmap::cleanup()
+{
+}
+
+void tst_QPixmap::swap()
+{
+ QPixmap p1( 16, 16 ), p2( 32, 32 );
+ p1.fill( Qt::white );
+ p2.fill( Qt::black );
+ const qint64 p1k = p1.cacheKey();
+ const qint64 p2k = p2.cacheKey();
+ p1.swap(p2);
+ QCOMPARE(p1.cacheKey(), p2k);
+ QCOMPARE(p1.size(), QSize(32,32));
+ QCOMPARE(p2.cacheKey(), p1k);
+ QCOMPARE(p2.size(), QSize(16,16));
+}
+
+void tst_QPixmap::fromImage_data()
+{
+ bool is16bit = false;
+#ifdef Q_WS_X11
+ if (QX11Info::appDepth() == 16)
+ is16bit = true;
+#endif
+
+ QTest::addColumn<QImage::Format>("format");
+
+ QTest::newRow("Format_Mono") << QImage::Format_Mono;
+ QTest::newRow("Format_MonoLSB") << QImage::Format_MonoLSB;
+// QTest::newRow("Format_Indexed8") << QImage::Format_Indexed8;
+ if (!is16bit)
+ QTest::newRow("Format_RGB32") << QImage::Format_RGB32;
+ QTest::newRow("Format_ARGB32") << QImage::Format_ARGB32;
+ QTest::newRow("Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
+ if (!is16bit)
+ QTest::newRow("Format_RGB16") << QImage::Format_RGB16;
+}
+
+void tst_QPixmap::fromImage()
+{
+ QFETCH(QImage::Format, format);
+
+ QImage image(37, 16, format);
+
+ if (image.colorCount() == 2) {
+ image.setColor(0, QColor(Qt::color0).rgba());
+ image.setColor(1, QColor(Qt::color1).rgba());
+ }
+ image.fill(0x7f7f7f7f);
+
+ const QPixmap pixmap = QPixmap::fromImage(image);
+#ifdef Q_WS_X11
+ if (pixmap.handle()->classId() == QPlatformPixmap::X11Class && !pixmap.x11PictureHandle())
+ QSKIP("Requires XRender support", SkipAll);
+#endif
+ const QImage result = pixmap.toImage();
+ image = image.convertToFormat(result.format());
+ QCOMPARE(result, image);
+}
+
+
+void tst_QPixmap::fromUninitializedImage_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+
+ QTest::newRow("Format_Mono") << QImage::Format_Mono;
+ QTest::newRow("Format_MonoLSB") << QImage::Format_MonoLSB;
+ QTest::newRow("Format_Indexed8") << QImage::Format_Indexed8;
+ QTest::newRow("Format_RGB32") << QImage::Format_RGB32;
+ QTest::newRow("Format_ARGB32") << QImage::Format_ARGB32;
+ QTest::newRow("Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("Format_RGB16") << QImage::Format_RGB16;
+}
+
+void tst_QPixmap::fromUninitializedImage()
+{
+ QFETCH(QImage::Format, format);
+
+ QImage image(100, 100, format);
+ QPixmap pix = QPixmap::fromImage(image);
+
+ // it simply shouldn't crash...
+ QVERIFY(true);
+
+}
+
+void tst_QPixmap::convertFromImage_data()
+{
+ QTest::addColumn<QImage>("img1");
+ QTest::addColumn<QImage>("img2");
+#ifdef Q_OS_SYMBIAN
+ const QString prefix = QLatin1String(SRCDIR) + "convertFromImage";
+#else
+ const QString prefix = QLatin1String(SRCDIR) + "/convertFromImage";
+#endif
+ {
+ QImage img1;
+ QImage img2;
+ QVERIFY(img1.load(prefix + "/task31722_0/img1.png"));
+ QVERIFY(img2.load(prefix + "/task31722_0/img2.png"));
+ QVERIFY(img1.load(prefix + "/task31722_0/img1.png"));
+ QVERIFY(img2.load(prefix + "/task31722_0/img2.png"));
+ QTest::newRow("Task 31722 0") << img1 << img2;
+ }
+ {
+ QImage img1;
+ QImage img2;
+ QVERIFY(img1.load(prefix + "/task31722_1/img1.png"));
+ QVERIFY(img2.load(prefix + "/task31722_1/img2.png"));
+ QTest::newRow("Task 31722 1") << img1 << img2;
+ }
+}
+
+void tst_QPixmap::convertFromImage()
+{
+ QFETCH(QImage, img1);
+ QFETCH(QImage, img2);
+
+ QPixmap pix = QPixmap::fromImage(img1);
+ pix = QPixmap::fromImage(img2);
+
+ QPixmap res = QPixmap::fromImage(img2);
+ QVERIFY( pixmapsAreEqual(&pix, &res) );
+}
+
+void tst_QPixmap::scroll_data()
+{
+ QTest::addColumn<QImage>("input");
+ QTest::addColumn<int>("dx");
+ QTest::addColumn<int>("dy");
+ QTest::addColumn<QRect>("rect");
+ QTest::addColumn<QRegion>("exposed");
+ QTest::addColumn<bool>("newPix");
+
+ QImage input(":/images/designer.png");
+
+ // Noop tests
+ QTest::newRow("null") << QImage() << 0 << 0 << QRect() << QRegion() << false;
+ QTest::newRow("dx_0_dy_0_null") << input << 0 << 0 << QRect() << QRegion() << false;
+ QTest::newRow("dx_1_dy_0_null") << input << 1 << 0 << QRect() << QRegion() << false;
+ QTest::newRow("dx_0_dy_1_null") << input << 0 << 1 << QRect() << QRegion() << false;
+ QTest::newRow("dx_0_dy_0_x_y_w_h") << input << 0 << 0 << input.rect() << QRegion() << false;
+
+ QRegion r;
+ // Scroll whole pixmap
+ r = QRegion(); r += QRect(0, 0, 128, 10);
+ QTest::newRow("dx_0_dy_10_x_y_w_h") << input << 0 << 10 << input.rect() << r << true;
+ r = QRegion(); r += QRect(0, 0, 10, 128);
+ QTest::newRow("dx_10_dy_0_x_y_w_h") << input << 10 << 0 << input.rect() << r << true;
+ r = QRegion(); r += QRect(0, 0, 128, 10); r += QRect(0, 10, 10, 118);
+ QTest::newRow("dx_10_dy_10_x_y_w_h") << input << 10 << 10 << input.rect() << r << true;
+ r = QRegion(); r += QRect(118, 0, 10, 128);
+ QTest::newRow("dx_-10_dy_0_x_y_w_h") << input << -10 << 0 << input.rect() << r << true;
+ r = QRegion(); r += QRect(0, 118, 128, 10);
+ QTest::newRow("dx_0_dy_-10_x_y_w_h") << input << 0 << -10 << input.rect() << r << true;
+ r = QRegion(); r += QRect(118, 0, 10, 118); r += QRect(0, 118, 128, 10);
+ QTest::newRow("dx_-10_dy_-10_x_y_w_h") << input << -10 << -10 << input.rect() << r << true;
+
+ // Scroll part of pixmap
+ QTest::newRow("dx_0_dy_0_50_50_100_100") << input << 0 << 0 << QRect(50, 50, 100, 100) << QRegion() << false;
+ r = QRegion(); r += QRect(50, 50, 10, 78);
+ QTest::newRow("dx_10_dy_0_50_50_100_100") << input << 10 << 0 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(50, 50, 78, 10);
+ QTest::newRow("dx_0_dy_10_50_50_100_100") << input << 0 << 10 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(50, 50, 78, 10); r += QRect(50, 60, 10, 68);
+ QTest::newRow("dx_10_dy_10_50_50_100_100") << input << 10 << 10 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(118, 50, 10, 78);
+ QTest::newRow("dx_-10_dy_0_50_50_100_100") << input << -10 << 0 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(50, 118, 78, 10);
+ QTest::newRow("dx_0_dy_-10_50_50_100_100") << input << 0 << -10 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(118, 50, 10, 68); r += QRect(50, 118, 78, 10);
+ QTest::newRow("dx_-10_dy_-10_50_50_100_100") << input << -10 << -10 << QRect(50, 50, 100, 100) << r << true;
+
+ // Scroll away the whole pixmap
+ r = input.rect();
+ QTest::newRow("dx_128_dy_0_x_y_w_h") << input << 128 << 0 << input.rect() << r << false;
+ QTest::newRow("dx_0_dy_128_x_y_w_h") << input << 0 << 128 << input.rect() << r << false;
+ QTest::newRow("dx_128_dy_128_x_y_w_h") << input << 128 << 128 << input.rect() << r << false;
+ QTest::newRow("dx_-128_dy_0_x_y_w_h") << input << -128 << 0 << input.rect() << r << false;
+ QTest::newRow("dx_0_dy_-128_x_y_w_h") << input << 0 << -128 << input.rect() << r << false;
+ QTest::newRow("dx_-128_dy_-128_x_y_w_h") << input << -128 << -128 << input.rect() << r << false;
+
+ // Scroll away part of the pixmap
+ r = QRegion(); r += QRect(64, 64, 64, 64);
+ QTest::newRow("dx_128_dy_128_64_64_128_128") << input << 128 << 128 << QRect(64, 64, 128, 128) << r << false;
+}
+
+void tst_QPixmap::scroll()
+{
+ QFETCH(QImage, input);
+ QFETCH(int, dx);
+ QFETCH(int, dy);
+ QFETCH(QRect, rect);
+ QFETCH(QRegion, exposed);
+ QFETCH(bool, newPix);
+
+ QPixmap pixmap = QPixmap::fromImage(input);
+ QRegion exp;
+ qint64 oldKey = pixmap.cacheKey();
+ pixmap.scroll(dx, dy, rect, &exp);
+ if (!newPix)
+ QCOMPARE(pixmap.cacheKey(), oldKey);
+ else
+ QVERIFY(pixmap.cacheKey() != oldKey);
+
+#if 0
+ // Remember to add to resources.
+ QString fileName = QString("images/%1.png").arg(QTest::currentDataTag());
+ pixmap.toImage().save(fileName);
+#else
+ QString fileName = QString(":/images/%1.png").arg(QTest::currentDataTag());
+#endif
+ QPixmap output(fileName);
+ QVERIFY(input.isNull() == output.isNull());
+ QVERIFY(lenientCompare(pixmap, output));
+ QCOMPARE(exp, exposed);
+}
+
+void tst_QPixmap::fill_data()
+{
+ QTest::addColumn<uint>("pixel");
+ QTest::addColumn<bool>("syscolor");
+ QTest::addColumn<bool>("bitmap");
+ for (int color = Qt::black; color < Qt::darkYellow; ++color)
+ QTest::newRow(QString("syscolor_%1").arg(color).toLatin1())
+ << uint(color) << true << false;
+
+#ifdef Q_WS_QWS
+ if (QScreen::instance()->depth() >= 24) {
+#elif defined (Q_WS_X11)
+ QPixmap pm(1, 1);
+ if (pm.x11PictureHandle()) {
+#elif defined (Q_OS_WINCE)
+ QPixmap pixmap(1,1);
+ if (QPixmap::grabWidget(QApplication::desktop()).depth() >= 24) {
+#else
+ QPixmap pixmap(1, 1); {
+#endif
+ QTest::newRow("alpha_7f_red") << 0x7fff0000u << false << false;
+ QTest::newRow("alpha_3f_blue") << 0x3f0000ffu << false << false;
+ QTest::newRow("alpha_b7_green") << 0xbf00ff00u << false << false;
+ QTest::newRow("alpha_7f_white") << 0x7fffffffu << false << false;
+ QTest::newRow("alpha_3f_white") << 0x3fffffffu << false << false;
+ QTest::newRow("alpha_b7_white") << 0xb7ffffffu << false << false;
+ QTest::newRow("alpha_7f_black") << 0x7f000000u << false << false;
+ QTest::newRow("alpha_3f_black") << 0x3f000000u << false << false;
+ QTest::newRow("alpha_b7_black") << 0xbf000000u << false << false;
+ }
+
+ QTest::newRow("bitmap_color0") << uint(Qt::color0) << true << true;
+ QTest::newRow("bitmap_color1") << uint(Qt::color1) << true << true;
+}
+
+void tst_QPixmap::fill()
+{
+ QFETCH(uint, pixel);
+ QFETCH(bool, syscolor);
+ QFETCH(bool, bitmap);
+
+ QColor color;
+
+ if (syscolor)
+ color = QColor(Qt::GlobalColor(pixel));
+ else
+ color = QColor(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel));
+
+ QColor compareColor = color;
+ if (bitmap && syscolor) {
+ // special case color0 and color1 for bitmaps.
+ if (pixel == Qt::color0)
+ compareColor.setRgb(255, 255, 255);
+ else
+ compareColor.setRgb(0, 0, 0);
+ }
+
+ QPixmap pm;
+
+ if (bitmap)
+ pm = QBitmap(400, 400);
+ else
+ pm = QPixmap(400, 400);
+
+#if defined(Q_WS_X11)
+ if (!bitmap && pm.handle()->classId() == QPlatformPixmap::X11Class && !pm.x11PictureHandle())
+ QSKIP("Requires XRender support", SkipSingle);
+#endif
+
+ pm.fill(color);
+ if (syscolor && !bitmap && pm.depth() < 24) {
+ QSKIP("Test does not work on displays without true color", SkipSingle);
+ }
+
+ QImage image = pm.toImage();
+ if (bitmap && syscolor) {
+ int pixelindex = (pixel == Qt::color0) ? 0 : 1;
+ QCOMPARE(image.pixelIndex(0,0), pixelindex);
+ }
+ QImage::Format format = compareColor.alpha() != 255
+ ? QImage::Format_ARGB32
+ : QImage::Format_RGB32;
+ image = image.convertToFormat(format);
+
+
+ QImage shouldBe(400, 400, format);
+ shouldBe.fill(compareColor.rgba());
+
+ QCOMPARE(image, shouldBe);
+}
+
+void tst_QPixmap::fill_transparent()
+{
+ QPixmap pixmap(10, 10);
+#ifdef Q_WS_X11
+ if (pixmap.handle()->classId() == QPlatformPixmap::X11Class && !pixmap.x11PictureHandle())
+ QSKIP("Requires XRender support", SkipAll);
+#endif
+ pixmap.fill(Qt::transparent);
+ QVERIFY(pixmap.hasAlphaChannel());
+}
+
+void tst_QPixmap::mask()
+{
+ QPixmap pm(100, 100);
+ QBitmap bm(100, 100);
+
+ pm.fill();
+ bm.fill();
+
+ QVERIFY(!pm.isNull());
+ QVERIFY(!bm.isNull());
+ if (!pm.hasAlphaChannel()) {
+ // This would fail if the default pixmap format is
+ // argb32_premultiplied. The mask will be all 1's.
+ // Therefore this is skipped when the alpha channel is present.
+ QVERIFY(pm.mask().isNull());
+ }
+
+ QImage img = bm.toImage();
+ QVERIFY(img.format() == QImage::Format_MonoLSB
+ || img.format() == QImage::Format_Mono);
+
+ pm.setMask(bm);
+ QVERIFY(!pm.mask().isNull());
+
+ bm = QBitmap();
+ // Invalid format here, since isNull() == true
+ QVERIFY(bm.toImage().isNull());
+ QCOMPARE(bm.toImage().format(), QImage::Format_Invalid);
+ pm.setMask(bm);
+ QVERIFY(pm.mask().isNull());
+
+ bm = QBitmap(100, 100);
+ bm.fill();
+ pm.setMask(bm);
+ QVERIFY(!pm.mask().isNull());
+}
+
+void tst_QPixmap::bitmapMask()
+{
+ QImage image(3, 3, QImage::Format_Mono);
+ image.setColor(0, Qt::color0);
+ image.setColor(1, Qt::color1);
+ image.fill(Qt::color0);
+ image.setPixel(1, 1, Qt::color1);
+ image.setPixel(0, 0, Qt::color1);
+
+ QImage image_mask(3, 3, QImage::Format_Mono);
+ image_mask.setColor(0, Qt::color0);
+ image_mask.setColor(1, Qt::color1);
+ image_mask.fill(Qt::color0);
+ image_mask.setPixel(1, 1, Qt::color1);
+ image_mask.setPixel(2, 0, Qt::color1);
+
+ QBitmap pm = QBitmap::fromImage(image);
+ QBitmap pm_mask = QBitmap::fromImage(image_mask);
+ pm.setMask(pm_mask);
+
+ image = pm.toImage();
+ image.setColor(0, Qt::color0);
+ image.setColor(1, Qt::color1);
+ image_mask = pm_mask.toImage();
+ image_mask.setColor(0, Qt::color0);
+ image_mask.setColor(1, Qt::color1);
+
+ QVERIFY(!image.pixel(0, 0));
+ QVERIFY(!image.pixel(2, 0));
+ QVERIFY(image.pixel(1, 1));
+}
+
+void tst_QPixmap::setGetMask_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QBitmap>("mask");
+ QTest::addColumn<QBitmap>("expected");
+
+ QPixmap pixmap(10, 10);
+ QBitmap mask(10, 10);
+ QPainter p;
+
+ p.begin(&pixmap);
+ p.fillRect(0, 0, 10, 10, QColor(Qt::black));
+ p.end();
+
+ QTest::newRow("nullmask 0") << QPixmap() << QBitmap() << QBitmap();
+ QTest::newRow("nullmask 1") << pixmap << QBitmap() << QBitmap();
+ mask.clear();
+ QTest::newRow("nullmask 2") << pixmap << mask << mask;
+ QTest::newRow("nullmask 3") << QPixmap(QBitmap()) << QBitmap() << QBitmap();
+
+ p.begin(&mask);
+ p.fillRect(1, 1, 5, 5, QColor(Qt::color1));
+ p.end();
+ QTest::newRow("simple mask 0") << pixmap << mask << mask;
+}
+
+void tst_QPixmap::setGetMask()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QBitmap, mask);
+ QFETCH(QBitmap, expected);
+
+ pixmap.setMask(mask);
+ QBitmap result = pixmap.mask();
+
+ QImage resultImage = result.toImage();
+ QImage expectedImage = expected.toImage();
+ QCOMPARE(resultImage.convertToFormat(expectedImage.format()),
+ expectedImage);
+}
+
+void tst_QPixmap::testMetrics()
+{
+ QPixmap pixmap(100, 100);
+
+ QCOMPARE(pixmap.width(), 100);
+ QCOMPARE(pixmap.height(), 100);
+ QVERIFY(pixmap.depth() >= QPixmap::defaultDepth());
+
+ QBitmap bitmap(100, 100);
+
+ QCOMPARE(bitmap.width(), 100);
+ QCOMPARE(bitmap.height(), 100);
+ QCOMPARE(bitmap.depth(), 1);
+
+ QPixmap null;
+
+ QCOMPARE(null.size().width(), null.width());
+ QCOMPARE(null.size().height(), null.height());
+}
+
+void tst_QPixmap::createMaskFromColor()
+{
+ QImage image(3, 3, QImage::Format_Indexed8);
+ image.setColorCount(10);
+ image.setColor(0, 0xffffffff);
+ image.setColor(1, 0xff000000);
+ image.setColor(2, 0xffff0000);
+ image.setColor(3, 0xff0000ff);
+ image.fill(0);
+ image.setPixel(1, 0, 1);
+ image.setPixel(0, 1, 2);
+ image.setPixel(1, 1, 3);
+
+ QImage im_mask = image.createMaskFromColor(0xffff0000);
+ QCOMPARE((uint) im_mask.pixel(0, 1), QColor(Qt::color0).rgba());
+ QCOMPARE((uint) im_mask.pixel(0, 1), QColor(Qt::color0).rgba());
+
+ QPixmap pixmap = QPixmap::fromImage(image);
+ QBitmap mask = pixmap.createMaskFromColor(Qt::red);
+ QBitmap inv_mask = pixmap.createMaskFromColor(Qt::red, Qt::MaskOutColor);
+ QCOMPARE((uint) mask.toImage().pixel(0, 1), QColor(Qt::color0).rgba());
+ QCOMPARE((uint) inv_mask.toImage().pixel(0, 1), QColor(Qt::color1).rgba());
+}
+
+
+void tst_QPixmap::cacheKey()
+{
+ QPixmap pixmap1(1, 1);
+ QPixmap pixmap2(1, 1);
+ qint64 pixmap1_key = pixmap1.cacheKey();
+
+ QVERIFY(pixmap1.cacheKey() != pixmap2.cacheKey());
+
+ pixmap2 = pixmap1;
+ QVERIFY(pixmap2.cacheKey() == pixmap1.cacheKey());
+
+ pixmap2.detach();
+ QVERIFY(pixmap2.cacheKey() != pixmap1.cacheKey());
+ QVERIFY(pixmap1.cacheKey() == pixmap1_key);
+}
+
+// Test drawing a bitmap on a pixmap.
+void tst_QPixmap::drawBitmap()
+{
+ QBitmap bitmap(10,10);
+ bitmap.fill(Qt::color1);
+
+ QPixmap pixmap(10,10);
+ QPainter painter2(&pixmap);
+ painter2.fillRect(0,0,10,10, QBrush(Qt::green));
+ painter2.setPen(Qt::red);
+ painter2.drawPixmap(0,0,10,10, bitmap);
+ painter2.end();
+
+ QPixmap expected(10, 10);
+ expected.fill(Qt::red);
+
+ QVERIFY(lenientCompare(pixmap, expected));
+}
+
+void tst_QPixmap::grabWidget()
+{
+ for (int opaque = 0; opaque < 2; ++opaque) {
+ QWidget widget;
+ QImage image(128, 128, opaque ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied);
+ for (int row = 0; row < image.height(); ++row) {
+ QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
+ for (int col = 0; col < image.width(); ++col)
+ line[col] = qRgba(rand() & 255, row, col, opaque ? 255 : 127);
+ }
+
+ QPalette pal = widget.palette();
+ pal.setBrush(QPalette::Window, QBrush(image));
+ widget.setPalette(pal);
+ widget.resize(128, 128);
+
+ QPixmap expected(64, 64);
+ if (!opaque)
+ expected.fill(Qt::transparent);
+
+ QPainter p(&expected);
+ p.translate(-64, -64);
+ p.drawTiledPixmap(0, 0, 128, 128, pal.brush(QPalette::Window).texture(), 0, 0);
+ p.end();
+
+ QPixmap actual = QPixmap::grabWidget(&widget, QRect(64, 64, 64, 64));
+ QVERIFY(lenientCompare(actual, expected));
+
+ actual = QPixmap::grabWidget(&widget, 64, 64);
+ QVERIFY(lenientCompare(actual, expected));
+
+ // Make sure a widget that is not yet shown is grabbed correctly.
+ QTreeWidget widget2;
+ actual = QPixmap::grabWidget(&widget2);
+ widget2.show();
+ expected = QPixmap::grabWidget(&widget2);
+
+ QVERIFY(lenientCompare(actual, expected));
+ }
+}
+
+void tst_QPixmap::grabWindow()
+{
+#ifdef Q_WS_QPA
+ QSKIP("QTBUG-20863 grabWindow is broken on most qpa backends", SkipAll);
+#endif
+#ifdef Q_OS_WINCE
+ // We get out of memory, if the desktop itself is too big.
+ if (QApplication::desktop()->width() <= 480)
+#endif
+ QVERIFY(QPixmap::grabWindow(QApplication::desktop()->winId()).isNull() == false);
+ QWidget w;
+ w.resize(640, 480);
+ w.show();
+ QTest::qWait(100);
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&w);
+#endif
+ QVERIFY(QPixmap::grabWindow(w.winId()).isNull() == false);
+
+ QWidget child(&w);
+ child.setGeometry(50, 50, 100, 100);
+ child.setPalette(Qt::red);
+ child.setAutoFillBackground(true);
+ child.show();
+ QTest::qWait(100);
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&child);
+#endif
+
+ QPixmap grabWindowPixmap = QPixmap::grabWindow(child.winId());
+ QPixmap grabWidgetPixmap = QPixmap::grabWidget(&child);
+ lenientCompare(grabWindowPixmap, grabWidgetPixmap);
+}
+
+void tst_QPixmap::isNull()
+{
+ {
+ QPixmap pixmap(1,1);
+ QVERIFY(pixmap.isNull() == false);
+ }
+ {
+ QPixmap pixmap(0,0);
+ QVERIFY(pixmap.isNull());
+ }
+
+ {
+ QPixmap pixmap(0,1);
+ QVERIFY(pixmap.isNull());
+ }
+ {
+ QPixmap pixmap(1,0);
+ QVERIFY(pixmap.isNull());
+ }
+ {
+ QPixmap pixmap(-1,-1);
+ QVERIFY(pixmap.isNull());
+ }
+ {
+ QPixmap pixmap(-1,5);
+ QVERIFY(pixmap.isNull());
+ }
+}
+
+void tst_QPixmap::convertFromImageNoDetach()
+{
+ QPixmap randomPixmap(10, 10);
+ if (randomPixmap.handle()->classId() != QPlatformPixmap::RasterClass)
+ QSKIP("Test only valid for raster pixmaps", SkipAll);
+
+ //first get the screen format
+ QImage::Format screenFormat = randomPixmap.toImage().format();
+ QVERIFY(screenFormat != QImage::Format_Invalid);
+
+ QImage orig(100,100, screenFormat);
+
+ QPixmap pix = QPixmap::fromImage(orig);
+ QImage copy = pix.toImage();
+
+ QVERIFY(copy.format() == screenFormat);
+
+ const QImage constOrig = orig;
+ const QImage constCopy = copy;
+ QVERIFY(constOrig.bits() == constCopy.bits());
+}
+
+void tst_QPixmap::convertFromImageDetach()
+{
+ QImage img(10,10, QImage::Format_RGB32);
+ img.fill(0);
+ QVERIFY(!img.isNull());
+ QPixmap p = QPixmap::fromImage(img);
+ QVERIFY(p.isDetached());
+ QPixmap copy = p;
+ QVERIFY(!copy.isDetached());
+ QVERIFY(!p.isDetached());
+ img.fill(1);
+ p = QPixmap::fromImage(img);
+ QVERIFY(copy.isDetached());
+}
+
+#if defined(Q_WS_WIN)
+void tst_QPixmap::toWinHBITMAP_data()
+{
+ QTest::addColumn<int>("red");
+ QTest::addColumn<int>("green");
+ QTest::addColumn<int>("blue");
+
+ QTest::newRow("red") << 255 << 0 << 0;
+ QTest::newRow("green") << 0 << 255 << 0;
+ QTest::newRow("blue") << 0 << 0 << 255;
+}
+
+void tst_QPixmap::toWinHBITMAP()
+{
+ QFETCH(int, red);
+ QFETCH(int, green);
+ QFETCH(int, blue);
+
+ QPixmap pm(100, 100);
+ pm.fill(QColor(red, green, blue));
+
+ HBITMAP bitmap = pm.toWinHBITMAP();
+
+ QVERIFY(bitmap != 0);
+
+ // Verify size
+ BITMAP bitmap_info;
+ memset(&bitmap_info, 0, sizeof(BITMAP));
+
+ int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info);
+ QVERIFY(res);
+
+ QCOMPARE(100, (int) bitmap_info.bmWidth);
+ QCOMPARE(100, (int) bitmap_info.bmHeight);
+
+ HDC display_dc = GetDC(0);
+ HDC bitmap_dc = CreateCompatibleDC(display_dc);
+
+ HBITMAP null_bitmap = (HBITMAP) SelectObject(bitmap_dc, bitmap);
+
+ COLORREF pixel = GetPixel(bitmap_dc, 0, 0);
+ QCOMPARE((int)GetRValue(pixel), red);
+ QCOMPARE((int)GetGValue(pixel), green);
+ QCOMPARE((int)GetBValue(pixel), blue);
+
+ // Clean up
+ SelectObject(bitmap_dc, null_bitmap);
+ DeleteObject(bitmap);
+ DeleteDC(bitmap_dc);
+ ReleaseDC(0, display_dc);
+
+}
+
+void tst_QPixmap::fromWinHBITMAP_data()
+{
+ toWinHBITMAP_data();
+}
+
+void tst_QPixmap::fromWinHBITMAP()
+{
+ QFETCH(int, red);
+ QFETCH(int, green);
+ QFETCH(int, blue);
+
+ HDC display_dc = GetDC(0);
+ HDC bitmap_dc = CreateCompatibleDC(display_dc);
+ HBITMAP bitmap = CreateCompatibleBitmap(display_dc, 100, 100);
+ SelectObject(bitmap_dc, bitmap);
+
+ SelectObject(bitmap_dc, GetStockObject(NULL_PEN));
+ HGDIOBJ old_brush = SelectObject(bitmap_dc, CreateSolidBrush(RGB(red, green, blue)));
+ Rectangle(bitmap_dc, 0, 0, 100, 100);
+
+#ifdef Q_OS_WINCE //the device context has to be deleted before QPixmap::fromWinHBITMAP()
+ DeleteDC(bitmap_dc);
+#endif
+ QPixmap pixmap = QPixmap::fromWinHBITMAP(bitmap);
+ QCOMPARE(pixmap.width(), 100);
+ QCOMPARE(pixmap.height(), 100);
+
+ QImage image = pixmap.toImage();
+ QRgb pixel = image.pixel(0, 0);
+ QCOMPARE(qRed(pixel), red);
+ QCOMPARE(qGreen(pixel), green);
+ QCOMPARE(qBlue(pixel), blue);
+
+ DeleteObject(SelectObject(bitmap_dc, old_brush));
+ DeleteObject(SelectObject(bitmap_dc, bitmap));
+#ifndef Q_OS_WINCE
+ DeleteDC(bitmap_dc);
+#endif
+ ReleaseDC(0, display_dc);
+}
+
+static void compareImages(const QImage &image1, const QImage &image2)
+{
+ QCOMPARE(image1.width(), image2.width());
+ QCOMPARE(image1.height(), image2.height());
+ QCOMPARE(image1.format(), image2.format());
+
+ static const int fuzz = 1;
+
+ for (int y = 0; y < image1.height(); y++)
+ {
+ for (int x = 0; x < image2.width(); x++)
+ {
+ QRgb p1 = image1.pixel(x, y);
+ QRgb p2 = image2.pixel(x, y);
+
+ bool pixelMatches =
+ qAbs(qRed(p1) - qRed(p2)) <= fuzz
+ && qAbs(qGreen(p1) - qGreen(p2)) <= fuzz
+ && qAbs(qBlue(p1) - qBlue(p2)) <= fuzz
+ && qAbs(qAlpha(p1) - qAlpha(p2)) <= fuzz;
+
+ QVERIFY(pixelMatches);
+ }
+ }
+}
+
+void tst_QPixmap::toWinHICON_data()
+{
+ QTest::addColumn<QString>("image");
+ QTest::addColumn<int>("width");
+ QTest::addColumn<int>("height");
+
+ const QString prefix = QLatin1String(SRCDIR) + "/convertFromToHICON";
+
+ QTest::newRow("32bpp_16x16") << prefix + QLatin1String("/icon_32bpp") << 16 << 16;
+ QTest::newRow("32bpp_32x32") << prefix + QLatin1String("/icon_32bpp") << 32 << 32;
+ QTest::newRow("32bpp_48x48") << prefix + QLatin1String("/icon_32bpp") << 48 << 48;
+ QTest::newRow("32bpp_256x256") << prefix + QLatin1String("/icon_32bpp") << 256 << 256;
+
+ QTest::newRow("8bpp_16x16") << prefix + QLatin1String("/icon_8bpp") << 16 << 16;
+ QTest::newRow("8bpp_32x32") << prefix + QLatin1String("/icon_8bpp") << 32 << 32;
+ QTest::newRow("8bpp_48x48") << prefix + QLatin1String("/icon_8bpp") << 48 << 48;
+}
+
+void tst_QPixmap::toWinHICON()
+{
+#ifdef Q_OS_WINCE
+ QSKIP("Test shall be enabled for Windows CE shortly.", SkipAll);
+#endif
+
+ QFETCH(int, width);
+ QFETCH(int, height);
+ QFETCH(QString, image);
+
+ QPixmap empty(width, height);
+ empty.fill(Qt::transparent);
+
+ HDC display_dc = GetDC(0);
+ HDC bitmap_dc = CreateCompatibleDC(display_dc);
+ HBITMAP bitmap = empty.toWinHBITMAP(QPixmap::Alpha);
+ SelectObject(bitmap_dc, bitmap);
+
+ QImage imageFromFile(image + QString(QLatin1String("_%1x%2.png")).arg(width).arg(height));
+ imageFromFile = imageFromFile.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ HICON icon = QPixmap::fromImage(imageFromFile).toWinHICON();
+
+ DrawIconEx(bitmap_dc, 0, 0, icon, width, height, 0, 0, DI_NORMAL);
+
+ DestroyIcon(icon);
+ DeleteDC(bitmap_dc);
+
+ QImage imageFromHICON = QPixmap::fromWinHBITMAP(bitmap, QPixmap::Alpha).toImage();
+
+ ReleaseDC(0, display_dc);
+
+ // fuzzy comparison must be used, as the pixel values change slightly during conversion
+ // between QImage::Format_ARGB32 and QImage::Format_ARGB32_Premultiplied, or elsewhere
+
+ // QVERIFY(imageFromHICON == imageFromFile);
+ compareImages(imageFromHICON, imageFromFile);
+}
+
+void tst_QPixmap::fromWinHICON_data()
+{
+ toWinHICON_data();
+}
+
+void tst_QPixmap::fromWinHICON()
+{
+#ifdef Q_OS_WINCE
+ QSKIP("Test shall be enabled for Windows CE shortly.", SkipAll);
+
+#else
+ QFETCH(int, width);
+ QFETCH(int, height);
+ QFETCH(QString, image);
+
+ HICON icon = (HICON)LoadImage(0, (wchar_t*)(image + QLatin1String(".ico")).utf16(), IMAGE_ICON, width, height, LR_LOADFROMFILE);
+ QImage imageFromHICON = QPixmap::fromWinHICON(icon).toImage();
+ DestroyIcon(icon);
+
+ QImage imageFromFile(image + QString(QLatin1String("_%1x%2.png")).arg(width).arg(height));
+ imageFromFile = imageFromFile.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ // fuzzy comparison must be used, as the pixel values change slightly during conversion
+ // between QImage::Format_ARGB32 and QImage::Format_ARGB32_Premultiplied, or elsewhere
+
+ // QVERIFY(imageFromHICON == imageFromFile);
+ compareImages(imageFromHICON, imageFromFile);
+#endif
+}
+
+#endif // Q_WS_WIN
+
+#if defined(Q_OS_SYMBIAN)
+Q_DECLARE_METATYPE(TDisplayMode)
+
+void tst_QPixmap::fromSymbianCFbsBitmap_data()
+{
+ QTest::addColumn<TDisplayMode>("format");
+ QTest::addColumn<int>("width");
+ QTest::addColumn<int>("height");
+ QTest::addColumn<QColor>("color");
+
+ const int smallWidth = 20;
+ const int smallHeight = 20;
+ const int largeWidth = 240;
+ const int largeHeight = 320;
+ const int notAlignedWidth = 250;
+ const int notAlignedHeight = 250;
+
+ // Indexed Color Formats - Disabled since images seem to be blank -> no palette?
+// QTest::newRow("EGray2 small") << EGray2 << smallWidth << smallHeight << QColor(Qt::black);
+// QTest::newRow("EGray2 big") << EGray2 << largeWidth << largeHeight << QColor(Qt::black);
+// QTest::newRow("EGray256 small") << EGray256 << smallWidth << smallHeight << QColor(Qt::blue);
+// QTest::newRow("EGray256 big") << EGray256 << largeWidth << largeHeight << QColor(Qt::blue);
+// QTest::newRow("EColor256 small") << EColor256 << smallWidth << smallHeight << QColor(Qt::red);
+// QTest::newRow("EColor256 big") << EColor256 << largeWidth << largeHeight << QColor(Qt::red);
+
+ // Direct Color Formats
+ QTest::newRow("EColor4K small") << EColor4K << smallWidth << smallHeight << QColor(Qt::red);
+ QTest::newRow("EColor4K big") << EColor4K << largeWidth << largeHeight << QColor(Qt::red);
+ QTest::newRow("EColor4K not aligned") << EColor4K << notAlignedWidth << notAlignedHeight << QColor(Qt::red);
+ QTest::newRow("EColor64K small") << EColor64K << smallWidth << smallHeight << QColor(Qt::green);
+ QTest::newRow("EColor64K big") << EColor64K << largeWidth << largeHeight << QColor(Qt::green);
+ QTest::newRow("EColor64K not aligned") << EColor64K << notAlignedWidth << notAlignedHeight << QColor(Qt::green);
+ QTest::newRow("EColor16M small") << EColor16M << smallWidth << smallHeight << QColor(Qt::yellow);
+ QTest::newRow("EColor16M big") << EColor16M << largeWidth << largeHeight << QColor(Qt::yellow);
+ QTest::newRow("EColor16M not aligned") << EColor16M << notAlignedWidth << notAlignedHeight << QColor(Qt::yellow);
+ QTest::newRow("EColor16MU small") << EColor16MU << smallWidth << smallHeight << QColor(Qt::red);
+ QTest::newRow("EColor16MU big") << EColor16MU << largeWidth << largeHeight << QColor(Qt::red);
+ QTest::newRow("EColor16MU not aligned") << EColor16MU << notAlignedWidth << notAlignedHeight << QColor(Qt::red);
+ QTest::newRow("EColor16MA small opaque") << EColor16MA << smallWidth << smallHeight << QColor(255, 255, 0);
+ QTest::newRow("EColor16MA big opaque") << EColor16MA << largeWidth << largeHeight << QColor(255, 255, 0);
+ QTest::newRow("EColor16MA not aligned opaque") << EColor16MA << notAlignedWidth << notAlignedHeight << QColor(255, 255, 0);
+
+ // Semi-transparent Colors - Disabled for now, since the QCOMPARE fails, but visually confirmed to work
+// QTest::newRow("EColor16MA small semi") << EColor16MA << smallWidth << smallHeight << QColor(255, 255, 0, 127);
+// QTest::newRow("EColor16MA big semi") << EColor16MA << largeWidth << largeHeight << QColor(255, 255, 0, 127);
+// QTest::newRow("EColor16MA small trans") << EColor16MA << smallWidth << smallHeight << QColor(255, 255, 0, 0);
+// QTest::newRow("EColor16MA big trans") << EColor16MA << largeWidth << largeHeight << QColor(255, 255, 0, 0);
+
+#if !defined(__SERIES60_31__)
+ QTest::newRow("EColor16MAP small") << EColor16MAP << smallWidth << smallHeight << QColor(Qt::red);
+ QTest::newRow("EColor16MAP big") << EColor16MAP << largeWidth << largeHeight << QColor(Qt::red);
+#endif
+}
+
+void tst_QPixmap::fromSymbianCFbsBitmap()
+{
+ QFETCH(TDisplayMode, format);
+ QFETCH(int, width);
+ QFETCH(int, height);
+ QFETCH(QColor, color);
+ int expectedDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(format);
+
+ CFbsBitmap *nativeBitmap = 0;
+ CFbsBitmapDevice *bitmapDevice = 0;
+ CBitmapContext *bitmapContext = 0;
+
+ nativeBitmap = new (ELeave) CFbsBitmap();
+ TInt err = nativeBitmap->Create(TSize(width, height), format);
+ CleanupStack::PushL(nativeBitmap);
+ QVERIFY(err == KErrNone);
+ bitmapDevice = CFbsBitmapDevice::NewL(nativeBitmap);
+ CleanupStack::PushL(bitmapDevice);
+
+ err = bitmapDevice->CreateBitmapContext(bitmapContext);
+ CleanupStack::PushL(bitmapContext);
+ QVERIFY(err == KErrNone);
+ TRgb symbianColor = TRgb(color.red(), color.green(), color.blue(), color.alpha());
+ bitmapContext->SetBrushColor(symbianColor);
+ bitmapContext->Clear();
+
+ __UHEAP_MARK;
+ { // Test the null case
+ CFbsBitmap *bitmap = 0;
+ QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(bitmap);
+ QVERIFY(pixmap.isNull());
+ }
+ __UHEAP_MARKEND;
+
+ __UHEAP_MARK;
+ { // Test the normal case
+ QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(nativeBitmap);
+// QCOMPARE(pixmap.depth(), expectedDepth); // Depth is not preserved now
+ QCOMPARE(pixmap.width(), width);
+ QCOMPARE(pixmap.height(), height);
+ QImage image = pixmap.toImage();
+
+ QColor actualColor(image.pixel(1, 1));
+ QCOMPARE(actualColor, color);
+
+ QImage shouldBe(pixmap.width(), pixmap.height(), image.format());
+ if (image.format() == QImage::Format_RGB16)
+ shouldBe.fill(qrgb565(color.rgba()).rawValue());
+ else
+ shouldBe.fill(color.rgba());
+ QCOMPARE(image, shouldBe);
+ }
+ __UHEAP_MARKEND;
+
+ CleanupStack::PopAndDestroy(3);
+}
+
+void tst_QPixmap::toSymbianCFbsBitmap_data()
+{
+ QTest::addColumn<int>("red");
+ QTest::addColumn<int>("green");
+ QTest::addColumn<int>("blue");
+
+ QTest::newRow("red") << 255 << 0 << 0;
+ QTest::newRow("green") << 0 << 255 << 0;
+ QTest::newRow("blue") << 0 << 0 << 255;
+}
+
+void tst_QPixmap::toSymbianCFbsBitmap()
+{
+ QFETCH(int, red);
+ QFETCH(int, green);
+ QFETCH(int, blue);
+
+ QPixmap pm(100, 100);
+ pm.fill(QColor(red, green, blue));
+
+ CFbsBitmap *bitmap = pm.toSymbianCFbsBitmap();
+
+ QVERIFY(bitmap != 0);
+
+ // Verify size
+ QCOMPARE(100, (int) bitmap->SizeInPixels().iWidth);
+ QCOMPARE(100, (int) bitmap->SizeInPixels().iHeight);
+
+ // Verify pixel color
+ TRgb pixel;
+ bitmap->GetPixel(pixel, TPoint(0,0));
+ QCOMPARE((int)pixel.Red(), red);
+ QCOMPARE((int)pixel.Green(), green);
+ QCOMPARE((int)pixel.Blue(), blue);
+
+ // Clean up
+ delete bitmap;
+}
+#endif
+
+void tst_QPixmap::onlyNullPixmapsOutsideGuiThread()
+{
+#ifdef Q_WS_QPA
+ QSKIP("QTBUG-20864 can't determine if threaded pixmaps are available for qpa", SkipAll);
+#endif
+#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+ class Thread : public QThread
+ {
+ public:
+ void run()
+ {
+ QTest::ignoreMessage(QtWarningMsg,
+ "QPixmap: It is not safe to use pixmaps outside the GUI thread");
+ QPixmap pixmap;
+ QVERIFY(pixmap.isNull());
+
+ QTest::ignoreMessage(QtWarningMsg,
+ "QPixmap: It is not safe to use pixmaps outside the GUI thread");
+ QPixmap pixmap1(100, 100);
+ QVERIFY(pixmap1.isNull());
+
+ QTest::ignoreMessage(QtWarningMsg,
+ "QPixmap: It is not safe to use pixmaps outside the GUI thread");
+ QPixmap pixmap2(pixmap1);
+ QVERIFY(pixmap2.isNull());
+ }
+ };
+ Thread thread;
+#if defined(Q_OS_SYMBIAN)
+ thread.setStackSize(0x10000);
+#endif
+ thread.start();
+#if defined(Q_OS_SYMBIAN)
+ QVERIFY(thread.wait(10000));
+#else
+ thread.wait();
+#endif
+
+#endif // !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+}
+
+void tst_QPixmap::refUnref()
+{
+ // Simple ref/unref
+ {
+ QPixmap p;
+ }
+ {
+ QBitmap b;
+ }
+
+ // Get a copy of a pixmap that goes out of scope
+ {
+ QPixmap b;
+ {
+ QPixmap a(10, 10);
+ a.fill(Qt::color0);
+ b = a;
+ }
+ }
+ {
+ QBitmap mask;
+ {
+ QBitmap bitmap(10, 10);
+ bitmap.fill(Qt::color1);
+ mask = bitmap.mask();
+ }
+ mask.fill(Qt::color0);
+ }
+
+}
+
+void tst_QPixmap::copy()
+{
+ QPixmap src(32, 32);
+ {
+ QPainter p(&src);
+ p.fillRect(0, 0, 32, 32, Qt::red);
+ p.fillRect(10, 10, 10, 10, Qt::blue);
+ }
+
+ QPixmap dest = src.copy(10, 10, 10, 10);
+
+ QPixmap expected(10, 10);
+ expected.fill(Qt::blue);
+ QVERIFY(lenientCompare(dest, expected));
+
+ QPixmap trans;
+ trans.fill(Qt::transparent);
+
+ QPixmap transCopy = trans.copy();
+ QVERIFY(pixmapsAreEqual(&trans, &transCopy));
+}
+
+void tst_QPixmap::depthOfNullObjects()
+{
+ QBitmap b1;
+ QVERIFY(b1.depth() == 0);
+ QPixmap p4;
+ QVERIFY(p4.depth() == 0);
+}
+
+void tst_QPixmap::transformed()
+{
+ QPixmap p1(20, 10);
+ p1.fill(Qt::red);
+ {
+ QPainter p(&p1);
+ p.drawRect(0, 0, p1.width() - 1, p1.height() - 1);
+ }
+
+ QPixmap p2(10, 20);
+ {
+ QPainter p(&p2);
+ p.rotate(90);
+ p.drawPixmap(0, -p1.height(), p1);
+ }
+
+ QPixmap p3(20, 10);
+ {
+ QPainter p(&p3);
+ p.rotate(180);
+ p.drawPixmap(-p1.width(), -p1.height(), p1);
+ }
+
+ QPixmap p4(10, 20);
+ {
+ QPainter p(&p4);
+ p.rotate(270);
+ p.drawPixmap(-p1.width(), 0, p1);
+ }
+
+ QPixmap p1_90 = p1.transformed(QTransform().rotate(90));
+ QPixmap p1_180 = p1.transformed(QTransform().rotate(180));
+ QPixmap p1_270 = p1.transformed(QTransform().rotate(270));
+
+ QVERIFY(lenientCompare(p1_90, p2));
+ QVERIFY(lenientCompare(p1_180, p3));
+ QVERIFY(lenientCompare(p1_270, p4));
+}
+
+void tst_QPixmap::transformed2()
+{
+ QPixmap pm(3, 3);
+ pm.fill(Qt::red);
+ QPainter p(&pm);
+ p.fillRect(0, 0, 3, 3, QBrush(Qt::Dense4Pattern));
+ p.end();
+
+ QTransform transform;
+ transform.rotate(-90);
+ transform.scale(3, 3);
+
+ QPixmap actual = pm.transformed(transform);
+
+ QPixmap expected(9, 9);
+ expected.fill(Qt::red);
+ p.begin(&expected);
+ p.setBrush(Qt::black);
+ p.setPen(Qt::NoPen);
+ p.drawRect(3, 0, 3, 3);
+ p.drawRect(0, 3, 3, 3);
+ p.drawRect(6, 3, 3, 3);
+ p.drawRect(3, 6, 3, 3);
+ p.end();
+
+ QVERIFY(lenientCompare(actual, expected));
+}
+
+void tst_QPixmap::fromImage_crash()
+{
+ QImage *img = new QImage(64, 64, QImage::Format_ARGB32_Premultiplied);
+
+ QPixmap pm = QPixmap::fromImage(*img);
+ QPainter painter(&pm);
+
+ delete img;
+}
+
+//This is testing QPlatformPixmap::createCompatiblePlatformPixmap - see QTBUG-5977
+void tst_QPixmap::splash_crash()
+{
+ QPixmap pix;
+ pix = QPixmap(":/images/designer.png");
+ QSplashScreen splash(pix);
+ splash.show();
+ QCoreApplication::processEvents();
+ splash.close();
+}
+
+void tst_QPixmap::fromData()
+{
+ unsigned char bits[] = { 0xaa, 0x55 };
+
+ QBitmap bm = QBitmap::fromData(QSize(8, 2), bits);
+ QImage img = bm.toImage();
+
+ QSet<QRgb> colors;
+ for (int y = 0; y < img.height(); ++y)
+ for (int x = 0; x < img.width(); ++x)
+ colors << img.pixel(x, y);
+
+ QCOMPARE(colors.size(), 2);
+
+ QCOMPARE(img.pixel(0, 0), QRgb(0xffffffff));
+ QCOMPARE(img.pixel(0, 1), QRgb(0xff000000));
+}
+
+void tst_QPixmap::loadFromDataNullValues()
+{
+ {
+ QPixmap pixmap;
+ pixmap.loadFromData(QByteArray());
+ QVERIFY(pixmap.isNull());
+ }
+ {
+ QPixmap pixmap;
+ pixmap.loadFromData(0, 123);
+ QVERIFY(pixmap.isNull());
+ }
+ {
+ QPixmap pixmap;
+ const uchar bla[] = "bla";
+ pixmap.loadFromData(bla, 0);
+ QVERIFY(pixmap.isNull());
+ }
+}
+
+void tst_QPixmap::loadFromDataImage_data()
+{
+ QTest::addColumn<QString>("imagePath");
+#ifdef Q_OS_SYMBIAN
+ const QString prefix = QLatin1String(SRCDIR) + "loadFromData";
+#else
+ const QString prefix = QLatin1String(SRCDIR) + "/loadFromData";
+#endif
+ QTest::newRow("designer_argb32.png") << prefix + "/designer_argb32.png";
+ // When no extension is provided we try all extensions that has been registered by image providers
+ QTest::newRow("designer_argb32") << prefix + "/designer_argb32.png";
+ QTest::newRow("designer_indexed8_no_alpha.png") << prefix + "/designer_indexed8_no_alpha.png";
+ QTest::newRow("designer_indexed8_with_alpha.png") << prefix + "/designer_indexed8_with_alpha.png";
+ QTest::newRow("designer_rgb32.png") << prefix + "/designer_rgb32.png";
+ QTest::newRow("designer_indexed8_no_alpha.gif") << prefix + "/designer_indexed8_no_alpha.gif";
+ QTest::newRow("designer_indexed8_with_alpha.gif") << prefix + "/designer_indexed8_with_alpha.gif";
+ QTest::newRow("designer_rgb32.jpg") << prefix + "/designer_rgb32.jpg";
+}
+
+void tst_QPixmap::loadFromDataImage()
+{
+ QFETCH(QString, imagePath);
+
+ QImage imageRef(imagePath);
+ QPixmap pixmapWithCopy = QPixmap::fromImage(imageRef);
+
+ QFile file(imagePath);
+ file.open(QIODevice::ReadOnly);
+ QByteArray rawData = file.readAll();
+
+ QPixmap directLoadingPixmap;
+ directLoadingPixmap.loadFromData(rawData);
+
+ QVERIFY(pixmapsAreEqual(&pixmapWithCopy, &directLoadingPixmap));
+}
+
+void tst_QPixmap::fromImageReader_data()
+{
+ QTest::addColumn<QString>("imagePath");
+#ifdef Q_OS_SYMBIAN
+ const QString prefix = QLatin1String(SRCDIR) + "loadFromData";
+#else
+ const QString prefix = QLatin1String(SRCDIR) + "/loadFromData";
+#endif
+ QTest::newRow("designer_argb32.png") << prefix + "/designer_argb32.png";
+ QTest::newRow("designer_indexed8_no_alpha.png") << prefix + "/designer_indexed8_no_alpha.png";
+ QTest::newRow("designer_indexed8_with_alpha.png") << prefix + "/designer_indexed8_with_alpha.png";
+ QTest::newRow("designer_rgb32.png") << prefix + "/designer_rgb32.png";
+ QTest::newRow("designer_indexed8_no_alpha.gif") << prefix + "/designer_indexed8_no_alpha.gif";
+ QTest::newRow("designer_indexed8_with_alpha.gif") << prefix + "/designer_indexed8_with_alpha.gif";
+ QTest::newRow("designer_rgb32.jpg") << prefix + "/designer_rgb32.jpg";
+ QTest::newRow("designer_indexed8_with_alpha_animated") << prefix + "/designer_indexed8_with_alpha_animated.gif";
+ QTest::newRow("designer_indexed8_with_alpha_animated") << prefix + "/designer_indexed8_no_alpha_animated.gif";
+}
+
+void tst_QPixmap::fromImageReader()
+{
+ QFETCH(QString, imagePath);
+
+ QImage imageRef(imagePath);
+ QPixmap pixmapWithCopy = QPixmap::fromImage(imageRef);
+
+ QImageReader imageReader(imagePath);
+
+ QPixmap directLoadingPixmap = QPixmap::fromImageReader(&imageReader);
+
+ QVERIFY(pixmapsAreEqual(&pixmapWithCopy, &directLoadingPixmap));
+}
+
+void tst_QPixmap::fromImageReaderAnimatedGif_data()
+{
+ QTest::addColumn<QString>("imagePath");
+ QTest::newRow("gif with alpha") << QString::fromLatin1("/designer_indexed8_with_alpha_animated.gif");
+ QTest::newRow("gif without alpha") << QString::fromLatin1("/designer_indexed8_no_alpha_animated.gif");
+}
+
+void tst_QPixmap::fromImageReaderAnimatedGif()
+{
+ QFETCH(QString, imagePath);
+#ifdef Q_OS_SYMBIAN
+ const QString prefix = QLatin1String(SRCDIR) + "loadFromData";
+#else
+ const QString prefix = QLatin1String(SRCDIR) + "/loadFromData";
+#endif
+ const QString path = prefix + imagePath;
+
+ QImageReader referenceReader(path);
+ QImageReader pixmapReader(path);
+
+ QVERIFY(referenceReader.canRead());
+ QVERIFY(referenceReader.imageCount() > 1);
+
+ for (int i = 0; i < referenceReader.imageCount(); ++i) {
+ QImage refImage = referenceReader.read();
+ QPixmap refPixmap = QPixmap::fromImage(refImage);
+
+ QPixmap directLoadingPixmap = QPixmap::fromImageReader(&pixmapReader);
+ QVERIFY(pixmapsAreEqual(&refPixmap, &directLoadingPixmap));
+ }
+}
+
+void tst_QPixmap::task_246446()
+{
+ // This crashed without the bugfix in 246446
+ QPixmap pm(10, 10);
+ pm.fill(Qt::transparent); // force 32-bit depth
+ QBitmap bm;
+ pm.setMask(bm);
+ {
+ QPixmap pm2(pm);
+ }
+ QVERIFY(pm.width() == 10);
+ QVERIFY(pm.mask().isNull());
+}
+
+void tst_QPixmap::preserveDepth()
+{
+ QPixmap target(64, 64);
+ target.fill(Qt::transparent);
+
+ QPixmap source(64, 64);
+ source.fill(Qt::white);
+
+ int depth = source.depth();
+
+ QPainter painter(&target);
+ painter.setBrush(source);
+ painter.drawRect(target.rect());
+ painter.end();
+
+ QCOMPARE(depth, source.depth());
+}
+
+void tst_QPixmap::loadAsBitmapOrPixmap()
+{
+ QImage tmp(10, 10, QImage::Format_RGB32);
+ tmp.save("temp_image.png");
+
+ bool ok;
+
+ // Check that we can load the pixmap as a pixmap and that it then turns into a pixmap
+ QPixmap pixmap("temp_image.png");
+ QVERIFY(!pixmap.isNull());
+ QVERIFY(pixmap.depth() > 1);
+ QVERIFY(!pixmap.isQBitmap());
+
+ pixmap = QPixmap();
+ ok = pixmap.load("temp_image.png");
+ QVERIFY(ok);
+ QVERIFY(!pixmap.isNull());
+ QVERIFY(pixmap.depth() > 1);
+ QVERIFY(!pixmap.isQBitmap());
+
+ //now we can try to load it without an extension
+ pixmap = QPixmap();
+ ok = pixmap.load("temp_image");
+ QVERIFY(ok);
+ QVERIFY(!pixmap.isNull());
+ QVERIFY(pixmap.depth() > 1);
+ QVERIFY(!pixmap.isQBitmap());
+
+ // The do the same check for bitmaps..
+ QBitmap bitmap("temp_image.png");
+ QVERIFY(!bitmap.isNull());
+ QVERIFY(bitmap.depth() == 1);
+ QVERIFY(bitmap.isQBitmap());
+
+ bitmap = QBitmap();
+ ok = bitmap.load("temp_image.png");
+ QVERIFY(ok);
+ QVERIFY(!bitmap.isNull());
+ QVERIFY(bitmap.depth() == 1);
+ QVERIFY(bitmap.isQBitmap());
+}
+
+void tst_QPixmap::toImageDeepCopy()
+{
+ QPixmap pixmap(64, 64);
+ pixmap.fill(Qt::white);
+
+ QPainter painter(&pixmap);
+ QImage first = pixmap.toImage();
+
+ painter.setBrush(Qt::black);
+ painter.drawEllipse(pixmap.rect());
+
+ QImage second = pixmap.toImage();
+
+ QVERIFY(first != second);
+}
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG)
+Q_OPENVG_EXPORT VGImage qPixmapToVGImage(const QPixmap& pixmap);
+class FriendlyVGPlatformPixmap : public QVGPlatformPixmap
+{
+public:
+ FriendlyVGPlatformPixmap(PixelType type) : QVGPlatformPixmap(type) { }
+ bool sourceIsNull() { return source.isNull(); }
+ friend QPixmap pixmapFromVGImage(VGImage image);
+};
+QPixmap pixmapFromVGImage(VGImage image)
+{
+ if (image != VG_INVALID_HANDLE) {
+ int w = vgGetParameteri(image, VG_IMAGE_WIDTH);
+ int h = vgGetParameteri(image, VG_IMAGE_HEIGHT);
+ FriendlyVGPlatformPixmap *pd = new FriendlyVGPlatformPixmap(QPlatformPixmap::PixmapType);
+ pd->resize(w, h);
+ pd->vgImage = image;
+ pd->recreate = false;
+ pd->prevSize = QSize(pd->w, pd->h);
+ return QPixmap(pd);
+ }
+ return QPixmap();
+}
+class Content : public QWidget
+{
+public:
+ void paintEvent(QPaintEvent *) {
+ QPainter painter(this);
+ QColor testPixel(qRgb(200, 150, 100));
+ if (pm.isNull()) { // first phase: create a VGImage
+ painter.beginNativePainting();
+ vgimage = vgCreateImage(VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER);
+ QImage img(20, 10, QImage::Format_ARGB32_Premultiplied);
+ img.fill(qRgb(0, 0, 0));
+ QPainter p(&img);
+ p.fillRect(0, 0, img.width(), img.height(), testPixel);
+ p.end();
+ vgImageSubData(vgimage, img.bits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
+ // Now the area 0,0 20x10 (in OpenVG coords) is filled with some color.
+ painter.endNativePainting();
+ } else { // second phase: check if readback works
+ painter.drawPixmap(0, 0, pm);
+ // Drawing should not cause readback, this is important for performance;
+ noreadback_ok = static_cast<FriendlyVGPlatformPixmap *>(pm.handle())->sourceIsNull();
+ // However toImage() requires readback.
+ QImage img = pm.toImage();
+ readback_ok = img.width() == pm.width();
+ readback_ok &= img.height() == pm.height();
+ readback_ok &= !static_cast<FriendlyVGPlatformPixmap *>(pm.handle())->sourceIsNull();
+ uint pix = img.pixel(1, 1);
+ content_ok = qRed(pix) == testPixel.red();
+ content_ok &= qGreen(pix) == testPixel.green();
+ content_ok &= qBlue(pix) == testPixel.blue();
+ pix = img.pixel(img.width() - 1, img.height() - 1);
+ content_ok &= qRed(pix) == 0;
+ content_ok &= qGreen(pix) == 0;
+ content_ok &= qBlue(pix) == 0;
+ }
+ }
+ int w;
+ int h;
+ VGImage vgimage;
+ QPixmap pm;
+ bool noreadback_ok;
+ bool readback_ok;
+ bool content_ok;
+};
+void tst_QPixmap::vgImageReadBack()
+{
+ QPixmap tmp(10, 20);
+ if (tmp.handle()->classId() == QPlatformPixmap::OpenVGClass) {
+ Content c;
+ c.w = 50;
+ c.h = 60;
+ c.vgimage = VG_INVALID_HANDLE;
+ c.noreadback_ok = c.readback_ok = c.content_ok = false;
+ c.showFullScreen();
+ QTest::qWaitForWindowShown(&c);
+ QVERIFY(c.vgimage != VG_INVALID_HANDLE);
+ QPixmap pm = pixmapFromVGImage(c.vgimage);
+ QVERIFY(!pm.isNull());
+ QCOMPARE(pm.width(), c.w);
+ QCOMPARE(pm.height(), c.h);
+ QVERIFY(qPixmapToVGImage(pm) == c.vgimage);
+ QVERIFY(static_cast<FriendlyVGPlatformPixmap *>(pm.handle())->sourceIsNull());
+ c.pm = pm;
+ // Make sure the second phase in paintEvent is executed too.
+ c.hide();
+ c.showFullScreen();
+ QTest::qWaitForWindowShown(&c);
+ QVERIFY(c.noreadback_ok);
+ QVERIFY(c.readback_ok);
+ QVERIFY(c.content_ok);
+ } else {
+ QSKIP("Not using openvg graphicssystem", SkipSingle);
+ }
+}
+#endif // Symbian & OpenVG
+
+void tst_QPixmap::scaled_QTBUG19157()
+{
+ QPixmap foo(5000, 1);
+ foo = foo.scaled(1024, 1024, Qt::KeepAspectRatio);
+ QVERIFY(!foo.isNull());
+}
+
+QTEST_MAIN(tst_QPixmap)
+#include "tst_qpixmap.moc"
diff --git a/tests/auto/gui/image/qpixmapcache/.gitignore b/tests/auto/gui/image/qpixmapcache/.gitignore
new file mode 100644
index 0000000000..2bc572c2dd
--- /dev/null
+++ b/tests/auto/gui/image/qpixmapcache/.gitignore
@@ -0,0 +1 @@
+tst_qpixmapcache
diff --git a/tests/auto/gui/image/qpixmapcache/qpixmapcache.pro b/tests/auto/gui/image/qpixmapcache/qpixmapcache.pro
new file mode 100644
index 0000000000..1ffafd6c25
--- /dev/null
+++ b/tests/auto/gui/image/qpixmapcache/qpixmapcache.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += gui-private
+SOURCES += tst_qpixmapcache.cpp
+
+
+
diff --git a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp
new file mode 100644
index 0000000000..9f7192dc1c
--- /dev/null
+++ b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp
@@ -0,0 +1,521 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define Q_TEST_QPIXMAPCACHE
+
+#include <QtTest/QtTest>
+
+
+#include <qpixmapcache.h>
+#include "../../../src/gui/image/qpixmapcache_p.h"
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPixmapCache : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPixmapCache();
+ virtual ~tst_QPixmapCache();
+
+
+public slots:
+ void init();
+private slots:
+ void cacheLimit();
+ void setCacheLimit();
+ void find();
+ void insert();
+ void replace();
+ void remove();
+ void clear();
+ void pixmapKey();
+ void noLeak();
+};
+
+static QPixmapCache::KeyData* getPrivate(QPixmapCache::Key &key)
+{
+ return (*reinterpret_cast<QPixmapCache::KeyData**>(&key));
+}
+
+static QPixmapCache::KeyData** getPrivateRef(QPixmapCache::Key &key)
+{
+ return (reinterpret_cast<QPixmapCache::KeyData**>(&key));
+}
+
+static int originalCacheLimit;
+
+tst_QPixmapCache::tst_QPixmapCache()
+{
+ originalCacheLimit = QPixmapCache::cacheLimit();
+}
+
+tst_QPixmapCache::~tst_QPixmapCache()
+{
+}
+
+void tst_QPixmapCache::init()
+{
+ QPixmapCache::setCacheLimit(originalCacheLimit);
+ QPixmapCache::clear();
+}
+
+void tst_QPixmapCache::cacheLimit()
+{
+ // make sure the default is reasonable;
+ // it was between 2048 and 10240 last time I looked at it
+ QVERIFY(originalCacheLimit >= 1024 && originalCacheLimit <= 20480);
+
+ QPixmapCache::setCacheLimit(100);
+ QCOMPARE(QPixmapCache::cacheLimit(), 100);
+
+ QPixmapCache::setCacheLimit(-50);
+ QCOMPARE(QPixmapCache::cacheLimit(), -50);
+}
+
+void tst_QPixmapCache::setCacheLimit()
+{
+ QPixmap *p1 = new QPixmap(2, 3);
+ QPixmapCache::insert("P1", *p1);
+ QVERIFY(QPixmapCache::find("P1") != 0);
+ delete p1;
+
+ QPixmapCache::setCacheLimit(0);
+ QVERIFY(QPixmapCache::find("P1") == 0);
+
+ p1 = new QPixmap(2, 3);
+ QPixmapCache::setCacheLimit(1000);
+ QPixmapCache::insert("P1", *p1);
+ QVERIFY(QPixmapCache::find("P1") != 0);
+
+ delete p1;
+
+ //The int part of the API
+ p1 = new QPixmap(2, 3);
+ QPixmapCache::Key key = QPixmapCache::insert(*p1);
+ QVERIFY(QPixmapCache::find(key, p1) != 0);
+ delete p1;
+
+ QPixmapCache::setCacheLimit(0);
+ QVERIFY(QPixmapCache::find(key, p1) == 0);
+
+ p1 = new QPixmap(2, 3);
+ QPixmapCache::setCacheLimit(1000);
+ QPixmapCache::replace(key, *p1);
+ QVERIFY(QPixmapCache::find(key, p1) == 0);
+
+ delete p1;
+
+ //Let check if keys are released when the pixmap cache is
+ //full or has been flushed.
+ QPixmapCache::clear();
+ p1 = new QPixmap(2, 3);
+ key = QPixmapCache::insert(*p1);
+ QVERIFY(QPixmapCache::find(key, p1) != 0);
+ p1->detach(); // dectach so that the cache thinks no-one is using it.
+ QPixmapCache::setCacheLimit(0);
+ QVERIFY(QPixmapCache::find(key, p1) == 0);
+ QPixmapCache::setCacheLimit(1000);
+ key = QPixmapCache::insert(*p1);
+ QCOMPARE(getPrivate(key)->isValid, true);
+ QCOMPARE(getPrivate(key)->key, 1);
+
+ delete p1;
+
+ //Let check if removing old entries doesn't let you get
+ // wrong pixmaps
+ QPixmapCache::clear();
+ QPixmap p2;
+ p1 = new QPixmap(2, 3);
+ key = QPixmapCache::insert(*p1);
+ QVERIFY(QPixmapCache::find(key, &p2) != 0);
+ //we flush the cache
+ p1->detach();
+ p2.detach();
+ QPixmapCache::setCacheLimit(0);
+ QPixmapCache::setCacheLimit(1000);
+ QPixmapCache::Key key2 = QPixmapCache::insert(*p1);
+ QCOMPARE(getPrivate(key2)->key, 1);
+ QVERIFY(QPixmapCache::find(key, &p2) == 0);
+ QVERIFY(QPixmapCache::find(key2, &p2) != 0);
+ QCOMPARE(p2, *p1);
+
+ delete p1;
+
+ //Here we simulate the flushing when the app is idle
+ QPixmapCache::clear();
+ QPixmapCache::setCacheLimit(originalCacheLimit);
+ p1 = new QPixmap(300, 300);
+ key = QPixmapCache::insert(*p1);
+ p1->detach();
+ QCOMPARE(getPrivate(key)->key, 1);
+ key2 = QPixmapCache::insert(*p1);
+ p1->detach();
+ key2 = QPixmapCache::insert(*p1);
+ p1->detach();
+ QPixmapCache::Key key3 = QPixmapCache::insert(*p1);
+ p1->detach();
+ QPixmapCache::flushDetachedPixmaps();
+ key2 = QPixmapCache::insert(*p1);
+ QCOMPARE(getPrivate(key2)->key, 1);
+ //This old key is not valid anymore after the flush
+ QCOMPARE(getPrivate(key)->isValid, false);
+ QVERIFY(QPixmapCache::find(key, &p2) == 0);
+ delete p1;
+}
+
+void tst_QPixmapCache::find()
+{
+ QPixmap p1(10, 10);
+ p1.fill(Qt::red);
+ QVERIFY(QPixmapCache::insert("P1", p1));
+
+ QPixmap p2;
+ QVERIFY(QPixmapCache::find("P1", p2));
+ QCOMPARE(p2.width(), 10);
+ QCOMPARE(p2.height(), 10);
+ QCOMPARE(p1, p2);
+
+ // obsolete
+ QPixmap *p3 = QPixmapCache::find("P1");
+ QVERIFY(p3);
+ QCOMPARE(p1, *p3);
+
+ //The int part of the API
+ QPixmapCache::Key key = QPixmapCache::insert(p1);
+
+ QVERIFY(QPixmapCache::find(key, &p2));
+ QCOMPARE(p2.width(), 10);
+ QCOMPARE(p2.height(), 10);
+ QCOMPARE(p1, p2);
+
+ QPixmapCache::clear();
+ QPixmapCache::setCacheLimit(128);
+
+ QPixmap p4(10,10);
+ key = QPixmapCache::insert(p4);
+ p4.detach();
+
+ QPixmap p5(10,10);
+ QList<QPixmapCache::Key> keys;
+ for (int i = 0; i < 4000; ++i)
+ QPixmapCache::insert(p5);
+
+ //at that time the first key has been erase because no more place in the cache
+ QVERIFY(QPixmapCache::find(key, &p1) == 0);
+ QCOMPARE(getPrivate(key)->isValid, false);
+}
+
+void tst_QPixmapCache::insert()
+{
+ QPixmap p1(10, 10);
+ p1.fill(Qt::red);
+
+ QPixmap p2(10, 10);
+ p2.fill(Qt::yellow);
+
+ // Calcuate estimated num of items what fits to cache
+ int estimatedNum = (1024 * QPixmapCache::cacheLimit())
+ / ((p1.width() * p1.height() * p1.depth()) / 8);
+
+ // Mare sure we will put enough items to reach the cache limit
+ const int numberOfKeys = estimatedNum + 1000;
+
+ // make sure it doesn't explode
+ for (int i = 0; i < numberOfKeys; ++i)
+ QPixmapCache::insert("0", p1);
+
+ // ditto
+ for (int j = 0; j < numberOfKeys; ++j) {
+ QPixmap p3(10, 10);
+ QPixmapCache::insert(QString::number(j), p3);
+ }
+
+ int num = 0;
+ for (int k = 0; k < numberOfKeys; ++k) {
+ if (QPixmapCache::find(QString::number(k)))
+ ++num;
+ }
+
+ if (QPixmapCache::find("0"))
+ ++num;
+
+ QVERIFY(num <= estimatedNum);
+ QPixmap p3;
+ QPixmapCache::insert("null", p3);
+
+ QPixmap c1(10, 10);
+ c1.fill(Qt::yellow);
+ QPixmapCache::insert("custom", c1);
+ QVERIFY(!c1.isDetached());
+ QPixmap c2(10, 10);
+ c2.fill(Qt::red);
+ QPixmapCache::insert("custom", c2);
+ //We have deleted the old pixmap in the cache for the same key
+ QVERIFY(c1.isDetached());
+
+ //The int part of the API
+ // make sure it doesn't explode
+ QList<QPixmapCache::Key> keys;
+ for (int i = 0; i < numberOfKeys; ++i) {
+ QPixmap p3(10,10);
+ keys.append(QPixmapCache::insert(p3));
+ }
+
+ num = 0;
+ for (int k = 0; k < numberOfKeys; ++k) {
+ if (QPixmapCache::find(keys.at(k), &p2))
+ ++num;
+ }
+
+ estimatedNum = (1024 * QPixmapCache::cacheLimit())
+ / ((p1.width() * p1.height() * p1.depth()) / 8);
+ QVERIFY(num <= estimatedNum);
+}
+
+void tst_QPixmapCache::replace()
+{
+ //The int part of the API
+ QPixmap p1(10, 10);
+ p1.fill(Qt::red);
+
+ QPixmap p2(10, 10);
+ p2.fill(Qt::yellow);
+
+ QPixmapCache::Key key = QPixmapCache::insert(p1);
+ QCOMPARE(getPrivate(key)->isValid, true);
+
+ QPixmap p3;
+ QVERIFY(QPixmapCache::find(key, &p3) == 1);
+
+ QPixmapCache::replace(key, p2);
+
+ QVERIFY(QPixmapCache::find(key, &p3) == 1);
+ QCOMPARE(getPrivate(key)->isValid, true);
+ QCOMPARE(getPrivate(key)->key, 1);
+
+ QCOMPARE(p3.width(), 10);
+ QCOMPARE(p3.height(), 10);
+ QCOMPARE(p3, p2);
+
+ //Broken keys
+ QCOMPARE(QPixmapCache::replace(QPixmapCache::Key(), p2), false);
+}
+
+void tst_QPixmapCache::remove()
+{
+ QPixmap p1(10, 10);
+ p1.fill(Qt::red);
+
+ QPixmapCache::insert("red", p1);
+ p1.fill(Qt::yellow);
+
+ QPixmap p2;
+ QVERIFY(QPixmapCache::find("red", p2));
+ QVERIFY(p1.toImage() != p2.toImage());
+ QVERIFY(p1.toImage() == p1.toImage()); // sanity check
+
+ QPixmapCache::remove("red");
+ QVERIFY(QPixmapCache::find("red") == 0);
+ QPixmapCache::remove("red");
+ QVERIFY(QPixmapCache::find("red") == 0);
+
+ QPixmapCache::remove("green");
+ QVERIFY(QPixmapCache::find("green") == 0);
+
+ //The int part of the API
+ QPixmapCache::clear();
+ p1.fill(Qt::red);
+ QPixmapCache::Key key = QPixmapCache::insert(p1);
+ p1.fill(Qt::yellow);
+
+ QVERIFY(QPixmapCache::find(key, &p2));
+ QVERIFY(p1.toImage() != p2.toImage());
+ QVERIFY(p1.toImage() == p1.toImage()); // sanity check
+
+ QPixmapCache::remove(key);
+ QVERIFY(QPixmapCache::find(key, &p1) == 0);
+
+ //Broken key
+ QPixmapCache::remove(QPixmapCache::Key());
+ QVERIFY(QPixmapCache::find(QPixmapCache::Key(), &p1) == 0);
+
+ //Test if keys are release
+ QPixmapCache::clear();
+ key = QPixmapCache::insert(p1);
+ QCOMPARE(getPrivate(key)->key, 1);
+ QPixmapCache::remove(key);
+ key = QPixmapCache::insert(p1);
+ QCOMPARE(getPrivate(key)->key, 1);
+
+ //Test if pixmaps are correctly deleted
+ QPixmapCache::clear();
+ key = QPixmapCache::insert(p1);
+ QCOMPARE(getPrivate(key)->key, 1);
+ QVERIFY(QPixmapCache::find(key, &p1) != 0);
+ QPixmapCache::remove(key);
+ QCOMPARE(p1.isDetached(), true);
+
+ //We mix both part of the API
+ QPixmapCache::clear();
+ p1.fill(Qt::red);
+ QPixmapCache::insert("red", p1);
+ key = QPixmapCache::insert(p1);
+ QPixmapCache::remove(key);
+ QVERIFY(QPixmapCache::find(key, &p1) == 0);
+ QVERIFY(QPixmapCache::find("red") != 0);
+}
+
+void tst_QPixmapCache::clear()
+{
+ QPixmap p1(10, 10);
+ p1.fill(Qt::red);
+
+ // Calcuate estimated num of items what fits to cache
+ int estimatedNum = (1024 * QPixmapCache::cacheLimit())
+ / ((p1.width() * p1.height() * p1.depth()) / 8);
+
+ // Mare sure we will put enough items to reach the cache limit
+ const int numberOfKeys = estimatedNum + 1000;
+
+ for (int i = 0; i < numberOfKeys; ++i)
+ QVERIFY(QPixmapCache::find("x" + QString::number(i)) == 0);
+
+ for (int j = 0; j < numberOfKeys; ++j)
+ QPixmapCache::insert(QString::number(j), p1);
+
+ int num = 0;
+ for (int k = 0; k < numberOfKeys; ++k) {
+ if (QPixmapCache::find(QString::number(k), p1))
+ ++num;
+ }
+ QVERIFY(num > 0);
+
+ QPixmapCache::clear();
+
+ for (int k = 0; k < numberOfKeys; ++k)
+ QVERIFY(QPixmapCache::find(QString::number(k)) == 0);
+
+ //The int part of the API
+ QPixmap p2(10, 10);
+ p2.fill(Qt::red);
+
+ QList<QPixmapCache::Key> keys;
+ for (int k = 0; k < numberOfKeys; ++k)
+ keys.append(QPixmapCache::insert(p2));
+
+ QPixmapCache::clear();
+
+ for (int k = 0; k < numberOfKeys; ++k) {
+ QVERIFY(QPixmapCache::find(keys.at(k), &p1) == 0);
+ QCOMPARE(getPrivate(keys[k])->isValid, false);
+ }
+}
+
+void tst_QPixmapCache::pixmapKey()
+{
+ QPixmapCache::Key key;
+ //Default constructed keys have no d pointer unless
+ //we use them
+ QVERIFY(!getPrivate(key));
+ //Let's put a d pointer
+ QPixmapCache::KeyData** keyd = getPrivateRef(key);
+ *keyd = new QPixmapCache::KeyData;
+ QCOMPARE(getPrivate(key)->ref, 1);
+ QPixmapCache::Key key2;
+ //Let's put a d pointer
+ QPixmapCache::KeyData** key2d = getPrivateRef(key2);
+ *key2d = new QPixmapCache::KeyData;
+ QCOMPARE(getPrivate(key2)->ref, 1);
+ key = key2;
+ QCOMPARE(getPrivate(key2)->ref, 2);
+ QCOMPARE(getPrivate(key)->ref, 2);
+ QPixmapCache::Key key3;
+ //Let's put a d pointer
+ QPixmapCache::KeyData** key3d = getPrivateRef(key3);
+ *key3d = new QPixmapCache::KeyData;
+ QPixmapCache::Key key4 = key3;
+ QCOMPARE(getPrivate(key3)->ref, 2);
+ QCOMPARE(getPrivate(key4)->ref, 2);
+ key4 = key;
+ QCOMPARE(getPrivate(key4)->ref, 3);
+ QCOMPARE(getPrivate(key3)->ref, 1);
+ QPixmapCache::Key key5(key3);
+ QCOMPARE(getPrivate(key3)->ref, 2);
+ QCOMPARE(getPrivate(key5)->ref, 2);
+
+ //let test default constructed keys
+ QPixmapCache::Key key6;
+ QVERIFY(!getPrivate(key6));
+ QPixmapCache::Key key7;
+ QVERIFY(!getPrivate(key7));
+ key6 = key7;
+ QVERIFY(!getPrivate(key6));
+ QVERIFY(!getPrivate(key7));
+ QPixmapCache::Key key8(key7);
+ QVERIFY(!getPrivate(key8));
+}
+
+QT_BEGIN_NAMESPACE
+extern int q_QPixmapCache_keyHashSize();
+QT_END_NAMESPACE
+
+void tst_QPixmapCache::noLeak()
+{
+ QPixmapCache::Key key;
+
+ int oldSize = q_QPixmapCache_keyHashSize();
+ for (int i = 0; i < 100; ++i) {
+ QPixmap pm(128, 128);
+ pm.fill(Qt::transparent);
+ key = QPixmapCache::insert(pm);
+ QPixmapCache::remove(key);
+ }
+ int newSize = q_QPixmapCache_keyHashSize();
+
+ QCOMPARE(oldSize, newSize);
+}
+
+QTEST_MAIN(tst_QPixmapCache)
+#include "tst_qpixmapcache.moc"
diff --git a/tests/auto/gui/image/qpixmapfilter/noise.png b/tests/auto/gui/image/qpixmapfilter/noise.png
new file mode 100644
index 0000000000..1bebaf528e
--- /dev/null
+++ b/tests/auto/gui/image/qpixmapfilter/noise.png
Binary files differ
diff --git a/tests/auto/gui/image/qpixmapfilter/qpixmapfilter.pro b/tests/auto/gui/image/qpixmapfilter/qpixmapfilter.pro
new file mode 100644
index 0000000000..21e10b7ab9
--- /dev/null
+++ b/tests/auto/gui/image/qpixmapfilter/qpixmapfilter.pro
@@ -0,0 +1,13 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += gui-private
+
+SOURCES += tst_qpixmapfilter.cpp
+
+wince*: {
+ addFiles.files = noise.png
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+}
+
diff --git a/tests/auto/gui/image/qpixmapfilter/tst_qpixmapfilter.cpp b/tests/auto/gui/image/qpixmapfilter/tst_qpixmapfilter.cpp
new file mode 100644
index 0000000000..5634285ad4
--- /dev/null
+++ b/tests/auto/gui/image/qpixmapfilter/tst_qpixmapfilter.cpp
@@ -0,0 +1,450 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qpixmap.h>
+#include <private/qpixmapfilter_p.h>
+#include <qpainter.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPixmapFilter : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPixmapFilter();
+ virtual ~tst_QPixmapFilter();
+
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void colorizeSetColor();
+ void colorizeSetStrength();
+ void colorizeProcess();
+ void colorizeDraw();
+ void colorizeDrawStrength();
+ void colorizeDrawSubRect();
+ void colorizeProcessSubRect();
+ void convolutionBoundingRectFor();
+ void convolutionDrawSubRect();
+ void dropShadowBoundingRectFor();
+ void blurIndexed8();
+
+ void testDefaultImplementations();
+};
+
+class CustomFilter : public QPixmapFilter
+{
+public:
+ enum { Type = QPixmapFilter::UserFilter + 1 };
+
+ CustomFilter() : QPixmapFilter((QPixmapFilter::FilterType) Type, 0) { };
+
+ void draw(QPainter *p, const QPointF &pt, const QPixmap &src, const QRectF &srcRect = QRectF()) const {
+ p->drawPixmap(QRectF(pt, srcRect.size()), src, srcRect);
+ }
+};
+
+tst_QPixmapFilter::tst_QPixmapFilter()
+{
+}
+
+tst_QPixmapFilter::~tst_QPixmapFilter()
+{
+}
+
+void tst_QPixmapFilter::init()
+{
+}
+
+void tst_QPixmapFilter::cleanup()
+{
+}
+
+void tst_QPixmapFilter::testDefaultImplementations()
+{
+ CustomFilter filter;
+ QCOMPARE(filter.type(), (QPixmapFilter::FilterType) CustomFilter::Type);
+
+ QCOMPARE(filter.boundingRectFor(QRectF(1, 2, 4, 8)), QRectF(1, 2, 4, 8));
+
+ QPixmap src(10, 10);
+ src.fill(Qt::blue);
+
+ QPixmap test(src.size());
+ QPainter p(&test);
+ filter.draw(&p, QPointF(0, 0), src, src.rect());
+ p.end();
+
+ QCOMPARE(test.toImage().pixel(0, 0), 0xff0000ff);
+}
+
+void tst_QPixmapFilter::colorizeSetColor()
+{
+ QPixmapColorizeFilter filter;
+ filter.setColor(QColor(50, 100, 200));
+ QCOMPARE(filter.color(), QColor(50, 100, 200));
+}
+
+void tst_QPixmapFilter::colorizeSetStrength()
+{
+ QPixmapColorizeFilter filter;
+ QCOMPARE(filter.strength(), qreal(1));
+ filter.setStrength(0.5);
+ QCOMPARE(filter.strength(), qreal(0.5));
+ filter.setStrength(0.0);
+ QCOMPARE(filter.strength(), qreal(0.0));
+}
+
+void tst_QPixmapFilter::colorizeProcess()
+{
+ QPixmapColorizeFilter filter;
+ filter.setColor(QColor(100, 100, 100));
+
+ QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(0, 0, 50, 50));
+ QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(30, 20, 10, 40));
+ QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(2.2, 6.3, 11.4, 47.5));
+
+ QPixmap source("noise.png");
+ QImage result(source.size(), QImage::Format_ARGB32_Premultiplied);
+ result.fill(0);
+ QPainter p(&result);
+ filter.draw(&p, QPointF(0, 0), source);
+ p.end();
+ QImage resultImg = result;
+ for(int y = 0; y < resultImg.height(); y++)
+ {
+ for(int x = 0; x < resultImg.width(); x++)
+ {
+ QRgb pixel = resultImg.pixel(x,y);
+ QCOMPARE(qRed(pixel), qGreen(pixel));
+ QCOMPARE(qGreen(pixel), qBlue(pixel));
+ }
+ }
+}
+
+void tst_QPixmapFilter::colorizeDraw()
+{
+ QPixmapColorizeFilter filter;
+ filter.setColor(QColor(100, 100, 100));
+
+ QPixmap pixmap("noise.png");
+ QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
+ QPainter painter(&result);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(result.rect(), QColor(128, 0, 0, 0));
+ painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ filter.draw(&painter, QPointF(0, 0), pixmap);
+ painter.end();
+
+ QImage resultImg = result;
+ for(int y = 0; y < resultImg.height(); y++)
+ {
+ for(int x = 0; x < resultImg.width(); x++)
+ {
+ QRgb pixel = resultImg.pixel(x,y);
+ QCOMPARE(qRed(pixel), qGreen(pixel));
+ QCOMPARE(qGreen(pixel), qBlue(pixel));
+ }
+ }
+}
+
+void tst_QPixmapFilter::colorizeDrawStrength()
+{
+ QPixmapColorizeFilter filter;
+ filter.setColor(Qt::blue);
+ filter.setStrength(0.3);
+
+ QImage source(256, 128, QImage::Format_ARGB32);
+ source.fill(qRgb(255, 0, 0));
+ QPixmap pixmap = QPixmap::fromImage(source);
+
+ QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
+ QPainter painter(&result);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ filter.draw(&painter, QPointF(0, 0), pixmap);
+ painter.end();
+
+ QImage resultImg = result;
+ for(int y = 0; y < resultImg.height(); y++)
+ {
+ for(int x = 0; x < resultImg.width(); x++)
+ {
+ QRgb pixel = resultImg.pixel(x,y);
+ QCOMPARE(qRed(pixel), 206);
+ QCOMPARE(qGreen(pixel), 26);
+ QCOMPARE(qBlue(pixel), 75);
+ }
+ }
+}
+
+void tst_QPixmapFilter::colorizeDrawSubRect()
+{
+ QPixmapColorizeFilter filter;
+ filter.setColor(QColor(255, 255, 255));
+
+ QPixmap pixmap("noise.png");
+ QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
+ QPainter painter(&result);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(result.rect(), QColor(128, 0, 0, 255));
+ painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ filter.draw(&painter, QPointF(16, 16), pixmap, QRectF(16, 16, 16, 16));
+ painter.end();
+
+ QImage resultImg = result;
+ QImage sourceImg = pixmap.toImage();
+ for(int y = 0; y < resultImg.height(); y++)
+ {
+ for(int x = 0; x < resultImg.width(); x++)
+ {
+ QRgb pixel = resultImg.pixel(x,y);
+ if(x>=16 && x<32 && y>=16 && y<32) {
+ QCOMPARE(qRed(pixel), qGreen(pixel));
+ QCOMPARE(qGreen(pixel), qBlue(pixel));
+ } else {
+ QCOMPARE(qRed(pixel), 128);
+ QCOMPARE(qGreen(pixel), 0);
+ QCOMPARE(qBlue(pixel), 0);
+ QCOMPARE(qAlpha(pixel), 255);
+ }
+ }
+ }
+}
+
+void tst_QPixmapFilter::colorizeProcessSubRect()
+{
+ QPixmapColorizeFilter filter;
+ filter.setColor(QColor(200, 200, 200));
+
+ QPixmap source("noise.png");
+ QImage result(QSize(16, 16), QImage::Format_ARGB32_Premultiplied);
+ result.fill(0);
+ QPainter p(&result);
+ filter.draw(&p, QPointF(0, 0), source, QRectF(16, 16, 16, 16));
+ p.end();
+
+ QImage resultImg = result;
+ for(int y = 0; y < resultImg.height(); y++)
+ {
+ for(int x = 0; x < resultImg.width(); x++)
+ {
+ QRgb pixel = resultImg.pixel(x,y);
+ QCOMPARE(qRed(pixel), qGreen(pixel));
+ QCOMPARE(qGreen(pixel), qBlue(pixel));
+ }
+ }
+}
+
+void tst_QPixmapFilter::convolutionBoundingRectFor()
+{
+ QPixmapConvolutionFilter filter;
+ QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(0, 0, 50, 50));
+ QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(30, 20, 10, 40));
+ QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(2.2, 6.3, 11.4, 47.5));
+ qreal kernel[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+ filter.setConvolutionKernel(kernel, 2, 2);
+ QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(-1, -1, 51, 51));
+ QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(29, 19, 11, 41));
+ QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(1.2, 5.3, 12.4, 48.5));
+
+ filter.setConvolutionKernel(kernel, 3, 3);
+ QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(-1, -1, 52, 52));
+ QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(29, 19, 12, 42));
+ QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(1.2, 5.3, 13.4, 49.5));
+
+ filter.setConvolutionKernel(kernel, 4, 4);
+ QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(-2, -2, 53, 53));
+ QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(28, 18, 13, 43));
+ QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(0.2, 4.3, 14.4, 50.5));
+}
+
+void tst_QPixmapFilter::convolutionDrawSubRect()
+{
+ QPixmapConvolutionFilter filter;
+ qreal kernel[] = {
+ 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 1
+ };
+ filter.setConvolutionKernel(kernel, 3, 3);
+
+ QPixmap pixmap("noise.png");
+ QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
+ QPainter painter(&result);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(result.rect(), QColor(128, 0, 0, 255));
+ painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ filter.draw(&painter, QPointF(16, 16), pixmap, QRectF(16, 16, 16, 16));
+ painter.end();
+
+ QImage resultImg = result;
+ QImage sourceImg = pixmap.toImage();
+ for(int y = 0; y < resultImg.height()-1; y++)
+ {
+ for(int x = 0; x < resultImg.width()-1; x++)
+ {
+ QRgb pixel = resultImg.pixel(x,y);
+ QRgb srcPixel = sourceImg.pixel(x+1,y+1);
+ if(x>=15 && x<33 && y>=15 && y<33) {
+ QCOMPARE(pixel, srcPixel);
+ } else {
+ QCOMPARE(qRed(pixel), 128);
+ QCOMPARE(qGreen(pixel), 0);
+ QCOMPARE(qBlue(pixel), 0);
+ QCOMPARE(qAlpha(pixel), 255);
+ }
+ }
+ }
+
+
+ kernel[2] = 1;
+ kernel[8] = 0;
+ filter.setConvolutionKernel(kernel, 3, 3);
+
+ QPainter painter2(&result);
+ painter2.setCompositionMode(QPainter::CompositionMode_Source);
+ painter2.fillRect(result.rect(), QColor(128, 0, 0, 255));
+ painter2.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ filter.draw(&painter2, QPointF(16, 16), pixmap, QRectF(16, 16, 16, 16));
+ painter2.end();
+
+ resultImg = result;
+ sourceImg = pixmap.toImage();
+ for(int y = 1; y < resultImg.height(); y++)
+ {
+ for(int x = 0; x < resultImg.width()-1; x++)
+ {
+ QRgb pixel = resultImg.pixel(x,y);
+ QRgb srcPixel = sourceImg.pixel(x+1,y-1);
+ if(x>=15 && x<33 && y>=15 && y<33) {
+ QCOMPARE(pixel, srcPixel);
+ } else {
+ QCOMPARE(qRed(pixel), 128);
+ QCOMPARE(qGreen(pixel), 0);
+ QCOMPARE(qBlue(pixel), 0);
+ QCOMPARE(qAlpha(pixel), 255);
+ }
+ }
+ }
+
+}
+
+void tst_QPixmapFilter::dropShadowBoundingRectFor()
+{
+ QPixmapDropShadowFilter filter;
+ filter.setBlurRadius(0);
+
+ QCOMPARE(filter.blurRadius(), 0.);
+
+ const QRectF rect1(0, 0, 50, 50);
+ const QRectF rect2(30, 20, 10, 40);
+ const QRectF rect3(2.2, 6.3, 11.4, 47.5);
+
+ filter.setOffset(QPointF(0,0));
+ QCOMPARE(filter.boundingRectFor(rect1), rect1);
+ QCOMPARE(filter.boundingRectFor(rect2), rect2);
+ QCOMPARE(filter.boundingRectFor(rect3), rect3);
+
+ filter.setOffset(QPointF(1,1));
+ QCOMPARE(filter.offset(), QPointF(1, 1));
+ QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(0, 0, 1, 1));
+ QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(0, 0, 1, 1));
+ QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(0, 0, 1, 1));
+
+ filter.setOffset(QPointF(-1,-1));
+ QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-1, -1, 0, 0));
+ QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-1, -1, 0, 0));
+ QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-1, -1, 0, 0));
+
+ filter.setBlurRadius(2);
+ filter.setOffset(QPointF(0,0));
+ qreal delta = 2;
+ QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-delta, -delta, delta, delta));
+ QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-delta, -delta, delta, delta));
+ QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-delta, -delta, delta, delta));
+
+ filter.setOffset(QPointF(1,1));
+ QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-delta + 1, -delta + 1, delta + 1, delta + 1));
+ QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-delta + 1, -delta + 1, delta + 1, delta + 1));
+ QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-delta + 1, -delta + 1, delta + 1, delta + 1));
+
+ filter.setOffset(QPointF(-10,-10));
+ QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-delta - 10, -delta - 10, 0, 0));
+ QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-delta - 10, -delta - 10, 0, 0));
+ QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-delta - 10, -delta - 10, 0, 0));
+}
+
+QT_BEGIN_NAMESPACE
+void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);
+QT_END_NAMESPACE
+
+void tst_QPixmapFilter::blurIndexed8()
+{
+ QImage img(16, 32, QImage::Format_Indexed8);
+ img.setColorCount(256);
+ for (int i = 0; i < 256; ++i)
+ img.setColor(i, qRgb(i, i, i));
+
+ img.fill(255);
+
+ QImage original = img;
+ qt_blurImage(img, 10, true, false);
+ QCOMPARE(original.size(), img.size());
+
+ original = img;
+ qt_blurImage(img, 10, true, true);
+ QCOMPARE(original.size(), QSize(img.height(), img.width()));
+}
+
+QTEST_MAIN(tst_QPixmapFilter)
+#include "tst_qpixmapfilter.moc"
diff --git a/tests/auto/gui/image/qvolatileimage/qvolatileimage.pro b/tests/auto/gui/image/qvolatileimage/qvolatileimage.pro
new file mode 100644
index 0000000000..45d80b85f2
--- /dev/null
+++ b/tests/auto/gui/image/qvolatileimage/qvolatileimage.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+
+QT += gui-private widgets
+
+SOURCES += tst_qvolatileimage.cpp
+
+symbian {
+ TARGET.EPOCHEAPSIZE = 0x200000 0x800000
+ LIBS += -lfbscli
+}
diff --git a/tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp b/tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp
new file mode 100644
index 0000000000..bacca66dcd
--- /dev/null
+++ b/tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp
@@ -0,0 +1,403 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpaintengine.h>
+#include <QtGui/private/qvolatileimage_p.h>
+#ifdef Q_OS_SYMBIAN
+#include <fbs.h>
+#endif
+
+class tst_QVolatileImage : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QVolatileImage() { }
+
+private slots:
+ void create();
+ void ensureFormat();
+ void dataAccess();
+ void sharing();
+ void paint();
+ void fill();
+ void copy();
+ void bitmap();
+};
+
+void tst_QVolatileImage::create()
+{
+ QVolatileImage nullImg;
+ QVERIFY(nullImg.isNull());
+
+ QVolatileImage img(100, 200, QImage::Format_ARGB32);
+ QVERIFY(!img.isNull());
+ QCOMPARE(img.width(), 100);
+ QCOMPARE(img.height(), 200);
+ QCOMPARE(img.format(), QImage::Format_ARGB32);
+ QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height());
+ QCOMPARE(img.hasAlphaChannel(), true);
+ QCOMPARE(img.depth(), 32);
+
+ QImage source(12, 23, QImage::Format_ARGB32_Premultiplied);
+ img = QVolatileImage(source);
+ QVERIFY(!img.isNull());
+ QCOMPARE(img.width(), 12);
+ QCOMPARE(img.height(), 23);
+ QCOMPARE(img.format(), source.format());
+ QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height());
+ QVERIFY(img.imageRef() == source);
+ QVERIFY(img.toImage() == source);
+ QCOMPARE(img.hasAlphaChannel(), true);
+ QCOMPARE(img.hasAlphaChannel(), img.imageRef().hasAlphaChannel());
+ QCOMPARE(img.hasAlphaChannel(), img.toImage().hasAlphaChannel());
+ QCOMPARE(img.depth(), 32);
+
+#ifdef Q_OS_SYMBIAN
+ CFbsBitmap *bmp = new CFbsBitmap;
+ QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone);
+ QVolatileImage bmpimg(bmp);
+ QVERIFY(!bmpimg.isNull());
+ QCOMPARE(bmpimg.width(), 100);
+ QCOMPARE(bmpimg.height(), 50);
+ // Verify that we only did handle duplication, not pixel data copying.
+ QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
+ delete bmp;
+ // Check if content is still valid.
+ QImage copyimg = bmpimg.toImage();
+ QCOMPARE(copyimg.format(), QImage::Format_ARGB32_Premultiplied);
+#endif
+}
+
+void tst_QVolatileImage::ensureFormat()
+{
+ QImage source(12, 23, QImage::Format_ARGB32_Premultiplied);
+ QVolatileImage img(source);
+ QVERIFY(!img.isNull());
+ QVERIFY(img.imageRef() == source);
+ QVERIFY(img.toImage() == source);
+
+ QVERIFY(img.ensureFormat(QImage::Format_ARGB32_Premultiplied)); // no-op
+ QVERIFY(img.imageRef() == source);
+ QVERIFY(img.toImage() == source);
+ QVERIFY(img.format() == QImage::Format_ARGB32_Premultiplied);
+
+ QVERIFY(img.ensureFormat(QImage::Format_RGB32)); // new data under-the-hood
+ QVERIFY(img.imageRef() != source);
+ QVERIFY(img.toImage() != source);
+ QVERIFY(img.format() == QImage::Format_RGB32);
+
+#ifdef Q_OS_SYMBIAN
+ CFbsBitmap *bmp = new CFbsBitmap;
+ QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone);
+ QVolatileImage bmpimg(bmp);
+ QVERIFY(bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied)); // no-op
+ QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
+
+ // A different format should cause data copying.
+ QVERIFY(bmpimg.ensureFormat(QImage::Format_RGB32));
+ QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress());
+ const uchar *prevBits = bmpimg.constBits();
+
+ QVERIFY(bmpimg.ensureFormat(QImage::Format_RGB16));
+ QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress());
+ QVERIFY(bmpimg.constBits() != prevBits);
+ prevBits = bmpimg.constBits();
+
+ QVERIFY(bmpimg.ensureFormat(QImage::Format_MonoLSB));
+ QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress());
+ QVERIFY(bmpimg.constBits() != prevBits);
+
+ delete bmp;
+#endif
+}
+
+void tst_QVolatileImage::dataAccess()
+{
+ QImage source(12, 23, QImage::Format_ARGB32_Premultiplied);
+ QVolatileImage img(source);
+ QVERIFY(!img.isNull());
+ img.beginDataAccess();
+ QVERIFY(img.constBits());
+ QVERIFY(img.imageRef().constBits());
+ QVERIFY(img.bits());
+ QVERIFY(img.imageRef().bits());
+ img.endDataAccess();
+
+ img = QVolatileImage(12, 23, QImage::Format_ARGB32);
+ img.beginDataAccess();
+ QVERIFY(img.constBits() && img.bits());
+ img.endDataAccess();
+}
+
+void tst_QVolatileImage::sharing()
+{
+ QVolatileImage img1(100, 100, QImage::Format_ARGB32);
+ QVolatileImage img2 = img1;
+ img1.beginDataAccess();
+ img2.beginDataAccess();
+ QVERIFY(img1.constBits() == img2.constBits());
+ img2.endDataAccess();
+ img1.endDataAccess();
+ img1.imageRef(); // non-const call, should detach
+ img1.beginDataAccess();
+ img2.beginDataAccess();
+ QVERIFY(img1.constBits() != img2.constBits());
+ img2.endDataAccess();
+ img1.endDataAccess();
+
+ // toImage() should return a copy of the internal QImage.
+ // imageRef() is a reference to the internal QImage.
+ QVERIFY(img1.imageRef().constBits() != img1.toImage().constBits());
+
+#ifdef Q_OS_SYMBIAN
+ CFbsBitmap *bmp = new CFbsBitmap;
+ QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone);
+ QVolatileImage bmpimg(bmp);
+ QVolatileImage bmpimg2;
+ bmpimg2 = bmpimg;
+ QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
+ QCOMPARE(bmpimg2.constBits(), (const uchar *) bmp->DataAddress());
+ // Now force a detach, which should copy the pixel data under-the-hood.
+ bmpimg.imageRef();
+ QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress());
+ QCOMPARE(bmpimg2.constBits(), (const uchar *) bmp->DataAddress());
+ delete bmp;
+#endif
+}
+
+bool fuzzyCompareImages(const QImage &image1, const QImage &image2, int tolerance)
+{
+ if (image1.bytesPerLine() != image2.bytesPerLine()
+ || image1.width() != image2.width()
+ || image1.height() != image2.height()) {
+ return false;
+ }
+ for (int i = 0; i < image1.height(); i++) {
+ const uchar *line1 = image1.scanLine(i);
+ const uchar *line2 = image2.scanLine(i);
+ int bytes = image1.bytesPerLine();
+ for (int j = 0; j < bytes; j++) {
+ int delta = line1[j] - line2[j];
+ if (qAbs(delta) > tolerance)
+ return false;
+ }
+ }
+ return true;
+}
+
+void tst_QVolatileImage::paint()
+{
+#ifdef Q_OS_SYMBIAN
+ QVolatileImage img(100, 100, QImage::Format_ARGB32);
+ img.beginDataAccess();
+ img.imageRef().fill(QColor(Qt::green).rgba());
+ QPainter p(&img.imageRef());
+ p.drawRect(10, 10, 50, 50);
+ p.end();
+ img.endDataAccess();
+ QImage imgA = img.toImage();
+
+ // The following assumes that on openvg the pixmapdata is backed by QVolatileImage)
+ // (and that openvg is in use)
+ // It should pass with any engine nonetheless.
+ // See if painting into the underlying QImage succeeds.
+ QPixmap pm(100, 100);
+ if (pm.paintEngine()->type() == QPaintEngine::Raster) {
+ pm.fill(Qt::green);
+ QPainter pmp(&pm);
+ pmp.drawRect(10, 10, 50, 50);
+ pmp.end();
+ QImage imgB = pm.toImage();
+ QVERIFY(fuzzyCompareImages(imgA, imgB, 0));
+ // Exercise the accelerated QVolatileImagePaintEngine::drawPixmap() a bit.
+ QPixmap targetPm(pm.size());
+ targetPm.fill(Qt::black);
+ pmp.begin(&targetPm);
+ pmp.drawPixmap(QPointF(0, 0), pm);
+ pmp.end();
+ imgB = targetPm.toImage();
+ QVERIFY(fuzzyCompareImages(imgA, imgB, 0));
+ // Now the overload taking rects.
+ targetPm.fill(Qt::black);
+ pmp.begin(&targetPm);
+ QRectF rect(QPointF(0, 0), pm.size());
+ pmp.drawPixmap(rect, pm, rect);
+ pmp.end();
+ imgB = targetPm.toImage();
+ QVERIFY(fuzzyCompareImages(imgA, imgB, 0));
+ } else {
+ QSKIP("Pixmaps not painted via raster, skipping paint test", SkipSingle);
+ }
+#endif
+}
+
+void tst_QVolatileImage::fill()
+{
+ QVolatileImage img(100, 100, QImage::Format_ARGB32_Premultiplied);
+ QColor col = QColor(10, 20, 30);
+ img.fill(col.rgba());
+ QVERIFY(img.imageRef().pixel(1, 1) == col.rgba());
+ QVERIFY(img.toImage().pixel(1, 1) == col.rgba());
+
+#ifdef Q_OS_SYMBIAN
+ CFbsBitmap *bmp = static_cast<CFbsBitmap *>(img.duplicateNativeImage());
+ QVERIFY(bmp);
+ TRgb pix;
+ bmp->GetPixel(pix, TPoint(1, 1));
+ QCOMPARE(pix.Red(), col.red());
+ QCOMPARE(pix.Green(), col.green());
+ QCOMPARE(pix.Blue(), col.blue());
+ delete bmp;
+#endif
+}
+
+void tst_QVolatileImage::copy()
+{
+ QVolatileImage img(100, 100, QImage::Format_RGB32);
+ img.beginDataAccess();
+ img.imageRef().fill(QColor(Qt::green).rgba());
+ QPainter p(&img.imageRef());
+ p.drawRect(10, 10, 50, 50);
+ p.end();
+ img.endDataAccess();
+
+ QVolatileImage img2(100, 100, QImage::Format_RGB32);
+ img2.copyFrom(&img, QRect());
+ QImage imgA = img.toImage();
+ QImage imgB = img2.toImage();
+ QCOMPARE(imgA.size(), imgB.size());
+ QVERIFY(fuzzyCompareImages(imgA, imgB, 0));
+
+ img2 = QVolatileImage(20, 20, QImage::Format_RGB32);
+ img2.copyFrom(&img, QRect(5, 5, 20, 20));
+ imgA = img.toImage().copy(5, 5, 20, 20);
+ imgB = img2.toImage();
+ QCOMPARE(imgA.size(), imgB.size());
+ QVERIFY(fuzzyCompareImages(imgA, imgB, 0));
+}
+
+void tst_QVolatileImage::bitmap()
+{
+#ifdef Q_OS_SYMBIAN
+ CFbsBitmap *bmp = new CFbsBitmap;
+ QVERIFY(bmp->Create(TSize(100, 50), EColor64K) == KErrNone);
+ QVolatileImage bmpimg(bmp);
+ CFbsBitmap *dupbmp = static_cast<CFbsBitmap *>(bmpimg.duplicateNativeImage());
+ QVERIFY(dupbmp);
+ QVERIFY(dupbmp != bmp);
+ QCOMPARE(dupbmp->DataAddress(), bmp->DataAddress());
+ delete dupbmp;
+ delete bmp;
+ bmpimg.beginDataAccess();
+ qMemSet(bmpimg.bits(), 0, bmpimg.byteCount());
+ qMemSet(bmpimg.bits(), 1, bmpimg.bytesPerLine() * bmpimg.height());
+ bmpimg.endDataAccess();
+
+ // Test bgr->rgb conversion in case of EColor16M.
+ bmp = new CFbsBitmap;
+ QVERIFY(bmp->Create(TSize(101, 89), EColor16M) == KErrNone);
+ bmp->BeginDataAccess();
+ TUint32 *addr = bmp->DataAddress();
+ uint rgb = QColor(10, 20, 30).rgb();
+ qMemCopy(bmp->DataAddress(), &rgb, 3);
+ bmp->EndDataAccess();
+ TRgb symrgb;
+ bmp->GetPixel(symrgb, TPoint(0, 0));
+ QVERIFY(symrgb.Red() == 10 && symrgb.Green() == 20 && symrgb.Blue() == 30);
+ bmpimg = QVolatileImage(bmp);
+ QVERIFY(bmpimg.toImage().pixel(0, 0) == rgb);
+ // check if there really was a conversion
+ bmp->BeginDataAccess();
+ bmpimg.beginDataAccess();
+ qMemCopy(&rgb, bmpimg.constBits(), 3);
+ uint rgb2 = rgb;
+ qMemCopy(&rgb2, bmp->DataAddress(), 3);
+ QVERIFY(rgb != rgb2);
+ bmpimg.endDataAccess(true);
+ bmp->EndDataAccess(true);
+ delete bmp;
+
+ bmp = new CFbsBitmap;
+ QVERIFY(bmp->Create(TSize(101, 89), EGray2) == KErrNone);
+ bmpimg = QVolatileImage(bmp); // inverts pixels, but should do it in place
+ QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
+ QCOMPARE(bmpimg.format(), QImage::Format_MonoLSB);
+ bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied);
+ QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress());
+ QCOMPARE(bmpimg.format(), QImage::Format_ARGB32_Premultiplied);
+ delete bmp;
+
+ // The following two formats must be optimal always.
+ bmp = new CFbsBitmap;
+ QVERIFY(bmp->Create(TSize(101, 89), EColor16MAP) == KErrNone);
+ bmpimg = QVolatileImage(bmp);
+ QCOMPARE(bmpimg.format(), QImage::Format_ARGB32_Premultiplied);
+ QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
+ bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied);
+ QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
+ delete bmp;
+ bmp = new CFbsBitmap;
+ QVERIFY(bmp->Create(TSize(101, 89), EColor16MU) == KErrNone);
+ bmpimg = QVolatileImage(bmp);
+ QCOMPARE(bmpimg.format(), QImage::Format_RGB32);
+ QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
+ bmpimg.ensureFormat(QImage::Format_RGB32);
+ QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
+ delete bmp;
+
+#else
+ QSKIP("CFbsBitmap is only available on Symbian, skipping bitmap test", SkipSingle);
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication::setGraphicsSystem("openvg");
+ QApplication app(argc, argv);
+ tst_QVolatileImage tc;
+ return QTest::qExec(&tc, argc, argv);
+}
+
+#include "tst_qvolatileimage.moc"
diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro
new file mode 100644
index 0000000000..880c3c8613
--- /dev/null
+++ b/tests/auto/gui/kernel/kernel.pro
@@ -0,0 +1,17 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qclipboard \
+ qdrag \
+ qevent \
+ qfileopenevent \
+ qguivariant \
+ qkeysequence \
+ qmouseevent \
+ qmouseevent_modal \
+ qpalette \
+ qshortcut \
+ qtouchevent \
+
+symbian {
+ SUBDIRS += qsoftkeymanager
+}
diff --git a/tests/auto/gui/kernel/qclipboard/.gitignore b/tests/auto/gui/kernel/qclipboard/.gitignore
new file mode 100644
index 0000000000..4fcf7d55fc
--- /dev/null
+++ b/tests/auto/gui/kernel/qclipboard/.gitignore
@@ -0,0 +1,5 @@
+tst_qclipboard
+copier/copier
+copier/copier.exe
+paster/paster
+paster/paster.exe
diff --git a/tests/auto/gui/kernel/qclipboard/copier/copier.pro b/tests/auto/gui/kernel/qclipboard/copier/copier.pro
new file mode 100644
index 0000000000..d345d33eb5
--- /dev/null
+++ b/tests/auto/gui/kernel/qclipboard/copier/copier.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+CONFIG -= app_bundle
+QT += widgets
+win32: DESTDIR = ../copier
+# Input
+SOURCES += main.cpp
+
diff --git a/tests/auto/gui/kernel/qclipboard/copier/main.cpp b/tests/auto/gui/kernel/qclipboard/copier/main.cpp
new file mode 100644
index 0000000000..e4417352ff
--- /dev/null
+++ b/tests/auto/gui/kernel/qclipboard/copier/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QApplication>
+#include <QClipboard>
+#include <QStringList>
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ QClipboard *board = QApplication::clipboard();
+#ifdef Q_OS_WINCE
+ board->setText(QLatin1String("testString.!"));
+#else
+ board->setText(app.arguments().at(1));
+#endif
+ return 0;
+}
diff --git a/tests/auto/gui/kernel/qclipboard/paster/main.cpp b/tests/auto/gui/kernel/qclipboard/paster/main.cpp
new file mode 100644
index 0000000000..4df4d7fb45
--- /dev/null
+++ b/tests/auto/gui/kernel/qclipboard/paster/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QApplication>
+#include <QClipboard>
+#include <QStringList>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ QClipboard *board = QApplication::clipboard();
+#ifdef Q_OS_WINCE
+ return (board->text() == QLatin1String("testString.!")) ? 0 : 1;
+#else
+ return (board->text() == app.arguments().at(1)) ? 0 : 1;
+#endif
+}
diff --git a/tests/auto/gui/kernel/qclipboard/paster/paster.pro b/tests/auto/gui/kernel/qclipboard/paster/paster.pro
new file mode 100644
index 0000000000..d214c9e90a
--- /dev/null
+++ b/tests/auto/gui/kernel/qclipboard/paster/paster.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+win32: DESTDIR = ../paster
+CONFIG -= app_bundle
+QT += widgets
+# Input
+SOURCES += main.cpp
+
+
diff --git a/tests/auto/gui/kernel/qclipboard/qclipboard.pro b/tests/auto/gui/kernel/qclipboard/qclipboard.pro
new file mode 100644
index 0000000000..692ca5dd3f
--- /dev/null
+++ b/tests/auto/gui/kernel/qclipboard/qclipboard.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = test copier paster
+
+
diff --git a/tests/auto/gui/kernel/qclipboard/test/test.pro b/tests/auto/gui/kernel/qclipboard/test/test.pro
new file mode 100644
index 0000000000..12c6b6ce4f
--- /dev/null
+++ b/tests/auto/gui/kernel/qclipboard/test/test.pro
@@ -0,0 +1,32 @@
+load(qttest_p4)
+SOURCES += ../tst_qclipboard.cpp
+TARGET = ../tst_qclipboard
+
+win32 {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qclipboard
+} else {
+ TARGET = ../../release/tst_qclipboard
+ }
+}
+
+wince*|symbian: {
+ copier.files = ../copier/copier.exe
+ copier.path = copier
+ paster.files = ../paster/paster.exe
+ paster.path = paster
+
+ symbian: {
+ LIBS += -lbafl -lestor -letext
+
+ load(data_caging_paths)
+ rsc.files = $${EPOCROOT}$$HW_ZDIR$$APP_RESOURCE_DIR/copier.rsc
+ rsc.files += $${EPOCROOT}$$HW_ZDIR$$APP_RESOURCE_DIR/paster.rsc
+ rsc.path = $$APP_RESOURCE_DIR
+ reg_resource.files = $${EPOCROOT}$$HW_ZDIR$$REG_RESOURCE_IMPORT_DIR/copier_reg.rsc
+ reg_resource.files += $${EPOCROOT}$$HW_ZDIR$$REG_RESOURCE_IMPORT_DIR/paster_reg.rsc
+ reg_resource.path = $$REG_RESOURCE_IMPORT_DIR
+ }
+
+ DEPLOYMENT += copier paster rsc reg_resource
+} \ No newline at end of file
diff --git a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp
new file mode 100644
index 0000000000..4d3bb29e13
--- /dev/null
+++ b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/QDebug>
+#include <QtWidgets/QApplication>
+#include <QtGui/QClipboard>
+#ifdef Q_WS_MAC
+#include <Carbon/Carbon.h>
+#endif
+#ifdef Q_OS_SYMBIAN
+#include "private/qcore_symbian_p.h"
+#include "txtetext.h"
+#include <baclipb.h>
+#endif
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "txtclipboard.h"
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QClipboard : public QObject
+{
+ Q_OBJECT
+private slots:
+
+ void copy_exit_paste();
+ void capabiliyFunctions();
+ void modes();
+ void testSignals();
+ void setMimeData();
+ void clearBeforeSetText();
+#ifdef Q_OS_SYMBIAN
+ void pasteCopySymbian();
+ void copyPasteSymbian();
+#endif
+
+private:
+ bool nativeClipboardWorking();
+};
+
+
+bool tst_QClipboard::nativeClipboardWorking()
+{
+#ifdef Q_WS_MAC
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ return status == noErr;
+#endif
+ return true;
+}
+
+Q_DECLARE_METATYPE(QClipboard::Mode)
+
+/*
+ Tests that the capability functions are implemented on all
+ platforms.
+*/
+void tst_QClipboard::capabiliyFunctions()
+{
+ QClipboard * const clipboard = QApplication::clipboard();
+
+ clipboard->supportsSelection();
+ clipboard->supportsFindBuffer();
+ clipboard->ownsSelection();
+ clipboard->ownsClipboard();
+ clipboard->ownsFindBuffer();
+}
+
+/*
+ Test that text inserted into the clipboard in different modes is
+ kept separate.
+*/
+void tst_QClipboard::modes()
+{
+ QClipboard * const clipboard = QApplication::clipboard();
+
+ if (!nativeClipboardWorking())
+ QSKIP("Native clipboard not working in this setup", SkipAll);
+
+ const QString defaultMode = "default mode text;";
+ clipboard->setText(defaultMode);
+ QCOMPARE(clipboard->text(), defaultMode);
+
+ if (clipboard->supportsSelection()) {
+ const QString selectionMode = "selection mode text";
+ clipboard->setText(selectionMode, QClipboard::Selection);
+ QCOMPARE(clipboard->text(QClipboard::Selection), selectionMode);
+ QCOMPARE(clipboard->text(), defaultMode);
+ }
+
+ if (clipboard->supportsFindBuffer()) {
+ const QString searchMode = "find mode text";
+ clipboard->setText(searchMode, QClipboard::FindBuffer);
+ QCOMPARE(clipboard->text(QClipboard::FindBuffer), searchMode);
+ QCOMPARE(clipboard->text(), defaultMode);
+ }
+}
+
+/*
+ Test that the appropriate signals are emitted when the cliboard
+ contents is changed by calling the qt functions.
+*/
+void tst_QClipboard::testSignals()
+{
+ qRegisterMetaType<QClipboard::Mode>("QClipboard::Mode");
+
+ if (!nativeClipboardWorking())
+ QSKIP("Native clipboard not working in this setup", SkipAll);
+
+ QClipboard * const clipboard = QApplication::clipboard();
+
+ QSignalSpy changedSpy(clipboard, SIGNAL(changed(QClipboard::Mode)));
+ QSignalSpy dataChangedSpy(clipboard, SIGNAL(dataChanged()));
+ QSignalSpy searchChangedSpy(clipboard, SIGNAL(findBufferChanged()));
+ QSignalSpy selectionChangedSpy(clipboard, SIGNAL(selectionChanged()));
+
+ const QString text = "clipboard text;";
+
+ // Test the default mode signal.
+ clipboard->setText(text);
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(searchChangedSpy.count(), 0);
+ QCOMPARE(selectionChangedSpy.count(), 0);
+ QCOMPARE(changedSpy.count(), 1);
+ QCOMPARE(changedSpy.at(0).count(), 1);
+ QCOMPARE(qVariantValue<QClipboard::Mode>(changedSpy.at(0).at(0)), QClipboard::Clipboard);
+
+ changedSpy.clear();
+
+ // Test the selection mode signal.
+ if (clipboard->supportsSelection()) {
+ clipboard->setText(text, QClipboard::Selection);
+ QCOMPARE(selectionChangedSpy.count(), 1);
+ QCOMPARE(changedSpy.count(), 1);
+ QCOMPARE(changedSpy.at(0).count(), 1);
+ QCOMPARE(qVariantValue<QClipboard::Mode>(changedSpy.at(0).at(0)), QClipboard::Selection);
+ } else {
+ QCOMPARE(selectionChangedSpy.count(), 0);
+ }
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(searchChangedSpy.count(), 0);
+
+ changedSpy.clear();
+
+ // Test the search mode signal.
+ if (clipboard->supportsFindBuffer()) {
+ clipboard->setText(text, QClipboard::FindBuffer);
+ QCOMPARE(searchChangedSpy.count(), 1);
+ QCOMPARE(changedSpy.count(), 1);
+ QCOMPARE(changedSpy.at(0).count(), 1);
+ QCOMPARE(qVariantValue<QClipboard::Mode>(changedSpy.at(0).at(0)), QClipboard::FindBuffer);
+ } else {
+ QCOMPARE(searchChangedSpy.count(), 0);
+ }
+ QCOMPARE(dataChangedSpy.count(), 1);
+}
+
+/*
+ Test that pasted text remain on the clipboard
+ after a Qt application exits.
+*/
+void tst_QClipboard::copy_exit_paste()
+{
+#ifndef QT_NO_PROCESS
+#if defined Q_WS_X11 || defined Q_WS_QWS || defined (Q_WS_QPA)
+ QSKIP("This test does not make sense on X11 and embedded, copied data disappears from the clipboard when the application exits ", SkipAll);
+ // ### It's still possible to test copy/paste - just keep the apps running
+#elif defined (Q_OS_SYMBIAN) && defined (Q_CC_NOKIAX86)
+ QSKIP("emulator cannot launch multiple processes",SkipAll);
+#endif
+ if (!nativeClipboardWorking())
+ QSKIP("Native clipboard not working in this setup", SkipAll);
+ const QStringList stringArgument = QStringList() << "Test string.";
+ QCOMPARE(QProcess::execute("copier/copier", stringArgument), 0);
+#ifdef Q_WS_MAC
+ // The Pasteboard needs a moment to breathe (at least on older Macs).
+ QTest::qWait(100);
+#endif
+ QCOMPARE(QProcess::execute("paster/paster", stringArgument), 0);
+#endif
+}
+
+void tst_QClipboard::setMimeData()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Native clipboard not working in this setup", SkipAll);
+ QMimeData *mimeData = new QMimeData;
+ const QString TestName(QLatin1String("tst_QClipboard::setMimeData() mimeData"));
+ mimeData->setObjectName(TestName);
+#if defined(Q_OS_WINCE)
+ // need to set text on CE
+ mimeData->setText(QLatin1String("Qt/CE foo"));
+#endif
+
+ QApplication::clipboard()->setMimeData(mimeData);
+ QCOMPARE(QApplication::clipboard()->mimeData(), (const QMimeData *)mimeData);
+ QCOMPARE(QApplication::clipboard()->mimeData()->objectName(), TestName);
+
+ // set it to the same data again, it shouldn't delete mimeData (and crash as a result)
+ QApplication::clipboard()->setMimeData(mimeData);
+ QCOMPARE(QApplication::clipboard()->mimeData(), (const QMimeData *)mimeData);
+ QCOMPARE(QApplication::clipboard()->mimeData()->objectName(), TestName);
+ QApplication::clipboard()->clear();
+ const QMimeData *appMimeData = QApplication::clipboard()->mimeData();
+ QVERIFY(appMimeData != mimeData || appMimeData->objectName() != TestName);
+
+ // check for crash when using the same mimedata object on several clipboards
+ QMimeData *data = new QMimeData;
+ data->setText("foo");
+
+ QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard);
+ QApplication::clipboard()->setMimeData(data, QClipboard::Selection);
+ QApplication::clipboard()->setMimeData(data, QClipboard::FindBuffer);
+
+ QSignalSpy spySelection(QApplication::clipboard(), SIGNAL(selectionChanged()));
+ QSignalSpy spyData(QApplication::clipboard(), SIGNAL(dataChanged()));
+ QSignalSpy spyFindBuffer(QApplication::clipboard(), SIGNAL(findBufferChanged()));
+
+ QApplication::clipboard()->clear(QClipboard::Clipboard);
+ QApplication::clipboard()->clear(QClipboard::Selection); // used to crash on X11
+ QApplication::clipboard()->clear(QClipboard::FindBuffer);
+
+#if defined(Q_WS_X11)
+ QCOMPARE(spySelection.count(), 1);
+ QCOMPARE(spyData.count(), 1);
+ QCOMPARE(spyFindBuffer.count(), 0);
+#elif defined(Q_WS_MAC)
+ QCOMPARE(spySelection.count(), 0);
+ QCOMPARE(spyData.count(), 1);
+ QCOMPARE(spyFindBuffer.count(), 1);
+#elif defined(Q_WS_WIN)
+ QCOMPARE(spySelection.count(), 0);
+ QCOMPARE(spyData.count(), 1);
+ QCOMPARE(spyFindBuffer.count(), 0);
+#endif
+
+ // an other crash test
+ data = new QMimeData;
+ data->setText("foo");
+
+ QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard);
+ QApplication::clipboard()->setMimeData(data, QClipboard::Selection);
+ QApplication::clipboard()->setMimeData(data, QClipboard::FindBuffer);
+
+ QMimeData *newData = new QMimeData;
+ newData->setText("bar");
+
+ spySelection.clear();
+ spyData.clear();
+ spyFindBuffer.clear();
+
+ QApplication::clipboard()->setMimeData(newData, QClipboard::Clipboard);
+ QApplication::clipboard()->setMimeData(newData, QClipboard::Selection); // used to crash on X11
+ QApplication::clipboard()->setMimeData(newData, QClipboard::FindBuffer);
+
+#if defined(Q_WS_X11)
+ QCOMPARE(spySelection.count(), 1);
+ QCOMPARE(spyData.count(), 1);
+ QCOMPARE(spyFindBuffer.count(), 0);
+#elif defined(Q_WS_MAC)
+ QCOMPARE(spySelection.count(), 0);
+ QCOMPARE(spyData.count(), 1);
+ QCOMPARE(spyFindBuffer.count(), 1);
+#elif defined(Q_WS_WIN)
+ QCOMPARE(spySelection.count(), 0);
+ QCOMPARE(spyData.count(), 1);
+ QCOMPARE(spyFindBuffer.count(), 0);
+#endif
+}
+
+void tst_QClipboard::clearBeforeSetText()
+{
+ QApplication::processEvents();
+
+ if (!nativeClipboardWorking())
+ QSKIP("Native clipboard not working in this setup", SkipAll);
+
+ const QString text = "tst_QClipboard::clearBeforeSetText()";
+
+ // setText() should work after processEvents()
+ QApplication::clipboard()->setText(text);
+ QCOMPARE(QApplication::clipboard()->text(), text);
+ QApplication::processEvents();
+ QCOMPARE(QApplication::clipboard()->text(), text);
+
+ // same with clear()
+ QApplication::clipboard()->clear();
+ QVERIFY(QApplication::clipboard()->text().isEmpty());
+ QApplication::processEvents();
+ QVERIFY(QApplication::clipboard()->text().isEmpty());
+
+ // setText() again
+ QApplication::clipboard()->setText(text);
+ QCOMPARE(QApplication::clipboard()->text(), text);
+ QApplication::processEvents();
+ QCOMPARE(QApplication::clipboard()->text(), text);
+
+ // clear() immediately followed by setText() should still return the text
+ QApplication::clipboard()->clear();
+ QVERIFY(QApplication::clipboard()->text().isEmpty());
+ QApplication::clipboard()->setText(text);
+ QCOMPARE(QApplication::clipboard()->text(), text);
+ QApplication::processEvents();
+ QCOMPARE(QApplication::clipboard()->text(), text);
+}
+
+/*
+ Test that text copied from qt application
+ can be pasted with symbian clipboard
+*/
+#ifdef Q_OS_SYMBIAN
+// ### This test case only makes sense in symbian
+void tst_QClipboard::pasteCopySymbian()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Native clipboard not working in this setup", SkipAll);
+ const QString string("Test string symbian.");
+ QApplication::clipboard()->setText(string);
+
+ const TInt KPlainTextBegin = 0;
+ RFs fs = qt_s60GetRFs();
+ CClipboard* cb = CClipboard::NewForReadingLC(fs);
+
+ CPlainText* text = CPlainText::NewL();
+ CleanupStack::PushL(text);
+ TInt dataLength = text->PasteFromStoreL(cb->Store(), cb->StreamDictionary(),
+ KPlainTextBegin);
+ if (dataLength == 0) {
+ User::Leave(KErrNotFound);
+ }
+ HBufC* hBuf = HBufC::NewL(dataLength);
+ TPtr buf = hBuf->Des();
+ text->Extract(buf, KPlainTextBegin, dataLength);
+
+ QString storeString = qt_TDesC2QString(buf);
+ CleanupStack::PopAndDestroy(text);
+ CleanupStack::PopAndDestroy(cb);
+
+ QCOMPARE(string, storeString);
+}
+#endif
+
+/*
+ Test that text copied to symbian clipboard
+ can be pasted to qt clipboard
+*/
+#ifdef Q_OS_SYMBIAN
+// ### This test case only makes sense in symbian
+void tst_QClipboard::copyPasteSymbian()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Native clipboard not working in this setup", SkipAll);
+ const QString string("Test string symbian.");
+ const TInt KPlainTextBegin = 0;
+
+ RFs fs = qt_s60GetRFs();
+ CClipboard* cb = CClipboard::NewForWritingLC(fs);
+ CStreamStore& store = cb->Store();
+ CStreamDictionary& dict = cb->StreamDictionary();
+ RStoreWriteStream symbianStream;
+ TStreamId symbianStId = symbianStream.CreateLC(cb->Store());
+
+ CPlainText* text = CPlainText::NewL();
+ CleanupStack::PushL(text);
+ TPtrC textPtr(qt_QString2TPtrC(string));
+ text->InsertL(KPlainTextBegin, textPtr);
+ text->CopyToStoreL(store, dict, KPlainTextBegin, textPtr.Length());
+ CleanupStack::PopAndDestroy(text);
+ (cb->StreamDictionary()).AssignL(KClipboardUidTypePlainText, symbianStId);
+ cb->CommitL();
+ CleanupStack::PopAndDestroy(2, cb);
+
+ QCOMPARE(QApplication::clipboard()->text(), string);
+}
+#endif
+
+QTEST_MAIN(tst_QClipboard)
+
+#include "tst_qclipboard.moc"
diff --git a/tests/auto/gui/kernel/qdrag/.gitignore b/tests/auto/gui/kernel/qdrag/.gitignore
new file mode 100644
index 0000000000..d210808afe
--- /dev/null
+++ b/tests/auto/gui/kernel/qdrag/.gitignore
@@ -0,0 +1 @@
+tst_qdrag
diff --git a/tests/auto/gui/kernel/qdrag/qdrag.pro b/tests/auto/gui/kernel/qdrag/qdrag.pro
new file mode 100644
index 0000000000..d9d645559b
--- /dev/null
+++ b/tests/auto/gui/kernel/qdrag/qdrag.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qdrag.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdrag.cpp
+
+
diff --git a/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp b/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp
new file mode 100644
index 0000000000..4d18cefb2c
--- /dev/null
+++ b/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qdrag.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QDrag : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QDrag();
+ virtual ~tst_QDrag();
+
+private slots:
+ void getSetCheck();
+};
+
+tst_QDrag::tst_QDrag()
+{
+}
+
+tst_QDrag::~tst_QDrag()
+{
+}
+
+// Testing get/set functions
+void tst_QDrag::getSetCheck()
+{
+ QDrag obj1(0);
+ // QMimeData * QDrag::mimeData()
+ // void QDrag::setMimeData(QMimeData *)
+ QMimeData *var1 = new QMimeData;
+ obj1.setMimeData(var1);
+ QCOMPARE(var1, obj1.mimeData());
+ obj1.setMimeData(var1);
+ QCOMPARE(var1, obj1.mimeData());
+ obj1.setMimeData((QMimeData *)0);
+ QCOMPARE((QMimeData *)0, obj1.mimeData());
+ // delete var1; // No delete, since QDrag takes ownership
+
+ Qt::DropAction result = obj1.start();
+ QCOMPARE(result, Qt::IgnoreAction);
+ result = obj1.start(Qt::MoveAction | Qt::LinkAction);
+ QCOMPARE(result, Qt::IgnoreAction);
+}
+
+QTEST_MAIN(tst_QDrag)
+#include "tst_qdrag.moc"
diff --git a/tests/auto/gui/kernel/qevent/.gitignore b/tests/auto/gui/kernel/qevent/.gitignore
new file mode 100644
index 0000000000..2a3ef2a115
--- /dev/null
+++ b/tests/auto/gui/kernel/qevent/.gitignore
@@ -0,0 +1 @@
+tst_qevent
diff --git a/tests/auto/gui/kernel/qevent/qevent.pro b/tests/auto/gui/kernel/qevent/qevent.pro
new file mode 100644
index 0000000000..6042b6cdc9
--- /dev/null
+++ b/tests/auto/gui/kernel/qevent/qevent.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+SOURCES += tst_qevent.cpp
+QT = core
+CONFIG += parallel_test
diff --git a/tests/auto/gui/kernel/qevent/tst_qevent.cpp b/tests/auto/gui/kernel/qevent/tst_qevent.cpp
new file mode 100644
index 0000000000..ae39380883
--- /dev/null
+++ b/tests/auto/gui/kernel/qevent/tst_qevent.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qcoreevent.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QEvent : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QEvent();
+ ~tst_QEvent();
+
+private slots:
+ void registerEventType_data();
+ void registerEventType();
+};
+
+tst_QEvent::tst_QEvent()
+{ }
+
+tst_QEvent::~tst_QEvent()
+{ }
+
+void tst_QEvent::registerEventType_data()
+{
+ QTest::addColumn<int>("hint");
+ QTest::addColumn<int>("expected");
+
+ // default argument
+ QTest::newRow("default") << -1 << int(QEvent::MaxUser);
+ // hint not valid
+ QTest::newRow("User-1") << int(QEvent::User - 1) << int(QEvent::MaxUser - 1);
+ // hint valid, but already taken
+ QTest::newRow("MaxUser-1") << int(QEvent::MaxUser - 1) << int(QEvent::MaxUser - 2);
+ // hint valid, but not taken
+ QTest::newRow("User + 1000") << int(QEvent::User + 1000) << int(QEvent::User + 1000);
+}
+
+void tst_QEvent::registerEventType()
+{
+ QFETCH(int, hint);
+ QFETCH(int, expected);
+ QCOMPARE(QEvent::registerEventType(hint), expected);
+}
+
+QTEST_MAIN(tst_QEvent)
+#include "tst_qevent.moc"
diff --git a/tests/auto/gui/kernel/qfileopenevent/qfileopenevent.pro b/tests/auto/gui/kernel/qfileopenevent/qfileopenevent.pro
new file mode 100644
index 0000000000..73724828db
--- /dev/null
+++ b/tests/auto/gui/kernel/qfileopenevent/qfileopenevent.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+QT += widgets
+SUBDIRS = test qfileopeneventexternal
diff --git a/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp
new file mode 100644
index 0000000000..5d1a6a390f
--- /dev/null
+++ b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include <QApplication>
+#include <QEvent>
+
+struct MyApplication : public QApplication
+{
+ MyApplication(int& argc, char** argv)
+ : QApplication(argc, argv)
+ {}
+
+ bool event(QEvent * event)
+ {
+ if (event->type() == QEvent::FileOpen) {
+ QFileOpenEvent* ev = static_cast<QFileOpenEvent *>(event);
+ QFile file;
+ bool ok = ev->openFile(file, QFile::Append | QFile::Unbuffered);
+ if (ok)
+ file.write(QByteArray("+external"));
+ return true;
+ } else {
+ return QApplication::event(event);
+ }
+ }
+};
+
+int main(int argc, char *argv[])
+{
+ MyApplication a(argc, argv);
+ a.sendPostedEvents(&a, QEvent::FileOpen);
+ return 0;
+}
diff --git a/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro
new file mode 100644
index 0000000000..cb61b82e38
--- /dev/null
+++ b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET = qfileopeneventexternal
+QT += core gui widgets
+SOURCES += qfileopeneventexternal.cpp
+symbian: {
+ RSS_RULES += "embeddability=KAppEmbeddable;"
+ RSS_RULES.datatype_list += "priority = EDataTypePriorityHigh; type = \"application/x-tst_qfileopenevent\";"
+ LIBS += -lapparc \
+ -leikcore -lefsrv -lcone
+}
diff --git a/tests/auto/gui/kernel/qfileopenevent/test/test.pro b/tests/auto/gui/kernel/qfileopenevent/test/test.pro
new file mode 100644
index 0000000000..3f16dcf6ee
--- /dev/null
+++ b/tests/auto/gui/kernel/qfileopenevent/test/test.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+TARGET = tst_qfileopenevent
+HEADERS +=
+SOURCES += tst_qfileopenevent.cpp
+symbian {
+ LIBS+=-lefsrv -lapgrfx -lapmime
+}
diff --git a/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp b/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp
new file mode 100644
index 0000000000..69cc4ccc01
--- /dev/null
+++ b/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QEvent>
+
+#ifdef Q_OS_SYMBIAN
+#include <apgcli.h>
+#include "private/qcore_symbian_p.h"
+#endif
+
+class tst_qfileopenevent : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qfileopenevent(){}
+ ~tst_qfileopenevent();
+
+public slots:
+ void initTestCase();
+
+private slots:
+ void constructor();
+ void fileOpen();
+ void handleLifetime();
+ void multiOpen();
+ void sendAndReceive();
+ void external_data();
+ void external();
+
+private:
+#ifdef Q_OS_SYMBIAN
+ RFile createRFile(const TDesC& filename, const TDesC8& content);
+#else
+ void createFile(const QString &filename, const QByteArray &content);
+#endif
+ QFileOpenEvent * createFileAndEvent(const QString &filename, const QByteArray &content);
+ void checkReadAndWrite(QFileOpenEvent& event, const QByteArray& readContent, const QByteArray& writeContent, bool writeOk);
+ QByteArray readFileContent(QFileOpenEvent& event);
+ bool appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent);
+
+ bool event(QEvent *);
+
+private:
+#ifdef Q_OS_SYMBIAN
+ struct AutoRFs : public RFs
+ {
+ AutoRFs()
+ {
+ qt_symbian_throwIfError(Connect());
+ qt_symbian_throwIfError(ShareProtected());
+ }
+
+ ~AutoRFs()
+ {
+ Close();
+ }
+ };
+ AutoRFs fsSession;
+#endif
+};
+
+tst_qfileopenevent::~tst_qfileopenevent()
+{
+};
+
+void tst_qfileopenevent::initTestCase()
+{
+}
+
+#ifdef Q_OS_SYMBIAN
+RFile tst_qfileopenevent::createRFile(const TDesC& filename, const TDesC8& content)
+{
+ RFile file;
+ qt_symbian_throwIfError(file.Replace(fsSession, filename, EFileWrite));
+ qt_symbian_throwIfError(file.Write(content));
+ return file;
+}
+#else
+void tst_qfileopenevent::createFile(const QString &filename, const QByteArray &content)
+{
+ QFile file(filename);
+ file.open(QFile::WriteOnly);
+ file.write(content);
+ file.close();
+}
+#endif
+
+QFileOpenEvent * tst_qfileopenevent::createFileAndEvent(const QString &filename, const QByteArray &content)
+{
+#ifdef Q_OS_SYMBIAN
+ RFile rFile = createRFile(qt_QString2TPtrC(filename), TPtrC8((TText8*)content.constData(), content.size()));
+ QScopedPointer<RFile, QScopedPointerRCloser<RFile> > closeRFile(&rFile);
+ return new QFileOpenEvent(rFile);
+#else
+ createFile(filename, content);
+ return new QFileOpenEvent(filename);
+#endif
+}
+
+void tst_qfileopenevent::constructor()
+{
+ // check that filename get/set works
+ QFileOpenEvent nameTest(QLatin1String("fileNameTest"));
+ QCOMPARE(nameTest.file(), QLatin1String("fileNameTest"));
+
+ // check that url get/set works
+ QFileOpenEvent urlTest(QUrl(QLatin1String("file:///urlNameTest")));
+ QCOMPARE(urlTest.url().toString(), QLatin1String("file:///urlNameTest"));
+
+#ifdef Q_OS_SYMBIAN
+ // check that RFile construction works
+ RFile rFile = createRFile(_L("testRFile"), _L8("test content"));
+ QFileOpenEvent rFileTest(rFile);
+ QString targetName(QLatin1String("testRFile"));
+ QCOMPARE(rFileTest.file().right(targetName.size()), targetName);
+ QCOMPARE(rFileTest.url().toString().right(targetName.size()), targetName);
+ rFile.Close();
+#endif
+}
+
+QByteArray tst_qfileopenevent::readFileContent(QFileOpenEvent& event)
+{
+ QFile file;
+ event.openFile(file, QFile::ReadOnly);
+ file.seek(0);
+ QByteArray data = file.readAll();
+ return data;
+}
+
+bool tst_qfileopenevent::appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent)
+{
+ QFile file;
+ bool ok = event.openFile(file, QFile::Append | QFile::Unbuffered);
+ if (ok)
+ ok = file.write(writeContent) == writeContent.size();
+ return ok;
+}
+
+void tst_qfileopenevent::checkReadAndWrite(QFileOpenEvent& event, const QByteArray& readContent, const QByteArray& writeContent, bool writeOk)
+{
+ QCOMPARE(readFileContent(event), readContent);
+ QCOMPARE(appendFileContent(event, writeContent), writeOk);
+ QCOMPARE(readFileContent(event), writeOk ? readContent+writeContent : readContent);
+}
+
+void tst_qfileopenevent::fileOpen()
+{
+#ifdef Q_OS_SYMBIAN
+ // create writeable file
+ {
+ RFile rFile = createRFile(_L("testFileOpen"), _L8("test content"));
+ QFileOpenEvent rFileTest(rFile);
+ checkReadAndWrite(rFileTest, QByteArray("test content"), QByteArray("+RFileWrite"), true);
+ rFile.Close();
+ }
+
+ // open read-only RFile
+ {
+ RFile rFile;
+ int err = rFile.Open(fsSession, _L("testFileOpen"), EFileRead);
+ QFileOpenEvent rFileTest(rFile);
+ checkReadAndWrite(rFileTest, QByteArray("test content+RFileWrite"), QByteArray("+RFileRead"), false);
+ rFile.Close();
+ }
+#else
+ createFile(QLatin1String("testFileOpen"), QByteArray("test content+RFileWrite"));
+#endif
+
+ // filename event
+ QUrl fileUrl; // need to get the URL during the file test, for use in the URL test
+ {
+ QFileOpenEvent nameTest(QLatin1String("testFileOpen"));
+ fileUrl = nameTest.url();
+ checkReadAndWrite(nameTest, QByteArray("test content+RFileWrite"), QByteArray("+nameWrite"), true);
+ }
+
+ // url event
+ {
+ QFileOpenEvent urlTest(fileUrl);
+ checkReadAndWrite(urlTest, QByteArray("test content+RFileWrite+nameWrite"), QByteArray("+urlWrite"), true);
+ }
+
+ QFile::remove(QLatin1String("testFileOpen"));
+}
+
+void tst_qfileopenevent::handleLifetime()
+{
+ QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testHandleLifetime"), QByteArray("test content")));
+
+ // open a QFile after the original RFile is closed
+ QFile qFile;
+ QCOMPARE(event->openFile(qFile, QFile::Append | QFile::Unbuffered), true);
+ event.reset(0);
+
+ // write to the QFile after the event is closed
+ QString writeContent(QLatin1String("+closed original handles"));
+ QCOMPARE(int(qFile.write(writeContent.toUtf8())), writeContent.size());
+ qFile.close();
+
+ // check the content
+ QFile check("testHandleLifetime");
+ check.open(QFile::ReadOnly);
+ QString content(check.readAll());
+ QCOMPARE(content, QLatin1String("test content+closed original handles"));
+ check.close();
+
+ QFile::remove(QLatin1String("testHandleLifetime"));
+}
+
+void tst_qfileopenevent::multiOpen()
+{
+ QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testMultiOpen"), QByteArray("itlum")));
+
+ QFile files[5];
+ for (int i=0; i<5; i++) {
+ QCOMPARE(event->openFile(files[i], QFile::ReadOnly), true);
+ }
+ for (int i=0; i<5; i++)
+ files[i].seek(i);
+ QString str;
+ for (int i=4; i>=0; i--) {
+ char c;
+ files[i].getChar(&c);
+ str.append(c);
+ files[i].close();
+ }
+ QCOMPARE(str, QLatin1String("multi"));
+
+ QFile::remove(QLatin1String("testMultiOpen"));
+}
+
+bool tst_qfileopenevent::event(QEvent *event)
+{
+ if (event->type() != QEvent::FileOpen)
+ return QObject::event(event);
+ QFileOpenEvent* fileOpenEvent = static_cast<QFileOpenEvent *>(event);
+ appendFileContent(*fileOpenEvent, "+received");
+ return true;
+}
+
+void tst_qfileopenevent::sendAndReceive()
+{
+ QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testSendAndReceive"), QByteArray("sending")));
+
+ QCoreApplication::instance()->postEvent(this, event.take());
+ QCoreApplication::instance()->processEvents();
+
+ // QTBUG-17468: On Mac, processEvents doesn't always process posted events
+ QCoreApplication::instance()->sendPostedEvents();
+
+ // check the content
+ QFile check("testSendAndReceive");
+ QCOMPARE(check.open(QFile::ReadOnly), true);
+ QString content(check.readAll());
+ QCOMPARE(content, QLatin1String("sending+received"));
+ check.close();
+
+ QFile::remove(QLatin1String("testSendAndReceive"));
+}
+
+void tst_qfileopenevent::external_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<QByteArray>("targetContent");
+ QTest::addColumn<bool>("sendHandle");
+
+ QString privateName(QLatin1String("tst_qfileopenevent_external"));
+ QString publicName(QLatin1String("C:\\Data\\tst_qfileopenevent_external"));
+ QByteArray writeSuccess("original+external");
+ QByteArray writeFail("original");
+ QTest::newRow("public name") << publicName << writeSuccess << false;
+ QTest::newRow("data caged name") << privateName << writeFail << false;
+ QTest::newRow("public handle") << publicName << writeSuccess << true;
+ QTest::newRow("data caged handle") << privateName << writeSuccess << true;
+}
+
+void tst_qfileopenevent::external()
+{
+#ifndef Q_OS_SYMBIAN
+ QSKIP("external app file open test only valid in Symbian", SkipAll);
+#else
+
+ QFETCH(QString, filename);
+ QFETCH(QByteArray, targetContent);
+ QFETCH(bool, sendHandle);
+
+ RFile rFile = createRFile(qt_QString2TPtrC(filename), _L8("original"));
+
+ // launch app with the file
+ RApaLsSession apa;
+ QCOMPARE(apa.Connect(), KErrNone);
+ TThreadId threadId;
+ TDataType type(_L8("application/x-tst_qfileopenevent"));
+ if (sendHandle) {
+ QCOMPARE(apa.StartDocument(rFile, type, threadId), KErrNone);
+ rFile.Close();
+ } else {
+ TFileName fullName;
+ rFile.FullName(fullName);
+ rFile.Close();
+ QCOMPARE(apa.StartDocument(fullName, type, threadId), KErrNone);
+ }
+
+ // wait for app exit
+ RThread appThread;
+ if (appThread.Open(threadId) == KErrNone) {
+ TRequestStatus status;
+ appThread.Logon(status);
+ User::WaitForRequest(status);
+ }
+
+ // check the contents
+ QFile check(filename);
+ QCOMPARE(check.open(QFile::ReadOnly), true);
+ QCOMPARE(check.readAll(), targetContent);
+ bool ok = check.remove();
+
+ QFile::remove(filename);
+#endif
+}
+
+QTEST_MAIN(tst_qfileopenevent)
+#include "tst_qfileopenevent.moc"
diff --git a/tests/auto/gui/kernel/qguivariant/.gitignore b/tests/auto/gui/kernel/qguivariant/.gitignore
new file mode 100644
index 0000000000..ea64ae90a0
--- /dev/null
+++ b/tests/auto/gui/kernel/qguivariant/.gitignore
@@ -0,0 +1 @@
+tst_qguivariant
diff --git a/tests/auto/gui/kernel/qguivariant/qguivariant.pro b/tests/auto/gui/kernel/qguivariant/qguivariant.pro
new file mode 100644
index 0000000000..68082f0037
--- /dev/null
+++ b/tests/auto/gui/kernel/qguivariant/qguivariant.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qguivariant.cpp
+
+
+
diff --git a/tests/auto/gui/kernel/qguivariant/tst_qguivariant.cpp b/tests/auto/gui/kernel/qguivariant/tst_qguivariant.cpp
new file mode 100644
index 0000000000..988580b874
--- /dev/null
+++ b/tests/auto/gui/kernel/qguivariant/tst_qguivariant.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qvariant.h>
+
+
+
+class tst_QGuiVariant : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QGuiVariant();
+
+private slots:
+ void variantWithoutApplication();
+};
+
+tst_QGuiVariant::tst_QGuiVariant()
+{}
+
+void tst_QGuiVariant::variantWithoutApplication()
+{
+ QVariant v = QString("red");
+
+ QVERIFY(qvariant_cast<QColor>(v) == QColor(Qt::red));
+}
+
+
+QTEST_APPLESS_MAIN(tst_QGuiVariant)
+#include "tst_qguivariant.moc"
diff --git a/tests/auto/gui/kernel/qkeysequence/.gitignore b/tests/auto/gui/kernel/qkeysequence/.gitignore
new file mode 100644
index 0000000000..e06a7b0f43
--- /dev/null
+++ b/tests/auto/gui/kernel/qkeysequence/.gitignore
@@ -0,0 +1 @@
+tst_qkeysequence
diff --git a/tests/auto/gui/kernel/qkeysequence/keys_de.qm b/tests/auto/gui/kernel/qkeysequence/keys_de.qm
new file mode 100644
index 0000000000..5d7aedd765
--- /dev/null
+++ b/tests/auto/gui/kernel/qkeysequence/keys_de.qm
Binary files differ
diff --git a/tests/auto/gui/kernel/qkeysequence/keys_de.ts b/tests/auto/gui/kernel/qkeysequence/keys_de.ts
new file mode 100644
index 0000000000..1db18f1fdd
--- /dev/null
+++ b/tests/auto/gui/kernel/qkeysequence/keys_de.ts
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="de">
+<context>
+ <name>tst_QKeySequence</name>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="369"/>
+ <source>Shift+K</source>
+ <translation type="obsolete">Umschalt+K</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="370"/>
+ <source>Ctrl+K</source>
+ <translation type="obsolete">Strg+K</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="371"/>
+ <source>Alt+K</source>
+ <translation type="obsolete">Alt+K</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="391"/>
+ <source>Shift++</source>
+ <translation>Umschalt++</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="392"/>
+ <source>Ctrl++</source>
+ <translation>Strg++</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="393"/>
+ <source>Alt++</source>
+ <translation>Alt++</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="394"/>
+ <source>Meta++</source>
+ <translation>Meta++</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="401"/>
+ <source>Shift+,, Shift++</source>
+ <translation>Umschalt+,, Umschalt++</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="402"/>
+ <source>Shift+,, Ctrl++</source>
+ <translation>Umschalt+,, Strg++</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="403"/>
+ <source>Shift+,, Alt++</source>
+ <translation>Umschalt+,, Alt++</translation>
+ </message>
+ <message>
+ <location filename="tst_qkeysequence.cpp" line="404"/>
+ <source>Shift+,, Meta++</source>
+ <translation>Umschalt+,, Meta++</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/gui/kernel/qkeysequence/qkeysequence.pro b/tests/auto/gui/kernel/qkeysequence/qkeysequence.pro
new file mode 100644
index 0000000000..6cfbe459ea
--- /dev/null
+++ b/tests/auto/gui/kernel/qkeysequence/qkeysequence.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qkeysequence.cpp
+
+RESOURCES += qkeysequence.qrc
diff --git a/tests/auto/gui/kernel/qkeysequence/qkeysequence.qrc b/tests/auto/gui/kernel/qkeysequence/qkeysequence.qrc
new file mode 100644
index 0000000000..e224faaddd
--- /dev/null
+++ b/tests/auto/gui/kernel/qkeysequence/qkeysequence.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource>
+ <file>keys_de.qm</file>
+ <file>qt_de.qm</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/kernel/qkeysequence/qt_de.qm b/tests/auto/gui/kernel/qkeysequence/qt_de.qm
new file mode 100644
index 0000000000..595e4d7e8f
--- /dev/null
+++ b/tests/auto/gui/kernel/qkeysequence/qt_de.qm
Binary files differ
diff --git a/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp b/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
new file mode 100644
index 0000000000..5753fb8df4
--- /dev/null
+++ b/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
@@ -0,0 +1,636 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <private/qapplication_p.h>
+#include <qkeysequence.h>
+#include <private/qkeysequence_p.h>
+#include <QTranslator>
+#include <QLibraryInfo>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#ifdef Q_WS_MAC
+#include <Carbon/Carbon.h>
+struct MacSpecialKey {
+ int key;
+ ushort macSymbol;
+};
+
+static const int NumEntries = 21;
+static const MacSpecialKey entries[NumEntries] = {
+ { Qt::Key_Escape, 0x238B },
+ { Qt::Key_Tab, 0x21E5 },
+ { Qt::Key_Backtab, 0x21E4 },
+ { Qt::Key_Backspace, 0x232B },
+ { Qt::Key_Return, 0x21B5 },
+ { Qt::Key_Enter, 0x21B5 },
+ { Qt::Key_Delete, 0x2326 },
+ { Qt::Key_Home, 0x2196 },
+ { Qt::Key_End, 0x2198 },
+ { Qt::Key_Left, 0x2190 },
+ { Qt::Key_Up, 0x2191 },
+ { Qt::Key_Right, 0x2192 },
+ { Qt::Key_Down, 0x2193 },
+ { Qt::Key_PageUp, 0x21DE },
+ { Qt::Key_PageDown, 0x21DF },
+ { Qt::Key_Shift, kShiftUnicode },
+ { Qt::Key_Control, kCommandUnicode },
+ { Qt::Key_Meta, kControlUnicode },
+ { Qt::Key_Alt, kOptionUnicode },
+ { Qt::Key_CapsLock, 0x21EA },
+};
+
+static bool operator<(const MacSpecialKey &entry, int key)
+{
+ return entry.key < key;
+}
+
+static bool operator<(int key, const MacSpecialKey &entry)
+{
+ return key < entry.key;
+}
+
+static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntries;
+
+static QChar macSymbolForQtKey(int key)
+{
+ const MacSpecialKey *i = qBinaryFind(entries, MacSpecialKeyEntriesEnd, key);
+ if (i == MacSpecialKeyEntriesEnd)
+ return QChar();
+ return QChar(i->macSymbol);
+}
+
+#endif
+
+class tst_QKeySequence : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QKeySequence();
+ virtual ~tst_QKeySequence();
+
+private slots:
+ void swap();
+ void operatorQString_data();
+ void operatorQString();
+ void compareConstructors_data();
+ void compareConstructors();
+ void symetricConstructors_data();
+ void symetricConstructors();
+ void checkMultipleNames();
+ void checkMultipleCodes();
+ void mnemonic_data();
+ void mnemonic();
+ void toString_data();
+ void toString();
+ void streamOperators_data();
+ void streamOperators();
+ void fromString_data();
+ void fromString();
+ void ensureSorted();
+ void standardKeys_data();
+ void standardKeys();
+ void keyBindings();
+ void translated_data();
+ void translated();
+ void i18nKeys_data();
+ void i18nKeys();
+
+
+ void initTestCase();
+private:
+ QTranslator *ourTranslator;
+ QTranslator *qtTranslator;
+#ifdef Q_WS_MAC
+ static const QString MacCtrl;
+ static const QString MacMeta;
+ static const QString MacAlt;
+ static const QString MacShift;
+#endif
+
+
+};
+
+#ifdef Q_WS_MAC
+const QString tst_QKeySequence::MacCtrl = QString(QChar(0x2318));
+const QString tst_QKeySequence::MacMeta = QString(QChar(0x2303));
+const QString tst_QKeySequence::MacAlt = QString(QChar(0x2325));
+const QString tst_QKeySequence::MacShift = QString(QChar(0x21E7));
+#endif
+
+tst_QKeySequence::tst_QKeySequence()
+{
+}
+
+tst_QKeySequence::~tst_QKeySequence()
+{
+
+}
+
+void tst_QKeySequence::initTestCase()
+{
+ ourTranslator = new QTranslator(this);
+ ourTranslator->load(":/keys_de");
+ qtTranslator = new QTranslator(this);
+ qtTranslator->load(":/qt_de");
+}
+
+void tst_QKeySequence::swap()
+{
+ QKeySequence ks1(Qt::CTRL+Qt::Key_O);
+ QKeySequence ks2(Qt::CTRL+Qt::Key_L);
+ ks1.swap(ks2);
+ QCOMPARE(ks1[0], int(Qt::CTRL+Qt::Key_L));
+ QCOMPARE(ks2[0], int(Qt::CTRL+Qt::Key_O));
+}
+
+void tst_QKeySequence::operatorQString_data()
+{
+ QTest::addColumn<int>("modifiers");
+ QTest::addColumn<int>("keycode");
+ QTest::addColumn<QString>("keystring");
+
+ QTest::newRow( "No modifier" ) << 0 << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString( "\x0c5" );
+
+#ifndef Q_WS_MAC
+ QTest::newRow( "Ctrl+Left" ) << int(Qt::CTRL) << int(Qt::Key_Left) << QString( "Ctrl+Left" );
+ QTest::newRow( "Ctrl+," ) << int(Qt::CTRL) << int(Qt::Key_Comma) << QString( "Ctrl+," );
+ QTest::newRow( "Alt+Left" ) << int(Qt::ALT) << int(Qt::Key_Left) << QString( "Alt+Left" );
+ QTest::newRow( "Alt+Shift+Left" ) << int(Qt::ALT | Qt::SHIFT) << int(Qt::Key_Left) << QString( "Alt+Shift+Left" );
+ QTest::newRow( "Ctrl" ) << int(Qt::CTRL) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString( "Ctrl+\x0c5" );
+ QTest::newRow( "Alt" ) << int(Qt::ALT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString( "Alt+\x0c5" );
+ QTest::newRow( "Shift" ) << int(Qt::SHIFT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString( "Shift+\x0c5" );
+ QTest::newRow( "Meta" ) << int(Qt::META) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString( "Meta+\x0c5" );
+#else
+ QTest::newRow( "Ctrl+Left" ) << int(Qt::CTRL) << int(Qt::Key_Left) << MacCtrl + macSymbolForQtKey(Qt::Key_Left);
+ QTest::newRow( "Ctrl+," ) << int(Qt::CTRL) << int(Qt::Key_Comma) << MacCtrl + ",";
+ QTest::newRow( "Alt+Left" ) << int(Qt::ALT) << int(Qt::Key_Left) << MacAlt + macSymbolForQtKey(Qt::Key_Left);
+ QTest::newRow( "Alt+Shift+Left" ) << int(Qt::ALT | Qt::SHIFT) << int(Qt::Key_Left) << MacAlt + MacShift + macSymbolForQtKey(Qt::Key_Left);
+ QTest::newRow( "Ctrl" ) << int(Qt::CTRL) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << MacCtrl + "\x0c5";
+ QTest::newRow( "Alt" ) << int(Qt::ALT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << MacAlt + "\x0c5";
+ QTest::newRow( "Shift" ) << int(Qt::SHIFT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << MacShift + "\x0c5";
+ QTest::newRow( "Meta" ) << int(Qt::META) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << MacMeta + "\x0c5";
+#endif
+}
+
+void tst_QKeySequence::symetricConstructors_data()
+{
+ QTest::addColumn<int>("modifiers");
+ QTest::addColumn<int>("keycode");
+
+ QTest::newRow( "No modifier" ) << 0 << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
+ QTest::newRow( "Ctrl" ) << int(Qt::CTRL) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
+ QTest::newRow( "Alt" ) << int(Qt::ALT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
+ QTest::newRow( "Shift" ) << int(Qt::SHIFT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
+ QTest::newRow( "Meta" ) << int(Qt::META) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
+}
+
+void tst_QKeySequence::compareConstructors_data()
+{
+ operatorQString_data();
+}
+
+// operator QString()
+void tst_QKeySequence::operatorQString()
+{
+ QKeySequence seq;
+ QFETCH( int, modifiers );
+ QFETCH( int, keycode );
+ QFETCH( QString, keystring );
+
+ seq = QKeySequence( modifiers | keycode );
+
+ QCOMPARE( (QString)seq, keystring );
+}
+
+// this verifies that the constructors can handle the same strings in and out
+void tst_QKeySequence::symetricConstructors()
+{
+ QFETCH( int, modifiers );
+ QFETCH( int, keycode );
+
+ QKeySequence seq1( modifiers | keycode );
+ QKeySequence seq2( (QString)seq1 );
+
+ QVERIFY( seq1 == seq2 );
+}
+
+/* Compares QKeySequence constructurs with int or QString arguments
+ We don't do this for 3.0 since it doesn't support unicode accelerators */
+void tst_QKeySequence::compareConstructors()
+{
+ QFETCH( int, modifiers );
+ QFETCH( int, keycode );
+ QFETCH( QString, keystring );
+
+ QKeySequence qstringSeq( keystring );
+ QKeySequence intSeq( modifiers | keycode );
+
+ QVERIFY( qstringSeq == intSeq );
+}
+
+void tst_QKeySequence::checkMultipleNames()
+{
+ QKeySequence oldK( "Ctrl+Page Up" );
+ QKeySequence newK( "Ctrl+PgUp" );
+ QVERIFY( oldK == newK );
+}
+
+//TODO: could test third constructor, or test fromString on all constructor-data
+void tst_QKeySequence::checkMultipleCodes()
+{
+ QKeySequence seq1("Alt+d, l");
+ QKeySequence seq2 = QKeySequence::fromString("Alt+d, l");
+ QVERIFY( seq1 == seq2 );
+
+ QKeySequence seq3("Alt+d,l");
+ QKeySequence seq4 = QKeySequence::fromString("Alt+d,l");
+ QVERIFY( seq3 == seq4 );
+}
+
+/*
+* We must ensure that the keyBindings data is always sorted
+* so that we can safely perform binary searches.
+*/
+void tst_QKeySequence::ensureSorted()
+{
+//### accessing static members from private classes does not work on msvc at the moment
+#if defined(QT_BUILD_INTERNAL) && !defined(Q_WS_WIN)
+ uint N = QKeySequencePrivate::numberOfKeyBindings;
+ uint val = QKeySequencePrivate::keyBindings[0].shortcut;
+ for ( uint i = 1 ; i < N ; ++i) {
+ uint nextval = QKeySequencePrivate::keyBindings[i].shortcut;
+ if (nextval < val)
+ qDebug() << "Data not sorted at index " << i;
+ QVERIFY(nextval >= val);
+ val = nextval;
+ }
+#endif
+}
+
+void tst_QKeySequence::standardKeys_data()
+{
+ QTest::addColumn<int>("standardKey");
+ QTest::addColumn<QString>("expected");
+ QTest::newRow("unknownkey") << (int)QKeySequence::UnknownKey<< QString("");
+ QTest::newRow("copy") << (int)QKeySequence::Copy << QString("CTRL+C");
+ QTest::newRow("cut") << (int)QKeySequence::Cut << QString("CTRL+X");
+ QTest::newRow("paste") << (int)QKeySequence::Paste << QString("CTRL+V");
+ QTest::newRow("delete") << (int)QKeySequence::Delete<< QString("DEL");
+ QTest::newRow("open") << (int)QKeySequence::Open << QString("CTRL+O");
+ QTest::newRow("find") << (int)QKeySequence::Find<< QString("CTRL+F");
+#ifdef Q_WS_WIN
+ QTest::newRow("addTab") << (int)QKeySequence::AddTab<< QString("CTRL+T");
+ QTest::newRow("findNext") << (int)QKeySequence::FindNext<< QString("F3");
+ QTest::newRow("findPrevious") << (int)QKeySequence::FindPrevious << QString("SHIFT+F3");
+ QTest::newRow("close") << (int)QKeySequence::Close<< QString("CTRL+F4");
+ QTest::newRow("replace") << (int)QKeySequence::Replace<< QString("CTRL+H");
+#endif
+ QTest::newRow("bold") << (int)QKeySequence::Bold << QString("CTRL+B");
+ QTest::newRow("italic") << (int)QKeySequence::Italic << QString("CTRL+I");
+ QTest::newRow("underline") << (int)QKeySequence::Underline << QString("CTRL+U");
+ QTest::newRow("selectall") << (int)QKeySequence::SelectAll << QString("CTRL+A");
+ QTest::newRow("print") << (int)QKeySequence::Print << QString("CTRL+P");
+ QTest::newRow("movenextchar") << (int)QKeySequence::MoveToNextChar<< QString("RIGHT");
+ QTest::newRow("zoomIn") << (int)QKeySequence::ZoomIn<< QString("CTRL++");
+ QTest::newRow("zoomOut") << (int)QKeySequence::ZoomOut<< QString("CTRL+-");
+ QTest::newRow("whatsthis") << (int)QKeySequence::WhatsThis<< QString("SHIFT+F1");
+
+#if defined(Q_WS_MAC)
+ QTest::newRow("help") << (int)QKeySequence::HelpContents<< QString("Ctrl+?");
+ QTest::newRow("nextChild") << (int)QKeySequence::NextChild << QString("CTRL+}");
+ QTest::newRow("previousChild") << (int)QKeySequence::PreviousChild << QString("CTRL+{");
+ QTest::newRow("MoveToEndOfBlock") << (int)QKeySequence::MoveToEndOfBlock << QString("ALT+DOWN");
+ QTest::newRow("forward") << (int)QKeySequence::Forward << QString("CTRL+]");
+ QTest::newRow("backward") << (int)QKeySequence::Back << QString("CTRL+[");
+ QTest::newRow("SelectEndOfDocument") << (int)QKeySequence::SelectEndOfDocument<< QString("CTRL+SHIFT+DOWN"); //mac only
+#elif defined(Q_WS_S60)
+ QTest::newRow("help") << (int)QKeySequence::HelpContents<< QString("F2");
+ QTest::newRow("SelectEndOfDocument") << (int)QKeySequence::SelectEndOfDocument<< QString("CTRL+SHIFT+END"); //mac only
+#else
+ QTest::newRow("help") << (int)QKeySequence::HelpContents<< QString("F1");
+ QTest::newRow("nextChild") << (int)QKeySequence::NextChild<< QString("CTRL+Tab");
+ QTest::newRow("previousChild") << (int)QKeySequence::PreviousChild<< QString("CTRL+SHIFT+BACKTAB");
+ QTest::newRow("forward") << (int)QKeySequence::Forward << QString("ALT+RIGHT");
+ QTest::newRow("backward") << (int)QKeySequence::Back << QString("ALT+LEFT");
+ QTest::newRow("MoveToEndOfBlock") << (int)QKeySequence::MoveToEndOfBlock<< QString(""); //mac only
+ QTest::newRow("SelectEndOfDocument") << (int)QKeySequence::SelectEndOfDocument<< QString("CTRL+SHIFT+END"); //mac only
+#endif
+}
+
+void tst_QKeySequence::standardKeys()
+{
+ QFETCH(int, standardKey);
+ QFETCH(QString, expected);
+ QKeySequence ks((QKeySequence::StandardKey)standardKey);
+ QKeySequence ks2(expected);
+ QVERIFY(ks == ks2);
+}
+
+void tst_QKeySequence::keyBindings()
+{
+ QList<QKeySequence> bindings = QKeySequence::keyBindings(QKeySequence::Copy);
+ QList<QKeySequence> expected;
+#if defined(Q_WS_MAC) || defined (Q_WS_S60)
+ expected << QKeySequence("CTRL+C");
+#elif defined Q_WS_X11
+ expected << QKeySequence("CTRL+C") << QKeySequence("F16") << QKeySequence("CTRL+INSERT");
+#else
+ expected << QKeySequence("CTRL+C") << QKeySequence("CTRL+INSERT");
+#endif
+ QVERIFY(bindings == expected);
+}
+
+
+
+void tst_QKeySequence::mnemonic_data()
+{
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<QString>("key");
+ QTest::addColumn<bool>("warning");
+
+ QTest::newRow("1") << QString::fromLatin1("&bonjour") << QString::fromLatin1("ALT+B") << false;
+ QTest::newRow("2") << QString::fromLatin1("&&bonjour") << QString() << false;
+ QTest::newRow("3") << QString::fromLatin1("&&bon&jour") << QString::fromLatin1("ALT+J") << false;
+ QTest::newRow("4") << QString::fromLatin1("&&bon&jo&ur") << QString::fromLatin1("ALT+J") << true;
+ QTest::newRow("5") << QString::fromLatin1("b&on&&jour") << QString::fromLatin1("ALT+O") << false;
+ QTest::newRow("6") << QString::fromLatin1("bonjour") << QString() << false;
+ QTest::newRow("7") << QString::fromLatin1("&&&bonjour") << QString::fromLatin1("ALT+B") << false;
+ QTest::newRow("8") << QString::fromLatin1("bonjour&&&") << QString() << false;
+ QTest::newRow("9") << QString::fromLatin1("bo&&nj&o&&u&r") << QString::fromLatin1("ALT+O") << true;
+ QTest::newRow("10") << QString::fromLatin1("BON&JOUR") << QString::fromLatin1("ALT+J") << false;
+ QTest::newRow("11") << QString::fromUtf8("bonjour") << QString() << false;
+}
+
+void tst_QKeySequence::mnemonic()
+{
+#ifdef Q_WS_MAC
+ QSKIP("mnemonics are not used on Mac OS X", SkipAll);
+#endif
+ QFETCH(QString, string);
+ QFETCH(QString, key);
+ QFETCH(bool, warning);
+
+#ifndef QT_NO_DEBUG
+ if (warning) {
+ QString str = QString::fromLatin1("QKeySequence::mnemonic: \"%1\" contains multiple occurrences of '&'").arg(string);
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(str));
+ // qWarning(qPrintable(str));
+ }
+#endif
+ QKeySequence seq = QKeySequence::mnemonic(string);
+ QKeySequence res = QKeySequence(key);
+
+ QCOMPARE(seq, res);
+}
+
+
+
+void tst_QKeySequence::toString_data()
+{
+ QTest::addColumn<QString>("strSequence");
+ QTest::addColumn<QString>("neutralString");
+ QTest::addColumn<QString>("platformString");
+
+
+#ifndef Q_WS_MAC
+ QTest::newRow("Ctrl+Left") << QString("Ctrl+Left") << QString("Ctrl+Left") << QString("Ctrl+Left");
+ QTest::newRow("Alt+Left") << QString("Alt+Left") << QString("Alt+Left") << QString("Alt+Left");
+ QTest::newRow("Alt+Shift+Left") << QString("Alt+Shift+Left") << QString("Alt+Shift+Left") << QString("Alt+Shift+Left");
+ QTest::newRow("Ctrl") << QString("Ctrl+\x0c5") << QString("Ctrl+\x0c5") << QString("Ctrl+\x0c5");
+ QTest::newRow("Alt") << QString("Alt+\x0c5") << QString("Alt+\x0c5") << QString("Alt+\x0c5");
+ QTest::newRow("Shift") << QString("Shift+\x0c5") << QString("Shift+\x0c5") << QString("Shift+\x0c5");
+ QTest::newRow("Meta") << QString("Meta+\x0c5") << QString("Meta+\x0c5") << QString("Meta+\x0c5");
+ QTest::newRow("Ctrl+Plus") << QString("Ctrl++") << QString("Ctrl++") << QString("Ctrl++");
+ QTest::newRow("Ctrl+,") << QString("Ctrl+,") << QString("Ctrl+,") << QString("Ctrl+,");
+ QTest::newRow("Ctrl+,,Ctrl+,") << QString("Ctrl+,,Ctrl+,") << QString("Ctrl+,, Ctrl+,") << QString("Ctrl+,, Ctrl+,");
+ QTest::newRow("MultiKey") << QString("Alt+X, Ctrl+Y, Z") << QString("Alt+X, Ctrl+Y, Z")
+ << QString("Alt+X, Ctrl+Y, Z");
+
+ QTest::newRow("Invalid") << QString("Ctrly") << QString("") << QString("");
+#else
+ /*
+ QTest::newRow("Ctrl+Left") << MacCtrl + "Left" << QString("Ctrl+Left") << MacCtrl + macSymbolForQtKey(Qt::Key_Left);
+ QTest::newRow("Alt+Left") << MacAlt + "Left" << QString("Alt+Left") << MacAlt + macSymbolForQtKey(Qt::Key_Left);
+ QTest::newRow("Alt+Shift+Left") << MacAlt + MacShift + "Left" << QString("Alt+Shift+Left")
+ << MacAlt + MacShift + macSymbolForQtKey(Qt::Key_Left);
+ */
+ QTest::newRow("Ctrl+Right,Left") << MacCtrl + "Right, Left" << QString("Ctrl+Right, Left") << MacCtrl + macSymbolForQtKey(Qt::Key_Right) + QString(", ") + macSymbolForQtKey(Qt::Key_Left);
+ QTest::newRow("Ctrl") << MacCtrl + "\x0c5" << QString("Ctrl+\x0c5") << MacCtrl + "\x0c5";
+ QTest::newRow("Alt") << MacAlt + "\x0c5" << QString("Alt+\x0c5") << MacAlt + "\x0c5";
+ QTest::newRow("Shift") << MacShift + "\x0c5" << QString("Shift+\x0c5") << MacShift + "\x0c5";
+ QTest::newRow("Meta") << MacMeta + "\x0c5" << QString("Meta+\x0c5") << MacMeta + "\x0c5";
+ QTest::newRow("Ctrl+Plus") << MacCtrl + "+" << QString("Ctrl++") << MacCtrl + "+";
+ QTest::newRow("Ctrl+,") << MacCtrl + "," << QString("Ctrl+,") << MacCtrl + ",";
+ QTest::newRow("Ctrl+,,Ctrl+,") << MacCtrl + ",, " + MacCtrl + "," << QString("Ctrl+,, Ctrl+,") << MacCtrl + ",, " + MacCtrl + ",";
+ QTest::newRow("MultiKey") << MacAlt + "X, " + MacCtrl + "Y, Z" << QString("Alt+X, Ctrl+Y, Z")
+ << MacAlt + "X, " + MacCtrl + "Y, Z";
+ QTest::newRow("Invalid") << QString("Ctrly") << QString("") << QString("");
+#endif
+}
+
+void tst_QKeySequence::toString()
+{
+ QFETCH(QString, strSequence);
+ QFETCH(QString, neutralString);
+ QFETCH(QString, platformString);
+
+ QKeySequence ks1(strSequence);
+
+ QCOMPARE(ks1.toString(QKeySequence::NativeText), platformString);
+ QCOMPARE(ks1.toString(QKeySequence::PortableText), neutralString);
+
+}
+
+void tst_QKeySequence::streamOperators_data()
+{
+ operatorQString_data();
+}
+
+void tst_QKeySequence::streamOperators()
+{
+ QFETCH( int, modifiers );
+ QFETCH( int, keycode );
+
+ QByteArray data;
+ QKeySequence refK( modifiers | keycode );
+ QKeySequence orgK( "Ctrl+A" );
+ QKeySequence copyOrgK = orgK;
+ QVERIFY( copyOrgK == orgK );
+
+ QDataStream in(&data, QIODevice::WriteOnly);
+ in << refK;
+ QDataStream out(&data, QIODevice::ReadOnly);
+ out >> orgK;
+
+ QVERIFY( orgK == refK );
+
+ // check if detached
+ QVERIFY( orgK != copyOrgK );
+}
+
+void tst_QKeySequence::fromString_data()
+{
+ toString_data();
+}
+
+void tst_QKeySequence::fromString()
+{
+ QFETCH(QString, strSequence);
+ QFETCH(QString, neutralString);
+ QFETCH(QString, platformString);
+
+ QKeySequence ks1(strSequence);
+ QKeySequence ks2 = QKeySequence::fromString(ks1.toString());
+ QKeySequence ks3 = QKeySequence::fromString(neutralString, QKeySequence::PortableText);
+ QKeySequence ks4 = QKeySequence::fromString(platformString, QKeySequence::NativeText);
+
+
+ // assume the transitive property exists here.
+ QCOMPARE(ks2, ks1);
+ QCOMPARE(ks3, ks1);
+ QCOMPARE(ks4, ks1);
+}
+
+void tst_QKeySequence::translated_data()
+{
+ qApp->installTranslator(ourTranslator);
+ qApp->installTranslator(qtTranslator);
+
+ QTest::addColumn<QString>("transKey");
+ QTest::addColumn<QString>("compKey");
+
+ QTest::newRow("Shift++") << tr("Shift++") << QString("Umschalt++");
+ QTest::newRow("Ctrl++") << tr("Ctrl++") << QString("Strg++");
+ QTest::newRow("Alt++") << tr("Alt++") << QString("Alt++");
+ QTest::newRow("Meta++") << tr("Meta++") << QString("Meta++");
+
+ QTest::newRow("Shift+,, Shift++") << tr("Shift+,, Shift++") << QString("Umschalt+,, Umschalt++");
+ QTest::newRow("Shift+,, Ctrl++") << tr("Shift+,, Ctrl++") << QString("Umschalt+,, Strg++");
+ QTest::newRow("Shift+,, Alt++") << tr("Shift+,, Alt++") << QString("Umschalt+,, Alt++");
+ QTest::newRow("Shift+,, Meta++") << tr("Shift+,, Meta++") << QString("Umschalt+,, Meta++");
+
+ QTest::newRow("Ctrl+,, Shift++") << tr("Ctrl+,, Shift++") << QString("Strg+,, Umschalt++");
+ QTest::newRow("Ctrl+,, Ctrl++") << tr("Ctrl+,, Ctrl++") << QString("Strg+,, Strg++");
+ QTest::newRow("Ctrl+,, Alt++") << tr("Ctrl+,, Alt++") << QString("Strg+,, Alt++");
+ QTest::newRow("Ctrl+,, Meta++") << tr("Ctrl+,, Meta++") << QString("Strg+,, Meta++");
+
+ qApp->removeTranslator(ourTranslator);
+ qApp->removeTranslator(qtTranslator);
+}
+
+void tst_QKeySequence::translated()
+{
+ QFETCH(QString, transKey);
+ QFETCH(QString, compKey);
+#ifdef Q_WS_MAC
+ QSKIP("No need to translate modifiers on Mac OS X", SkipAll);
+#elif defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
+ QSKIP("No need to translate modifiers on WinCE or Symbian", SkipAll);
+#endif
+
+ qApp->installTranslator(ourTranslator);
+ qApp->installTranslator(qtTranslator);
+
+ QKeySequence ks1(transKey);
+ QCOMPARE(ks1.toString(QKeySequence::NativeText), compKey);
+
+ qApp->removeTranslator(ourTranslator);
+ qApp->removeTranslator(qtTranslator);
+}
+
+
+void tst_QKeySequence::i18nKeys_data()
+{
+ QTest::addColumn<int>("keycode");
+ QTest::addColumn<QString>("keystring");
+
+ // Japanese keyboard support
+ QTest::newRow("Kanji") << (int)Qt::Key_Kanji << QString("Kanji");
+ QTest::newRow("Muhenkan") << (int)Qt::Key_Muhenkan << QString("Muhenkan");
+ QTest::newRow("Henkan") << (int)Qt::Key_Henkan << QString("Henkan");
+ QTest::newRow("Romaji") << (int)Qt::Key_Romaji << QString("Romaji");
+ QTest::newRow("Hiragana") << (int)Qt::Key_Hiragana << QString("Hiragana");
+ QTest::newRow("Katakana") << (int)Qt::Key_Katakana << QString("Katakana");
+ QTest::newRow("Hiragana Katakana") << (int)Qt::Key_Hiragana_Katakana << QString("Hiragana Katakana");
+ QTest::newRow("Zenkaku") << (int)Qt::Key_Zenkaku << QString("Zenkaku");
+ QTest::newRow("Hankaku") << (int)Qt::Key_Hankaku << QString("Hankaku");
+ QTest::newRow("Zenkaku Hankaku") << (int)Qt::Key_Zenkaku_Hankaku << QString("Zenkaku Hankaku");
+ QTest::newRow("Touroku") << (int)Qt::Key_Touroku << QString("Touroku");
+ QTest::newRow("Massyo") << (int)Qt::Key_Massyo << QString("Massyo");
+ QTest::newRow("Kana Lock") << (int)Qt::Key_Kana_Lock << QString("Kana Lock");
+ QTest::newRow("Kana Shift") << (int)Qt::Key_Kana_Shift << QString("Kana Shift");
+ QTest::newRow("Eisu Shift") << (int)Qt::Key_Eisu_Shift << QString("Eisu Shift");
+ QTest::newRow("Eisu_toggle") << (int)Qt::Key_Eisu_toggle << QString("Eisu toggle");
+ QTest::newRow("Code input") << (int)Qt::Key_Codeinput << QString("Code input");
+ QTest::newRow("Multiple Candidate") << (int)Qt::Key_MultipleCandidate << QString("Multiple Candidate");
+ QTest::newRow("Previous Candidate") << (int)Qt::Key_PreviousCandidate << QString("Previous Candidate");
+
+ // Korean keyboard support
+ QTest::newRow("Hangul") << (int)Qt::Key_Hangul << QString("Hangul");
+ QTest::newRow("Hangul Start") << (int)Qt::Key_Hangul_Start << QString("Hangul Start");
+ QTest::newRow("Hangul End") << (int)Qt::Key_Hangul_End << QString("Hangul End");
+ QTest::newRow("Hangul Hanja") << (int)Qt::Key_Hangul_Hanja << QString("Hangul Hanja");
+ QTest::newRow("Hangul Jamo") << (int)Qt::Key_Hangul_Jamo << QString("Hangul Jamo");
+ QTest::newRow("Hangul Romaja") << (int)Qt::Key_Hangul_Romaja << QString("Hangul Romaja");
+ QTest::newRow("Hangul Jeonja") << (int)Qt::Key_Hangul_Jeonja << QString("Hangul Jeonja");
+ QTest::newRow("Hangul Banja") << (int)Qt::Key_Hangul_Banja << QString("Hangul Banja");
+ QTest::newRow("Hangul PreHanja") << (int)Qt::Key_Hangul_PreHanja << QString("Hangul PreHanja");
+ QTest::newRow("Hangul PostHanja") << (int)Qt::Key_Hangul_PostHanja << QString("Hangul PostHanja");
+ QTest::newRow("Hangul Special") << (int)Qt::Key_Hangul_Special << QString("Hangul Special");
+}
+
+void tst_QKeySequence::i18nKeys()
+{
+ QFETCH(int, keycode);
+ QFETCH(QString, keystring);
+ QKeySequence seq(keycode);
+
+ QCOMPARE(seq, QKeySequence(keystring));
+ QCOMPARE(seq.toString(), keystring);
+}
+
+QTEST_MAIN(tst_QKeySequence)
+#include "tst_qkeysequence.moc"
diff --git a/tests/auto/gui/kernel/qmouseevent/.gitignore b/tests/auto/gui/kernel/qmouseevent/.gitignore
new file mode 100644
index 0000000000..17cd6be116
--- /dev/null
+++ b/tests/auto/gui/kernel/qmouseevent/.gitignore
@@ -0,0 +1 @@
+tst_qmouseevent
diff --git a/tests/auto/gui/kernel/qmouseevent/qmouseevent.pro b/tests/auto/gui/kernel/qmouseevent/qmouseevent.pro
new file mode 100644
index 0000000000..58cebd3d06
--- /dev/null
+++ b/tests/auto/gui/kernel/qmouseevent/qmouseevent.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qmouseevent.cpp
diff --git a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp
new file mode 100644
index 0000000000..5998aa0c08
--- /dev/null
+++ b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qdialog.h>
+
+
+#include <qevent.h>
+#include <qwidget.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/widgets/qmenubar.h gui/widgets/qmenubar.cpp
+
+class MouseEventWidget : public QWidget
+{
+public:
+ MouseEventWidget(QWidget *parent = 0) : QWidget(parent)
+ {
+ setFocusPolicy(Qt::StrongFocus);
+ }
+ bool mousePressEventRecieved;
+ bool mouseReleaseEventRecieved;
+ int mousePressButton;
+ int mousePressButtons;
+ int mousePressModifiers;
+ int mouseReleaseButton;
+ int mouseReleaseButtons;
+ int mouseReleaseModifiers;
+protected:
+ void mousePressEvent(QMouseEvent *e)
+ {
+ QWidget::mousePressEvent(e);
+ mousePressButton = e->button();
+ mousePressButtons = e->buttons();
+ mousePressModifiers = e->modifiers();
+ mousePressEventRecieved = TRUE;
+ e->accept();
+ }
+ void mouseReleaseEvent(QMouseEvent *e)
+ {
+ QWidget::mouseReleaseEvent(e);
+ mouseReleaseButton = e->button();
+ mouseReleaseButtons = e->buttons();
+ mouseReleaseModifiers = e->modifiers();
+ mouseReleaseEventRecieved = TRUE;
+ e->accept();
+ }
+};
+
+class tst_QMouseEvent : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QMouseEvent();
+ virtual ~tst_QMouseEvent();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void checkMousePressEvent_data();
+ void checkMousePressEvent();
+ void checkMouseReleaseEvent_data();
+ void checkMouseReleaseEvent();
+
+private:
+ MouseEventWidget* testMouseWidget;
+};
+
+
+
+tst_QMouseEvent::tst_QMouseEvent()
+{
+}
+
+tst_QMouseEvent::~tst_QMouseEvent()
+{
+
+}
+
+void tst_QMouseEvent::initTestCase()
+{
+ testMouseWidget = new MouseEventWidget(0);
+ testMouseWidget->show();
+}
+
+void tst_QMouseEvent::cleanupTestCase()
+{
+ delete testMouseWidget;
+}
+
+void tst_QMouseEvent::init()
+{
+ testMouseWidget->mousePressEventRecieved = FALSE;
+ testMouseWidget->mouseReleaseEventRecieved = FALSE;
+ testMouseWidget->mousePressButton = 0;
+ testMouseWidget->mousePressButtons = 0;
+ testMouseWidget->mousePressModifiers = 0;
+ testMouseWidget->mouseReleaseButton = 0;
+ testMouseWidget->mouseReleaseButtons = 0;
+ testMouseWidget->mouseReleaseModifiers = 0;
+}
+
+void tst_QMouseEvent::cleanup()
+{
+}
+
+void tst_QMouseEvent::checkMousePressEvent_data()
+{
+ QTest::addColumn<int>("buttonPressed");
+ QTest::addColumn<int>("keyPressed");
+
+ QTest::newRow("leftButton-nokey") << int(Qt::LeftButton) << int(Qt::NoButton);
+ QTest::newRow("leftButton-shiftkey") << int(Qt::LeftButton) << int(Qt::ShiftModifier);
+ QTest::newRow("leftButton-controlkey") << int(Qt::LeftButton) << int(Qt::ControlModifier);
+ QTest::newRow("leftButton-altkey") << int(Qt::LeftButton) << int(Qt::AltModifier);
+ QTest::newRow("leftButton-metakey") << int(Qt::LeftButton) << int(Qt::MetaModifier);
+ QTest::newRow("rightButton-nokey") << int(Qt::RightButton) << int(Qt::NoButton);
+ QTest::newRow("rightButton-shiftkey") << int(Qt::RightButton) << int(Qt::ShiftModifier);
+ QTest::newRow("rightButton-controlkey") << int(Qt::RightButton) << int(Qt::ControlModifier);
+ QTest::newRow("rightButton-altkey") << int(Qt::RightButton) << int(Qt::AltModifier);
+ QTest::newRow("rightButton-metakey") << int(Qt::RightButton) << int(Qt::MetaModifier);
+ QTest::newRow("midButton-nokey") << int(Qt::MidButton) << int(Qt::NoButton);
+ QTest::newRow("midButton-shiftkey") << int(Qt::MidButton) << int(Qt::ShiftModifier);
+ QTest::newRow("midButton-controlkey") << int(Qt::MidButton) << int(Qt::ControlModifier);
+ QTest::newRow("midButton-altkey") << int(Qt::MidButton) << int(Qt::AltModifier);
+ QTest::newRow("midButton-metakey") << int(Qt::MidButton) << int(Qt::MetaModifier);
+}
+
+void tst_QMouseEvent::checkMousePressEvent()
+{
+ QFETCH(int,buttonPressed);
+ QFETCH(int,keyPressed);
+ int button = buttonPressed;
+ int buttons = button;
+ int modifiers = keyPressed;
+
+ QTest::mousePress(testMouseWidget, Qt::MouseButton(buttonPressed), Qt::KeyboardModifiers(keyPressed));
+ QVERIFY(testMouseWidget->mousePressEventRecieved);
+ QCOMPARE(testMouseWidget->mousePressButton, button);
+ QCOMPARE(testMouseWidget->mousePressButtons, buttons);
+ QCOMPARE(testMouseWidget->mousePressModifiers, modifiers);
+
+ QTest::mouseRelease(testMouseWidget, Qt::MouseButton(buttonPressed), Qt::KeyboardModifiers(keyPressed));
+}
+
+void tst_QMouseEvent::checkMouseReleaseEvent_data()
+{
+ QTest::addColumn<int>("buttonReleased");
+ QTest::addColumn<int>("keyPressed");
+
+ QTest::newRow("leftButton-nokey") << int(Qt::LeftButton) << int(Qt::NoButton);
+ QTest::newRow("leftButton-shiftkey") << int(Qt::LeftButton) << int(Qt::ShiftModifier);
+ QTest::newRow("leftButton-controlkey") << int(Qt::LeftButton) << int(Qt::ControlModifier);
+ QTest::newRow("leftButton-altkey") << int(Qt::LeftButton) << int(Qt::AltModifier);
+ QTest::newRow("leftButton-metakey") << int(Qt::LeftButton) << int(Qt::MetaModifier);
+ QTest::newRow("rightButton-nokey") << int(Qt::RightButton) << int(Qt::NoButton);
+ QTest::newRow("rightButton-shiftkey") << int(Qt::RightButton) << int(Qt::ShiftModifier);
+ QTest::newRow("rightButton-controlkey") << int(Qt::RightButton) << int(Qt::ControlModifier);
+ QTest::newRow("rightButton-altkey") << int(Qt::RightButton) << int(Qt::AltModifier);
+ QTest::newRow("rightButton-metakey") << int(Qt::RightButton) << int(Qt::MetaModifier);
+ QTest::newRow("midButton-nokey") << int(Qt::MidButton) << int(Qt::NoButton);
+ QTest::newRow("midButton-shiftkey") << int(Qt::MidButton) << int(Qt::ShiftModifier);
+ QTest::newRow("midButton-controlkey") << int(Qt::MidButton) << int(Qt::ControlModifier);
+ QTest::newRow("midButton-altkey") << int(Qt::MidButton) << int(Qt::AltModifier);
+ QTest::newRow("midButton-metakey") << int(Qt::MidButton) << int(Qt::MetaModifier);
+}
+
+void tst_QMouseEvent::checkMouseReleaseEvent()
+{
+ QFETCH(int,buttonReleased);
+ QFETCH(int,keyPressed);
+ int button = buttonReleased;
+ int buttons = 0;
+ int modifiers = keyPressed;
+
+ QTest::mouseClick(testMouseWidget, Qt::MouseButton(buttonReleased), Qt::KeyboardModifiers(keyPressed));
+ QVERIFY(testMouseWidget->mouseReleaseEventRecieved);
+ QCOMPARE(testMouseWidget->mouseReleaseButton, button);
+ QCOMPARE(testMouseWidget->mouseReleaseButtons, buttons);
+ QCOMPARE(testMouseWidget->mouseReleaseModifiers, modifiers);
+}
+
+QTEST_MAIN(tst_QMouseEvent)
+#include "tst_qmouseevent.moc"
diff --git a/tests/auto/gui/kernel/qmouseevent_modal/.gitignore b/tests/auto/gui/kernel/qmouseevent_modal/.gitignore
new file mode 100644
index 0000000000..e15c9eb18c
--- /dev/null
+++ b/tests/auto/gui/kernel/qmouseevent_modal/.gitignore
@@ -0,0 +1 @@
+tst_qmouseevent_modal
diff --git a/tests/auto/gui/kernel/qmouseevent_modal/qmouseevent_modal.pro b/tests/auto/gui/kernel/qmouseevent_modal/qmouseevent_modal.pro
new file mode 100644
index 0000000000..2f28de2675
--- /dev/null
+++ b/tests/auto/gui/kernel/qmouseevent_modal/qmouseevent_modal.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qmouseevent_modal.cpp
+
+
+
diff --git a/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp b/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp
new file mode 100644
index 0000000000..7006feeeb8
--- /dev/null
+++ b/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qfontinfo.h>
+
+
+#include <qpushbutton.h>
+#include <qscrollbar.h>
+#include <qtimer.h>
+
+#include <qdialog.h>
+
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/widgets/qmenubar.h gui/widgets/qmenubar.cpp
+
+class TstWidget;
+class TstDialog;
+QT_FORWARD_DECLARE_CLASS(QPushButton)
+
+class tst_qmouseevent_modal : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_qmouseevent_modal();
+ virtual ~tst_qmouseevent_modal();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void mousePressRelease();
+
+private:
+ TstWidget *w;
+};
+
+class TstWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ TstWidget();
+public slots:
+ void buttonPressed();
+public:
+ QPushButton *pb;
+ TstDialog *d;
+};
+
+
+class TstDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ TstDialog( QWidget *mouseWidget, QWidget *parent, const char *name );
+ int count() { return c; }
+protected:
+ void showEvent ( QShowEvent * );
+public slots:
+ void releaseMouse();
+ void closeDialog();
+private:
+ QWidget *m;
+ int c;
+};
+
+tst_qmouseevent_modal::tst_qmouseevent_modal()
+{
+}
+
+tst_qmouseevent_modal::~tst_qmouseevent_modal()
+{
+}
+
+void tst_qmouseevent_modal::initTestCase()
+{
+ w = new TstWidget;
+ w->show();
+}
+
+void tst_qmouseevent_modal::cleanupTestCase()
+{
+ delete w;
+ w = 0;
+}
+
+void tst_qmouseevent_modal::init()
+{
+}
+
+void tst_qmouseevent_modal::cleanup()
+{
+}
+
+/*
+ Test for task 22500
+*/
+void tst_qmouseevent_modal::mousePressRelease()
+{
+
+ QVERIFY( !w->d->isVisible() );
+ QVERIFY( w->d->count() == 0 );
+
+ QTest::mousePress( w->pb, Qt::LeftButton );
+ QTest::qWait(200);
+
+ QVERIFY( !w->d->isVisible() );
+ QVERIFY( w->d->count() == 1 );
+ QVERIFY( !w->pb->isDown() );
+
+ QTest::mousePress( w->pb, Qt::LeftButton );
+ QTest::qWait(200);
+
+ QVERIFY( !w->d->isVisible() );
+ QVERIFY( w->d->count() == 2 );
+ QVERIFY( !w->pb->isDown() );
+
+ // With the current QWS mouse handling, the 3rd press would fail...
+
+ QTest::mousePress( w->pb, Qt::LeftButton );
+ QTest::qWait(200);
+
+ QVERIFY( !w->d->isVisible() );
+ QVERIFY( w->d->count() == 3 );
+ QVERIFY( !w->pb->isDown() );
+
+ QTest::mousePress( w->pb, Qt::LeftButton );
+ QTest::qWait(200);
+
+ QVERIFY( !w->d->isVisible() );
+ QVERIFY( w->d->count() == 4 );
+ QVERIFY( !w->pb->isDown() );
+}
+
+
+TstWidget::TstWidget()
+{
+ pb = new QPushButton( "Press me", this );
+ pb->setObjectName("testbutton");
+ QSize s = pb->sizeHint();
+ pb->setGeometry( 5, 5, s.width(), s.height() );
+
+ connect( pb, SIGNAL(pressed()), this, SLOT(buttonPressed()) );
+
+// QScrollBar *sb = new QScrollBar( Qt::Horizontal, this );
+
+// sb->setGeometry( 5, pb->geometry().bottom() + 5, 100, sb->sizeHint().height() );
+
+ d = new TstDialog( pb, this , 0 );
+}
+
+void TstWidget::buttonPressed()
+{
+ d->exec();
+}
+
+TstDialog::TstDialog( QWidget *mouseWidget, QWidget *parent, const char *name )
+ :QDialog( parent )
+{
+ setObjectName(name);
+ setModal(true);
+ m = mouseWidget;
+ c = 0;
+}
+
+void TstDialog::showEvent ( QShowEvent * )
+{
+ QTimer::singleShot(1, this, SLOT(releaseMouse()));
+ QTimer::singleShot(100, this, SLOT(closeDialog()));
+}
+
+void TstDialog::releaseMouse()
+{
+ QTest::mouseRelease(m, Qt::LeftButton);
+}
+
+void TstDialog::closeDialog()
+{
+ if ( isVisible() ) {
+ c++;
+ accept();
+ }
+}
+
+QTEST_MAIN(tst_qmouseevent_modal)
+#include "tst_qmouseevent_modal.moc"
diff --git a/tests/auto/gui/kernel/qpalette/.gitignore b/tests/auto/gui/kernel/qpalette/.gitignore
new file mode 100644
index 0000000000..3c1aebac19
--- /dev/null
+++ b/tests/auto/gui/kernel/qpalette/.gitignore
@@ -0,0 +1 @@
+tst_qpalette
diff --git a/tests/auto/gui/kernel/qpalette/qpalette.pro b/tests/auto/gui/kernel/qpalette/qpalette.pro
new file mode 100644
index 0000000000..4b240e5f9c
--- /dev/null
+++ b/tests/auto/gui/kernel/qpalette/qpalette.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qpalette.cpp
+
+
+
diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
new file mode 100644
index 0000000000..b63b8bf7b0
--- /dev/null
+++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include "qpalette.h"
+#include <qapplication.h>
+
+//TESTED_CLASS=QPalette
+//TESTED_FILES=qpalette.h qpalette.cpp
+
+class tst_QPalette : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QPalette();
+ virtual ~tst_QPalette();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void roleValues_data();
+ void roleValues();
+};
+
+tst_QPalette::tst_QPalette()
+{
+}
+
+tst_QPalette::~tst_QPalette()
+{
+}
+
+void tst_QPalette::initTestCase()
+{
+}
+
+void tst_QPalette::cleanupTestCase()
+{
+}
+
+void tst_QPalette::init()
+{
+}
+
+void tst_QPalette::cleanup()
+{
+}
+
+void tst_QPalette::roleValues_data()
+{
+ QTest::addColumn<int>("role");
+ QTest::addColumn<int>("value");
+
+ QTest::newRow("QPalette::WindowText") << int(QPalette::WindowText) << 0;
+ QTest::newRow("QPalette::Button") << int(QPalette::Button) << 1;
+ QTest::newRow("QPalette::Light") << int(QPalette::Light) << 2;
+ QTest::newRow("QPalette::Midlight") << int(QPalette::Midlight) << 3;
+ QTest::newRow("QPalette::Dark") << int(QPalette::Dark) << 4;
+ QTest::newRow("QPalette::Mid") << int(QPalette::Mid) << 5;
+ QTest::newRow("QPalette::Text") << int(QPalette::Text) << 6;
+ QTest::newRow("QPalette::BrightText") << int(QPalette::BrightText) << 7;
+ QTest::newRow("QPalette::ButtonText") << int(QPalette::ButtonText) << 8;
+ QTest::newRow("QPalette::Base") << int(QPalette::Base) << 9;
+ QTest::newRow("QPalette::Window") << int(QPalette::Window) << 10;
+ QTest::newRow("QPalette::Shadow") << int(QPalette::Shadow) << 11;
+ QTest::newRow("QPalette::Highlight") << int(QPalette::Highlight) << 12;
+ QTest::newRow("QPalette::HighlightedText") << int(QPalette::HighlightedText) << 13;
+ QTest::newRow("QPalette::Link") << int(QPalette::Link) << 14;
+ QTest::newRow("QPalette::LinkVisited") << int(QPalette::LinkVisited) << 15;
+ QTest::newRow("QPalette::AlternateBase") << int(QPalette::AlternateBase) << 16;
+ QTest::newRow("QPalette::NoRole") << int(QPalette::NoRole) << 17;
+ QTest::newRow("QPalette::ToolTipBase") << int(QPalette::ToolTipBase) << 18;
+ QTest::newRow("QPalette::ToolTipText") << int(QPalette::ToolTipText) << 19;
+
+ // Change this value as you add more roles.
+ QTest::newRow("QPalette::NColorRoles") << int(QPalette::NColorRoles) << 20;
+}
+
+void tst_QPalette::roleValues()
+{
+ QFETCH(int, role);
+ QFETCH(int, value);
+ QCOMPARE(role, value);
+}
+
+QTEST_MAIN(tst_QPalette)
+#include "tst_qpalette.moc"
diff --git a/tests/auto/gui/kernel/qshortcut/.gitignore b/tests/auto/gui/kernel/qshortcut/.gitignore
new file mode 100644
index 0000000000..3a17eb18e3
--- /dev/null
+++ b/tests/auto/gui/kernel/qshortcut/.gitignore
@@ -0,0 +1 @@
+tst_qshortcut
diff --git a/tests/auto/gui/kernel/qshortcut/qshortcut.pro b/tests/auto/gui/kernel/qshortcut/qshortcut.pro
new file mode 100644
index 0000000000..3f68d2377e
--- /dev/null
+++ b/tests/auto/gui/kernel/qshortcut/qshortcut.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+
+# Project Configuration ----------------------------------------------
+INCLUDEPATH += ../
+
+# Normal Test Files --------------------------------------------------
+QT += widgets
+HEADERS +=
+SOURCES += tst_qshortcut.cpp
+
+
diff --git a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp
new file mode 100644
index 0000000000..a78e8cfd27
--- /dev/null
+++ b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp
@@ -0,0 +1,1272 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qtextedit.h>
+#include <qpushbutton.h>
+#include <qmainwindow.h>
+#include <qstatusbar.h>
+#include <qboxlayout.h>
+#include <qdebug.h>
+#include <qstring.h>
+#include <qshortcut.h>
+
+class AccelForm;
+QT_BEGIN_NAMESPACE
+class QMainWindow;
+class QTextEdit;
+QT_END_NAMESPACE
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QShortcut : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QShortcut();
+ virtual ~tst_QShortcut();
+
+
+ enum Action {
+ SetupAccel,
+ TestAccel,
+ ClearAll
+ } currentAction;
+
+ enum Widget {
+ NoWidget,
+ TriggerSlot1,
+ TriggerSlot2,
+ TriggerSlot3,
+ TriggerSlot4,
+ TriggerSlot5,
+ TriggerSlot6,
+ TriggerSlot7
+ };
+
+ enum Result {
+ NoResult,
+ Slot1Triggered,
+ Slot2Triggered,
+ Slot3Triggered,
+ Slot4Triggered,
+ Slot5Triggered,
+ Slot6Triggered,
+ Slot7Triggered,
+ Ambiguous
+ } currentResult;
+
+public slots:
+ void slotTrig1() { currentResult = Slot1Triggered; }
+ void slotTrig2() { currentResult = Slot2Triggered; }
+ void slotTrig3() { currentResult = Slot3Triggered; }
+ void slotTrig4() { currentResult = Slot4Triggered; }
+ void slotTrig5() { currentResult = Slot5Triggered; }
+ void slotTrig6() { currentResult = Slot6Triggered; }
+ void slotTrig7() { currentResult = Slot7Triggered; }
+ void ambigSlot1() { currentResult = Ambiguous; ambigResult = Slot1Triggered; }
+ void ambigSlot2() { currentResult = Ambiguous; ambigResult = Slot2Triggered; }
+ void ambigSlot3() { currentResult = Ambiguous; ambigResult = Slot3Triggered; }
+ void ambigSlot4() { currentResult = Ambiguous; ambigResult = Slot4Triggered; }
+ void ambigSlot5() { currentResult = Ambiguous; ambigResult = Slot5Triggered; }
+ void ambigSlot6() { currentResult = Ambiguous; ambigResult = Slot6Triggered; }
+ void ambigSlot7() { currentResult = Ambiguous; ambigResult = Slot7Triggered; }
+ void statusMessage( const QString& message ) { sbText = message; }
+ void shortcutDestroyed(QObject* obj);
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void number_data();
+ void number();
+ void text_data();
+ void text();
+ void disabledItems();
+ void ambiguousItems();
+ void ambiguousRotation();
+ void keypressConsumption();
+ void unicodeCompare();
+ void context();
+
+protected:
+ static Qt::KeyboardModifiers toButtons( int key );
+ void defElements();
+
+ void clearAllShortcuts();
+ QShortcut *setupShortcut(int testWidget, const QKeySequence &ks);
+ QShortcut *setupShortcut(int testWidget, const QString &txt, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0);
+
+ QShortcut *setupShortcut(QWidget *parent, const char *name, int testWidget, const QString &txt, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0);
+ QShortcut *setupShortcut(QWidget *parent, const char *name, int testWidget, const QKeySequence &ks, Qt::ShortcutContext context = Qt::WindowShortcut);
+
+ void sendKeyEvents(QWidget *w, int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0);
+ void sendKeyEvents(int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0);
+
+ void testElement();
+
+ QMainWindow *mainW;
+ QList<QShortcut*> shortcuts;
+ QTextEdit *edit;
+ QString sbText;
+ Result ambigResult;
+};
+
+QT_BEGIN_NAMESPACE
+template<> struct QMetaTypeId<tst_QShortcut::Widget>
+{ enum { Defined = 1 }; static inline int qt_metatype_id() { return QMetaType::Int; } };
+template<> struct QMetaTypeId<tst_QShortcut::Result>
+{ enum { Defined = 1 }; static inline int qt_metatype_id() { return QMetaType::Int; } };
+template<> struct QMetaTypeId<tst_QShortcut::Action>
+{ enum { Defined = 1 }; static inline int qt_metatype_id() { return QMetaType::Int; } };
+QT_END_NAMESPACE
+
+class TestEdit : public QTextEdit
+{
+ Q_OBJECT
+public:
+ TestEdit(QWidget *parent, const char *name)
+ : QTextEdit(parent)
+ {
+ setObjectName(name);
+ }
+
+protected:
+ bool event(QEvent *e) {
+ // Make testedit allow any Ctrl+Key as shortcut
+ if (e->type() == QEvent::ShortcutOverride) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->modifiers() == Qt::ControlModifier
+ && ke->key() > Qt::Key_Any
+ && ke->key() < Qt::Key_ydiaeresis) {
+ ke->ignore();
+ return true;
+ }
+ }
+
+ // If keypress not processed as normal, check for
+ // Ctrl+Key event, and input custom string for
+ // result comparison.
+ if (e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->modifiers() && ke->key() > Qt::Key_Any
+ && ke->key() < Qt::Key_ydiaeresis) {
+ if (ke->modifiers() == Qt::ControlModifier)
+ insertPlainText(QString("<Ctrl+%1>").arg(char(ke->key())));
+ else if (ke->modifiers() == Qt::AltModifier)
+ insertPlainText(QString("<Alt+%1>").arg(char(ke->key())));
+ else if (ke->modifiers() == Qt::ShiftModifier)
+ insertPlainText(QString("<Shift+%1>").arg(char(ke->key())));
+ return true;
+ }
+ }
+ return QTextEdit::event(e);
+ }
+};
+
+tst_QShortcut::tst_QShortcut(): mainW( 0 )
+{
+}
+
+tst_QShortcut::~tst_QShortcut()
+{
+ clearAllShortcuts();
+}
+
+void tst_QShortcut::initTestCase()
+{
+ currentResult = NoResult;
+ mainW = new QMainWindow(0);
+ mainW->setWindowFlags(Qt::X11BypassWindowManagerHint);
+ edit = new TestEdit(mainW, "test_edit");
+ mainW->setFixedSize( 100, 100 );
+ mainW->setCentralWidget( edit );
+ mainW->show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(mainW);
+#endif
+ mainW->activateWindow();
+ QTest::qWait(100);
+ connect( mainW->statusBar(), SIGNAL(messageChanged(const QString&)),
+ this, SLOT(statusMessage(const QString&)) );
+}
+
+void tst_QShortcut::cleanupTestCase()
+{
+ delete mainW;
+}
+
+Qt::KeyboardModifiers tst_QShortcut::toButtons( int key )
+{
+ Qt::KeyboardModifiers result = Qt::NoModifier;
+ if ( key & Qt::SHIFT )
+ result |= Qt::ShiftModifier;
+ if ( key & Qt::CTRL )
+ result |= Qt::ControlModifier;
+ if ( key & Qt::META )
+ result |= Qt::MetaModifier;
+ if ( key & Qt::ALT )
+ result |= Qt::AltModifier;
+ return result;
+}
+
+void tst_QShortcut::defElements()
+{
+ QTest::addColumn<int>("action");
+ QTest::addColumn<int>("testWidget");
+ QTest::addColumn<QString>("txt");
+ QTest::addColumn<int>("k1");
+ QTest::addColumn<int>("c1");
+ QTest::addColumn<int>("k2");
+ QTest::addColumn<int>("c2");
+ QTest::addColumn<int>("k3");
+ QTest::addColumn<int>("c3");
+ QTest::addColumn<int>("k4");
+ QTest::addColumn<int>("c4");
+ QTest::addColumn<int>("result");
+}
+
+void tst_QShortcut::number()
+{
+ // We expect a failure on these tests, until QtTestKeyboard is
+ // fixed to do real platform dependent keyboard simulations
+ if (QTest::currentDataTag() == QString("N006a:Shift+Tab - [BackTab]")
+ || QTest::currentDataTag() == QString("N006b:Shift+Tab - [Shift+BackTab]"))
+ QEXPECT_FAIL("", "FLAW IN QTESTKEYBOARD: Keyboard events not passed through "
+ "platform dependent key handling code", Continue);
+ testElement();
+}
+void tst_QShortcut::text()
+{
+ testElement();
+}
+// ------------------------------------------------------------------
+// Number Elements --------------------------------------------------
+// ------------------------------------------------------------------
+void tst_QShortcut::number_data()
+{
+ defElements();
+
+ // Clear all
+ QTest::newRow("N00 - clear") << ClearAll <<0<<QString("")<<0<<0<<0<<0<<0<<0<<0<<0<<0;
+
+ //===========================================
+ // [Shift + key] on non-shift shortcuts testing
+ //===========================================
+
+ /* Testing Single Sequences
+ Shift + Qt::Key_M on Qt::Key_M
+ Qt::Key_M on Qt::Key_M
+ Shift + Qt::Key_Plus on Qt::Key_Pluss
+ Qt::Key_Plus on Qt::Key_Pluss
+ */
+ QTest::newRow("N001 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("N001:Shift + M - [M]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N001:M - [M]") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N001 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("N001:Shift++ [+]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N001:+ [+]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N001 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Shift + Qt::Key_M on Shift + Qt::Key_M
+ Qt::Key_M on Shift + Qt::Key_M
+ Shift + Qt::Key_Plus on Shift + Qt::Key_Pluss
+ Qt::Key_Plus on Shift + Qt::Key_Pluss
+ */
+ QTest::newRow("N002 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N002:M - [Shift+M]") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N002 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N002:Shift++ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N002:+ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N002 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Shift + Qt::Key_F1 on Qt::Key_F1
+ Qt::Key_F1 on Qt::Key_F1
+ */
+ QTest::newRow("N003 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("N003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N003:F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N003 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ /* Testing Single Sequences
+ Shift + Qt::Key_F1 on Shift + Qt::Key_F1
+ Qt::Key_F1 on Shift + Qt::Key_F1
+ */
+
+ QTest::newRow("N004 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N004:Shift+F1 - [Shift+F1]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N004 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Qt::Key_Tab on Qt::Key_Tab
+ Shift + Qt::Key_Tab on Qt::Key_Tab
+ Qt::Key_Backtab on Qt::Key_Tab
+ Shift + Qt::Key_Backtab on Qt::Key_Tab
+ */
+ QTest::newRow("N005a - slot1") << SetupAccel << TriggerSlot1 << QString("")<< int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005a:Tab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("N005a:Shift+Tab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ // (Shift+)BackTab != Tab, but Shift+BackTab == Shift+Tab
+ QTest::newRow("N005a:Backtab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005a:Shift+Backtab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005a - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Qt::Key_Tab on Shift + Qt::Key_Tab
+ Shift + Qt::Key_Tab on Shift + Qt::Key_Tab
+ Qt::Key_Backtab on Shift + Qt::Key_Tab
+ Shift + Qt::Key_Backtab on Shift + Qt::Key_Tab
+ */
+ QTest::newRow("N005b - slot1") << SetupAccel << TriggerSlot1 << QString("")<< int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005b:Tab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005b:Shift+Tab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N005b:BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005b:Shift+BackTab - [Shift+Tab]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N005b - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Qt::Key_Tab on Qt::Key_Backtab
+ Shift + Qt::Key_Tab on Qt::Key_Backtab
+ Qt::Key_Backtab on Qt::Key_Backtab
+ Shift + Qt::Key_Backtab on Qt::Key_Backtab
+ */
+ QTest::newRow("N006a - slot1") << SetupAccel << TriggerSlot1 << QString("")<< int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006a:Tab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ // This should work, since platform dependent code will transform the
+ // Shift+Tab into a Shift+BackTab, which should trigger the shortcut
+ QTest::newRow("N006a:Shift+Tab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL
+ QTest::newRow("N006a:BackTab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("N006a:Shift+BackTab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N006a - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Qt::Key_Tab on Shift + Qt::Key_Backtab
+ Shift + Qt::Key_Tab on Shift + Qt::Key_Backtab
+ Qt::Key_Backtab on Shift + Qt::Key_Backtab
+ Shift + Qt::Key_Backtab on Shift + Qt::Key_Backtab
+ */
+ QTest::newRow("N006b - slot1") << SetupAccel << TriggerSlot1 << QString("")<< int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006b:Tab - [Shift+BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006b:Shift+Tab - [Shift+BackTab]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N006b:BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006b:Shift+BackTab - [Shift+BackTab]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL
+ QTest::newRow("N006b - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ //===========================================
+ // [Shift + key] and [key] on shortcuts with
+ // and without modifiers
+ //===========================================
+
+ /* Testing Single Sequences
+ Qt::Key_F1
+ Shift + Qt::Key_F1
+ */
+ QTest::newRow("N007 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N007 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N007:F1") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N007:Shift + F1") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N007 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Qt::Key_M
+ Shift + Qt::Key_M
+ Ctrl + Qt::Key_M
+ Alt + Qt::Key_M
+ */
+ QTest::newRow("N01 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N02 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N03 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N04 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N:Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Shift+Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N:Ctrl+Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Alt+Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+
+ /* Testing Single Sequence Ambiguity
+ Qt::Key_M on shortcut2
+ */
+ QTest::newRow("N05 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N:Qt::Key_M on slot") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous;
+ QTest::newRow("N05 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Specialkeys
+ Qt::Key_aring
+ Qt::Key_Aring
+ Qt::UNICODE_ACCEL + Qt::Key_K
+ */
+ QTest::newRow("N06 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N07 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N08 - slot2") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::UNICODE_ACCEL + Qt::Key_K) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+
+ QTest::newRow("N:Qt::Key_aring") << TestAccel << NoWidget << QString("") << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Qt::Key_Aring") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString("") << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N:Qt::UNICODE_ACCEL + Qt::Key_K") << TestAccel << NoWidget << QString("") << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N09 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Multiple Sequences
+ Qt::Key_M
+ Qt::Key_I, Qt::Key_M
+ Shift+Qt::Key_I, Qt::Key_M
+ */
+ QTest::newRow("N10 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N11 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N12 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult;
+
+ QTest::newRow("N:Qt::Key_M (2)") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N13 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+}
+
+// ------------------------------------------------------------------
+// Text Elements ----------------------------------------------------
+// ------------------------------------------------------------------
+void tst_QShortcut::text_data()
+{
+ defElements();
+ // Clear all
+ QTest::newRow("T00 - clear") << ClearAll <<0<<QString("")<<0<<0<<0<<0<<0<<0<<0<<0<<0;
+
+ //===========================================
+ // [Shift + key] on non-shift shortcuts testing
+ //===========================================
+
+ /* Testing Single Sequences
+ Shift + Qt::Key_M on Qt::Key_M
+ Qt::Key_M on Qt::Key_M
+ Shift + Qt::Key_Plus on Qt::Key_Pluss
+ Qt::Key_Plus on Qt::Key_Pluss
+ */
+ QTest::newRow("T001 - slot1") << SetupAccel << TriggerSlot1 << QString("M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("T001:Shift+M - [M]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T001:M - [M]") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T001 - slot2") << SetupAccel << TriggerSlot2 << QString("+") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("T001:Shift++ [+]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T001:+ [+]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T001 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Shift + Qt::Key_M on Shift + Qt::Key_M
+ Qt::Key_M on Shift + Qt::Key_M
+ Shift + Qt::Key_Plus on Shift + Qt::Key_Pluss
+ Qt::Key_Plus on Shift + Qt::Key_Pluss
+ Shift + Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Pluss
+ Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Pluss
+ */
+ QTest::newRow("T002 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T002:M - [Shift+M]") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T002 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift++") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T002:Shift++ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T002:+ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T002 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Shift + Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Plus
+ Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Plus
+ Qt::Key_Plus on Ctrl + Qt::Key_Plus
+ */
+ QTest::newRow("T002b - slot1") << SetupAccel << TriggerSlot1 << QString("Ctrl++") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("T002b:Shift+Ctrl++ [Ctrl++]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T002b:Ctrl++ [Ctrl++]") << TestAccel << NoWidget << QString("") << int(Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T002b:+ [Ctrl++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T002b - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Shift + Qt::Key_F1 on Qt::Key_F1
+ Qt::Key_F1 on Qt::Key_F1
+ */
+ QTest::newRow("T003 - slot1") << SetupAccel << TriggerSlot1 << QString("F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ //commented out because the behaviour changed, those tests should be updated
+ //QTest::newRow("T003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T003:F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T003 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Shift + Qt::Key_F1 on Shift + Qt::Key_F1
+ Qt::Key_F1 on Shift + Qt::Key_F1
+ */
+ QTest::newRow("T004 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T004:Shift+F1 - [Shift+F1]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T004 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ //===========================================
+ // [Shift + key] and [key] on shortcuts with
+ // and without modifiers
+ //===========================================
+
+ /* Testing Single Sequences
+ Qt::Key_F1
+ Shift + Qt::Key_F1
+ */
+ QTest::newRow("T007 - slot1") << SetupAccel << TriggerSlot1 << QString("F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T007 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift+F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T007:F1") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T007:Shift + F1") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T007 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Sequences
+ Qt::Key_M
+ Shift + Qt::Key_M
+ Ctrl + Qt::Key_M
+ Alt + Qt::Key_M
+ */
+ QTest::newRow("T01 - slot1") << SetupAccel << TriggerSlot1 << QString("M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T02 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T03 - slot1") << SetupAccel << TriggerSlot1 << QString("Ctrl+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T04 - slot2") << SetupAccel << TriggerSlot2 << QString("Alt+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+
+ QTest::newRow("T:Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Shift + Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Ctrl + Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Alt + Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+
+ /* Testing Single Sequence Ambiguity
+ Qt::Key_M on shortcut2
+ */
+ QTest::newRow("T05 - slot2") << SetupAccel << TriggerSlot2 << QString("M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T:Qt::Key_M on TriggerSlot2") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous;
+ QTest::newRow("T06 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Single Specialkeys
+ Qt::Key_aring
+ Qt::Key_Aring
+ Qt::UNICODE_ACCEL + Qt::Key_K
+ */
+ /* see comments above on the #ifdef'ery */
+ QTest::newRow("T06 - slot1") << SetupAccel << TriggerSlot1 << QString("\x0C5")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T07 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift+\x0C5")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T08 - slot2") << SetupAccel << TriggerSlot1 << QString("K") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T:Qt::Key_aring") << TestAccel << NoWidget << QString("") << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Qt::Key_Aring") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString("") << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Qt::UNICODE_ACCEL + Qt::Key_K") << TestAccel << NoWidget << QString("") << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T09 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+
+ /* Testing Multiple Sequences
+ Qt::Key_M
+ Qt::Key_I, Qt::Key_M
+ Shift+Qt::Key_I, Qt::Key_M
+ */
+ QTest::newRow("T10 - slot1") << SetupAccel << TriggerSlot1 << QString("M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T11 - slot2") << SetupAccel << TriggerSlot2 << QString("I, M")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T12 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+I, M")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T:Qt::Key_M (2)") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T13 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+}
+
+// ------------------------------------------------------------------
+// Disabled Elements ------------------------------------------------
+// ------------------------------------------------------------------
+void tst_QShortcut::disabledItems()
+{
+ clearAllShortcuts();
+ mainW->activateWindow();
+ qApp->syncX();
+ QTest::qWait(100);
+
+ /* Testing Disabled Shortcuts
+ Qt::Key_M on slot1
+ Shift + Qt::Key_M on slot1
+ Qt::Key_M on slot2 (disabled)
+ Shift + Qt::Key_M on slot2 (disabled)
+ */
+
+ // Setup two identical shortcuts on different pushbuttons
+ QPushButton pb1(mainW);
+ QPushButton pb2(mainW);
+ pb1.setObjectName("pushbutton-1");
+ pb2.setObjectName("pushbutton-2");
+ pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger
+ pb2.show();
+
+ QShortcut *cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "M");
+ QShortcut *cut2 = setupShortcut(&pb1, "shortcut2-pb1", TriggerSlot1, "Shift+M");
+ QShortcut *cut3 = setupShortcut(&pb2, "shortcut3-pb2", TriggerSlot2, "M");
+ QShortcut *cut4 = setupShortcut(&pb2, "shortcut4-pb2", TriggerSlot2, "Shift+M");
+
+ cut3->setEnabled(false);
+ cut4->setEnabled(false);
+
+ currentResult = NoResult;
+ sendKeyEvents(Qt::Key_M, 'm');
+ QCOMPARE(currentResult, Slot1Triggered);
+
+ currentResult = NoResult;
+ sendKeyEvents(Qt::SHIFT+Qt::Key_M, 'M');
+ QCOMPARE(currentResult, Slot1Triggered);
+
+ cut2->setEnabled(false);
+ cut4->setEnabled(true);
+
+ /* Testing Disabled Shortcuts
+ Qt::Key_M on slot1
+ Shift + Qt::Key_M on slot1 (disabled)
+ Qt::Key_M on slot2 (disabled)
+ Shift + Qt::Key_M on slot2
+ */
+ currentResult = NoResult;
+ sendKeyEvents( Qt::Key_M, 'm' );
+ QCOMPARE( currentResult, Slot1Triggered );
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::SHIFT+Qt::Key_M, 'M' );
+ QCOMPARE( currentResult, Slot2Triggered );
+
+
+ /* Testing Disabled Accel
+ Qt::Key_F5 on slot1
+ Shift + Qt::Key_F5 on slot2 (disabled)
+ */
+ clearAllShortcuts();
+ cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "F5");
+ cut4 = setupShortcut(&pb2, "shortcut4-pb2", TriggerSlot2, "Shift+F5");
+
+ cut1->setKey(QKeySequence("F5"));
+ cut4->setKey(QKeySequence("Shift+F5"));
+
+ cut1->setEnabled(true);
+ cut4->setEnabled(false);
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::Key_F5, 0 );
+ QCOMPARE( currentResult, Slot1Triggered );
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::SHIFT+Qt::Key_F5, 0 );
+ QCOMPARE( currentResult, NoResult );
+
+#if 0
+ qFatal("Not testing statusbar text feedback yet, since not implemented");
+ /* Testing Disabled Accel, and the corresponding statusbar feedback
+ Ctrl + Qt::Key_K, Ctrl + Qt::Key_L on slot1
+ Ctrl + Qt::Key_K, Ctrl + Qt::Key_M on slot2 (disabled)
+ */
+ cut1->setKey(QKeySequence("Ctrl+K, Ctrl+L"));
+ cut4->setKey(QKeySequence("Ctrl+K, Ctrl+M"));
+
+ cut1->setEnabled(true);
+ cut4->setEnabled(false);
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 );
+ sendKeyEvents( Qt::CTRL+Qt::Key_Q, 0 );
+ QCOMPARE( currentResult, NoResult );
+ if (over_330)
+ QCOMPARE( sbText, QString("Ctrl+K, Ctrl+Q not defined") );
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 );
+ sendKeyEvents( Qt::CTRL+Qt::Key_M, 0 );
+ QCOMPARE( currentResult, NoResult );
+ if (over_330)
+ QCOMPARE( sbText, QString::null );
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 );
+ sendKeyEvents( Qt::CTRL+Qt::Key_L, 0 );
+ QCOMPARE( currentResult, Slot1Triggered );
+ if (over_330)
+ QCOMPARE( sbText, QString::null );
+#endif
+ clearAllShortcuts();
+ cut1 = 0;
+ cut4 = 0;
+}
+// ------------------------------------------------------------------
+// Ambiguous Elements -----------------------------------------------
+// ------------------------------------------------------------------
+void tst_QShortcut::ambiguousRotation()
+{
+ clearAllShortcuts();
+ /* Testing Shortcut rotation scheme
+ Ctrl + Qt::Key_A on slot1 (disabled)
+ Ctrl + Qt::Key_A on slot2 (disabled)
+ Ctrl + Qt::Key_A on slot3
+ Ctrl + Qt::Key_A on slot4
+ Ctrl + Qt::Key_A on slot5 (disabled)
+ Ctrl + Qt::Key_A on slot6
+ Ctrl + Qt::Key_A on slot7 (disabled)
+ */
+ QShortcut *cut1 = setupShortcut(TriggerSlot1, "Ctrl+A");
+ QShortcut *cut2 = setupShortcut(TriggerSlot2, "Ctrl+A");
+ QShortcut *cut3 = setupShortcut(TriggerSlot3, "Ctrl+A");
+ QShortcut *cut4 = setupShortcut(TriggerSlot4, "Ctrl+A");
+ QShortcut *cut5 = setupShortcut(TriggerSlot5, "Ctrl+A");
+ QShortcut *cut6 = setupShortcut(TriggerSlot6, "Ctrl+A");
+ QShortcut *cut7 = setupShortcut(TriggerSlot7, "Ctrl+A");
+
+ cut1->setEnabled(false);
+ cut2->setEnabled(false);
+ cut5->setEnabled(false);
+ cut7->setEnabled(false);
+
+ // Test proper rotation
+ // Start on first
+ // Go to last
+ // Go back to first
+ // Continue...
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot3Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot4Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot6Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot3Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot4Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot6Triggered);
+
+ /* Testing Shortcut rotation scheme
+ Ctrl + Qt::Key_A on slot1
+ Ctrl + Qt::Key_A on slot2
+ Ctrl + Qt::Key_A on slot3 (disabled)
+ Ctrl + Qt::Key_A on slot4 (disabled)
+ Ctrl + Qt::Key_A on slot5
+ Ctrl + Qt::Key_A on slot6 (disabled)
+ Ctrl + Qt::Key_A on slot7
+ */
+
+ cut1->setEnabled(true);
+ cut2->setEnabled(true);
+ cut5->setEnabled(true);
+ cut7->setEnabled(true);
+
+ cut3->setEnabled(false);
+ cut4->setEnabled(false);
+ cut6->setEnabled(false);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot1Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot2Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot5Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot7Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot1Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot2Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot5Triggered);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ QCOMPARE(currentResult, Ambiguous);
+ QCOMPARE(ambigResult, Slot7Triggered);
+
+ clearAllShortcuts();
+ cut1 = 0; cut2 = 0;
+ cut3 = 0; cut4 = 0;
+ cut5 = 0; cut6 = 0;
+ cut7 = 0;
+}
+
+void tst_QShortcut::ambiguousItems()
+{
+ clearAllShortcuts();
+ /* Testing Ambiguous Shortcuts
+ Qt::Key_M on Pushbutton 1
+ Qt::Key_M on Pushbutton 2
+ */
+
+ // Setup two identical shortcuts on different pushbuttons
+ QPushButton pb1(mainW);
+ QPushButton pb2(mainW);
+ pb1.setObjectName("pushbutton-1");
+ pb2.setObjectName("pushbutton-2");
+ pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger
+ pb2.show();
+
+ QShortcut *cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "M");
+ QShortcut *cut2 = setupShortcut(&pb1, "shortcut2-pb2", TriggerSlot2, "M");
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::Key_M, 'm' );
+ QCOMPARE( currentResult, Ambiguous );
+ QCOMPARE( ambigResult, Slot1Triggered );
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::Key_M, 'm' );
+ QCOMPARE( currentResult, Ambiguous );
+ QCOMPARE( ambigResult, Slot2Triggered );
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::Key_M, 'm' );
+ QCOMPARE( currentResult, Ambiguous );
+ QCOMPARE( ambigResult, Slot1Triggered );
+
+ clearAllShortcuts();
+ cut1 = 0; cut2 = 0;
+}
+
+
+// ------------------------------------------------------------------
+// Unicode and non-unicode Elements ---------------------------------
+// ------------------------------------------------------------------
+void tst_QShortcut::unicodeCompare()
+{
+ clearAllShortcuts();
+ /* Testing Unicode/non-Unicode Shortcuts
+ Qt::Key_M on Pushbutton 1
+ Qt::Key_M on Pushbutton 2
+ */
+ QPushButton pb1(mainW);
+ QPushButton pb2(mainW);
+ pb1.setObjectName("pushbutton-1");
+ pb2.setObjectName("pushbutton-2");
+ pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger
+ pb2.show();
+
+ QKeySequence ks1("Ctrl+M"); // Unicode
+ QKeySequence ks2(Qt::CTRL+Qt::Key_M); // non-Unicode
+ QShortcut *cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, ks1);
+ QShortcut *cut2 = setupShortcut(&pb1, "shortcut2-pb2", TriggerSlot2, ks2);
+
+ currentResult = NoResult;
+ sendKeyEvents( Qt::CTRL+Qt::Key_M, 0 );
+ QCOMPARE( currentResult, Ambiguous );
+ // They _are_ ambiguous, so the QKeySequence operator==
+ // should indicate the same
+ QVERIFY( ks1 == ks2 );
+ QVERIFY( !(ks1 != ks2) );
+
+ clearAllShortcuts();
+ cut1 = 0; cut2 = 0;
+}
+
+// ------------------------------------------------------------------
+// Keypress consumption verification --------------------------------
+// ------------------------------------------------------------------
+void tst_QShortcut::keypressConsumption()
+{
+ clearAllShortcuts();
+ edit->clear();
+ QCOMPARE(edit->toPlainText().size(), 0);
+
+ QShortcut *cut1 = setupShortcut(edit, "shortcut1-line", TriggerSlot1, "Ctrl+I, A");
+ QShortcut *cut2 = setupShortcut(edit, "shortcut1-line", TriggerSlot2, "Ctrl+I, B");
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ sendKeyEvents(edit, Qt::CTRL + Qt::Key_I, 0); // Send key to edit
+ QCOMPARE( currentResult, NoResult );
+ QCOMPARE( ambigResult, NoResult );
+ QCOMPARE(edit->toPlainText(), QString(""));
+
+ // Make sure next keypress is eaten (failing multiple keysequence)
+ sendKeyEvents(edit, Qt::Key_C, 'c'); // Send key to edit
+ QCOMPARE( currentResult, NoResult );
+ QCOMPARE( ambigResult, NoResult );
+ QCOMPARE(edit->toPlainText(), QString(""));
+
+ // Next keypress should be normal
+ sendKeyEvents(edit, Qt::Key_C, 'c'); // Send key to edit
+ QCOMPARE( currentResult, NoResult );
+ QCOMPARE( ambigResult, NoResult );
+ QCOMPARE(edit->toPlainText(), QString("c"));
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ edit->clear();
+ QCOMPARE(edit->toPlainText().size(), 0);
+
+ cut1->setEnabled(false);
+ cut2->setEnabled(false);
+
+ // Make sure keypresses is passed on, since all multiple keysequences
+ // with Ctrl+I are disabled
+ sendKeyEvents(edit, Qt::CTRL + Qt::Key_I, 0); // Send key to edit
+ QCOMPARE( currentResult, NoResult );
+ QCOMPARE( ambigResult, NoResult );
+ QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>"));
+
+ sendKeyEvents(edit, Qt::Key_A, 'a'); // Send key to edit
+ QCOMPARE( currentResult, NoResult );
+ QCOMPARE( ambigResult, NoResult );
+ QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>a"));
+
+ clearAllShortcuts();
+}
+
+// ------------------------------------------------------------------
+// Context Validation -----------------------------------------------
+// ------------------------------------------------------------------
+void tst_QShortcut::context()
+{
+ clearAllShortcuts();
+
+ QWidget myBox;
+ TestEdit *other1 = new TestEdit(&myBox, "test_edit_other1");
+ TestEdit *other2 = new TestEdit(&myBox, "test_edit_other2");
+ QHBoxLayout *layout = new QHBoxLayout(&myBox);
+ layout->addWidget(other1);
+ layout->addWidget(other2);
+ myBox.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&myBox);
+#endif
+
+ setupShortcut(other1, "ActiveWindow", TriggerSlot1, QKeySequence("Alt+1"), Qt::WindowShortcut);
+ setupShortcut(other2, "Focus", TriggerSlot2, QKeySequence("Alt+2"), Qt::WidgetShortcut);
+ setupShortcut(edit, "Application", TriggerSlot3, QKeySequence("Alt+3"), Qt::ApplicationShortcut);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ edit->clear();
+ other1->clear();
+ other2->clear();
+
+ // edit doesn't have focus, so ActiveWindow context should work
+ // ..but Focus context shouldn't..
+ // Changing focus to edit should make focus context work
+ // Application context should always work
+
+
+ // Focus on 'other1' edit, so Active Window context should trigger
+ other1->activateWindow(); // <---
+ QApplication::setActiveWindow(other1);
+ QCOMPARE(qApp->activeWindow(), other1->window());
+ QCOMPARE(qApp->focusWidget(), (QWidget *)other1);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ edit->clear();
+ other1->clear();
+ other2->clear();
+
+ QCOMPARE(qApp->focusWidget(), (QWidget *)other1);
+ sendKeyEvents(other1, Qt::ALT+Qt::Key_1);
+ QCOMPARE(currentResult, Slot1Triggered);
+ QCOMPARE(ambigResult, NoResult);
+ QCOMPARE(edit->toPlainText(), QString(""));
+ QCOMPARE(other1->toPlainText(), QString(""));
+ QCOMPARE(other2->toPlainText(), QString(""));
+
+ // ..but not Focus context on 'other2'..
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ edit->clear();
+ other1->clear();
+ other2->clear();
+
+ sendKeyEvents(other1, Qt::ALT+Qt::Key_2);
+ QCOMPARE(currentResult, NoResult);
+ QCOMPARE(ambigResult, NoResult);
+ QCOMPARE(edit->toPlainText(), QString(""));
+ QCOMPARE(other1->toPlainText(), QString("<Alt+2>"));
+ QCOMPARE(other2->toPlainText(), QString(""));
+
+ // ..however, application global context on 'edit' should..
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ edit->clear();
+ other1->clear();
+ other2->clear();
+
+ sendKeyEvents(other1, Qt::ALT+Qt::Key_3);
+ QCOMPARE(currentResult, Slot3Triggered);
+ QCOMPARE(ambigResult, NoResult);
+ QCOMPARE(edit->toPlainText(), QString(""));
+ QCOMPARE(other1->toPlainText(), QString(""));
+ QCOMPARE(other2->toPlainText(), QString(""));
+
+ // Changing focus to 'other2' should make the Focus context there work
+ other2->activateWindow();
+ other2->setFocus(); // ###
+ qApp->syncX();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(other2);
+#endif
+ QTest::qWait(100);
+ QCOMPARE(qApp->activeWindow(), other2->window());
+ QCOMPARE(qApp->focusWidget(), (QWidget *)other2);
+
+ currentResult = NoResult;
+ ambigResult = NoResult;
+ edit->clear();
+ other1->clear();
+ other2->clear();
+
+ sendKeyEvents(other2, Qt::ALT+Qt::Key_2);
+ QCOMPARE(currentResult, Slot2Triggered);
+ QCOMPARE(ambigResult, NoResult);
+ QCOMPARE(edit->toPlainText(), QString(""));
+ QCOMPARE(other1->toPlainText(), QString(""));
+ QCOMPARE(other2->toPlainText(), QString(""));
+
+ clearAllShortcuts();
+ delete other1;
+ delete other2;
+ edit->activateWindow();
+ qApp->syncX();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(edit);
+#endif
+ QTest::qWait(100);
+}
+
+// ------------------------------------------------------------------
+// Element Testing helper functions ---------------------------------
+// ------------------------------------------------------------------
+void tst_QShortcut::clearAllShortcuts()
+{
+ qDeleteAll(shortcuts);
+ shortcuts.clear();
+}
+
+QShortcut *tst_QShortcut::setupShortcut(int testWidget, const QKeySequence &ks)
+{
+ return setupShortcut(mainW, QTest::currentDataTag() ? QTest::currentDataTag() : "", testWidget, ks);
+}
+
+QShortcut *tst_QShortcut::setupShortcut(int testWidget, const QString &txt, int k1, int k2, int k3, int k4)
+{
+ return setupShortcut(mainW, QTest::currentDataTag() ? QTest::currentDataTag() : "", testWidget,
+ (txt.isEmpty() ? QKeySequence(k1, k2, k3, k4) : QKeySequence(txt)));
+}
+
+QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int testWidget, const QString &txt, int k1, int k2, int k3, int k4)
+{
+ return setupShortcut(parent, name, testWidget,
+ (txt.isEmpty() ? QKeySequence(k1, k2, k3, k4) : QKeySequence(txt)));
+}
+
+QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int testWidget,
+ const QKeySequence &ks, Qt::ShortcutContext context)
+{
+ // Set up shortcut for next test
+ QShortcut *cut = new QShortcut(QKeySequence(), parent, 0, 0, context);
+ cut->setObjectName(name);
+ cut->setKey(ks);
+
+ const char *normal = 0;
+ const char *ambig = 0;
+ switch(testWidget)
+ {
+ case TriggerSlot1:
+ normal = SLOT(slotTrig1());
+ ambig = SLOT(ambigSlot1());
+ break;
+ case TriggerSlot2:
+ normal = SLOT(slotTrig2());
+ ambig = SLOT(ambigSlot2());
+ break;
+ case TriggerSlot3:
+ normal = SLOT(slotTrig3());
+ ambig = SLOT(ambigSlot3());
+ break;
+ case TriggerSlot4:
+ normal = SLOT(slotTrig4());
+ ambig = SLOT(ambigSlot4());
+ break;
+ case TriggerSlot5:
+ normal = SLOT(slotTrig5());
+ ambig = SLOT(ambigSlot5());
+ break;
+ case TriggerSlot6:
+ normal = SLOT(slotTrig6());
+ ambig = SLOT(ambigSlot6());
+ break;
+ case TriggerSlot7:
+ normal = SLOT(slotTrig7());
+ ambig = SLOT(ambigSlot7());
+ break;
+ }
+ connect(cut, SIGNAL(activated()), this, normal);
+ connect(cut, SIGNAL(activatedAmbiguously()), this, ambig);
+ connect(cut, SIGNAL(destroyed(QObject*)), this, SLOT(shortcutDestroyed(QObject*)));
+ shortcuts.append(cut);
+ return cut;
+}
+
+void tst_QShortcut::shortcutDestroyed(QObject* obj)
+{
+ shortcuts.removeAll(static_cast<QShortcut *>(obj));
+}
+
+void tst_QShortcut::sendKeyEvents(int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4)
+{
+ sendKeyEvents(mainW, k1, c1, k2, c2, k3, c3, k4, c4);
+}
+
+void tst_QShortcut::sendKeyEvents(QWidget *w, int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4)
+{
+ Qt::KeyboardModifiers b1 = toButtons( k1 );
+ Qt::KeyboardModifiers b2 = toButtons( k2 );
+ Qt::KeyboardModifiers b3 = toButtons( k3 );
+ Qt::KeyboardModifiers b4 = toButtons( k4 );
+ k1 &= ~Qt::MODIFIER_MASK;
+ k2 &= ~Qt::MODIFIER_MASK;
+ k3 &= ~Qt::MODIFIER_MASK;
+ k4 &= ~Qt::MODIFIER_MASK;
+
+
+ if (k1 || c1.toAscii()) {
+ QString c(c1.unicode() == QChar::Null ? QString() : QString(c1));
+ QTest::sendKeyEvent(QTest::Press, w, static_cast<Qt::Key>(k1), c, b1);
+ QTest::sendKeyEvent(QTest::Release, w, static_cast<Qt::Key>(k1), c, b1);
+ }
+
+ if (k2 || c2.toAscii()) {
+ QString c(c2.unicode() == QChar::Null ? QString() : QString(c2));
+ QTest::sendKeyEvent(QTest::Press, w, static_cast<Qt::Key>(k2), c, b2);
+ QTest::sendKeyEvent(QTest::Release, w, static_cast<Qt::Key>(k2), c, b2);
+ }
+
+ if (k3 || c3.toAscii()) {
+ QString c(c3.unicode() == QChar::Null ? QString() : QString(c3));
+ QTest::sendKeyEvent(QTest::Press, w, static_cast<Qt::Key>(k3), c, b3);
+ QTest::sendKeyEvent(QTest::Release, w, static_cast<Qt::Key>(k3), c, b3);
+ }
+
+ if (k4 || c4.toAscii()) {
+ QString c(c4.unicode() == QChar::Null ? QString() : QString(c4));
+ QTest::sendKeyEvent(QTest::Press, w, static_cast<Qt::Key>(k4), c, b4);
+ QTest::sendKeyEvent(QTest::Release, w, static_cast<Qt::Key>(k4), c, b4);
+ }
+}
+
+void tst_QShortcut::testElement()
+{
+ currentResult = NoResult;
+ QFETCH(int, action);
+ QFETCH(int, testWidget);
+ QFETCH(QString, txt);
+ QFETCH(int, k1);
+ QFETCH(int, c1);
+ QFETCH(int, k2);
+ QFETCH(int, c2);
+ QFETCH(int, k3);
+ QFETCH(int, c3);
+ QFETCH(int, k4);
+ QFETCH(int, c4);
+ QFETCH(int, result);
+
+ if (action == ClearAll) {
+ clearAllShortcuts();
+ QCOMPARE(TRUE, TRUE);
+ } else if (action == SetupAccel) {
+ setupShortcut(testWidget, txt, k1, k2, k3, k4);
+ QCOMPARE(TRUE, TRUE);
+ } else {
+ sendKeyEvents(k1, c1, k2, c2, k3, c3, k4, c4);
+ QCOMPARE(int(currentResult), result);
+ }
+}
+
+QTEST_MAIN(tst_QShortcut)
+#include "tst_qshortcut.moc"
diff --git a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
new file mode 100644
index 0000000000..55f99b6cdd
--- /dev/null
+++ b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
@@ -0,0 +1,3 @@
+SOURCES=tst_qtouchevent.cpp
+TARGET=tst_qtouchevent
+QT += testlib widgets
diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
new file mode 100644
index 0000000000..f0347e39ff
--- /dev/null
+++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
@@ -0,0 +1,1398 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include <QtTest>
+
+class tst_QTouchEventWidget : public QWidget
+{
+public:
+ QList<QTouchEvent::TouchPoint> touchBeginPoints, touchUpdatePoints, touchEndPoints;
+ bool seenTouchBegin, seenTouchUpdate, seenTouchEnd;
+ bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd;
+ bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd;
+
+ tst_QTouchEventWidget()
+ : QWidget()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ touchBeginPoints.clear();
+ touchUpdatePoints.clear();
+ touchEndPoints.clear();
+ seenTouchBegin = seenTouchUpdate = seenTouchEnd = false;
+ acceptTouchBegin = acceptTouchUpdate = acceptTouchEnd = true;
+ deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
+ }
+
+ bool event(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (seenTouchBegin) qWarning("TouchBegin: already seen a TouchBegin");
+ if (seenTouchUpdate) qWarning("TouchBegin: TouchUpdate cannot happen before TouchBegin");
+ if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin");
+ seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd;
+ touchBeginPoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ event->setAccepted(acceptTouchBegin);
+ if (deleteInTouchBegin)
+ delete this;
+ break;
+ case QEvent::TouchUpdate:
+ if (!seenTouchBegin) qWarning("TouchUpdate: have not seen TouchBegin");
+ if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate");
+ seenTouchUpdate = seenTouchBegin && !seenTouchEnd;
+ touchUpdatePoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ event->setAccepted(acceptTouchUpdate);
+ if (deleteInTouchUpdate)
+ delete this;
+ break;
+ case QEvent::TouchEnd:
+ if (!seenTouchBegin) qWarning("TouchEnd: have not seen TouchBegin");
+ if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd");
+ seenTouchEnd = seenTouchBegin && !seenTouchEnd;
+ touchEndPoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ event->setAccepted(acceptTouchEnd);
+ if (deleteInTouchEnd)
+ delete this;
+ break;
+ default:
+ return QWidget::event(event);
+ }
+ return true;
+ }
+};
+
+class tst_QTouchEventGraphicsItem : public QGraphicsItem
+{
+public:
+ QList<QTouchEvent::TouchPoint> touchBeginPoints, touchUpdatePoints, touchEndPoints;
+ bool seenTouchBegin, seenTouchUpdate, seenTouchEnd;
+ int touchBeginCounter, touchUpdateCounter, touchEndCounter;
+ bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd;
+ bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd;
+ tst_QTouchEventGraphicsItem **weakpointer;
+
+ tst_QTouchEventGraphicsItem()
+ : QGraphicsItem(), weakpointer(0)
+ {
+ reset();
+ }
+
+ ~tst_QTouchEventGraphicsItem()
+ {
+ if (weakpointer)
+ *weakpointer = 0;
+ }
+
+ void reset()
+ {
+ touchBeginPoints.clear();
+ touchUpdatePoints.clear();
+ touchEndPoints.clear();
+ seenTouchBegin = seenTouchUpdate = seenTouchEnd = false;
+ touchBeginCounter = touchUpdateCounter = touchEndCounter = 0;
+ acceptTouchBegin = acceptTouchUpdate = acceptTouchEnd = true;
+ deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
+ }
+
+ QRectF boundingRect() const { return QRectF(0, 0, 10, 10); }
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) { }
+
+ bool sceneEvent(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (seenTouchBegin) qWarning("TouchBegin: already seen a TouchBegin");
+ if (seenTouchUpdate) qWarning("TouchBegin: TouchUpdate cannot happen before TouchBegin");
+ if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin");
+ seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd;
+ ++touchBeginCounter;
+ touchBeginPoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ event->setAccepted(acceptTouchBegin);
+ if (deleteInTouchBegin)
+ delete this;
+ break;
+ case QEvent::TouchUpdate:
+ if (!seenTouchBegin) qWarning("TouchUpdate: have not seen TouchBegin");
+ if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate");
+ seenTouchUpdate = seenTouchBegin && !seenTouchEnd;
+ ++touchUpdateCounter;
+ touchUpdatePoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ event->setAccepted(acceptTouchUpdate);
+ if (deleteInTouchUpdate)
+ delete this;
+ break;
+ case QEvent::TouchEnd:
+ if (!seenTouchBegin) qWarning("TouchEnd: have not seen TouchBegin");
+ if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd");
+ seenTouchEnd = seenTouchBegin && !seenTouchEnd;
+ ++touchEndCounter;
+ touchEndPoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ event->setAccepted(acceptTouchEnd);
+ if (deleteInTouchEnd)
+ delete this;
+ break;
+ default:
+ return QGraphicsItem::sceneEvent(event);
+ }
+ return true;
+ }
+};
+
+class tst_QTouchEvent : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QTouchEvent() { }
+ ~tst_QTouchEvent() { }
+
+private slots:
+ void touchDisabledByDefault();
+ void touchEventAcceptedByDefault();
+ void touchBeginPropagatesWhenIgnored();
+ void touchUpdateAndEndNeverPropagate();
+ void basicRawEventTranslation();
+ void multiPointRawEventTranslationOnTouchScreen();
+ void multiPointRawEventTranslationOnTouchPad();
+ void deleteInEventHandler();
+ void deleteInRawEventTranslation();
+ void crashInQGraphicsSceneAfterNotHandlingTouchBegin();
+ void touchBeginWithGraphicsWidget();
+};
+
+void tst_QTouchEvent::touchDisabledByDefault()
+{
+ // QWidget
+ {
+ // the widget attribute is not enabled by default
+ QWidget widget;
+ QVERIFY(!widget.testAttribute(Qt::WA_AcceptTouchEvents));
+
+ // events should not be accepted since they are not enabled
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ touchPoints.append(QTouchEvent::TouchPoint(0));
+ QTouchEvent touchEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ touchPoints);
+ bool res = QApplication::sendEvent(&widget, &touchEvent);
+ QVERIFY(!res);
+ QVERIFY(!touchEvent.isAccepted());
+ }
+
+ // QGraphicsView
+ {
+ QGraphicsScene scene;
+ tst_QTouchEventGraphicsItem item;
+ QGraphicsView view(&scene);
+ scene.addItem(&item);
+ item.setPos(100, 100);
+ view.resize(200, 200);
+ view.fitInView(scene.sceneRect());
+
+ // touch events are not accepted by default
+ QVERIFY(!item.acceptTouchEvents());
+
+ // compose an event to the scene that is over the item
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(view.mapFromScene(item.mapToScene(item.boundingRect().center())));
+ touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
+ touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
+ QTouchEvent touchEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
+ QVERIFY(!res);
+ QVERIFY(!touchEvent.isAccepted());
+ QVERIFY(!item.seenTouchBegin);
+ }
+}
+
+void tst_QTouchEvent::touchEventAcceptedByDefault()
+{
+ // QWidget
+ {
+ // enabling touch events should automatically accept touch events
+ QWidget widget;
+ widget.setAttribute(Qt::WA_AcceptTouchEvents);
+
+ // QWidget handles touch event by converting them into a mouse event, so the event is both
+ // accepted and handled (res == true)
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ touchPoints.append(QTouchEvent::TouchPoint(0));
+ QTouchEvent touchEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ touchPoints);
+ bool res = QApplication::sendEvent(&widget, &touchEvent);
+ QVERIFY(res);
+ QVERIFY(touchEvent.isAccepted());
+
+ // tst_QTouchEventWidget does handle, sending succeeds
+ tst_QTouchEventWidget touchWidget;
+ touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ touchEvent.ignore();
+ res = QApplication::sendEvent(&touchWidget, &touchEvent);
+ QVERIFY(res);
+ QVERIFY(touchEvent.isAccepted());
+ }
+
+ // QGraphicsView
+ {
+ QGraphicsScene scene;
+ tst_QTouchEventGraphicsItem item;
+ QGraphicsView view(&scene);
+ scene.addItem(&item);
+ item.setPos(100, 100);
+ view.resize(200, 200);
+ view.fitInView(scene.sceneRect());
+
+ // enabling touch events on the item also enables events on the viewport
+ item.setAcceptTouchEvents(true);
+ QVERIFY(view.viewport()->testAttribute(Qt::WA_AcceptTouchEvents));
+
+ // compose an event to the scene that is over the item
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(view.mapFromScene(item.mapToScene(item.boundingRect().center())));
+ touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
+ touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
+ QTouchEvent touchEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
+ QVERIFY(res);
+ QVERIFY(touchEvent.isAccepted());
+ QVERIFY(item.seenTouchBegin);
+ }
+}
+
+void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
+{
+ // QWidget
+ {
+ tst_QTouchEventWidget window, child, grandchild;
+ child.setParent(&window);
+ grandchild.setParent(&child);
+
+ // all widgets accept touch events, grandchild ignores, so child sees the event, but not window
+ window.setAttribute(Qt::WA_AcceptTouchEvents);
+ child.setAttribute(Qt::WA_AcceptTouchEvents);
+ grandchild.setAttribute(Qt::WA_AcceptTouchEvents);
+ grandchild.acceptTouchBegin = false;
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ touchPoints.append(QTouchEvent::TouchPoint(0));
+ QTouchEvent touchEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ touchPoints);
+ bool res = QApplication::sendEvent(&grandchild, &touchEvent);
+ QVERIFY(res);
+ QVERIFY(touchEvent.isAccepted());
+ QVERIFY(grandchild.seenTouchBegin);
+ QVERIFY(child.seenTouchBegin);
+ QVERIFY(!window.seenTouchBegin);
+
+ // disable touch on grandchild. even though it doesn't accept it, child should still get the
+ // TouchBegin
+ grandchild.reset();
+ child.reset();
+ window.reset();
+ grandchild.setAttribute(Qt::WA_AcceptTouchEvents, false);
+
+ touchEvent.ignore();
+ res = QApplication::sendEvent(&grandchild, &touchEvent);
+ QVERIFY(res);
+ QVERIFY(touchEvent.isAccepted());
+ QVERIFY(!grandchild.seenTouchBegin);
+ QVERIFY(child.seenTouchBegin);
+ QVERIFY(!window.seenTouchBegin);
+ }
+
+ // QGraphicsView
+ {
+ QGraphicsScene scene;
+ tst_QTouchEventGraphicsItem root, child, grandchild;
+ QGraphicsView view(&scene);
+ scene.addItem(&root);
+ root.setPos(100, 100);
+ child.setParentItem(&root);
+ grandchild.setParentItem(&child);
+ view.resize(200, 200);
+ view.fitInView(scene.sceneRect());
+
+ // all items accept touch events, grandchild ignores, so child sees the event, but not root
+ root.setAcceptTouchEvents(true);
+ child.setAcceptTouchEvents(true);
+ grandchild.setAcceptTouchEvents(true);
+ grandchild.acceptTouchBegin = false;
+
+ // compose an event to the scene that is over the grandchild
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(view.mapFromScene(grandchild.mapToScene(grandchild.boundingRect().center())));
+ touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
+ touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
+ QTouchEvent touchEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
+ QVERIFY(res);
+ QVERIFY(touchEvent.isAccepted());
+ QVERIFY(grandchild.seenTouchBegin);
+ QVERIFY(child.seenTouchBegin);
+ QVERIFY(!root.seenTouchBegin);
+ }
+
+ // QGraphicsView
+ {
+ QGraphicsScene scene;
+ tst_QTouchEventGraphicsItem root, child, grandchild;
+ QGraphicsView view(&scene);
+ scene.addItem(&root);
+ root.setPos(100, 100);
+ child.setParentItem(&root);
+ grandchild.setParentItem(&child);
+ view.resize(200, 200);
+ view.fitInView(scene.sceneRect());
+
+ // leave touch disabled on grandchild. even though it doesn't accept it, child should
+ // still get the TouchBegin
+ root.setAcceptTouchEvents(true);
+ child.setAcceptTouchEvents(true);
+
+ // compose an event to the scene that is over the grandchild
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(view.mapFromScene(grandchild.mapToScene(grandchild.boundingRect().center())));
+ touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
+ touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
+ QTouchEvent touchEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
+ QVERIFY(res);
+ QVERIFY(touchEvent.isAccepted());
+ QVERIFY(!grandchild.seenTouchBegin);
+ QVERIFY(child.seenTouchBegin);
+ QVERIFY(!root.seenTouchBegin);
+ }
+}
+
+void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
+{
+ // QWidget
+ {
+ tst_QTouchEventWidget window, child;
+ child.setParent(&window);
+
+ window.setAttribute(Qt::WA_AcceptTouchEvents);
+ child.setAttribute(Qt::WA_AcceptTouchEvents);
+ child.acceptTouchUpdate = false;
+ child.acceptTouchEnd = false;
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ touchPoints.append(QTouchEvent::TouchPoint(0));
+ QTouchEvent touchBeginEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ touchPoints);
+ bool res = QApplication::sendEvent(&child, &touchBeginEvent);
+ QVERIFY(res);
+ QVERIFY(touchBeginEvent.isAccepted());
+ QVERIFY(child.seenTouchBegin);
+ QVERIFY(!window.seenTouchBegin);
+
+ // send the touch update to the child, but ignore it, it doesn't propagate
+ QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ touchPoints);
+ res = QApplication::sendEvent(&child, &touchUpdateEvent);
+ QVERIFY(res);
+ QVERIFY(!touchUpdateEvent.isAccepted());
+ QVERIFY(child.seenTouchUpdate);
+ QVERIFY(!window.seenTouchUpdate);
+
+ // send the touch end, same thing should happen as with touch update
+ QTouchEvent touchEndEvent(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ touchPoints);
+ res = QApplication::sendEvent(&child, &touchEndEvent);
+ QVERIFY(res);
+ QVERIFY(!touchEndEvent.isAccepted());
+ QVERIFY(child.seenTouchEnd);
+ QVERIFY(!window.seenTouchEnd);
+ }
+
+ // QGraphicsView
+ {
+ QGraphicsScene scene;
+ tst_QTouchEventGraphicsItem root, child, grandchild;
+ QGraphicsView view(&scene);
+ scene.addItem(&root);
+ root.setPos(100, 100);
+ child.setParentItem(&root);
+ grandchild.setParentItem(&child);
+ view.resize(200, 200);
+ view.fitInView(scene.sceneRect());
+
+ root.setAcceptTouchEvents(true);
+ child.setAcceptTouchEvents(true);
+ child.acceptTouchUpdate = false;
+ child.acceptTouchEnd = false;
+
+ // compose an event to the scene that is over the child
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(view.mapFromScene(grandchild.mapToScene(grandchild.boundingRect().center())));
+ touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
+ touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
+ QTouchEvent touchBeginEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ bool res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
+ QVERIFY(res);
+ QVERIFY(touchBeginEvent.isAccepted());
+ QVERIFY(child.seenTouchBegin);
+ QVERIFY(!root.seenTouchBegin);
+
+ // send the touch update to the child, but ignore it, it doesn't propagate
+ touchPoint.setState(Qt::TouchPointMoved);
+ QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
+ QVERIFY(res);
+ // the scene accepts the event, since it found an item to send the event to
+ QVERIFY(!touchUpdateEvent.isAccepted());
+ QVERIFY(child.seenTouchUpdate);
+ QVERIFY(!root.seenTouchUpdate);
+
+ // send the touch end, same thing should happen as with touch update
+ touchPoint.setState(Qt::TouchPointReleased);
+ QTouchEvent touchEndEvent(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
+ QVERIFY(res);
+ // the scene accepts the event, since it found an item to send the event to
+ QVERIFY(!touchEndEvent.isAccepted());
+ QVERIFY(child.seenTouchEnd);
+ QVERIFY(!root.seenTouchEnd);
+ }
+}
+
+QPointF normalized(const QPointF &pos, const QRectF &rect)
+{
+ return QPointF(pos.x() / rect.width(), pos.y() / rect.height());
+}
+
+void tst_QTouchEvent::basicRawEventTranslation()
+{
+ tst_QTouchEventWidget touchWidget;
+ touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ touchWidget.setGeometry(100, 100, 400, 300);
+
+ QPointF pos = touchWidget.rect().center();
+ QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint());
+ QPointF delta(10, 10);
+ QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+
+ QTouchEvent::TouchPoint rawTouchPoint;
+ rawTouchPoint.setId(0);
+
+ // this should be translated to a TouchBegin
+ rawTouchPoint.setState(Qt::TouchPointPressed);
+ rawTouchPoint.setScreenPos(screenPos);
+ rawTouchPoint.setNormalizedPos(normalized(rawTouchPoint.pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget,
+ QTouchEvent::TouchScreen,
+ QList<QTouchEvent::TouchPoint>() << rawTouchPoint);
+ QVERIFY(touchWidget.seenTouchBegin);
+ QVERIFY(!touchWidget.seenTouchUpdate);
+ QVERIFY(!touchWidget.seenTouchEnd);
+ QCOMPARE(touchWidget.touchBeginPoints.count(), 1);
+ QTouchEvent::TouchPoint touchBeginPoint = touchWidget.touchBeginPoints.first();
+ QCOMPARE(touchBeginPoint.id(), rawTouchPoint.id());
+ QCOMPARE(touchBeginPoint.state(), rawTouchPoint.state());
+ QCOMPARE(touchBeginPoint.pos(), pos);
+ QCOMPARE(touchBeginPoint.startPos(), pos);
+ QCOMPARE(touchBeginPoint.lastPos(), pos);
+ QCOMPARE(touchBeginPoint.scenePos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchBeginPoint.startScenePos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchBeginPoint.lastScenePos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchBeginPoint.screenPos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchBeginPoint.startScreenPos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchBeginPoint.lastScreenPos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchBeginPoint.normalizedPos(), rawTouchPoint.normalizedPos());
+ QCOMPARE(touchBeginPoint.startNormalizedPos(), touchBeginPoint.normalizedPos());
+ QCOMPARE(touchBeginPoint.lastNormalizedPos(), touchBeginPoint.normalizedPos());
+ QCOMPARE(touchBeginPoint.rect(), QRectF(pos, QSizeF(0, 0)));
+ QCOMPARE(touchBeginPoint.screenRect(), QRectF(rawTouchPoint.screenPos(), QSizeF(0, 0)));
+ QCOMPARE(touchBeginPoint.sceneRect(), touchBeginPoint.screenRect());
+ QCOMPARE(touchBeginPoint.pressure(), qreal(1.));
+
+ // moving the point should translate to TouchUpdate
+ rawTouchPoint.setState(Qt::TouchPointMoved);
+ rawTouchPoint.setScreenPos(screenPos + delta);
+ rawTouchPoint.setNormalizedPos(normalized(rawTouchPoint.pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget,
+ QTouchEvent::TouchScreen,
+ QList<QTouchEvent::TouchPoint>() << rawTouchPoint);
+ QVERIFY(touchWidget.seenTouchBegin);
+ QVERIFY(touchWidget.seenTouchUpdate);
+ QVERIFY(!touchWidget.seenTouchEnd);
+ QCOMPARE(touchWidget.touchUpdatePoints.count(), 1);
+ QTouchEvent::TouchPoint touchUpdatePoint = touchWidget.touchUpdatePoints.first();
+ QCOMPARE(touchUpdatePoint.id(), rawTouchPoint.id());
+ QCOMPARE(touchUpdatePoint.state(), rawTouchPoint.state());
+ QCOMPARE(touchUpdatePoint.pos(), pos + delta);
+ QCOMPARE(touchUpdatePoint.startPos(), pos);
+ QCOMPARE(touchUpdatePoint.lastPos(), pos);
+ QCOMPARE(touchUpdatePoint.scenePos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchUpdatePoint.startScenePos(), screenPos);
+ QCOMPARE(touchUpdatePoint.lastScenePos(), screenPos);
+ QCOMPARE(touchUpdatePoint.screenPos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchUpdatePoint.startScreenPos(), screenPos);
+ QCOMPARE(touchUpdatePoint.lastScreenPos(), screenPos);
+ QCOMPARE(touchUpdatePoint.normalizedPos(), rawTouchPoint.normalizedPos());
+ QCOMPARE(touchUpdatePoint.startNormalizedPos(), touchBeginPoint.normalizedPos());
+ QCOMPARE(touchUpdatePoint.lastNormalizedPos(), touchBeginPoint.normalizedPos());
+ QCOMPARE(touchUpdatePoint.rect(), QRectF(pos + delta, QSizeF(0, 0)));
+ QCOMPARE(touchUpdatePoint.screenRect(), QRectF(rawTouchPoint.screenPos(), QSizeF(0, 0)));
+ QCOMPARE(touchUpdatePoint.sceneRect(), touchUpdatePoint.screenRect());
+ QCOMPARE(touchUpdatePoint.pressure(), qreal(1.));
+
+ // releasing the point translates to TouchEnd
+ rawTouchPoint.setState(Qt::TouchPointReleased);
+ rawTouchPoint.setScreenPos(screenPos + delta + delta);
+ rawTouchPoint.setNormalizedPos(normalized(rawTouchPoint.pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget,
+ QTouchEvent::TouchScreen,
+ QList<QTouchEvent::TouchPoint>() << rawTouchPoint);
+ QVERIFY(touchWidget.seenTouchBegin);
+ QVERIFY(touchWidget.seenTouchUpdate);
+ QVERIFY(touchWidget.seenTouchEnd);
+ QCOMPARE(touchWidget.touchEndPoints.count(), 1);
+ QTouchEvent::TouchPoint touchEndPoint = touchWidget.touchEndPoints.first();
+ QCOMPARE(touchEndPoint.id(), rawTouchPoint.id());
+ QCOMPARE(touchEndPoint.state(), rawTouchPoint.state());
+ QCOMPARE(touchEndPoint.pos(), pos + delta + delta);
+ QCOMPARE(touchEndPoint.startPos(), pos);
+ QCOMPARE(touchEndPoint.lastPos(), pos + delta);
+ QCOMPARE(touchEndPoint.scenePos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchEndPoint.startScenePos(), screenPos);
+ QCOMPARE(touchEndPoint.lastScenePos(), screenPos + delta);
+ QCOMPARE(touchEndPoint.screenPos(), rawTouchPoint.screenPos());
+ QCOMPARE(touchEndPoint.startScreenPos(), screenPos);
+ QCOMPARE(touchEndPoint.lastScreenPos(), screenPos + delta);
+ QCOMPARE(touchEndPoint.normalizedPos(), rawTouchPoint.normalizedPos());
+ QCOMPARE(touchEndPoint.startNormalizedPos(), touchBeginPoint.normalizedPos());
+ QCOMPARE(touchEndPoint.lastNormalizedPos(), touchUpdatePoint.normalizedPos());
+ QCOMPARE(touchEndPoint.rect(), QRectF(pos + delta + delta, QSizeF(0, 0)));
+ QCOMPARE(touchEndPoint.screenRect(), QRectF(rawTouchPoint.screenPos(), QSizeF(0, 0)));
+ QCOMPARE(touchEndPoint.sceneRect(), touchEndPoint.screenRect());
+ QCOMPARE(touchEndPoint.pressure(), qreal(0.));
+}
+
+void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
+{
+ tst_QTouchEventWidget touchWidget;
+ touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ touchWidget.setGeometry(100, 100, 400, 300);
+
+ tst_QTouchEventWidget leftWidget;
+ leftWidget.setParent(&touchWidget);
+ leftWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ leftWidget.setGeometry(0, 100, 100, 100);
+ leftWidget.show();
+
+ tst_QTouchEventWidget rightWidget;
+ rightWidget.setParent(&touchWidget);
+ rightWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ rightWidget.setGeometry(300, 100, 100, 100);
+ rightWidget.show();
+
+ QPointF leftPos = leftWidget.rect().center();
+ QPointF rightPos = rightWidget.rect().center();
+ QPointF centerPos = touchWidget.rect().center();
+ QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint());
+ QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint());
+ QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint());
+ QPointF delta(10, 10);
+ QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+
+ QList<QTouchEvent::TouchPoint> rawTouchPoints;
+ rawTouchPoints.append(QTouchEvent::TouchPoint(0));
+ rawTouchPoints.append(QTouchEvent::TouchPoint(1));
+
+ // generate TouchBegins on both leftWidget and rightWidget
+ rawTouchPoints[0].setState(Qt::TouchPointPressed);
+ rawTouchPoints[0].setScreenPos(leftScreenPos);
+ rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
+ rawTouchPoints[1].setState(Qt::TouchPointPressed);
+ rawTouchPoints[1].setScreenPos(rightScreenPos);
+ rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchScreen, rawTouchPoints);
+ QVERIFY(!touchWidget.seenTouchBegin);
+ QVERIFY(!touchWidget.seenTouchUpdate);
+ QVERIFY(!touchWidget.seenTouchEnd);
+ QVERIFY(leftWidget.seenTouchBegin);
+ QVERIFY(!leftWidget.seenTouchUpdate);
+ QVERIFY(!leftWidget.seenTouchEnd);
+ QVERIFY(rightWidget.seenTouchBegin);
+ QVERIFY(!rightWidget.seenTouchUpdate);
+ QVERIFY(!rightWidget.seenTouchEnd);
+ QCOMPARE(leftWidget.touchBeginPoints.count(), 1);
+ QCOMPARE(rightWidget.touchBeginPoints.count(), 1);
+ {
+ QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchBeginPoints.first();
+ QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
+ QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
+ QCOMPARE(leftTouchPoint.pos(), leftPos);
+ QCOMPARE(leftTouchPoint.startPos(), leftPos);
+ QCOMPARE(leftTouchPoint.lastPos(), leftPos);
+ QCOMPARE(leftTouchPoint.scenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.screenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.rect(), QRectF(leftPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.sceneRect(), QRectF(leftScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.screenRect(), QRectF(leftScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.pressure(), qreal(1.));
+
+ QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchBeginPoints.first();
+ QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
+ QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
+ QCOMPARE(rightTouchPoint.pos(), rightPos);
+ QCOMPARE(rightTouchPoint.startPos(), rightPos);
+ QCOMPARE(rightTouchPoint.lastPos(), rightPos);
+ QCOMPARE(rightTouchPoint.scenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.screenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.rect(), QRectF(rightPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.sceneRect(), QRectF(rightScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.screenRect(), QRectF(rightScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.pressure(), qreal(1.));
+ }
+
+ // generate TouchUpdates on both leftWidget and rightWidget
+ rawTouchPoints[0].setState(Qt::TouchPointMoved);
+ rawTouchPoints[0].setScreenPos(centerScreenPos);
+ rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
+ rawTouchPoints[1].setState(Qt::TouchPointMoved);
+ rawTouchPoints[1].setScreenPos(centerScreenPos);
+ rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchScreen, rawTouchPoints);
+ QVERIFY(!touchWidget.seenTouchBegin);
+ QVERIFY(!touchWidget.seenTouchUpdate);
+ QVERIFY(!touchWidget.seenTouchEnd);
+ QVERIFY(leftWidget.seenTouchBegin);
+ QVERIFY(leftWidget.seenTouchUpdate);
+ QVERIFY(!leftWidget.seenTouchEnd);
+ QVERIFY(rightWidget.seenTouchBegin);
+ QVERIFY(rightWidget.seenTouchUpdate);
+ QVERIFY(!rightWidget.seenTouchEnd);
+ QCOMPARE(leftWidget.touchUpdatePoints.count(), 1);
+ QCOMPARE(rightWidget.touchUpdatePoints.count(), 1);
+ {
+ QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchUpdatePoints.first();
+ QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
+ QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
+ QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
+ QCOMPARE(leftTouchPoint.startPos(), leftPos);
+ QCOMPARE(leftTouchPoint.lastPos(), leftPos);
+ QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos);
+ QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos);
+ QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.pressure(), qreal(1.));
+
+ QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchUpdatePoints.first();
+ QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
+ QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
+ QCOMPARE(rightTouchPoint.pos(), QPointF(rightWidget.mapFromParent(centerPos.toPoint())));
+ QCOMPARE(rightTouchPoint.startPos(), rightPos);
+ QCOMPARE(rightTouchPoint.lastPos(), rightPos);
+ QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos);
+ QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos);
+ QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.rect(), QRectF(rightWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.pressure(), qreal(1.));
+ }
+
+ // generate TouchEnds on both leftWidget and rightWidget
+ rawTouchPoints[0].setState(Qt::TouchPointReleased);
+ rawTouchPoints[0].setScreenPos(centerScreenPos);
+ rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
+ rawTouchPoints[1].setState(Qt::TouchPointReleased);
+ rawTouchPoints[1].setScreenPos(centerScreenPos);
+ rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchScreen, rawTouchPoints);
+ QVERIFY(!touchWidget.seenTouchBegin);
+ QVERIFY(!touchWidget.seenTouchUpdate);
+ QVERIFY(!touchWidget.seenTouchEnd);
+ QVERIFY(leftWidget.seenTouchBegin);
+ QVERIFY(leftWidget.seenTouchUpdate);
+ QVERIFY(leftWidget.seenTouchEnd);
+ QVERIFY(rightWidget.seenTouchBegin);
+ QVERIFY(rightWidget.seenTouchUpdate);
+ QVERIFY(rightWidget.seenTouchEnd);
+ QCOMPARE(leftWidget.touchEndPoints.count(), 1);
+ QCOMPARE(rightWidget.touchEndPoints.count(), 1);
+ {
+ QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchEndPoints.first();
+ QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
+ QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
+ QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
+ QCOMPARE(leftTouchPoint.startPos(), leftPos);
+ QCOMPARE(leftTouchPoint.lastPos(), leftTouchPoint.pos());
+ QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos);
+ QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScenePos(), leftTouchPoint.scenePos());
+ QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos);
+ QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScreenPos(), leftTouchPoint.screenPos());
+ QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.pressure(), qreal(0.));
+
+ QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchEndPoints.first();
+ QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
+ QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
+ QCOMPARE(rightTouchPoint.pos(), QPointF(rightWidget.mapFromParent(centerPos.toPoint())));
+ QCOMPARE(rightTouchPoint.startPos(), rightPos);
+ QCOMPARE(rightTouchPoint.lastPos(), rightTouchPoint.pos());
+ QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos);
+ QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScenePos(), rightTouchPoint.scenePos());
+ QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos);
+ QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScreenPos(), rightTouchPoint.screenPos());
+ QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.rect(), QRectF(rightWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.pressure(), qreal(0.));
+ }
+}
+
+void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
+{
+ tst_QTouchEventWidget touchWidget;
+ touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ touchWidget.setGeometry(100, 100, 400, 300);
+
+ tst_QTouchEventWidget leftWidget;
+ leftWidget.setParent(&touchWidget);
+ leftWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ leftWidget.setGeometry(0, 100, 100, 100);
+ leftWidget.show();
+
+ tst_QTouchEventWidget rightWidget;
+ rightWidget.setParent(&touchWidget);
+ rightWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ rightWidget.setGeometry(300, 100, 100, 100);
+ rightWidget.show();
+
+ QPointF leftPos = leftWidget.rect().center();
+ QPointF rightPos = rightWidget.rect().center();
+ QPointF centerPos = touchWidget.rect().center();
+ QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint());
+ QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint());
+ QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint());
+ QPointF delta(10, 10);
+ QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+
+ QList<QTouchEvent::TouchPoint> rawTouchPoints;
+ rawTouchPoints.append(QTouchEvent::TouchPoint(0));
+ rawTouchPoints.append(QTouchEvent::TouchPoint(1));
+
+ // generate TouchBegin on leftWidget only
+ rawTouchPoints[0].setState(Qt::TouchPointPressed);
+ rawTouchPoints[0].setScreenPos(leftScreenPos);
+ rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
+ rawTouchPoints[1].setState(Qt::TouchPointPressed);
+ rawTouchPoints[1].setScreenPos(rightScreenPos);
+ rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchPad, rawTouchPoints);
+ QVERIFY(!touchWidget.seenTouchBegin);
+ QVERIFY(!touchWidget.seenTouchUpdate);
+ QVERIFY(!touchWidget.seenTouchEnd);
+ QVERIFY(leftWidget.seenTouchBegin);
+ QVERIFY(!leftWidget.seenTouchUpdate);
+ QVERIFY(!leftWidget.seenTouchEnd);
+ QVERIFY(!rightWidget.seenTouchBegin);
+ QVERIFY(!rightWidget.seenTouchUpdate);
+ QVERIFY(!rightWidget.seenTouchEnd);
+ QCOMPARE(leftWidget.touchBeginPoints.count(), 2);
+ QCOMPARE(rightWidget.touchBeginPoints.count(), 0);
+ {
+ QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchBeginPoints.at(0);
+ QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
+ QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
+ QCOMPARE(leftTouchPoint.pos(), leftPos);
+ QCOMPARE(leftTouchPoint.startPos(), leftPos);
+ QCOMPARE(leftTouchPoint.lastPos(), leftPos);
+ QCOMPARE(leftTouchPoint.scenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.screenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.rect(), QRectF(leftPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.sceneRect(), QRectF(leftScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.screenRect(), QRectF(leftScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.pressure(), qreal(1.));
+
+ QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchBeginPoints.at(1);
+ QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
+ QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
+ QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
+ QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
+ QCOMPARE(rightTouchPoint.lastPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
+ QCOMPARE(rightTouchPoint.scenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.screenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.rect(), QRectF(leftWidget.mapFromGlobal(rightScreenPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.sceneRect(), QRectF(rightScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.screenRect(), QRectF(rightScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.pressure(), qreal(1.));
+ }
+
+ // generate TouchUpdate on leftWidget
+ rawTouchPoints[0].setState(Qt::TouchPointMoved);
+ rawTouchPoints[0].setScreenPos(centerScreenPos);
+ rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
+ rawTouchPoints[1].setState(Qt::TouchPointMoved);
+ rawTouchPoints[1].setScreenPos(centerScreenPos);
+ rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchPad, rawTouchPoints);
+ QVERIFY(!touchWidget.seenTouchBegin);
+ QVERIFY(!touchWidget.seenTouchUpdate);
+ QVERIFY(!touchWidget.seenTouchEnd);
+ QVERIFY(leftWidget.seenTouchBegin);
+ QVERIFY(leftWidget.seenTouchUpdate);
+ QVERIFY(!leftWidget.seenTouchEnd);
+ QVERIFY(!rightWidget.seenTouchBegin);
+ QVERIFY(!rightWidget.seenTouchUpdate);
+ QVERIFY(!rightWidget.seenTouchEnd);
+ QCOMPARE(leftWidget.touchUpdatePoints.count(), 2);
+ QCOMPARE(rightWidget.touchUpdatePoints.count(), 0);
+ {
+ QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchUpdatePoints.at(0);
+ QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
+ QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
+ QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
+ QCOMPARE(leftTouchPoint.startPos(), leftPos);
+ QCOMPARE(leftTouchPoint.lastPos(), leftPos);
+ QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos);
+ QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos);
+ QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.pressure(), qreal(1.));
+
+ QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchUpdatePoints.at(1);
+ QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
+ QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
+ QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
+ QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
+ QCOMPARE(rightTouchPoint.lastPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
+ QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos);
+ QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos);
+ QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.pressure(), qreal(1.));
+ }
+
+ // generate TouchEnd on leftWidget
+ rawTouchPoints[0].setState(Qt::TouchPointReleased);
+ rawTouchPoints[0].setScreenPos(centerScreenPos);
+ rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
+ rawTouchPoints[1].setState(Qt::TouchPointReleased);
+ rawTouchPoints[1].setScreenPos(centerScreenPos);
+ rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchPad, rawTouchPoints);
+ QVERIFY(!touchWidget.seenTouchBegin);
+ QVERIFY(!touchWidget.seenTouchUpdate);
+ QVERIFY(!touchWidget.seenTouchEnd);
+ QVERIFY(leftWidget.seenTouchBegin);
+ QVERIFY(leftWidget.seenTouchUpdate);
+ QVERIFY(leftWidget.seenTouchEnd);
+ QVERIFY(!rightWidget.seenTouchBegin);
+ QVERIFY(!rightWidget.seenTouchUpdate);
+ QVERIFY(!rightWidget.seenTouchEnd);
+ QCOMPARE(leftWidget.touchEndPoints.count(), 2);
+ QCOMPARE(rightWidget.touchEndPoints.count(), 0);
+ {
+ QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchEndPoints.at(0);
+ QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
+ QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
+ QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
+ QCOMPARE(leftTouchPoint.startPos(), leftPos);
+ QCOMPARE(leftTouchPoint.lastPos(), leftTouchPoint.pos());
+ QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos);
+ QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScenePos(), leftTouchPoint.scenePos());
+ QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos);
+ QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
+ QCOMPARE(leftTouchPoint.lastScreenPos(), leftTouchPoint.screenPos());
+ QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
+ QCOMPARE(leftTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(leftTouchPoint.pressure(), qreal(0.));
+
+ QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchEndPoints.at(1);
+ QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
+ QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
+ QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
+ QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
+ QCOMPARE(rightTouchPoint.lastPos(), rightTouchPoint.pos());
+ QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos);
+ QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScenePos(), rightTouchPoint.scenePos());
+ QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos);
+ QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
+ QCOMPARE(rightTouchPoint.lastScreenPos(), rightTouchPoint.screenPos());
+ QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
+ QCOMPARE(rightTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
+ QCOMPARE(rightTouchPoint.pressure(), qreal(0.));
+ }
+}
+
+void tst_QTouchEvent::deleteInEventHandler()
+{
+ // QWidget
+ {
+ QWidget window;
+ tst_QTouchEventWidget *child1, *child2, *child3;
+ child1 = new tst_QTouchEventWidget;
+ child2 = new tst_QTouchEventWidget;
+ child3 = new tst_QTouchEventWidget;
+ child1->setParent(&window);
+ child2->setParent(&window);
+ child3->setParent(&window);
+ child1->setAttribute(Qt::WA_AcceptTouchEvents);
+ child2->setAttribute(Qt::WA_AcceptTouchEvents);
+ child3->setAttribute(Qt::WA_AcceptTouchEvents);
+ child1->deleteInTouchBegin = true;
+ child2->deleteInTouchUpdate = true;
+ child3->deleteInTouchEnd = true;
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ touchPoints.append(QTouchEvent::TouchPoint(0));
+ QTouchEvent touchBeginEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ touchPoints);
+ QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointStationary,
+ touchPoints);
+ QTouchEvent touchEndEvent(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ touchPoints);
+ QWeakPointer<QWidget> p;
+ bool res;
+
+ touchBeginEvent.ignore();
+ p = child1;
+ res = QApplication::sendEvent(child1, &touchBeginEvent);
+ // event is handled, but widget should be deleted
+ QVERIFY(res && touchBeginEvent.isAccepted() && p.isNull());
+
+ touchBeginEvent.ignore();
+ p = child2;
+ res = QApplication::sendEvent(child2, &touchBeginEvent);
+ QVERIFY(res && touchBeginEvent.isAccepted() && !p.isNull());
+ touchUpdateEvent.ignore();
+ res = QApplication::sendEvent(child2, &touchUpdateEvent);
+ QVERIFY(res && touchUpdateEvent.isAccepted() && p.isNull());
+
+ touchBeginEvent.ignore();
+ p = child3;
+ res = QApplication::sendEvent(child3, &touchBeginEvent);
+ QVERIFY(res && touchBeginEvent.isAccepted() && !p.isNull());
+ touchUpdateEvent.ignore();
+ res = QApplication::sendEvent(child3, &touchUpdateEvent);
+ QVERIFY(res && touchUpdateEvent.isAccepted() && !p.isNull());
+ touchEndEvent.ignore();
+ res = QApplication::sendEvent(child3, &touchEndEvent);
+ QVERIFY(res && touchEndEvent.isAccepted() && p.isNull());
+ }
+
+ // QGraphicsView
+ {
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ tst_QTouchEventGraphicsItem *root, *child1, *child2, *child3;
+ root = new tst_QTouchEventGraphicsItem;
+ child1 = new tst_QTouchEventGraphicsItem;
+ child2 = new tst_QTouchEventGraphicsItem;
+ child3 = new tst_QTouchEventGraphicsItem;
+ child1->setParentItem(root);
+ child2->setParentItem(root);
+ child3->setParentItem(root);
+ child1->setZValue(1.);
+ child2->setZValue(0.);
+ child3->setZValue(-1.);
+ child1->setAcceptTouchEvents(true);
+ child2->setAcceptTouchEvents(true);
+ child3->setAcceptTouchEvents(true);
+ child1->deleteInTouchBegin = true;
+ child2->deleteInTouchUpdate = true;
+ child3->deleteInTouchEnd = true;
+
+ scene.addItem(root);
+ view.resize(200, 200);
+ view.fitInView(scene.sceneRect());
+
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(view.mapFromScene(child1->mapToScene(child1->boundingRect().center())));
+ touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
+ touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ touchPoints.append(touchPoint);
+ QTouchEvent touchBeginEvent(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ touchPoints);
+ touchPoints[0].setState(Qt::TouchPointMoved);
+ QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ touchPoints);
+ touchPoints[0].setState(Qt::TouchPointReleased);
+ QTouchEvent touchEndEvent(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ touchPoints);
+ bool res;
+
+ child1->weakpointer = &child1;
+ touchBeginEvent.ignore();
+ res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
+ QVERIFY(res && touchBeginEvent.isAccepted() && !child1);
+ touchUpdateEvent.ignore();
+ res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
+ QVERIFY(res && touchUpdateEvent.isAccepted() && !child1);
+ touchEndEvent.ignore();
+ res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
+ QVERIFY(res && touchUpdateEvent.isAccepted() && !child1);
+
+ child2->weakpointer = &child2;
+ touchBeginEvent.ignore();
+ res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
+ QVERIFY(res && touchBeginEvent.isAccepted() && child2);
+ touchUpdateEvent.ignore();
+ res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
+ QVERIFY(res && !touchUpdateEvent.isAccepted() && !child2);
+ touchEndEvent.ignore();
+ res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
+ QVERIFY(res && !touchUpdateEvent.isAccepted() && !child2);
+
+ child3->weakpointer = &child3;
+ res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
+ QVERIFY(res && touchBeginEvent.isAccepted() && child3);
+ res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
+ QVERIFY(res && !touchUpdateEvent.isAccepted() && child3);
+ res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
+ QVERIFY(res && !touchEndEvent.isAccepted() && !child3);
+
+ delete root;
+ }
+}
+
+void tst_QTouchEvent::deleteInRawEventTranslation()
+{
+ tst_QTouchEventWidget touchWidget;
+ touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
+ touchWidget.setGeometry(100, 100, 300, 300);
+
+ tst_QTouchEventWidget *leftWidget = new tst_QTouchEventWidget;
+ leftWidget->setParent(&touchWidget);
+ leftWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ leftWidget->setGeometry(0, 100, 100, 100);
+ leftWidget->deleteInTouchBegin = true;
+ leftWidget->show();
+
+ tst_QTouchEventWidget *centerWidget = new tst_QTouchEventWidget;
+ centerWidget->setParent(&touchWidget);
+ centerWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ centerWidget->setGeometry(100, 100, 100, 100);
+ centerWidget->deleteInTouchUpdate = true;
+ centerWidget->show();
+
+ tst_QTouchEventWidget *rightWidget = new tst_QTouchEventWidget;
+ rightWidget->setParent(&touchWidget);
+ rightWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ rightWidget->setGeometry(200, 100, 100, 100);
+ rightWidget->deleteInTouchEnd = true;
+ rightWidget->show();
+
+ QPointF leftPos = leftWidget->rect().center();
+ QPointF centerPos = centerWidget->rect().center();
+ QPointF rightPos = rightWidget->rect().center();
+ QPointF leftScreenPos = leftWidget->mapToGlobal(leftPos.toPoint());
+ QPointF centerScreenPos = centerWidget->mapToGlobal(centerPos.toPoint());
+ QPointF rightScreenPos = rightWidget->mapToGlobal(rightPos.toPoint());
+ QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+
+ QWeakPointer<QWidget> pl = leftWidget, pc = centerWidget, pr = rightWidget;
+
+ QList<QTouchEvent::TouchPoint> rawTouchPoints;
+ rawTouchPoints.append(QTouchEvent::TouchPoint(0));
+ rawTouchPoints.append(QTouchEvent::TouchPoint(1));
+ rawTouchPoints.append(QTouchEvent::TouchPoint(2));
+ rawTouchPoints[0].setState(Qt::TouchPointPressed);
+ rawTouchPoints[0].setScreenPos(leftScreenPos);
+ rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
+ rawTouchPoints[1].setState(Qt::TouchPointPressed);
+ rawTouchPoints[1].setScreenPos(centerScreenPos);
+ rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
+ rawTouchPoints[2].setState(Qt::TouchPointPressed);
+ rawTouchPoints[2].setScreenPos(rightScreenPos);
+ rawTouchPoints[2].setNormalizedPos(normalized(rawTouchPoints[2].pos(), screenGeometry));
+
+ // generate begin events on all widgets, the left widget should die
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchScreen, rawTouchPoints);
+ QVERIFY(pl.isNull() && !pc.isNull() && !pr.isNull());
+
+ // generate update events on all widget, the center widget should die
+ rawTouchPoints[0].setState(Qt::TouchPointMoved);
+ rawTouchPoints[1].setState(Qt::TouchPointMoved);
+ rawTouchPoints[2].setState(Qt::TouchPointMoved);
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchScreen, rawTouchPoints);
+
+ // generate end events on all widget, the right widget should die
+ rawTouchPoints[0].setState(Qt::TouchPointReleased);
+ rawTouchPoints[1].setState(Qt::TouchPointReleased);
+ rawTouchPoints[2].setState(Qt::TouchPointReleased);
+ qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchScreen, rawTouchPoints);
+}
+
+void tst_QTouchEvent::crashInQGraphicsSceneAfterNotHandlingTouchBegin()
+{
+ QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
+ rect->setAcceptTouchEvents(true);
+
+ QGraphicsRectItem *mainRect = new QGraphicsRectItem(0, 0, 100, 100, rect);
+ mainRect->setBrush(Qt::lightGray);
+
+ QGraphicsRectItem *button = new QGraphicsRectItem(-20, -20, 40, 40, mainRect);
+ button->setPos(50, 50);
+ button->setBrush(Qt::darkGreen);
+
+ QGraphicsView view;
+ QGraphicsScene scene;
+ scene.addItem(rect);
+ scene.setSceneRect(0,0,100,100);
+ view.setScene(&scene);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QPoint centerPos = view.mapFromScene(rect->boundingRect().center());
+ // Touch the button
+ QTest::touchEvent(view.viewport()).press(0, centerPos);
+ QTest::touchEvent(view.viewport()).release(0, centerPos);
+ // Touch outside of the button
+ QTest::touchEvent(view.viewport()).press(0, view.mapFromScene(QPoint(10, 10)));
+ QTest::touchEvent(view.viewport()).release(0, view.mapFromScene(QPoint(10, 10)));
+}
+
+void tst_QTouchEvent::touchBeginWithGraphicsWidget()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ tst_QTouchEventGraphicsItem *root;
+ root = new tst_QTouchEventGraphicsItem;
+ root->setAcceptTouchEvents(true);
+ scene.addItem(root);
+
+ QGraphicsWidget *glassWidget = new QGraphicsWidget;
+ glassWidget->setMinimumSize(100, 100);
+ scene.addItem(glassWidget);
+
+ view.resize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.fitInView(scene.sceneRect());
+
+ QTest::touchEvent()
+ .press(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport());
+ QTest::touchEvent()
+ .stationary(0)
+ .press(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
+ QTest::touchEvent()
+ .release(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport())
+ .release(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
+
+ QCOMPARE(root->touchBeginCounter, 1);
+ QCOMPARE(root->touchUpdateCounter, 1);
+ QCOMPARE(root->touchEndCounter, 1);
+ QCOMPARE(root->touchUpdatePoints.size(), 2);
+
+ root->reset();
+ glassWidget->setWindowFlags(Qt::Window); // make the glassWidget a panel
+
+ QTest::touchEvent()
+ .press(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport());
+ QTest::touchEvent()
+ .stationary(0)
+ .press(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
+ QTest::touchEvent()
+ .release(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport())
+ .release(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
+
+ QCOMPARE(root->touchBeginCounter, 0);
+ QCOMPARE(root->touchUpdateCounter, 0);
+ QCOMPARE(root->touchEndCounter, 0);
+
+
+ delete root;
+ delete glassWidget;
+}
+
+QTEST_MAIN(tst_QTouchEvent)
+
+#include "tst_qtouchevent.moc"
diff --git a/tests/auto/gui/math3d/math3d.pro b/tests/auto/gui/math3d/math3d.pro
new file mode 100644
index 0000000000..d977afa6e0
--- /dev/null
+++ b/tests/auto/gui/math3d/math3d.pro
@@ -0,0 +1,6 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qquaternion \
+ qvectornd \
+ qmatrixnxn \
+
diff --git a/tests/auto/gui/math3d/qmatrixnxn/qmatrixnxn.pro b/tests/auto/gui/math3d/qmatrixnxn/qmatrixnxn.pro
new file mode 100644
index 0000000000..cf6e4a128e
--- /dev/null
+++ b/tests/auto/gui/math3d/qmatrixnxn/qmatrixnxn.pro
@@ -0,0 +1,2 @@
+load(qttest_p4)
+SOURCES += tst_qmatrixnxn.cpp
diff --git a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
new file mode 100644
index 0000000000..98a559af85
--- /dev/null
+++ b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
@@ -0,0 +1,3385 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qmath.h>
+#include <QtGui/qmatrix4x4.h>
+
+class tst_QMatrixNxN : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMatrixNxN() {}
+ ~tst_QMatrixNxN() {}
+
+private slots:
+ void create2x2();
+ void create3x3();
+ void create4x4();
+ void create4x3();
+
+ void isIdentity2x2();
+ void isIdentity3x3();
+ void isIdentity4x4();
+ void isIdentity4x3();
+
+ void compare2x2();
+ void compare3x3();
+ void compare4x4();
+ void compare4x3();
+
+ void transposed2x2();
+ void transposed3x3();
+ void transposed4x4();
+ void transposed4x3();
+
+ void add2x2_data();
+ void add2x2();
+ void add3x3_data();
+ void add3x3();
+ void add4x4_data();
+ void add4x4();
+ void add4x3_data();
+ void add4x3();
+
+ void subtract2x2_data();
+ void subtract2x2();
+ void subtract3x3_data();
+ void subtract3x3();
+ void subtract4x4_data();
+ void subtract4x4();
+ void subtract4x3_data();
+ void subtract4x3();
+
+ void multiply2x2_data();
+ void multiply2x2();
+ void multiply3x3_data();
+ void multiply3x3();
+ void multiply4x4_data();
+ void multiply4x4();
+ void multiply4x3_data();
+ void multiply4x3();
+
+ void multiplyFactor2x2_data();
+ void multiplyFactor2x2();
+ void multiplyFactor3x3_data();
+ void multiplyFactor3x3();
+ void multiplyFactor4x4_data();
+ void multiplyFactor4x4();
+ void multiplyFactor4x3_data();
+ void multiplyFactor4x3();
+
+ void divideFactor2x2_data();
+ void divideFactor2x2();
+ void divideFactor3x3_data();
+ void divideFactor3x3();
+ void divideFactor4x4_data();
+ void divideFactor4x4();
+ void divideFactor4x3_data();
+ void divideFactor4x3();
+
+ void negate2x2_data();
+ void negate2x2();
+ void negate3x3_data();
+ void negate3x3();
+ void negate4x4_data();
+ void negate4x4();
+ void negate4x3_data();
+ void negate4x3();
+
+ void inverted4x4_data();
+ void inverted4x4();
+
+ void orthonormalInverse4x4();
+
+ void scale4x4_data();
+ void scale4x4();
+
+ void translate4x4_data();
+ void translate4x4();
+
+ void rotate4x4_data();
+ void rotate4x4();
+
+ void normalMatrix_data();
+ void normalMatrix();
+
+ void optimizedTransforms();
+
+ void ortho();
+ void frustum();
+ void perspective();
+ void flipCoordinates();
+
+ void convertGeneric();
+
+ void optimize_data();
+ void optimize();
+
+ void columnsAndRows();
+
+ void convertQMatrix();
+ void convertQTransform();
+
+ void fill();
+
+ void mapRect_data();
+ void mapRect();
+
+ void mapVector_data();
+ void mapVector();
+
+ void properties();
+ void metaTypes();
+
+private:
+ static void setMatrix(QMatrix2x2& m, const qreal *values);
+ static void setMatrixDirect(QMatrix2x2& m, const qreal *values);
+ static bool isSame(const QMatrix2x2& m, const qreal *values);
+ static bool isIdentity(const QMatrix2x2& m);
+
+ static void setMatrix(QMatrix3x3& m, const qreal *values);
+ static void setMatrixDirect(QMatrix3x3& m, const qreal *values);
+ static bool isSame(const QMatrix3x3& m, const qreal *values);
+ static bool isIdentity(const QMatrix3x3& m);
+
+ static void setMatrix(QMatrix4x4& m, const qreal *values);
+ static void setMatrixDirect(QMatrix4x4& m, const qreal *values);
+ static bool isSame(const QMatrix4x4& m, const qreal *values);
+ static bool isIdentity(const QMatrix4x4& m);
+
+ static void setMatrix(QMatrix4x3& m, const qreal *values);
+ static void setMatrixDirect(QMatrix4x3& m, const qreal *values);
+ static bool isSame(const QMatrix4x3& m, const qreal *values);
+ static bool isIdentity(const QMatrix4x3& m);
+};
+
+static const qreal nullValues2[] =
+ {0.0f, 0.0f,
+ 0.0f, 0.0f};
+
+static qreal const identityValues2[16] =
+ {1.0f, 0.0f,
+ 0.0f, 1.0f};
+
+static const qreal doubleIdentity2[] =
+ {2.0f, 0.0f,
+ 0.0f, 2.0f};
+
+static qreal const uniqueValues2[16] =
+ {1.0f, 2.0f,
+ 5.0f, 6.0f};
+
+static qreal const transposedValues2[16] =
+ {1.0f, 5.0f,
+ 2.0f, 6.0f};
+
+static const qreal nullValues3[] =
+ {0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f};
+
+static qreal const identityValues3[16] =
+ {1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f};
+
+static const qreal doubleIdentity3[] =
+ {2.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f};
+
+static qreal const uniqueValues3[16] =
+ {1.0f, 2.0f, 3.0f,
+ 5.0f, 6.0f, 7.0f,
+ 9.0f, 10.0f, 11.0f};
+
+static qreal const transposedValues3[16] =
+ {1.0f, 5.0f, 9.0f,
+ 2.0f, 6.0f, 10.0f,
+ 3.0f, 7.0f, 11.0f};
+
+static const qreal nullValues4[] =
+ {0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f};
+
+static qreal const identityValues4[16] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+
+static const qreal doubleIdentity4[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 2.0f};
+
+static qreal const uniqueValues4[16] =
+ {1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f,
+ 13.0f, 14.0f, 15.0f, 16.0f};
+
+static qreal const transposedValues4[16] =
+ {1.0f, 5.0f, 9.0f, 13.0f,
+ 2.0f, 6.0f, 10.0f, 14.0f,
+ 3.0f, 7.0f, 11.0f, 15.0f,
+ 4.0f, 8.0f, 12.0f, 16.0f};
+
+static const qreal nullValues4x3[] =
+ {0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f};
+
+static qreal const identityValues4x3[12] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f};
+
+static qreal const doubleIdentity4x3[12] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f, 0.0f};
+
+static qreal const uniqueValues4x3[12] =
+ {1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f};
+
+static qreal const transposedValues3x4[12] =
+ {1.0f, 5.0f, 9.0f,
+ 2.0f, 6.0f, 10.0f,
+ 3.0f, 7.0f, 11.0f,
+ 4.0f, 8.0f, 12.0f};
+
+// Set a matrix to a specified array of values, which are assumed
+// to be in row-major order. This sets the values using floating-point.
+void tst_QMatrixNxN::setMatrix(QMatrix2x2& m, const qreal *values)
+{
+ for (int row = 0; row < 2; ++row)
+ for (int col = 0; col < 2; ++col)
+ m(row, col) = values[row * 2 + col];
+}
+void tst_QMatrixNxN::setMatrix(QMatrix3x3& m, const qreal *values)
+{
+ for (int row = 0; row < 3; ++row)
+ for (int col = 0; col < 3; ++col)
+ m(row, col) = values[row * 3 + col];
+}
+void tst_QMatrixNxN::setMatrix(QMatrix4x4& m, const qreal *values)
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ m(row, col) = values[row * 4 + col];
+}
+void tst_QMatrixNxN::setMatrix(QMatrix4x3& m, const qreal *values)
+{
+ for (int row = 0; row < 3; ++row)
+ for (int col = 0; col < 4; ++col)
+ m(row, col) = values[row * 4 + col];
+}
+
+// Set a matrix to a specified array of values, which are assumed
+// to be in row-major order. This sets the values directly into
+// the internal data() array.
+void tst_QMatrixNxN::setMatrixDirect(QMatrix2x2& m, const qreal *values)
+{
+ qreal *data = m.data();
+ for (int row = 0; row < 2; ++row) {
+ for (int col = 0; col < 2; ++col) {
+ data[row + col * 2] = values[row * 2 + col];
+ }
+ }
+}
+void tst_QMatrixNxN::setMatrixDirect(QMatrix3x3& m, const qreal *values)
+{
+ qreal *data = m.data();
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ data[row + col * 3] = values[row * 3 + col];
+ }
+ }
+}
+void tst_QMatrixNxN::setMatrixDirect(QMatrix4x4& m, const qreal *values)
+{
+ qreal *data = m.data();
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ data[row + col * 4] = values[row * 4 + col];
+ }
+ }
+}
+void tst_QMatrixNxN::setMatrixDirect(QMatrix4x3& m, const qreal *values)
+{
+ qreal *data = m.data();
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ data[row + col * 3] = values[row * 4 + col];
+ }
+ }
+}
+
+// QVector2/3/4D use float internally, which can sometimes lead
+// to precision issues when converting to and from qreal during
+// operations involving QMatrix4x4. This fuzzy compare is slightly
+// "fuzzier" than the default qFuzzyCompare for qreal to compensate.
+static bool fuzzyCompare(qreal x, qreal y)
+{
+ return qFuzzyIsNull((float)(x - y));
+}
+
+static bool fuzzyCompare(const QVector3D &v1, const QVector3D &v2)
+{
+ if (!fuzzyCompare(v1.x(), v2.x()))
+ return false;
+ if (!fuzzyCompare(v1.y(), v2.y()))
+ return false;
+ if (!fuzzyCompare(v1.z(), v2.z()))
+ return false;
+ return true;
+}
+
+// Determine if a matrix is the same as a specified array of values.
+// The values are assumed to be specified in row-major order.
+bool tst_QMatrixNxN::isSame(const QMatrix2x2& m, const qreal *values)
+{
+ const qreal *mv = m.constData();
+ for (int row = 0; row < 2; ++row) {
+ for (int col = 0; col < 2; ++col) {
+ // Check the values using the operator() function.
+ if (!fuzzyCompare(m(row, col), values[row * 2 + col])) {
+ qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 2 + col];
+ return false;
+ }
+
+ // Check the values using direct access, which verifies that the values
+ // are stored internally in column-major order.
+ if (!fuzzyCompare(mv[col * 2 + row], values[row * 2 + col])) {
+ qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 2 + row] << "expected =" << values[row * 2 + col];
+ return false;
+ }
+ }
+ }
+ return true;
+}
+bool tst_QMatrixNxN::isSame(const QMatrix3x3& m, const qreal *values)
+{
+ const qreal *mv = m.constData();
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ // Check the values using the operator() access function.
+ if (!fuzzyCompare(m(row, col), values[row * 3 + col])) {
+ qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 3 + col];
+ return false;
+ }
+
+ // Check the values using direct access, which verifies that the values
+ // are stored internally in column-major order.
+ if (!fuzzyCompare(mv[col * 3 + row], values[row * 3 + col])) {
+ qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 3 + row] << "expected =" << values[row * 3 + col];
+ return false;
+ }
+ }
+ }
+ return true;
+}
+bool tst_QMatrixNxN::isSame(const QMatrix4x4& m, const qreal *values)
+{
+ const qreal *mv = m.constData();
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ // Check the values using the operator() access function.
+ if (!fuzzyCompare(m(row, col), values[row * 4 + col])) {
+ qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 4 + col];
+ return false;
+ }
+
+ // Check the values using direct access, which verifies that the values
+ // are stored internally in column-major order.
+ if (!fuzzyCompare(mv[col * 4 + row], values[row * 4 + col])) {
+ qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 4 + row] << "expected =" << values[row * 4 + col];
+ return false;
+ }
+ }
+ }
+ return true;
+}
+bool tst_QMatrixNxN::isSame(const QMatrix4x3& m, const qreal *values)
+{
+ const qreal *mv = m.constData();
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ // Check the values using the operator() access function.
+ if (!fuzzyCompare(m(row, col), values[row * 4 + col])) {
+ qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 4 + col];
+ return false;
+ }
+
+ // Check the values using direct access, which verifies that the values
+ // are stored internally in column-major order.
+ if (!fuzzyCompare(mv[col * 3 + row], values[row * 4 + col])) {
+ qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 3 + row] << "expected =" << values[row * 4 + col];
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// Determine if a matrix is the identity.
+bool tst_QMatrixNxN::isIdentity(const QMatrix2x2& m)
+{
+ return isSame(m, identityValues2);
+}
+bool tst_QMatrixNxN::isIdentity(const QMatrix3x3& m)
+{
+ return isSame(m, identityValues3);
+}
+bool tst_QMatrixNxN::isIdentity(const QMatrix4x4& m)
+{
+ return isSame(m, identityValues4);
+}
+bool tst_QMatrixNxN::isIdentity(const QMatrix4x3& m)
+{
+ return isSame(m, identityValues4x3);
+}
+
+// Test the creation of QMatrix2x2 objects in various ways:
+// construct, copy, and modify.
+void tst_QMatrixNxN::create2x2()
+{
+ QMatrix2x2 m1;
+ QVERIFY(isIdentity(m1));
+ QVERIFY(m1.isIdentity());
+
+ QMatrix2x2 m2;
+ setMatrix(m2, uniqueValues2);
+ QVERIFY(isSame(m2, uniqueValues2));
+ QVERIFY(!m2.isIdentity());
+
+ QMatrix2x2 m3;
+ setMatrixDirect(m3, uniqueValues2);
+ QVERIFY(isSame(m3, uniqueValues2));
+
+ QMatrix2x2 m4(m3);
+ QVERIFY(isSame(m4, uniqueValues2));
+
+ QMatrix2x2 m5;
+ m5 = m3;
+ QVERIFY(isSame(m5, uniqueValues2));
+
+ m5.setToIdentity();
+ QVERIFY(isIdentity(m5));
+
+ QMatrix2x2 m6(uniqueValues2);
+ QVERIFY(isSame(m6, uniqueValues2));
+ qreal vals[4];
+ m6.copyDataTo(vals);
+ for (int index = 0; index < 4; ++index)
+ QCOMPARE(vals[index], uniqueValues2[index]);
+}
+
+// Test the creation of QMatrix3x3 objects in various ways:
+// construct, copy, and modify.
+void tst_QMatrixNxN::create3x3()
+{
+ QMatrix3x3 m1;
+ QVERIFY(isIdentity(m1));
+ QVERIFY(m1.isIdentity());
+
+ QMatrix3x3 m2;
+ setMatrix(m2, uniqueValues3);
+ QVERIFY(isSame(m2, uniqueValues3));
+ QVERIFY(!m2.isIdentity());
+
+ QMatrix3x3 m3;
+ setMatrixDirect(m3, uniqueValues3);
+ QVERIFY(isSame(m3, uniqueValues3));
+
+ QMatrix3x3 m4(m3);
+ QVERIFY(isSame(m4, uniqueValues3));
+
+ QMatrix3x3 m5;
+ m5 = m3;
+ QVERIFY(isSame(m5, uniqueValues3));
+
+ m5.setToIdentity();
+ QVERIFY(isIdentity(m5));
+
+ QMatrix3x3 m6(uniqueValues3);
+ QVERIFY(isSame(m6, uniqueValues3));
+ qreal vals[9];
+ m6.copyDataTo(vals);
+ for (int index = 0; index < 9; ++index)
+ QCOMPARE(vals[index], uniqueValues3[index]);
+}
+
+// Test the creation of QMatrix4x4 objects in various ways:
+// construct, copy, and modify.
+void tst_QMatrixNxN::create4x4()
+{
+ QMatrix4x4 m1;
+ QVERIFY(isIdentity(m1));
+ QVERIFY(m1.isIdentity());
+
+ QMatrix4x4 m2;
+ setMatrix(m2, uniqueValues4);
+ QVERIFY(isSame(m2, uniqueValues4));
+ QVERIFY(!m2.isIdentity());
+
+ QMatrix4x4 m3;
+ setMatrixDirect(m3, uniqueValues4);
+ QVERIFY(isSame(m3, uniqueValues4));
+
+ QMatrix4x4 m4(m3);
+ QVERIFY(isSame(m4, uniqueValues4));
+
+ QMatrix4x4 m5;
+ m5 = m3;
+ QVERIFY(isSame(m5, uniqueValues4));
+
+ m5.setToIdentity();
+ QVERIFY(isIdentity(m5));
+
+ QMatrix4x4 m6(uniqueValues4);
+ QVERIFY(isSame(m6, uniqueValues4));
+ qreal vals[16];
+ m6.copyDataTo(vals);
+ for (int index = 0; index < 16; ++index)
+ QCOMPARE(vals[index], uniqueValues4[index]);
+
+ QMatrix4x4 m8
+ (uniqueValues4[0], uniqueValues4[1], uniqueValues4[2], uniqueValues4[3],
+ uniqueValues4[4], uniqueValues4[5], uniqueValues4[6], uniqueValues4[7],
+ uniqueValues4[8], uniqueValues4[9], uniqueValues4[10], uniqueValues4[11],
+ uniqueValues4[12], uniqueValues4[13], uniqueValues4[14], uniqueValues4[15]);
+ QVERIFY(isSame(m8, uniqueValues4));
+}
+
+// Test the creation of QMatrix4x3 objects in various ways:
+// construct, copy, and modify.
+void tst_QMatrixNxN::create4x3()
+{
+ QMatrix4x3 m1;
+ QVERIFY(isIdentity(m1));
+ QVERIFY(m1.isIdentity());
+
+ QMatrix4x3 m2;
+ setMatrix(m2, uniqueValues4x3);
+ QVERIFY(isSame(m2, uniqueValues4x3));
+ QVERIFY(!m2.isIdentity());
+
+ QMatrix4x3 m3;
+ setMatrixDirect(m3, uniqueValues4x3);
+ QVERIFY(isSame(m3, uniqueValues4x3));
+
+ QMatrix4x3 m4(m3);
+ QVERIFY(isSame(m4, uniqueValues4x3));
+
+ QMatrix4x3 m5;
+ m5 = m3;
+ QVERIFY(isSame(m5, uniqueValues4x3));
+
+ m5.setToIdentity();
+ QVERIFY(isIdentity(m5));
+
+ QMatrix4x3 m6(uniqueValues4x3);
+ QVERIFY(isSame(m6, uniqueValues4x3));
+ qreal vals[12];
+ m6.copyDataTo(vals);
+ for (int index = 0; index < 12; ++index)
+ QCOMPARE(vals[index], uniqueValues4x3[index]);
+}
+
+// Test isIdentity() for 2x2 matrices.
+void tst_QMatrixNxN::isIdentity2x2()
+{
+ for (int i = 0; i < 2 * 2; ++i) {
+ QMatrix2x2 m;
+ QVERIFY(m.isIdentity());
+ m.data()[i] = 42.0f;
+ QVERIFY(!m.isIdentity());
+ }
+}
+
+// Test isIdentity() for 3x3 matrices.
+void tst_QMatrixNxN::isIdentity3x3()
+{
+ for (int i = 0; i < 3 * 3; ++i) {
+ QMatrix3x3 m;
+ QVERIFY(m.isIdentity());
+ m.data()[i] = 42.0f;
+ QVERIFY(!m.isIdentity());
+ }
+}
+
+// Test isIdentity() for 4x4 matrices.
+void tst_QMatrixNxN::isIdentity4x4()
+{
+ for (int i = 0; i < 4 * 4; ++i) {
+ QMatrix4x4 m;
+ QVERIFY(m.isIdentity());
+ m.data()[i] = 42.0f;
+ QVERIFY(!m.isIdentity());
+ }
+
+ // Force the "Identity" flag bit to be lost and check again.
+ QMatrix4x4 m2;
+ m2.data()[0] = 1.0f;
+ QVERIFY(m2.isIdentity());
+}
+
+// Test isIdentity() for 4x3 matrices.
+void tst_QMatrixNxN::isIdentity4x3()
+{
+ for (int i = 0; i < 4 * 3; ++i) {
+ QMatrix4x3 m;
+ QVERIFY(m.isIdentity());
+ m.data()[i] = 42.0f;
+ QVERIFY(!m.isIdentity());
+ }
+}
+
+// Test 2x2 matrix comparisons.
+void tst_QMatrixNxN::compare2x2()
+{
+ QMatrix2x2 m1(uniqueValues2);
+ QMatrix2x2 m2(uniqueValues2);
+ QMatrix2x2 m3(transposedValues2);
+
+ QVERIFY(m1 == m2);
+ QVERIFY(!(m1 != m2));
+ QVERIFY(m1 != m3);
+ QVERIFY(!(m1 == m3));
+}
+
+// Test 3x3 matrix comparisons.
+void tst_QMatrixNxN::compare3x3()
+{
+ QMatrix3x3 m1(uniqueValues3);
+ QMatrix3x3 m2(uniqueValues3);
+ QMatrix3x3 m3(transposedValues3);
+
+ QVERIFY(m1 == m2);
+ QVERIFY(!(m1 != m2));
+ QVERIFY(m1 != m3);
+ QVERIFY(!(m1 == m3));
+}
+
+// Test 4x4 matrix comparisons.
+void tst_QMatrixNxN::compare4x4()
+{
+ QMatrix4x4 m1(uniqueValues4);
+ QMatrix4x4 m2(uniqueValues4);
+ QMatrix4x4 m3(transposedValues4);
+
+ QVERIFY(m1 == m2);
+ QVERIFY(!(m1 != m2));
+ QVERIFY(m1 != m3);
+ QVERIFY(!(m1 == m3));
+}
+
+// Test 4x3 matrix comparisons.
+void tst_QMatrixNxN::compare4x3()
+{
+ QMatrix4x3 m1(uniqueValues4x3);
+ QMatrix4x3 m2(uniqueValues4x3);
+ QMatrix4x3 m3(transposedValues3x4);
+
+ QVERIFY(m1 == m2);
+ QVERIFY(!(m1 != m2));
+ QVERIFY(m1 != m3);
+ QVERIFY(!(m1 == m3));
+}
+
+// Test matrix 2x2 transpose operations.
+void tst_QMatrixNxN::transposed2x2()
+{
+ // Transposing the identity should result in the identity.
+ QMatrix2x2 m1;
+ QMatrix2x2 m2 = m1.transposed();
+ QVERIFY(isIdentity(m2));
+
+ // Transpose a more interesting matrix that allows us to track
+ // exactly where each source element ends up.
+ QMatrix2x2 m3(uniqueValues2);
+ QMatrix2x2 m4 = m3.transposed();
+ QVERIFY(isSame(m4, transposedValues2));
+
+ // Transpose in-place, just to check that the compiler is sane.
+ m3 = m3.transposed();
+ QVERIFY(isSame(m3, transposedValues2));
+}
+
+// Test matrix 3x3 transpose operations.
+void tst_QMatrixNxN::transposed3x3()
+{
+ // Transposing the identity should result in the identity.
+ QMatrix3x3 m1;
+ QMatrix3x3 m2 = m1.transposed();
+ QVERIFY(isIdentity(m2));
+
+ // Transpose a more interesting matrix that allows us to track
+ // exactly where each source element ends up.
+ QMatrix3x3 m3(uniqueValues3);
+ QMatrix3x3 m4 = m3.transposed();
+ QVERIFY(isSame(m4, transposedValues3));
+
+ // Transpose in-place, just to check that the compiler is sane.
+ m3 = m3.transposed();
+ QVERIFY(isSame(m3, transposedValues3));
+}
+
+// Test matrix 4x4 transpose operations.
+void tst_QMatrixNxN::transposed4x4()
+{
+ // Transposing the identity should result in the identity.
+ QMatrix4x4 m1;
+ QMatrix4x4 m2 = m1.transposed();
+ QVERIFY(isIdentity(m2));
+
+ // Transpose a more interesting matrix that allows us to track
+ // exactly where each source element ends up.
+ QMatrix4x4 m3(uniqueValues4);
+ QMatrix4x4 m4 = m3.transposed();
+ QVERIFY(isSame(m4, transposedValues4));
+
+ // Transpose in-place, just to check that the compiler is sane.
+ m3 = m3.transposed();
+ QVERIFY(isSame(m3, transposedValues4));
+}
+
+// Test matrix 4x3 transpose operations.
+void tst_QMatrixNxN::transposed4x3()
+{
+ QMatrix4x3 m3(uniqueValues4x3);
+ QMatrix3x4 m4 = m3.transposed();
+ qreal values[12];
+ m4.copyDataTo(values);
+ for (int index = 0; index < 12; ++index)
+ QCOMPARE(values[index], transposedValues3x4[index]);
+}
+
+// Test matrix addition for 2x2 matrices.
+void tst_QMatrixNxN::add2x2_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues2 << (void *)nullValues2 << (void *)nullValues2;
+
+ QTest::newRow("identity/null")
+ << (void *)identityValues2 << (void *)nullValues2 << (void *)identityValues2;
+
+ QTest::newRow("identity/identity")
+ << (void *)identityValues2 << (void *)identityValues2 << (void *)doubleIdentity2;
+
+ static qreal const sumValues[16] =
+ {2.0f, 7.0f,
+ 7.0f, 12.0f};
+ QTest::newRow("unique")
+ << (void *)uniqueValues2 << (void *)transposedValues2 << (void *)sumValues;
+}
+void tst_QMatrixNxN::add2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix2x2 m1((const qreal *)m1Values);
+ QMatrix2x2 m2((const qreal *)m2Values);
+
+ QMatrix2x2 m4(m1);
+ m4 += m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix2x2 m5;
+ m5 = m1 + m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix addition for 3x3 matrices.
+void tst_QMatrixNxN::add3x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues3 << (void *)nullValues3 << (void *)nullValues3;
+
+ QTest::newRow("identity/null")
+ << (void *)identityValues3 << (void *)nullValues3 << (void *)identityValues3;
+
+ QTest::newRow("identity/identity")
+ << (void *)identityValues3 << (void *)identityValues3 << (void *)doubleIdentity3;
+
+ static qreal const sumValues[16] =
+ {2.0f, 7.0f, 12.0f,
+ 7.0f, 12.0f, 17.0f,
+ 12.0f, 17.0f, 22.0f};
+ QTest::newRow("unique")
+ << (void *)uniqueValues3 << (void *)transposedValues3 << (void *)sumValues;
+}
+void tst_QMatrixNxN::add3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix3x3 m1((const qreal *)m1Values);
+ QMatrix3x3 m2((const qreal *)m2Values);
+
+ QMatrix3x3 m4(m1);
+ m4 += m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix3x3 m5;
+ m5 = m1 + m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix addition for 4x4 matrices.
+void tst_QMatrixNxN::add4x4_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (void *)nullValues4 << (void *)nullValues4;
+
+ QTest::newRow("identity/null")
+ << (void *)identityValues4 << (void *)nullValues4 << (void *)identityValues4;
+
+ QTest::newRow("identity/identity")
+ << (void *)identityValues4 << (void *)identityValues4 << (void *)doubleIdentity4;
+
+ static qreal const sumValues[16] =
+ {2.0f, 7.0f, 12.0f, 17.0f,
+ 7.0f, 12.0f, 17.0f, 22.0f,
+ 12.0f, 17.0f, 22.0f, 27.0f,
+ 17.0f, 22.0f, 27.0f, 32.0f};
+ QTest::newRow("unique")
+ << (void *)uniqueValues4 << (void *)transposedValues4 << (void *)sumValues;
+}
+void tst_QMatrixNxN::add4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+ QMatrix4x4 m2((const qreal *)m2Values);
+
+ QMatrix4x4 m4(m1);
+ m4 += m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix4x4 m5;
+ m5 = m1 + m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix addition for 4x3 matrices.
+void tst_QMatrixNxN::add4x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4x3 << (void *)nullValues4x3 << (void *)nullValues4x3;
+
+ QTest::newRow("identity/null")
+ << (void *)identityValues4x3 << (void *)nullValues4x3 << (void *)identityValues4x3;
+
+ QTest::newRow("identity/identity")
+ << (void *)identityValues4x3 << (void *)identityValues4x3 << (void *)doubleIdentity4x3;
+
+ static qreal const sumValues[16] =
+ {2.0f, 7.0f, 12.0f, 6.0f,
+ 11.0f, 16.0f, 10.0f, 15.0f,
+ 20.0f, 14.0f, 19.0f, 24.0f};
+ QTest::newRow("unique")
+ << (void *)uniqueValues4x3 << (void *)transposedValues3x4 << (void *)sumValues;
+}
+void tst_QMatrixNxN::add4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x3 m1((const qreal *)m1Values);
+ QMatrix4x3 m2((const qreal *)m2Values);
+
+ QMatrix4x3 m4(m1);
+ m4 += m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix4x3 m5;
+ m5 = m1 + m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix subtraction for 2x2 matrices.
+void tst_QMatrixNxN::subtract2x2_data()
+{
+ // Use the same test cases as the add test.
+ add2x2_data();
+}
+void tst_QMatrixNxN::subtract2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix2x2 m1((const qreal *)m1Values);
+ QMatrix2x2 m2((const qreal *)m2Values);
+ QMatrix2x2 m3((const qreal *)m3Values);
+
+ QMatrix2x2 m4(m3);
+ m4 -= m1;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix2x2 m5;
+ m5 = m3 - m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+
+ QMatrix2x2 m6(m3);
+ m6 -= m2;
+ QVERIFY(isSame(m6, (const qreal *)m1Values));
+
+ QMatrix2x2 m7;
+ m7 = m3 - m2;
+ QVERIFY(isSame(m7, (const qreal *)m1Values));
+}
+
+// Test matrix subtraction for 3x3 matrices.
+void tst_QMatrixNxN::subtract3x3_data()
+{
+ // Use the same test cases as the add test.
+ add3x3_data();
+}
+void tst_QMatrixNxN::subtract3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix3x3 m1((const qreal *)m1Values);
+ QMatrix3x3 m2((const qreal *)m2Values);
+ QMatrix3x3 m3((const qreal *)m3Values);
+
+ QMatrix3x3 m4(m3);
+ m4 -= m1;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix3x3 m5;
+ m5 = m3 - m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+
+ QMatrix3x3 m6(m3);
+ m6 -= m2;
+ QVERIFY(isSame(m6, (const qreal *)m1Values));
+
+ QMatrix3x3 m7;
+ m7 = m3 - m2;
+ QVERIFY(isSame(m7, (const qreal *)m1Values));
+}
+
+// Test matrix subtraction for 4x4 matrices.
+void tst_QMatrixNxN::subtract4x4_data()
+{
+ // Use the same test cases as the add test.
+ add4x4_data();
+}
+void tst_QMatrixNxN::subtract4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+ QMatrix4x4 m2((const qreal *)m2Values);
+ QMatrix4x4 m3((const qreal *)m3Values);
+
+ QMatrix4x4 m4(m3);
+ m4 -= m1;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix4x4 m5;
+ m5 = m3 - m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+
+ QMatrix4x4 m6(m3);
+ m6 -= m2;
+ QVERIFY(isSame(m6, (const qreal *)m1Values));
+
+ QMatrix4x4 m7;
+ m7 = m3 - m2;
+ QVERIFY(isSame(m7, (const qreal *)m1Values));
+}
+
+// Test matrix subtraction for 4x3 matrices.
+void tst_QMatrixNxN::subtract4x3_data()
+{
+ // Use the same test cases as the add test.
+ add4x3_data();
+}
+void tst_QMatrixNxN::subtract4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x3 m1((const qreal *)m1Values);
+ QMatrix4x3 m2((const qreal *)m2Values);
+ QMatrix4x3 m3((const qreal *)m3Values);
+
+ QMatrix4x3 m4(m3);
+ m4 -= m1;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix4x3 m5;
+ m5 = m3 - m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+
+ QMatrix4x3 m6(m3);
+ m6 -= m2;
+ QVERIFY(isSame(m6, (const qreal *)m1Values));
+
+ QMatrix4x3 m7;
+ m7 = m3 - m2;
+ QVERIFY(isSame(m7, (const qreal *)m1Values));
+}
+
+// Test matrix multiplication for 2x2 matrices.
+void tst_QMatrixNxN::multiply2x2_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues2 << (void *)nullValues2 << (void *)nullValues2;
+
+ QTest::newRow("null/unique")
+ << (void *)nullValues2 << (void *)uniqueValues2 << (void *)nullValues2;
+
+ QTest::newRow("unique/null")
+ << (void *)uniqueValues2 << (void *)nullValues2 << (void *)nullValues2;
+
+ QTest::newRow("unique/identity")
+ << (void *)uniqueValues2 << (void *)identityValues2 << (void *)uniqueValues2;
+
+ QTest::newRow("identity/unique")
+ << (void *)identityValues2 << (void *)uniqueValues2 << (void *)uniqueValues2;
+
+ static qreal uniqueResult[4];
+ for (int row = 0; row < 2; ++row) {
+ for (int col = 0; col < 2; ++col) {
+ qreal sum = 0.0f;
+ for (int j = 0; j < 2; ++j)
+ sum += uniqueValues2[row * 2 + j] * transposedValues2[j * 2 + col];
+ uniqueResult[row * 2 + col] = sum;
+ }
+ }
+
+ QTest::newRow("unique/transposed")
+ << (void *)uniqueValues2 << (void *)transposedValues2 << (void *)uniqueResult;
+}
+void tst_QMatrixNxN::multiply2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix2x2 m1((const qreal *)m1Values);
+ QMatrix2x2 m2((const qreal *)m2Values);
+
+ QMatrix2x2 m5;
+ m5 = m1 * m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix multiplication for 3x3 matrices.
+void tst_QMatrixNxN::multiply3x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues3 << (void *)nullValues3 << (void *)nullValues3;
+
+ QTest::newRow("null/unique")
+ << (void *)nullValues3 << (void *)uniqueValues3 << (void *)nullValues3;
+
+ QTest::newRow("unique/null")
+ << (void *)uniqueValues3 << (void *)nullValues3 << (void *)nullValues3;
+
+ QTest::newRow("unique/identity")
+ << (void *)uniqueValues3 << (void *)identityValues3 << (void *)uniqueValues3;
+
+ QTest::newRow("identity/unique")
+ << (void *)identityValues3 << (void *)uniqueValues3 << (void *)uniqueValues3;
+
+ static qreal uniqueResult[9];
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ qreal sum = 0.0f;
+ for (int j = 0; j < 3; ++j)
+ sum += uniqueValues3[row * 3 + j] * transposedValues3[j * 3 + col];
+ uniqueResult[row * 3 + col] = sum;
+ }
+ }
+
+ QTest::newRow("unique/transposed")
+ << (void *)uniqueValues3 << (void *)transposedValues3 << (void *)uniqueResult;
+}
+void tst_QMatrixNxN::multiply3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix3x3 m1((const qreal *)m1Values);
+ QMatrix3x3 m2((const qreal *)m2Values);
+
+ QMatrix3x3 m5;
+ m5 = m1 * m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix multiplication for 4x4 matrices.
+void tst_QMatrixNxN::multiply4x4_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (void *)nullValues4 << (void *)nullValues4;
+
+ QTest::newRow("null/unique")
+ << (void *)nullValues4 << (void *)uniqueValues4 << (void *)nullValues4;
+
+ QTest::newRow("unique/null")
+ << (void *)uniqueValues4 << (void *)nullValues4 << (void *)nullValues4;
+
+ QTest::newRow("unique/identity")
+ << (void *)uniqueValues4 << (void *)identityValues4 << (void *)uniqueValues4;
+
+ QTest::newRow("identity/unique")
+ << (void *)identityValues4 << (void *)uniqueValues4 << (void *)uniqueValues4;
+
+ static qreal uniqueResult[16];
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ qreal sum = 0.0f;
+ for (int j = 0; j < 4; ++j)
+ sum += uniqueValues4[row * 4 + j] * transposedValues4[j * 4 + col];
+ uniqueResult[row * 4 + col] = sum;
+ }
+ }
+
+ QTest::newRow("unique/transposed")
+ << (void *)uniqueValues4 << (void *)transposedValues4 << (void *)uniqueResult;
+}
+void tst_QMatrixNxN::multiply4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+ QMatrix4x4 m2((const qreal *)m2Values);
+
+ QMatrix4x4 m4;
+ m4 = m1;
+ m4 *= m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix4x4 m5;
+ m5 = m1 * m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix multiplication for 4x3 matrices.
+void tst_QMatrixNxN::multiply4x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4x3 << (void *)nullValues4x3 << (void *)nullValues3;
+
+ QTest::newRow("null/unique")
+ << (void *)nullValues4x3 << (void *)uniqueValues4x3 << (void *)nullValues3;
+
+ QTest::newRow("unique/null")
+ << (void *)uniqueValues4x3 << (void *)nullValues4x3 << (void *)nullValues3;
+
+ static qreal uniqueResult[9];
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ qreal sum = 0.0f;
+ for (int j = 0; j < 4; ++j)
+ sum += uniqueValues4x3[row * 4 + j] * transposedValues3x4[j * 3 + col];
+ uniqueResult[row * 3 + col] = sum;
+ }
+ }
+
+ QTest::newRow("unique/transposed")
+ << (void *)uniqueValues4x3 << (void *)transposedValues3x4 << (void *)uniqueResult;
+}
+void tst_QMatrixNxN::multiply4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x3 m1((const qreal *)m1Values);
+ QMatrix3x4 m2((const qreal *)m2Values);
+
+ QGenericMatrix<3, 3, qreal> m4;
+ m4 = m1 * m2;
+ qreal values[9];
+ m4.copyDataTo(values);
+ for (int index = 0; index < 9; ++index)
+ QCOMPARE(values[index], ((const qreal *)m3Values)[index]);
+}
+
+// Test matrix multiplication by a factor for 2x2 matrices.
+void tst_QMatrixNxN::multiplyFactor2x2_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<void *>("m2Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues2 << (qreal)1.0f << (void *)nullValues2;
+
+ QTest::newRow("double identity")
+ << (void *)identityValues2 << (qreal)2.0f << (void *)doubleIdentity2;
+
+ static qreal const values[16] =
+ {1.0f, 2.0f,
+ 5.0f, 6.0f};
+ static qreal const doubleValues[16] =
+ {2.0f, 4.0f,
+ 10.0f, 12.0f};
+ static qreal const negDoubleValues[16] =
+ {-2.0f, -4.0f,
+ -10.0f, -12.0f};
+
+ QTest::newRow("unique")
+ << (void *)values << (qreal)2.0f << (void *)doubleValues;
+
+ QTest::newRow("neg")
+ << (void *)values << (qreal)-2.0f << (void *)negDoubleValues;
+
+ QTest::newRow("zero")
+ << (void *)values << (qreal)0.0f << (void *)nullValues4;
+}
+void tst_QMatrixNxN::multiplyFactor2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ QMatrix2x2 m1((const qreal *)m1Values);
+
+ QMatrix2x2 m3;
+ m3 = m1;
+ m3 *= factor;
+ QVERIFY(isSame(m3, (const qreal *)m2Values));
+
+ QMatrix2x2 m4;
+ m4 = m1 * factor;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix2x2 m5;
+ m5 = factor * m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+}
+
+// Test matrix multiplication by a factor for 3x3 matrices.
+void tst_QMatrixNxN::multiplyFactor3x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<void *>("m2Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues3 << (qreal)1.0f << (void *)nullValues3;
+
+ QTest::newRow("double identity")
+ << (void *)identityValues3 << (qreal)2.0f << (void *)doubleIdentity3;
+
+ static qreal const values[16] =
+ {1.0f, 2.0f, 3.0f,
+ 5.0f, 6.0f, 7.0f,
+ 9.0f, 10.0f, 11.0f};
+ static qreal const doubleValues[16] =
+ {2.0f, 4.0f, 6.0f,
+ 10.0f, 12.0f, 14.0f,
+ 18.0f, 20.0f, 22.0f};
+ static qreal const negDoubleValues[16] =
+ {-2.0f, -4.0f, -6.0f,
+ -10.0f, -12.0f, -14.0f,
+ -18.0f, -20.0f, -22.0f};
+
+ QTest::newRow("unique")
+ << (void *)values << (qreal)2.0f << (void *)doubleValues;
+
+ QTest::newRow("neg")
+ << (void *)values << (qreal)-2.0f << (void *)negDoubleValues;
+
+ QTest::newRow("zero")
+ << (void *)values << (qreal)0.0f << (void *)nullValues4;
+}
+void tst_QMatrixNxN::multiplyFactor3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ QMatrix3x3 m1((const qreal *)m1Values);
+
+ QMatrix3x3 m3;
+ m3 = m1;
+ m3 *= factor;
+ QVERIFY(isSame(m3, (const qreal *)m2Values));
+
+ QMatrix3x3 m4;
+ m4 = m1 * factor;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix3x3 m5;
+ m5 = factor * m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+}
+
+// Test matrix multiplication by a factor for 4x4 matrices.
+void tst_QMatrixNxN::multiplyFactor4x4_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<void *>("m2Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (qreal)1.0f << (void *)nullValues4;
+
+ QTest::newRow("double identity")
+ << (void *)identityValues4 << (qreal)2.0f << (void *)doubleIdentity4;
+
+ static qreal const values[16] =
+ {1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f,
+ 13.0f, 14.0f, 15.0f, 16.0f};
+ static qreal const doubleValues[16] =
+ {2.0f, 4.0f, 6.0f, 8.0f,
+ 10.0f, 12.0f, 14.0f, 16.0f,
+ 18.0f, 20.0f, 22.0f, 24.0f,
+ 26.0f, 28.0f, 30.0f, 32.0f};
+ static qreal const negDoubleValues[16] =
+ {-2.0f, -4.0f, -6.0f, -8.0f,
+ -10.0f, -12.0f, -14.0f, -16.0f,
+ -18.0f, -20.0f, -22.0f, -24.0f,
+ -26.0f, -28.0f, -30.0f, -32.0f};
+
+ QTest::newRow("unique")
+ << (void *)values << (qreal)2.0f << (void *)doubleValues;
+
+ QTest::newRow("neg")
+ << (void *)values << (qreal)-2.0f << (void *)negDoubleValues;
+
+ QTest::newRow("zero")
+ << (void *)values << (qreal)0.0f << (void *)nullValues4;
+}
+void tst_QMatrixNxN::multiplyFactor4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+
+ QMatrix4x4 m3;
+ m3 = m1;
+ m3 *= factor;
+ QVERIFY(isSame(m3, (const qreal *)m2Values));
+
+ QMatrix4x4 m4;
+ m4 = m1 * factor;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix4x4 m5;
+ m5 = factor * m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+}
+
+// Test matrix multiplication by a factor for 4x3 matrices.
+void tst_QMatrixNxN::multiplyFactor4x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<void *>("m2Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4x3 << (qreal)1.0f << (void *)nullValues4x3;
+
+ QTest::newRow("double identity")
+ << (void *)identityValues4x3 << (qreal)2.0f << (void *)doubleIdentity4x3;
+
+ static qreal const values[12] =
+ {1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f};
+ static qreal const doubleValues[12] =
+ {2.0f, 4.0f, 6.0f, 8.0f,
+ 10.0f, 12.0f, 14.0f, 16.0f,
+ 18.0f, 20.0f, 22.0f, 24.0f};
+ static qreal const negDoubleValues[12] =
+ {-2.0f, -4.0f, -6.0f, -8.0f,
+ -10.0f, -12.0f, -14.0f, -16.0f,
+ -18.0f, -20.0f, -22.0f, -24.0f};
+
+ QTest::newRow("unique")
+ << (void *)values << (qreal)2.0f << (void *)doubleValues;
+
+ QTest::newRow("neg")
+ << (void *)values << (qreal)-2.0f << (void *)negDoubleValues;
+
+ QTest::newRow("zero")
+ << (void *)values << (qreal)0.0f << (void *)nullValues4x3;
+}
+void tst_QMatrixNxN::multiplyFactor4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ QMatrix4x3 m1((const qreal *)m1Values);
+
+ QMatrix4x3 m3;
+ m3 = m1;
+ m3 *= factor;
+ QVERIFY(isSame(m3, (const qreal *)m2Values));
+
+ QMatrix4x3 m4;
+ m4 = m1 * factor;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix4x3 m5;
+ m5 = factor * m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+}
+
+// Test matrix division by a factor for 2x2 matrices.
+void tst_QMatrixNxN::divideFactor2x2_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor2x2_data();
+}
+void tst_QMatrixNxN::divideFactor2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ if (factor == 0.0f)
+ return;
+
+ QMatrix2x2 m2((const qreal *)m2Values);
+
+ QMatrix2x2 m3;
+ m3 = m2;
+ m3 /= factor;
+ QVERIFY(isSame(m3, (const qreal *)m1Values));
+
+ QMatrix2x2 m4;
+ m4 = m2 / factor;
+ QVERIFY(isSame(m4, (const qreal *)m1Values));
+}
+
+// Test matrix division by a factor for 3x3 matrices.
+void tst_QMatrixNxN::divideFactor3x3_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor3x3_data();
+}
+void tst_QMatrixNxN::divideFactor3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ if (factor == 0.0f)
+ return;
+
+ QMatrix3x3 m2((const qreal *)m2Values);
+
+ QMatrix3x3 m3;
+ m3 = m2;
+ m3 /= factor;
+ QVERIFY(isSame(m3, (const qreal *)m1Values));
+
+ QMatrix3x3 m4;
+ m4 = m2 / factor;
+ QVERIFY(isSame(m4, (const qreal *)m1Values));
+}
+
+// Test matrix division by a factor for 4x4 matrices.
+void tst_QMatrixNxN::divideFactor4x4_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor4x4_data();
+}
+void tst_QMatrixNxN::divideFactor4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ if (factor == 0.0f)
+ return;
+
+ QMatrix4x4 m2((const qreal *)m2Values);
+
+ QMatrix4x4 m3;
+ m3 = m2;
+ m3 /= factor;
+ QVERIFY(isSame(m3, (const qreal *)m1Values));
+
+ QMatrix4x4 m4;
+ m4 = m2 / factor;
+ QVERIFY(isSame(m4, (const qreal *)m1Values));
+}
+
+// Test matrix division by a factor for 4x3 matrices.
+void tst_QMatrixNxN::divideFactor4x3_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor4x3_data();
+}
+void tst_QMatrixNxN::divideFactor4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ if (factor == 0.0f)
+ return;
+
+ QMatrix4x3 m2((const qreal *)m2Values);
+
+ QMatrix4x3 m3;
+ m3 = m2;
+ m3 /= factor;
+ QVERIFY(isSame(m3, (const qreal *)m1Values));
+
+ QMatrix4x3 m4;
+ m4 = m2 / factor;
+ QVERIFY(isSame(m4, (const qreal *)m1Values));
+}
+
+// Test matrix negation for 2x2 matrices.
+void tst_QMatrixNxN::negate2x2_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor2x2_data();
+}
+void tst_QMatrixNxN::negate2x2()
+{
+ QFETCH(void *, m1Values);
+
+ const qreal *values = (const qreal *)m1Values;
+
+ QMatrix2x2 m1(values);
+
+ qreal negated[4];
+ for (int index = 0; index < 4; ++index)
+ negated[index] = -values[index];
+
+ QMatrix2x2 m2;
+ m2 = -m1;
+ QVERIFY(isSame(m2, negated));
+}
+
+// Test matrix negation for 3x3 matrices.
+void tst_QMatrixNxN::negate3x3_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor3x3_data();
+}
+void tst_QMatrixNxN::negate3x3()
+{
+ QFETCH(void *, m1Values);
+
+ const qreal *values = (const qreal *)m1Values;
+
+ QMatrix3x3 m1(values);
+
+ qreal negated[9];
+ for (int index = 0; index < 9; ++index)
+ negated[index] = -values[index];
+
+ QMatrix3x3 m2;
+ m2 = -m1;
+ QVERIFY(isSame(m2, negated));
+}
+
+// Test matrix negation for 4x4 matrices.
+void tst_QMatrixNxN::negate4x4_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor4x4_data();
+}
+void tst_QMatrixNxN::negate4x4()
+{
+ QFETCH(void *, m1Values);
+
+ const qreal *values = (const qreal *)m1Values;
+
+ QMatrix4x4 m1(values);
+
+ qreal negated[16];
+ for (int index = 0; index < 16; ++index)
+ negated[index] = -values[index];
+
+ QMatrix4x4 m2;
+ m2 = -m1;
+ QVERIFY(isSame(m2, negated));
+}
+
+// Test matrix negation for 4x3 matrices.
+void tst_QMatrixNxN::negate4x3_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor4x3_data();
+}
+void tst_QMatrixNxN::negate4x3()
+{
+ QFETCH(void *, m1Values);
+
+ const qreal *values = (const qreal *)m1Values;
+
+ QMatrix4x3 m1(values);
+
+ qreal negated[12];
+ for (int index = 0; index < 12; ++index)
+ negated[index] = -values[index];
+
+ QMatrix4x3 m2;
+ m2 = -m1;
+ QVERIFY(isSame(m2, negated));
+}
+
+// Matrix inverted. This is a more straight-forward implementation
+// of the algorithm at http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24
+// than the optimized version in the QMatrix4x4 code. Hopefully it is
+// easier to verify that this version is the same as the reference.
+
+struct Matrix3
+{
+ qreal v[9];
+};
+struct Matrix4
+{
+ qreal v[16];
+};
+
+static qreal m3Determinant(const Matrix3& m)
+{
+ return m.v[0] * (m.v[4] * m.v[8] - m.v[7] * m.v[5]) -
+ m.v[1] * (m.v[3] * m.v[8] - m.v[6] * m.v[5]) +
+ m.v[2] * (m.v[3] * m.v[7] - m.v[6] * m.v[4]);
+}
+
+static bool m3Inverse(const Matrix3& min, Matrix3& mout)
+{
+ qreal det = m3Determinant(min);
+ if (det == 0.0f)
+ return false;
+ mout.v[0] = (min.v[4] * min.v[8] - min.v[5] * min.v[7]) / det;
+ mout.v[1] = -(min.v[1] * min.v[8] - min.v[2] * min.v[7]) / det;
+ mout.v[2] = (min.v[1] * min.v[5] - min.v[4] * min.v[2]) / det;
+ mout.v[3] = -(min.v[3] * min.v[8] - min.v[5] * min.v[6]) / det;
+ mout.v[4] = (min.v[0] * min.v[8] - min.v[6] * min.v[2]) / det;
+ mout.v[5] = -(min.v[0] * min.v[5] - min.v[3] * min.v[2]) / det;
+ mout.v[6] = (min.v[3] * min.v[7] - min.v[6] * min.v[4]) / det;
+ mout.v[7] = -(min.v[0] * min.v[7] - min.v[6] * min.v[1]) / det;
+ mout.v[8] = (min.v[0] * min.v[4] - min.v[1] * min.v[3]) / det;
+ return true;
+}
+
+static void m3Transpose(Matrix3& m)
+{
+ qSwap(m.v[1], m.v[3]);
+ qSwap(m.v[2], m.v[6]);
+ qSwap(m.v[5], m.v[7]);
+}
+
+static void m4Submatrix(const Matrix4& min, Matrix3& mout, int i, int j)
+{
+ for (int di = 0; di < 3; ++di) {
+ for (int dj = 0; dj < 3; ++dj) {
+ int si = di + ((di >= i) ? 1 : 0);
+ int sj = dj + ((dj >= j) ? 1 : 0);
+ mout.v[di * 3 + dj] = min.v[si * 4 + sj];
+ }
+ }
+}
+
+static qreal m4Determinant(const Matrix4& m)
+{
+ qreal det;
+ qreal result = 0.0f;
+ qreal i = 1.0f;
+ Matrix3 msub;
+ for (int n = 0; n < 4; ++n, i *= -1.0f) {
+ m4Submatrix(m, msub, 0, n);
+ det = m3Determinant(msub);
+ result += m.v[n] * det * i;
+ }
+ return result;
+}
+
+static void m4Inverse(const Matrix4& min, Matrix4& mout)
+{
+ qreal det = m4Determinant(min);
+ Matrix3 msub;
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 4; ++j) {
+ qreal sign = 1.0f - ((i + j) % 2) * 2.0f;
+ m4Submatrix(min, msub, i, j);
+ mout.v[i + j * 4] = (m3Determinant(msub) * sign) / det;
+ }
+ }
+}
+
+// Test matrix inverted for 4x4 matrices.
+void tst_QMatrixNxN::inverted4x4_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<bool>("invertible");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (void *)identityValues4 << false;
+
+ QTest::newRow("identity")
+ << (void *)identityValues4 << (void *)identityValues4 << true;
+
+ QTest::newRow("unique")
+ << (void *)uniqueValues4 << (void *)identityValues4 << false;
+
+ static Matrix4 const invertible = {
+ {5.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 6.0f, 0.0f, 3.0f,
+ 0.0f, 0.0f, 7.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f}
+ };
+ static Matrix4 inverted;
+ m4Inverse(invertible, inverted);
+
+ QTest::newRow("invertible")
+ << (void *)invertible.v << (void *)inverted.v << true;
+
+ static Matrix4 const invertible2 = {
+ {1.0f, 2.0f, 4.0f, 2.0f,
+ 8.0f, 3.0f, 5.0f, 3.0f,
+ 6.0f, 7.0f, 9.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f}
+ };
+ static Matrix4 inverted2;
+ m4Inverse(invertible2, inverted2);
+
+ QTest::newRow("invertible2")
+ << (void *)invertible2.v << (void *)inverted2.v << true;
+
+ static Matrix4 const translate = {
+ {1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 1.0f, 0.0f, 3.0f,
+ 0.0f, 0.0f, 1.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f}
+ };
+ static Matrix4 const inverseTranslate = {
+ {1.0f, 0.0f, 0.0f, -2.0f,
+ 0.0f, 1.0f, 0.0f, -3.0f,
+ 0.0f, 0.0f, 1.0f, -4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f}
+ };
+
+ QTest::newRow("translate")
+ << (void *)translate.v << (void *)inverseTranslate.v << true;
+}
+void tst_QMatrixNxN::inverted4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(bool, invertible);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+
+ if (invertible)
+ QVERIFY(m1.determinant() != 0.0f);
+ else
+ QVERIFY(m1.determinant() == 0.0f);
+
+ Matrix4 m1alt;
+ memcpy(m1alt.v, (const qreal *)m1Values, sizeof(m1alt.v));
+
+ QCOMPARE(m1.determinant(), m4Determinant(m1alt));
+
+ QMatrix4x4 m2;
+ bool inv;
+ m2 = m1.inverted(&inv);
+ QVERIFY(isSame(m2, (const qreal *)m2Values));
+
+ if (invertible) {
+ QVERIFY(inv);
+
+ Matrix4 m2alt;
+ m4Inverse(m1alt, m2alt);
+ QVERIFY(isSame(m2, m2alt.v));
+
+ QMatrix4x4 m3;
+ m3 = m1 * m2;
+ QVERIFY(isIdentity(m3));
+
+ QMatrix4x4 m4;
+ m4 = m2 * m1;
+ QVERIFY(isIdentity(m4));
+ } else {
+ QVERIFY(!inv);
+ }
+
+ // Test again, after inferring the special matrix type.
+ m1.optimize();
+ m2 = m1.inverted(&inv);
+ QVERIFY(isSame(m2, (const qreal *)m2Values));
+ QCOMPARE(inv, invertible);
+}
+
+void tst_QMatrixNxN::orthonormalInverse4x4()
+{
+ QMatrix4x4 m1;
+ QVERIFY(qFuzzyCompare(m1.inverted(), m1));
+
+ QMatrix4x4 m2;
+ m2.rotate(45.0, 1.0, 0.0, 0.0);
+ m2.translate(10.0, 0.0, 0.0);
+
+ // Use operator() to drop the internal flags that
+ // mark the matrix as orthonormal. This will force inverted()
+ // to compute m3.inverted() the long way. We can then compare
+ // the result to what the faster algorithm produces on m2.
+ QMatrix4x4 m3 = m2;
+ m3(0, 0);
+ bool invertible;
+ QVERIFY(qFuzzyCompare(m2.inverted(&invertible), m3.inverted()));
+ QVERIFY(invertible);
+
+ QMatrix4x4 m4;
+ m4.rotate(45.0, 0.0, 1.0, 0.0);
+ QMatrix4x4 m5 = m4;
+ m5(0, 0);
+ QVERIFY(qFuzzyCompare(m4.inverted(), m5.inverted()));
+
+ QMatrix4x4 m6;
+ m1.rotate(88, 0.0, 0.0, 1.0);
+ m1.translate(-20.0, 20.0, 15.0);
+ m1.rotate(25, 1.0, 0.0, 0.0);
+ QMatrix4x4 m7 = m6;
+ m7(0, 0);
+ QVERIFY(qFuzzyCompare(m6.inverted(), m7.inverted()));
+}
+
+// Test the generation and use of 4x4 scale matrices.
+void tst_QMatrixNxN::scale4x4_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<void *>("resultValues");
+
+ static const qreal nullScale[] =
+ {0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (void *)nullScale;
+
+ QTest::newRow("identity")
+ << (qreal)1.0f << (qreal)1.0f << (qreal)1.0f << (void *)identityValues4;
+
+ static const qreal doubleScale[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("double")
+ << (qreal)2.0f << (qreal)2.0f << (qreal)2.0f << (void *)doubleScale;
+
+ static const qreal complexScale[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 11.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, -6.5f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("complex")
+ << (qreal)2.0f << (qreal)11.0f << (qreal)-6.5f << (void *)complexScale;
+
+ static const qreal complexScale2D[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -11.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("complex2D")
+ << (qreal)2.0f << (qreal)-11.0f << (qreal)1.0f << (void *)complexScale2D;
+}
+void tst_QMatrixNxN::scale4x4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(void *, resultValues);
+
+ QMatrix4x4 result((const qreal *)resultValues);
+
+ QMatrix4x4 m1;
+ m1.scale(QVector3D(x, y, z));
+ QVERIFY(isSame(m1, (const qreal *)resultValues));
+
+ QMatrix4x4 m2;
+ m2.scale(x, y, z);
+ QVERIFY(isSame(m2, (const qreal *)resultValues));
+
+ if (z == 1.0f) {
+ QMatrix4x4 m2b;
+ m2b.scale(x, y);
+ QVERIFY(m2b == m2);
+ }
+
+ QVector3D v1(2.0f, 3.0f, -4.0f);
+ QVector3D v2 = m1 * v1;
+ QCOMPARE(v2.x(), (qreal)(2.0f * x));
+ QCOMPARE(v2.y(), (qreal)(3.0f * y));
+ QCOMPARE(v2.z(), (qreal)(-4.0f * z));
+
+ v2 = v1 * m1;
+ QCOMPARE(v2.x(), (qreal)(2.0f * x));
+ QCOMPARE(v2.y(), (qreal)(3.0f * y));
+ QCOMPARE(v2.z(), (qreal)(-4.0f * z));
+
+ QVector4D v3(2.0f, 3.0f, -4.0f, 34.0f);
+ QVector4D v4 = m1 * v3;
+ QCOMPARE(v4.x(), (qreal)(2.0f * x));
+ QCOMPARE(v4.y(), (qreal)(3.0f * y));
+ QCOMPARE(v4.z(), (qreal)(-4.0f * z));
+ QCOMPARE(v4.w(), (qreal)34.0f);
+
+ v4 = v3 * m1;
+ QCOMPARE(v4.x(), (qreal)(2.0f * x));
+ QCOMPARE(v4.y(), (qreal)(3.0f * y));
+ QCOMPARE(v4.z(), (qreal)(-4.0f * z));
+ QCOMPARE(v4.w(), (qreal)34.0f);
+
+ QPoint p1(2, 3);
+ QPoint p2 = m1 * p1;
+ QCOMPARE(p2.x(), (int)(2.0f * x));
+ QCOMPARE(p2.y(), (int)(3.0f * y));
+
+ p2 = p1 * m1;
+ QCOMPARE(p2.x(), (int)(2.0f * x));
+ QCOMPARE(p2.y(), (int)(3.0f * y));
+
+ QPointF p3(2.0f, 3.0f);
+ QPointF p4 = m1 * p3;
+ QCOMPARE(p4.x(), (qreal)(2.0f * x));
+ QCOMPARE(p4.y(), (qreal)(3.0f * y));
+
+ p4 = p3 * m1;
+ QCOMPARE(p4.x(), (qreal)(2.0f * x));
+ QCOMPARE(p4.y(), (qreal)(3.0f * y));
+
+ QMatrix4x4 m3(uniqueValues4);
+ QMatrix4x4 m4(m3);
+ m4.scale(x, y, z);
+ QVERIFY(m4 == m3 * m1);
+
+ if (x == y && y == z) {
+ QMatrix4x4 m5;
+ m5.scale(x);
+ QVERIFY(isSame(m5, (const qreal *)resultValues));
+ }
+
+ if (z == 1.0f) {
+ QMatrix4x4 m4b(m3);
+ m4b.scale(x, y);
+ QVERIFY(m4b == m4);
+ }
+
+ // Test coverage when the special matrix type is unknown.
+
+ QMatrix4x4 m6;
+ m6(0, 0) = 1.0f;
+ m6.scale(QVector3D(x, y, z));
+ QVERIFY(isSame(m6, (const qreal *)resultValues));
+
+ QMatrix4x4 m7;
+ m7(0, 0) = 1.0f;
+ m7.scale(x, y, z);
+ QVERIFY(isSame(m7, (const qreal *)resultValues));
+
+ if (x == y && y == z) {
+ QMatrix4x4 m8;
+ m8(0, 0) = 1.0f;
+ m8.scale(x);
+ QVERIFY(isSame(m8, (const qreal *)resultValues));
+
+ m8.optimize();
+ m8.scale(1.0f);
+ QVERIFY(isSame(m8, (const qreal *)resultValues));
+
+ QMatrix4x4 m9;
+ m9.translate(0.0f, 0.0f, 0.0f);
+ m9.scale(x);
+ QVERIFY(isSame(m9, (const qreal *)resultValues));
+ }
+}
+
+// Test the generation and use of 4x4 translation matrices.
+void tst_QMatrixNxN::translate4x4_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<void *>("resultValues");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (void *)identityValues4;
+
+ static const qreal identityTranslate[] =
+ {1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 1.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("identity")
+ << (qreal)1.0f << (qreal)1.0f << (qreal)1.0f << (void *)identityTranslate;
+
+ static const qreal complexTranslate[] =
+ {1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 1.0f, 0.0f, 11.0f,
+ 0.0f, 0.0f, 1.0f, -6.5f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("complex")
+ << (qreal)2.0f << (qreal)11.0f << (qreal)-6.5f << (void *)complexTranslate;
+
+ static const qreal complexTranslate2D[] =
+ {1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 1.0f, 0.0f, -11.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("complex2D")
+ << (qreal)2.0f << (qreal)-11.0f << (qreal)0.0f << (void *)complexTranslate2D;
+}
+void tst_QMatrixNxN::translate4x4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(void *, resultValues);
+
+ QMatrix4x4 result((const qreal *)resultValues);
+
+ QMatrix4x4 m1;
+ m1.translate(QVector3D(x, y, z));
+ QVERIFY(isSame(m1, (const qreal *)resultValues));
+
+ QMatrix4x4 m2;
+ m2.translate(x, y, z);
+ QVERIFY(isSame(m2, (const qreal *)resultValues));
+
+ if (z == 0.0f) {
+ QMatrix4x4 m2b;
+ m2b.translate(x, y);
+ QVERIFY(m2b == m2);
+ }
+
+ QVector3D v1(2.0f, 3.0f, -4.0f);
+ QVector3D v2 = m1 * v1;
+ QCOMPARE(v2.x(), (qreal)(2.0f + x));
+ QCOMPARE(v2.y(), (qreal)(3.0f + y));
+ QCOMPARE(v2.z(), (qreal)(-4.0f + z));
+
+ QVector4D v3(2.0f, 3.0f, -4.0f, 1.0f);
+ QVector4D v4 = m1 * v3;
+ QCOMPARE(v4.x(), (qreal)(2.0f + x));
+ QCOMPARE(v4.y(), (qreal)(3.0f + y));
+ QCOMPARE(v4.z(), (qreal)(-4.0f + z));
+ QCOMPARE(v4.w(), (qreal)1.0f);
+
+ QVector4D v5(2.0f, 3.0f, -4.0f, 34.0f);
+ QVector4D v6 = m1 * v5;
+ QCOMPARE(v6.x(), (qreal)(2.0f + x * 34.0f));
+ QCOMPARE(v6.y(), (qreal)(3.0f + y * 34.0f));
+ QCOMPARE(v6.z(), (qreal)(-4.0f + z * 34.0f));
+ QCOMPARE(v6.w(), (qreal)34.0f);
+
+ QPoint p1(2, 3);
+ QPoint p2 = m1 * p1;
+ QCOMPARE(p2.x(), (int)(2.0f + x));
+ QCOMPARE(p2.y(), (int)(3.0f + y));
+
+ QPointF p3(2.0f, 3.0f);
+ QPointF p4 = m1 * p3;
+ QCOMPARE(p4.x(), (qreal)(2.0f + x));
+ QCOMPARE(p4.y(), (qreal)(3.0f + y));
+
+ QMatrix4x4 m3(uniqueValues4);
+ QMatrix4x4 m4(m3);
+ m4.translate(x, y, z);
+ QVERIFY(m4 == m3 * m1);
+
+ if (z == 0.0f) {
+ QMatrix4x4 m4b(m3);
+ m4b.translate(x, y);
+ QVERIFY(m4b == m4);
+ }
+}
+
+// Test the generation and use of 4x4 rotation matrices.
+void tst_QMatrixNxN::rotate4x4_data()
+{
+ QTest::addColumn<qreal>("angle");
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<void *>("resultValues");
+
+ static const qreal nullRotate[] =
+ {0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("null")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (void *)nullRotate;
+
+ static const qreal noRotate[] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("zerodegrees")
+ << (qreal)0.0f
+ << (qreal)2.0f << (qreal)3.0f << (qreal)-4.0f
+ << (void *)noRotate;
+
+ static const qreal xRotate[] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, -1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("xrotate")
+ << (qreal)90.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (void *)xRotate;
+
+ static const qreal xRotateNeg[] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("-xrotate")
+ << (qreal)90.0f
+ << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f
+ << (void *)xRotateNeg;
+
+ static const qreal yRotate[] =
+ {0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("yrotate")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (void *)yRotate;
+
+ static const qreal yRotateNeg[] =
+ {0.0f, 0.0f, -1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("-yrotate")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f
+ << (void *)yRotateNeg;
+
+ static const qreal zRotate[] =
+ {0.0f, -1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("zrotate")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (void *)zRotate;
+
+ static const qreal zRotateNeg[] =
+ {0.0f, 1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("-zrotate")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f
+ << (void *)zRotateNeg;
+
+ // Algorithm from http://en.wikipedia.org/wiki/Rotation_matrix.
+ // Deliberately different from the one in the code for cross-checking.
+ static qreal complexRotate[16];
+ qreal x = 1.0f;
+ qreal y = 2.0f;
+ qreal z = -6.0f;
+ qreal angle = -45.0f;
+ qreal c = qCos(angle * M_PI / 180.0f);
+ qreal s = qSin(angle * M_PI / 180.0f);
+ qreal len = qSqrt(x * x + y * y + z * z);
+ qreal xu = x / len;
+ qreal yu = y / len;
+ qreal zu = z / len;
+ complexRotate[0] = (qreal)((1 - xu * xu) * c + xu * xu);
+ complexRotate[1] = (qreal)(-zu * s - xu * yu * c + xu * yu);
+ complexRotate[2] = (qreal)(yu * s - xu * zu * c + xu * zu);
+ complexRotate[3] = 0;
+ complexRotate[4] = (qreal)(zu * s - xu * yu * c + xu * yu);
+ complexRotate[5] = (qreal)((1 - yu * yu) * c + yu * yu);
+ complexRotate[6] = (qreal)(-xu * s - yu * zu * c + yu * zu);
+ complexRotate[7] = 0;
+ complexRotate[8] = (qreal)(-yu * s - xu * zu * c + xu * zu);
+ complexRotate[9] = (qreal)(xu * s - yu * zu * c + yu * zu);
+ complexRotate[10] = (qreal)((1 - zu * zu) * c + zu * zu);
+ complexRotate[11] = 0;
+ complexRotate[12] = 0;
+ complexRotate[13] = 0;
+ complexRotate[14] = 0;
+ complexRotate[15] = 1;
+
+ QTest::newRow("complex")
+ << (qreal)angle
+ << (qreal)x << (qreal)y << (qreal)z
+ << (void *)complexRotate;
+}
+void tst_QMatrixNxN::rotate4x4()
+{
+ QFETCH(qreal, angle);
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(void *, resultValues);
+
+ QMatrix4x4 m1;
+ m1.rotate(angle, QVector3D(x, y, z));
+ QVERIFY(isSame(m1, (const qreal *)resultValues));
+
+ QMatrix4x4 m2;
+ m2.rotate(angle, x, y, z);
+ QVERIFY(isSame(m2, (const qreal *)resultValues));
+
+ QMatrix4x4 m3(uniqueValues4);
+ QMatrix4x4 m4(m3);
+ m4.rotate(angle, x, y, z);
+ QVERIFY(qFuzzyCompare(m4, m3 * m1));
+
+ // Null vectors don't make sense for quaternion rotations.
+ if (x != 0 || y != 0 || z != 0) {
+ QMatrix4x4 m5;
+ m5.rotate(QQuaternion::fromAxisAndAngle(QVector3D(x, y, z), angle));
+ QVERIFY(isSame(m5, (const qreal *)resultValues));
+ }
+
+#define ROTATE4(xin,yin,zin,win,xout,yout,zout,wout) \
+ do { \
+ xout = ((const qreal *)resultValues)[0] * xin + \
+ ((const qreal *)resultValues)[1] * yin + \
+ ((const qreal *)resultValues)[2] * zin + \
+ ((const qreal *)resultValues)[3] * win; \
+ yout = ((const qreal *)resultValues)[4] * xin + \
+ ((const qreal *)resultValues)[5] * yin + \
+ ((const qreal *)resultValues)[6] * zin + \
+ ((const qreal *)resultValues)[7] * win; \
+ zout = ((const qreal *)resultValues)[8] * xin + \
+ ((const qreal *)resultValues)[9] * yin + \
+ ((const qreal *)resultValues)[10] * zin + \
+ ((const qreal *)resultValues)[11] * win; \
+ wout = ((const qreal *)resultValues)[12] * xin + \
+ ((const qreal *)resultValues)[13] * yin + \
+ ((const qreal *)resultValues)[14] * zin + \
+ ((const qreal *)resultValues)[15] * win; \
+ } while (0)
+
+ // Rotate various test vectors using the straight-forward approach.
+ qreal v1x, v1y, v1z, v1w;
+ ROTATE4(2.0f, 3.0f, -4.0f, 1.0f, v1x, v1y, v1z, v1w);
+ v1x /= v1w;
+ v1y /= v1w;
+ v1z /= v1w;
+ qreal v3x, v3y, v3z, v3w;
+ ROTATE4(2.0f, 3.0f, -4.0f, 1.0f, v3x, v3y, v3z, v3w);
+ qreal v5x, v5y, v5z, v5w;
+ ROTATE4(2.0f, 3.0f, -4.0f, 34.0f, v5x, v5y, v5z, v5w);
+ qreal p1x, p1y, p1z, p1w;
+ ROTATE4(2.0f, 3.0f, 0.0f, 1.0f, p1x, p1y, p1z, p1w);
+ p1x /= p1w;
+ p1y /= p1w;
+ p1z /= p1w;
+
+ QVector3D v1(2.0f, 3.0f, -4.0f);
+ QVector3D v2 = m1 * v1;
+ QVERIFY(fuzzyCompare(v2.x(), v1x));
+ QVERIFY(fuzzyCompare(v2.y(), v1y));
+ QVERIFY(fuzzyCompare(v2.z(), v1z));
+
+ QVector4D v3(2.0f, 3.0f, -4.0f, 1.0f);
+ QVector4D v4 = m1 * v3;
+ QVERIFY(fuzzyCompare(v4.x(), v3x));
+ QVERIFY(fuzzyCompare(v4.y(), v3y));
+ QVERIFY(fuzzyCompare(v4.z(), v3z));
+ QVERIFY(fuzzyCompare(v4.w(), v3w));
+
+ QVector4D v5(2.0f, 3.0f, -4.0f, 34.0f);
+ QVector4D v6 = m1 * v5;
+ QVERIFY(fuzzyCompare(v6.x(), v5x));
+ QVERIFY(fuzzyCompare(v6.y(), v5y));
+ QVERIFY(fuzzyCompare(v6.z(), v5z));
+ QVERIFY(fuzzyCompare(v6.w(), v5w));
+
+ QPoint p1(2, 3);
+ QPoint p2 = m1 * p1;
+ QCOMPARE(p2.x(), qRound(p1x));
+ QCOMPARE(p2.y(), qRound(p1y));
+
+ QPointF p3(2.0f, 3.0f);
+ QPointF p4 = m1 * p3;
+ QVERIFY(fuzzyCompare(p4.x(), p1x));
+ QVERIFY(fuzzyCompare(p4.y(), p1y));
+
+ if (x != 0 || y != 0 || z != 0) {
+ QQuaternion q = QQuaternion::fromAxisAndAngle(QVector3D(x, y, z), angle);
+ QVector3D vq = q.rotatedVector(v1);
+ QVERIFY(fuzzyCompare(vq.x(), v1x));
+ QVERIFY(fuzzyCompare(vq.y(), v1y));
+ QVERIFY(fuzzyCompare(vq.z(), v1z));
+ }
+}
+
+static bool isSame(const QMatrix3x3& m1, const Matrix3& m2)
+{
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ if (!fuzzyCompare(m1(row, col), m2.v[row * 3 + col]))
+ return false;
+ }
+ }
+ return true;
+}
+
+// Test the computation of normal matrices from 4x4 transformation matrices.
+void tst_QMatrixNxN::normalMatrix_data()
+{
+ QTest::addColumn<void *>("mValues");
+
+ QTest::newRow("identity")
+ << (void *)identityValues4;
+ QTest::newRow("unique")
+ << (void *)uniqueValues4; // Not invertible because determinant == 0.
+
+ static qreal const translateValues[16] =
+ {1.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 1.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 1.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const scaleValues[16] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 7.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 9.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothValues[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const rotateValues[16] =
+ {0.0f, 0.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const nullScaleValues1[16] =
+ {0.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const nullScaleValues2[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const nullScaleValues3[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 0.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+
+ QTest::newRow("translate") << (void *)translateValues;
+ QTest::newRow("scale") << (void *)scaleValues;
+ QTest::newRow("both") << (void *)bothValues;
+ QTest::newRow("rotate") << (void *)rotateValues;
+ QTest::newRow("null scale 1") << (void *)nullScaleValues1;
+ QTest::newRow("null scale 2") << (void *)nullScaleValues2;
+ QTest::newRow("null scale 3") << (void *)nullScaleValues3;
+}
+void tst_QMatrixNxN::normalMatrix()
+{
+ QFETCH(void *, mValues);
+ const qreal *values = (const qreal *)mValues;
+
+ // Compute the expected answer the long way.
+ Matrix3 min;
+ Matrix3 answer;
+ min.v[0] = values[0];
+ min.v[1] = values[1];
+ min.v[2] = values[2];
+ min.v[3] = values[4];
+ min.v[4] = values[5];
+ min.v[5] = values[6];
+ min.v[6] = values[8];
+ min.v[7] = values[9];
+ min.v[8] = values[10];
+ bool invertible = m3Inverse(min, answer);
+ m3Transpose(answer);
+
+ // Perform the test.
+ QMatrix4x4 m1(values);
+ QMatrix3x3 n1 = m1.normalMatrix();
+
+ if (invertible)
+ QVERIFY(::isSame(n1, answer));
+ else
+ QVERIFY(isIdentity(n1));
+
+ // Perform the test again, after inferring special matrix types.
+ // This tests the optimized paths in the normalMatrix() function.
+ m1.optimize();
+ n1 = m1.normalMatrix();
+
+ if (invertible)
+ QVERIFY(::isSame(n1, answer));
+ else
+ QVERIFY(isIdentity(n1));
+}
+
+// Test optimized transformations on 4x4 matrices.
+void tst_QMatrixNxN::optimizedTransforms()
+{
+ static qreal const translateValues[16] =
+ {1.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 1.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 1.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const translateDoubleValues[16] =
+ {1.0f, 0.0f, 0.0f, 8.0f,
+ 0.0f, 1.0f, 0.0f, 10.0f,
+ 0.0f, 0.0f, 1.0f, -6.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const scaleValues[16] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 7.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 9.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const scaleDoubleValues[16] =
+ {4.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 49.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 81.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothValues[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothReverseValues[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f * 2.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f * 7.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f * 9.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothThenTranslateValues[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f + 2.0f * 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f + 7.0f * 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f + 9.0f * -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothThenScaleValues[16] =
+ {4.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 49.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 81.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+
+ QMatrix4x4 translate(translateValues);
+ QMatrix4x4 scale(scaleValues);
+ QMatrix4x4 both(bothValues);
+
+ QMatrix4x4 m1;
+ m1.translate(4.0f, 5.0f, -3.0f);
+ QVERIFY(isSame(m1, translateValues));
+ m1.translate(4.0f, 5.0f, -3.0f);
+ QVERIFY(isSame(m1, translateDoubleValues));
+
+ QMatrix4x4 m2;
+ m2.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ QVERIFY(isSame(m2, translateValues));
+ m2.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ QVERIFY(isSame(m2, translateDoubleValues));
+
+ QMatrix4x4 m3;
+ m3.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m3, scaleValues));
+ m3.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m3, scaleDoubleValues));
+
+ QMatrix4x4 m4;
+ m4.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m4, scaleValues));
+ m4.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m4, scaleDoubleValues));
+
+ QMatrix4x4 m5;
+ m5.translate(4.0f, 5.0f, -3.0f);
+ m5.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m5, bothValues));
+ m5.translate(4.0f, 5.0f, -3.0f);
+ QVERIFY(isSame(m5, bothThenTranslateValues));
+
+ QMatrix4x4 m6;
+ m6.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ m6.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m6, bothValues));
+ m6.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ QVERIFY(isSame(m6, bothThenTranslateValues));
+
+ QMatrix4x4 m7;
+ m7.scale(2.0f, 7.0f, 9.0f);
+ m7.translate(4.0f, 5.0f, -3.0f);
+ QVERIFY(isSame(m7, bothReverseValues));
+
+ QMatrix4x4 m8;
+ m8.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ m8.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ QVERIFY(isSame(m8, bothReverseValues));
+
+ QMatrix4x4 m9;
+ m9.translate(4.0f, 5.0f, -3.0f);
+ m9.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m9, bothValues));
+ m9.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m9, bothThenScaleValues));
+
+ QMatrix4x4 m10;
+ m10.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ m10.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m10, bothValues));
+ m10.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m10, bothThenScaleValues));
+}
+
+// Test orthographic projections.
+void tst_QMatrixNxN::ortho()
+{
+ QMatrix4x4 m1;
+ m1.ortho(QRect(0, 0, 300, 150));
+ QPointF p1 = m1 * QPointF(0, 0);
+ QPointF p2 = m1 * QPointF(300, 0);
+ QPointF p3 = m1 * QPointF(0, 150);
+ QPointF p4 = m1 * QPointF(300, 150);
+ QVector3D p5 = m1 * QVector3D(300, 150, 1);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0));
+ QVERIFY(fuzzyCompare(p1.y(), 1.0));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0));
+ QVERIFY(fuzzyCompare(p2.y(), 1.0));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0));
+ QVERIFY(fuzzyCompare(p3.y(), -1.0));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0));
+ QVERIFY(fuzzyCompare(p4.y(), -1.0));
+ QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0));
+ QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0));
+ QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0));
+
+ QMatrix4x4 m2;
+ m2.ortho(QRectF(0, 0, 300, 150));
+ p1 = m2 * QPointF(0, 0);
+ p2 = m2 * QPointF(300, 0);
+ p3 = m2 * QPointF(0, 150);
+ p4 = m2 * QPointF(300, 150);
+ p5 = m2 * QVector3D(300, 150, 1);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0));
+ QVERIFY(fuzzyCompare(p1.y(), 1.0));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0));
+ QVERIFY(fuzzyCompare(p2.y(), 1.0));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0));
+ QVERIFY(fuzzyCompare(p3.y(), -1.0));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0));
+ QVERIFY(fuzzyCompare(p4.y(), -1.0));
+ QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0));
+ QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0));
+ QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0));
+
+ QMatrix4x4 m3;
+ m3.ortho(0, 300, 150, 0, -1, 1);
+ p1 = m3 * QPointF(0, 0);
+ p2 = m3 * QPointF(300, 0);
+ p3 = m3 * QPointF(0, 150);
+ p4 = m3 * QPointF(300, 150);
+ p5 = m3 * QVector3D(300, 150, 1);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0));
+ QVERIFY(fuzzyCompare(p1.y(), 1.0));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0));
+ QVERIFY(fuzzyCompare(p2.y(), 1.0));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0));
+ QVERIFY(fuzzyCompare(p3.y(), -1.0));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0));
+ QVERIFY(fuzzyCompare(p4.y(), -1.0));
+ QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0));
+ QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0));
+ QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0));
+
+ QMatrix4x4 m4;
+ m4.ortho(0, 300, 150, 0, -2, 3);
+ p1 = m4 * QPointF(0, 0);
+ p2 = m4 * QPointF(300, 0);
+ p3 = m4 * QPointF(0, 150);
+ p4 = m4 * QPointF(300, 150);
+ p5 = m4 * QVector3D(300, 150, 1);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0));
+ QVERIFY(fuzzyCompare(p1.y(), 1.0));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0));
+ QVERIFY(fuzzyCompare(p2.y(), 1.0));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0));
+ QVERIFY(fuzzyCompare(p3.y(), -1.0));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0));
+ QVERIFY(fuzzyCompare(p4.y(), -1.0));
+ QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0));
+ QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0));
+ QVERIFY(fuzzyCompare(p5.z(), (qreal)-0.6));
+
+ // An empty view volume should leave the matrix alone.
+ QMatrix4x4 m5;
+ m5.ortho(0, 0, 150, 0, -2, 3);
+ QVERIFY(m5.isIdentity());
+ m5.ortho(0, 300, 150, 150, -2, 3);
+ QVERIFY(m5.isIdentity());
+ m5.ortho(0, 300, 150, 0, 2, 2);
+ QVERIFY(m5.isIdentity());
+}
+
+// Test perspective frustum projections.
+void tst_QMatrixNxN::frustum()
+{
+ QMatrix4x4 m1;
+ m1.frustum(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
+ QVector3D p1 = m1 * QVector3D(-1.0f, -1.0f, 1.0f);
+ QVector3D p2 = m1 * QVector3D(1.0f, -1.0f, 1.0f);
+ QVector3D p3 = m1 * QVector3D(-1.0f, 1.0f, 1.0f);
+ QVector3D p4 = m1 * QVector3D(1.0f, 1.0f, 1.0f);
+ QVector3D p5 = m1 * QVector3D(0.0f, 0.0f, 2.0f);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0f));
+ QVERIFY(fuzzyCompare(p1.y(), -1.0f));
+ QVERIFY(fuzzyCompare(p1.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0f));
+ QVERIFY(fuzzyCompare(p2.y(), -1.0f));
+ QVERIFY(fuzzyCompare(p2.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0f));
+ QVERIFY(fuzzyCompare(p3.y(), 1.0f));
+ QVERIFY(fuzzyCompare(p3.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0f));
+ QVERIFY(fuzzyCompare(p4.y(), 1.0f));
+ QVERIFY(fuzzyCompare(p4.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p5.x(), 0.0f));
+ QVERIFY(fuzzyCompare(p5.y(), 0.0f));
+ QVERIFY(fuzzyCompare(p5.z(), -0.5f));
+
+ // An empty view volume should leave the matrix alone.
+ QMatrix4x4 m5;
+ m5.frustum(0, 0, 150, 0, -2, 3);
+ QVERIFY(m5.isIdentity());
+ m5.frustum(0, 300, 150, 150, -2, 3);
+ QVERIFY(m5.isIdentity());
+ m5.frustum(0, 300, 150, 0, 2, 2);
+ QVERIFY(m5.isIdentity());
+}
+
+// Test perspective field-of-view projections.
+void tst_QMatrixNxN::perspective()
+{
+ QMatrix4x4 m1;
+ m1.perspective(45.0f, 1.0f, -1.0f, 1.0f);
+ QVector3D p1 = m1 * QVector3D(-1.0f, -1.0f, 1.0f);
+ QVector3D p2 = m1 * QVector3D(1.0f, -1.0f, 1.0f);
+ QVector3D p3 = m1 * QVector3D(-1.0f, 1.0f, 1.0f);
+ QVector3D p4 = m1 * QVector3D(1.0f, 1.0f, 1.0f);
+ QVector3D p5 = m1 * QVector3D(0.0f, 0.0f, 2.0f);
+ QVERIFY(fuzzyCompare(p1.x(), 2.41421));
+ QVERIFY(fuzzyCompare(p1.y(), 2.41421));
+ QVERIFY(fuzzyCompare(p1.z(), -1));
+ QVERIFY(fuzzyCompare(p2.x(), -2.41421));
+ QVERIFY(fuzzyCompare(p2.y(), 2.41421));
+ QVERIFY(fuzzyCompare(p2.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p3.x(), 2.41421));
+ QVERIFY(fuzzyCompare(p3.y(), -2.41421));
+ QVERIFY(fuzzyCompare(p3.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p4.x(), -2.41421));
+ QVERIFY(fuzzyCompare(p4.y(), -2.41421));
+ QVERIFY(fuzzyCompare(p4.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p5.x(), 0.0f));
+ QVERIFY(fuzzyCompare(p5.y(), 0.0f));
+ QVERIFY(fuzzyCompare(p5.z(), -0.5f));
+
+ // An empty view volume should leave the matrix alone.
+ QMatrix4x4 m5;
+ m5.perspective(45.0f, 1.0f, 0.0f, 0.0f);
+ QVERIFY(m5.isIdentity());
+ m5.perspective(45.0f, 0.0f, -1.0f, 1.0f);
+ QVERIFY(m5.isIdentity());
+ m5.perspective(0.0f, 1.0f, -1.0f, 1.0f);
+ QVERIFY(m5.isIdentity());
+}
+
+// Test left-handed vs right-handed coordinate flipping.
+void tst_QMatrixNxN::flipCoordinates()
+{
+ QMatrix4x4 m1;
+ m1.flipCoordinates();
+ QVector3D p1 = m1 * QVector3D(2, 3, 4);
+ QVERIFY(p1 == QVector3D(2, -3, -4));
+
+ QMatrix4x4 m2;
+ m2.scale(2.0f, 3.0f, 1.0f);
+ m2.flipCoordinates();
+ QVector3D p2 = m2 * QVector3D(2, 3, 4);
+ QVERIFY(p2 == QVector3D(4, -9, -4));
+
+ QMatrix4x4 m3;
+ m3.translate(2.0f, 3.0f, 1.0f);
+ m3.flipCoordinates();
+ QVector3D p3 = m3 * QVector3D(2, 3, 4);
+ QVERIFY(p3 == QVector3D(4, 0, -3));
+
+ QMatrix4x4 m4;
+ m4.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ m4.flipCoordinates();
+ QVector3D p4 = m4 * QVector3D(2, 3, 4);
+ QVERIFY(p4 == QVector3D(3, 2, -4));
+}
+
+// Test conversion of generic matrices to and from the non-generic types.
+void tst_QMatrixNxN::convertGeneric()
+{
+ QMatrix4x3 m1(uniqueValues4x3);
+
+ static qreal const unique4x4[16] = {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QMatrix4x4 m4(m1);
+ QVERIFY(isSame(m4, unique4x4));
+
+ QMatrix4x4 m5 = qGenericMatrixToMatrix4x4(m1);
+ QVERIFY(isSame(m5, unique4x4));
+
+ static qreal const conv4x4[12] = {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f
+ };
+ QMatrix4x4 m9(uniqueValues4);
+
+ QMatrix4x3 m10 = m9.toGenericMatrix<4, 3>();
+ QVERIFY(isSame(m10, conv4x4));
+
+ QMatrix4x3 m11 = qGenericMatrixFromMatrix4x4<4, 3>(m9);
+ QVERIFY(isSame(m11, conv4x4));
+}
+
+// Copy of "flagBits" in qmatrix4x4.h.
+enum {
+ Identity = 0x0000, // Identity matrix
+ Translation = 0x0001, // Contains a translation
+ Scale = 0x0002, // Contains a scale
+ Rotation2D = 0x0004, // Contains a rotation about the Z axis
+ Rotation = 0x0008, // Contains an arbitrary rotation
+ Perspective = 0x0010, // Last row is different from (0, 0, 0, 1)
+ General = 0x001f // General matrix, unknown contents
+};
+
+// Structure that allows direct access to "flagBits" for testing.
+struct Matrix4x4
+{
+ qreal m[4][4];
+ int flagBits;
+};
+
+// Test the inferring of special matrix types.
+void tst_QMatrixNxN::optimize_data()
+{
+ QTest::addColumn<void *>("mValues");
+ QTest::addColumn<int>("flagBits");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (int)General;
+ QTest::newRow("identity")
+ << (void *)identityValues4 << (int)Identity;
+ QTest::newRow("unique")
+ << (void *)uniqueValues4 << (int)General;
+
+ static qreal scaleValues[16] = {
+ 2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 3.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 4.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("scale")
+ << (void *)scaleValues << (int)Scale;
+
+ static qreal translateValues[16] = {
+ 1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 1.0f, 0.0f, 3.0f,
+ 0.0f, 0.0f, 1.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("translate")
+ << (void *)translateValues << (int)Translation;
+
+ static qreal scaleTranslateValues[16] = {
+ 1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("scaleTranslate")
+ << (void *)scaleTranslateValues << (int)(Scale | Translation);
+
+ static qreal rotateValues[16] = {
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("rotate")
+ << (void *)rotateValues << (int)Rotation2D;
+
+ // Left-handed system, not a simple rotation.
+ static qreal scaleRotateValues[16] = {
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("scaleRotate")
+ << (void *)scaleRotateValues << (int)(Scale | Rotation2D);
+
+ static qreal matrix2x2Values[16] = {
+ 1.0f, 2.0f, 0.0f, 0.0f,
+ 8.0f, 3.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 9.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("matrix2x2")
+ << (void *)matrix2x2Values << (int)(Scale | Rotation2D);
+
+ static qreal matrix3x3Values[16] = {
+ 1.0f, 2.0f, 4.0f, 0.0f,
+ 8.0f, 3.0f, 5.0f, 0.0f,
+ 6.0f, 7.0f, 9.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("matrix3x3")
+ << (void *)matrix3x3Values << (int)(Scale | Rotation2D | Rotation);
+
+ static qreal rotateTranslateValues[16] = {
+ 0.0f, 1.0f, 0.0f, 1.0f,
+ -1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 0.0f, 1.0f, 3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("rotateTranslate")
+ << (void *)rotateTranslateValues << (int)(Translation | Rotation2D);
+
+ // Left-handed system, not a simple rotation.
+ static qreal scaleRotateTranslateValues[16] = {
+ 0.0f, 1.0f, 0.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 0.0f, 1.0f, 3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("scaleRotateTranslate")
+ << (void *)scaleRotateTranslateValues << (int)(Translation | Scale | Rotation2D);
+
+ static qreal belowValues[16] = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 4.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("below")
+ << (void *)belowValues << (int)General;
+}
+void tst_QMatrixNxN::optimize()
+{
+ QFETCH(void *, mValues);
+ QFETCH(int, flagBits);
+
+ QMatrix4x4 m((const qreal *)mValues);
+ m.optimize();
+
+ QCOMPARE(reinterpret_cast<Matrix4x4 *>(&m)->flagBits, flagBits);
+}
+
+void tst_QMatrixNxN::columnsAndRows()
+{
+ QMatrix4x4 m1(uniqueValues4);
+
+ QVERIFY(m1.column(0) == QVector4D(1, 5, 9, 13));
+ QVERIFY(m1.column(1) == QVector4D(2, 6, 10, 14));
+ QVERIFY(m1.column(2) == QVector4D(3, 7, 11, 15));
+ QVERIFY(m1.column(3) == QVector4D(4, 8, 12, 16));
+
+ QVERIFY(m1.row(0) == QVector4D(1, 2, 3, 4));
+ QVERIFY(m1.row(1) == QVector4D(5, 6, 7, 8));
+ QVERIFY(m1.row(2) == QVector4D(9, 10, 11, 12));
+ QVERIFY(m1.row(3) == QVector4D(13, 14, 15, 16));
+
+ m1.setColumn(0, QVector4D(-1, -5, -9, -13));
+ m1.setColumn(1, QVector4D(-2, -6, -10, -14));
+ m1.setColumn(2, QVector4D(-3, -7, -11, -15));
+ m1.setColumn(3, QVector4D(-4, -8, -12, -16));
+
+ QVERIFY(m1.column(0) == QVector4D(-1, -5, -9, -13));
+ QVERIFY(m1.column(1) == QVector4D(-2, -6, -10, -14));
+ QVERIFY(m1.column(2) == QVector4D(-3, -7, -11, -15));
+ QVERIFY(m1.column(3) == QVector4D(-4, -8, -12, -16));
+
+ QVERIFY(m1.row(0) == QVector4D(-1, -2, -3, -4));
+ QVERIFY(m1.row(1) == QVector4D(-5, -6, -7, -8));
+ QVERIFY(m1.row(2) == QVector4D(-9, -10, -11, -12));
+ QVERIFY(m1.row(3) == QVector4D(-13, -14, -15, -16));
+
+ m1.setRow(0, QVector4D(1, 5, 9, 13));
+ m1.setRow(1, QVector4D(2, 6, 10, 14));
+ m1.setRow(2, QVector4D(3, 7, 11, 15));
+ m1.setRow(3, QVector4D(4, 8, 12, 16));
+
+ QVERIFY(m1.column(0) == QVector4D(1, 2, 3, 4));
+ QVERIFY(m1.column(1) == QVector4D(5, 6, 7, 8));
+ QVERIFY(m1.column(2) == QVector4D(9, 10, 11, 12));
+ QVERIFY(m1.column(3) == QVector4D(13, 14, 15, 16));
+
+ QVERIFY(m1.row(0) == QVector4D(1, 5, 9, 13));
+ QVERIFY(m1.row(1) == QVector4D(2, 6, 10, 14));
+ QVERIFY(m1.row(2) == QVector4D(3, 7, 11, 15));
+ QVERIFY(m1.row(3) == QVector4D(4, 8, 12, 16));
+}
+
+// Test converting QMatrix objects into QMatrix4x4 and then
+// checking that transformations in the original perform the
+// equivalent transformations in the new matrix.
+void tst_QMatrixNxN::convertQMatrix()
+{
+ QMatrix m1;
+ m1.translate(-3.5, 2.0);
+ QPointF p1 = m1.map(QPointF(100.0, 150.0));
+ QCOMPARE(p1.x(), 100.0 - 3.5);
+ QCOMPARE(p1.y(), 150.0 + 2.0);
+
+ QMatrix4x4 m2(m1);
+ QPointF p2 = m2 * QPointF(100.0, 150.0);
+ QCOMPARE((double)p2.x(), 100.0 - 3.5);
+ QCOMPARE((double)p2.y(), 150.0 + 2.0);
+ QVERIFY(m1 == m2.toAffine());
+
+ QMatrix m3;
+ m3.scale(1.5, -2.0);
+ QPointF p3 = m3.map(QPointF(100.0, 150.0));
+ QCOMPARE(p3.x(), 1.5 * 100.0);
+ QCOMPARE(p3.y(), -2.0 * 150.0);
+
+ QMatrix4x4 m4(m3);
+ QPointF p4 = m4 * QPointF(100.0, 150.0);
+ QCOMPARE((double)p4.x(), 1.5 * 100.0);
+ QCOMPARE((double)p4.y(), -2.0 * 150.0);
+ QVERIFY(m3 == m4.toAffine());
+
+ QMatrix m5;
+ m5.rotate(45.0);
+ QPointF p5 = m5.map(QPointF(100.0, 150.0));
+
+ QMatrix4x4 m6(m5);
+ QPointF p6 = m6 * QPointF(100.0, 150.0);
+ QVERIFY(fuzzyCompare(p5.x(), p6.x()));
+ QVERIFY(fuzzyCompare(p5.y(), p6.y()));
+
+ QMatrix m7 = m6.toAffine();
+ QVERIFY(fuzzyCompare(m5.m11(), m7.m11()));
+ QVERIFY(fuzzyCompare(m5.m12(), m7.m12()));
+ QVERIFY(fuzzyCompare(m5.m21(), m7.m21()));
+ QVERIFY(fuzzyCompare(m5.m22(), m7.m22()));
+ QVERIFY(fuzzyCompare(m5.dx(), m7.dx()));
+ QVERIFY(fuzzyCompare(m5.dy(), m7.dy()));
+}
+
+// Test converting QTransform objects into QMatrix4x4 and then
+// checking that transformations in the original perform the
+// equivalent transformations in the new matrix.
+void tst_QMatrixNxN::convertQTransform()
+{
+ QTransform m1;
+ m1.translate(-3.5, 2.0);
+ QPointF p1 = m1.map(QPointF(100.0, 150.0));
+ QCOMPARE(p1.x(), 100.0 - 3.5);
+ QCOMPARE(p1.y(), 150.0 + 2.0);
+
+ QMatrix4x4 m2(m1);
+ QPointF p2 = m2 * QPointF(100.0, 150.0);
+ QCOMPARE((double)p2.x(), 100.0 - 3.5);
+ QCOMPARE((double)p2.y(), 150.0 + 2.0);
+ QVERIFY(m1 == m2.toTransform());
+
+ QTransform m3;
+ m3.scale(1.5, -2.0);
+ QPointF p3 = m3.map(QPointF(100.0, 150.0));
+ QCOMPARE(p3.x(), 1.5 * 100.0);
+ QCOMPARE(p3.y(), -2.0 * 150.0);
+
+ QMatrix4x4 m4(m3);
+ QPointF p4 = m4 * QPointF(100.0, 150.0);
+ QCOMPARE((double)p4.x(), 1.5 * 100.0);
+ QCOMPARE((double)p4.y(), -2.0 * 150.0);
+ QVERIFY(m3 == m4.toTransform());
+
+ QTransform m5;
+ m5.rotate(45.0);
+ QPointF p5 = m5.map(QPointF(100.0, 150.0));
+
+ QMatrix4x4 m6(m5);
+ QPointF p6 = m6 * QPointF(100.0, 150.0);
+ QVERIFY(fuzzyCompare(p5.x(), p6.x()));
+ QVERIFY(fuzzyCompare(p5.y(), p6.y()));
+
+ QTransform m7 = m6.toTransform();
+ QVERIFY(fuzzyCompare(m5.m11(), m7.m11()));
+ QVERIFY(fuzzyCompare(m5.m12(), m7.m12()));
+ QVERIFY(fuzzyCompare(m5.m21(), m7.m21()));
+ QVERIFY(fuzzyCompare(m5.m22(), m7.m22()));
+ QVERIFY(fuzzyCompare(m5.dx(), m7.dx()));
+ QVERIFY(fuzzyCompare(m5.dy(), m7.dy()));
+ QVERIFY(fuzzyCompare(m5.m13(), m7.m13()));
+ QVERIFY(fuzzyCompare(m5.m23(), m7.m23()));
+ QVERIFY(fuzzyCompare(m5.m33(), m7.m33()));
+}
+
+// Test filling matrices with specific values.
+void tst_QMatrixNxN::fill()
+{
+ QMatrix4x4 m1;
+ m1.fill(0.0f);
+ QVERIFY(isSame(m1, nullValues4));
+
+ static const qreal fillValues4[] =
+ {2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f};
+ m1.fill(2.5f);
+ QVERIFY(isSame(m1, fillValues4));
+
+ QMatrix4x3 m2;
+ m2.fill(0.0f);
+ QVERIFY(isSame(m2, nullValues4x3));
+
+ static const qreal fillValues4x3[] =
+ {2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f};
+ m2.fill(2.5f);
+ QVERIFY(isSame(m2, fillValues4x3));
+}
+
+// Test the mapRect() function for QRect and QRectF.
+void tst_QMatrixNxN::mapRect_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("width");
+ QTest::addColumn<qreal>("height");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("rect")
+ << (qreal)1.0f << (qreal)-20.5f << (qreal)100.0f << (qreal)63.75f;
+}
+void tst_QMatrixNxN::mapRect()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, width);
+ QFETCH(qreal, height);
+
+ QRectF rect(x, y, width, height);
+ QRect recti(qRound(x), qRound(y), qRound(width), qRound(height));
+
+ QMatrix4x4 m1;
+ QVERIFY(m1.mapRect(rect) == rect);
+ QVERIFY(m1.mapRect(recti) == recti);
+
+ QMatrix4x4 m2;
+ m2.translate(-100.5f, 64.0f);
+ QRectF translated = rect.translated(-100.5f, 64.0f);
+ QRect translatedi = QRect(qRound(recti.x() - 100.5f), recti.y() + 64,
+ recti.width(), recti.height());
+ QVERIFY(m2.mapRect(rect) == translated);
+ QVERIFY(m2.mapRect(recti) == translatedi);
+
+ QMatrix4x4 m3;
+ m3.scale(-100.5f, 64.0f);
+ qreal scalex = x * -100.5f;
+ qreal scaley = y * 64.0f;
+ qreal scalewid = width * -100.5f;
+ qreal scaleht = height * 64.0f;
+ if (scalewid < 0.0f) {
+ scalewid = -scalewid;
+ scalex -= scalewid;
+ }
+ if (scaleht < 0.0f) {
+ scaleht = -scaleht;
+ scaley -= scaleht;
+ }
+ QRectF scaled(scalex, scaley, scalewid, scaleht);
+ QVERIFY(m3.mapRect(rect) == scaled);
+ scalex = recti.x() * -100.5f;
+ scaley = recti.y() * 64.0f;
+ scalewid = recti.width() * -100.5f;
+ scaleht = recti.height() * 64.0f;
+ if (scalewid < 0.0f) {
+ scalewid = -scalewid;
+ scalex -= scalewid;
+ }
+ if (scaleht < 0.0f) {
+ scaleht = -scaleht;
+ scaley -= scaleht;
+ }
+ QRect scaledi(qRound(scalex), qRound(scaley),
+ qRound(scalewid), qRound(scaleht));
+ QVERIFY(m3.mapRect(recti) == scaledi);
+
+ QMatrix4x4 m4;
+ m4.translate(-100.5f, 64.0f);
+ m4.scale(-2.5f, 4.0f);
+ qreal transx1 = x * -2.5f - 100.5f;
+ qreal transy1 = y * 4.0f + 64.0f;
+ qreal transx2 = (x + width) * -2.5f - 100.5f;
+ qreal transy2 = (y + height) * 4.0f + 64.0f;
+ if (transx1 > transx2)
+ qSwap(transx1, transx2);
+ if (transy1 > transy2)
+ qSwap(transy1, transy2);
+ QRectF trans(transx1, transy1, transx2 - transx1, transy2 - transy1);
+ QVERIFY(m4.mapRect(rect) == trans);
+ transx1 = recti.x() * -2.5f - 100.5f;
+ transy1 = recti.y() * 4.0f + 64.0f;
+ transx2 = (recti.x() + recti.width()) * -2.5f - 100.5f;
+ transy2 = (recti.y() + recti.height()) * 4.0f + 64.0f;
+ if (transx1 > transx2)
+ qSwap(transx1, transx2);
+ if (transy1 > transy2)
+ qSwap(transy1, transy2);
+ QRect transi(qRound(transx1), qRound(transy1),
+ qRound(transx2) - qRound(transx1),
+ qRound(transy2) - qRound(transy1));
+ QVERIFY(m4.mapRect(recti) == transi);
+
+ m4.rotate(45.0f, 0.0f, 0.0f, 1.0f);
+
+ QTransform t4;
+ t4.translate(-100.5f, 64.0f);
+ t4.scale(-2.5f, 4.0f);
+ t4.rotate(45.0f);
+ QRectF mr = m4.mapRect(rect);
+ QRectF tr = t4.mapRect(rect);
+ QVERIFY(fuzzyCompare(mr.x(), tr.x()));
+ QVERIFY(fuzzyCompare(mr.y(), tr.y()));
+ QVERIFY(fuzzyCompare(mr.width(), tr.width()));
+ QVERIFY(fuzzyCompare(mr.height(), tr.height()));
+
+ QRect mri = m4.mapRect(recti);
+ QRect tri = t4.mapRect(recti);
+ QVERIFY(mri == tri);
+}
+
+void tst_QMatrixNxN::mapVector_data()
+{
+ QTest::addColumn<void *>("mValues");
+
+ QTest::newRow("null")
+ << (void *)nullValues4;
+
+ QTest::newRow("identity")
+ << (void *)identityValues4;
+
+ QTest::newRow("unique")
+ << (void *)uniqueValues4;
+
+ static const qreal scale[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 11.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, -6.5f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("scale")
+ << (void *)scale;
+
+ static const qreal scaleTranslate[] =
+ {2.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 11.0f, 0.0f, 2.0f,
+ 0.0f, 0.0f, -6.5f, 3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("scaleTranslate")
+ << (void *)scaleTranslate;
+
+ static const qreal translate[] =
+ {1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 2.0f,
+ 0.0f, 0.0f, 1.0f, 3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("translate")
+ << (void *)translate;
+}
+void tst_QMatrixNxN::mapVector()
+{
+ QFETCH(void *, mValues);
+
+ QMatrix4x4 m1((const qreal *)mValues);
+
+ QVector3D v(3.5f, -1.0f, 2.5f);
+
+ QVector3D expected
+ (v.x() * m1(0, 0) + v.y() * m1(0, 1) + v.z() * m1(0, 2),
+ v.x() * m1(1, 0) + v.y() * m1(1, 1) + v.z() * m1(1, 2),
+ v.x() * m1(2, 0) + v.y() * m1(2, 1) + v.z() * m1(2, 2));
+
+ QVector3D actual = m1.mapVector(v);
+ m1.optimize();
+ QVector3D actual2 = m1.mapVector(v);
+
+ QVERIFY(fuzzyCompare(actual.x(), expected.x()));
+ QVERIFY(fuzzyCompare(actual.y(), expected.y()));
+ QVERIFY(fuzzyCompare(actual.z(), expected.z()));
+ QVERIFY(fuzzyCompare(actual2.x(), expected.x()));
+ QVERIFY(fuzzyCompare(actual2.y(), expected.y()));
+ QVERIFY(fuzzyCompare(actual2.z(), expected.z()));
+}
+
+class tst_QMatrixNxN4x4Properties : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix)
+public:
+ tst_QMatrixNxN4x4Properties(QObject *parent = 0) : QObject(parent) {}
+
+ QMatrix4x4 matrix() const { return m; }
+ void setMatrix(const QMatrix4x4& value) { m = value; }
+
+private:
+ QMatrix4x4 m;
+};
+
+// Test getting and setting matrix properties via the metaobject system.
+void tst_QMatrixNxN::properties()
+{
+ tst_QMatrixNxN4x4Properties obj;
+
+ QMatrix4x4 m1(uniqueValues4);
+ obj.setMatrix(m1);
+
+ QMatrix4x4 m2 = qVariantValue<QMatrix4x4>(obj.property("matrix"));
+ QVERIFY(isSame(m2, uniqueValues4));
+
+ QMatrix4x4 m3(transposedValues4);
+ obj.setProperty("matrix", qVariantFromValue(m3));
+
+ m2 = qVariantValue<QMatrix4x4>(obj.property("matrix"));
+ QVERIFY(isSame(m2, transposedValues4));
+}
+
+void tst_QMatrixNxN::metaTypes()
+{
+ QVERIFY(QMetaType::type("QMatrix4x4") == QMetaType::QMatrix4x4);
+
+ QCOMPARE(QByteArray(QMetaType::typeName(QMetaType::QMatrix4x4)),
+ QByteArray("QMatrix4x4"));
+
+ QVERIFY(QMetaType::isRegistered(QMetaType::QMatrix4x4));
+
+ QVERIFY(qMetaTypeId<QMatrix4x4>() == QMetaType::QMatrix4x4);
+}
+
+QTEST_APPLESS_MAIN(tst_QMatrixNxN)
+
+#include "tst_qmatrixnxn.moc"
diff --git a/tests/auto/gui/math3d/qquaternion/qquaternion.pro b/tests/auto/gui/math3d/qquaternion/qquaternion.pro
new file mode 100644
index 0000000000..6f740cfd42
--- /dev/null
+++ b/tests/auto/gui/math3d/qquaternion/qquaternion.pro
@@ -0,0 +1,2 @@
+load(qttest_p4)
+SOURCES += tst_qquaternion.cpp
diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
new file mode 100644
index 0000000000..7bc50efeeb
--- /dev/null
+++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
@@ -0,0 +1,888 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qmath.h>
+#include <QtGui/qquaternion.h>
+
+class tst_QQuaternion : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QQuaternion() {}
+ ~tst_QQuaternion() {}
+
+private slots:
+ void create();
+
+ void length_data();
+ void length();
+
+ void normalized_data();
+ void normalized();
+
+ void normalize_data();
+ void normalize();
+
+ void compare();
+
+ void add_data();
+ void add();
+
+ void subtract_data();
+ void subtract();
+
+ void multiply_data();
+ void multiply();
+
+ void multiplyFactor_data();
+ void multiplyFactor();
+
+ void divide_data();
+ void divide();
+
+ void negate_data();
+ void negate();
+
+ void conjugate_data();
+ void conjugate();
+
+ void fromAxisAndAngle_data();
+ void fromAxisAndAngle();
+
+ void slerp_data();
+ void slerp();
+
+ void nlerp_data();
+ void nlerp();
+
+ void properties();
+ void metaTypes();
+};
+
+// QVector3D uses float internally, which can lead to some precision
+// issues when using it with the qreal-based QQuaternion.
+static bool fuzzyCompare(qreal x, qreal y)
+{
+ return qFuzzyIsNull(float(x - y));
+}
+
+// Test the creation of QQuaternion objects in various ways:
+// construct, copy, and modify.
+void tst_QQuaternion::create()
+{
+ QQuaternion identity;
+ QCOMPARE(identity.x(), (qreal)0.0f);
+ QCOMPARE(identity.y(), (qreal)0.0f);
+ QCOMPARE(identity.z(), (qreal)0.0f);
+ QCOMPARE(identity.scalar(), (qreal)1.0f);
+ QVERIFY(identity.isIdentity());
+
+ QQuaternion v1(34.0f, 1.0f, 2.5f, -89.25f);
+ QCOMPARE(v1.x(), (qreal)1.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.scalar(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ QQuaternion v1i(34, 1, 2, -89);
+ QCOMPARE(v1i.x(), (qreal)1.0f);
+ QCOMPARE(v1i.y(), (qreal)2.0f);
+ QCOMPARE(v1i.z(), (qreal)-89.0f);
+ QCOMPARE(v1i.scalar(), (qreal)34.0f);
+ QVERIFY(!v1i.isNull());
+
+ QQuaternion v2(v1);
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.5f);
+ QCOMPARE(v2.z(), (qreal)-89.25f);
+ QCOMPARE(v2.scalar(), (qreal)34.0f);
+ QVERIFY(!v2.isNull());
+
+ QQuaternion v4;
+ QCOMPARE(v4.x(), (qreal)0.0f);
+ QCOMPARE(v4.y(), (qreal)0.0f);
+ QCOMPARE(v4.z(), (qreal)0.0f);
+ QCOMPARE(v4.scalar(), (qreal)1.0f);
+ QVERIFY(v4.isIdentity());
+ v4 = v1;
+ QCOMPARE(v4.x(), (qreal)1.0f);
+ QCOMPARE(v4.y(), (qreal)2.5f);
+ QCOMPARE(v4.z(), (qreal)-89.25f);
+ QCOMPARE(v4.scalar(), (qreal)34.0f);
+ QVERIFY(!v4.isNull());
+
+ QQuaternion v9(34, QVector3D(1.0f, 2.5f, -89.25f));
+ QCOMPARE(v9.x(), (qreal)1.0f);
+ QCOMPARE(v9.y(), (qreal)2.5f);
+ QCOMPARE(v9.z(), (qreal)-89.25f);
+ QCOMPARE(v9.scalar(), (qreal)34.0f);
+ QVERIFY(!v9.isNull());
+
+ v1.setX(3.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.scalar(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setY(10.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.scalar(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setZ(15.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QCOMPARE(v1.scalar(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setScalar(6.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QCOMPARE(v1.scalar(), (qreal)6.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setVector(2.0f, 6.5f, -1.25f);
+ QCOMPARE(v1.x(), (qreal)2.0f);
+ QCOMPARE(v1.y(), (qreal)6.5f);
+ QCOMPARE(v1.z(), (qreal)-1.25f);
+ QCOMPARE(v1.scalar(), (qreal)6.0f);
+ QVERIFY(!v1.isNull());
+ QVERIFY(v1.vector() == QVector3D(2.0f, 6.5f, -1.25f));
+
+ v1.setVector(QVector3D(-2.0f, -6.5f, 1.25f));
+ QCOMPARE(v1.x(), (qreal)-2.0f);
+ QCOMPARE(v1.y(), (qreal)-6.5f);
+ QCOMPARE(v1.z(), (qreal)1.25f);
+ QCOMPARE(v1.scalar(), (qreal)6.0f);
+ QVERIFY(!v1.isNull());
+ QVERIFY(v1.vector() == QVector3D(-2.0f, -6.5f, 1.25f));
+
+ v1.setX(0.0f);
+ v1.setY(0.0f);
+ v1.setZ(0.0f);
+ v1.setScalar(0.0f);
+ QCOMPARE(v1.x(), (qreal)0.0f);
+ QCOMPARE(v1.y(), (qreal)0.0f);
+ QCOMPARE(v1.z(), (qreal)0.0f);
+ QCOMPARE(v1.scalar(), (qreal)0.0f);
+ QVERIFY(v1.isNull());
+
+ QVector4D v10 = v9.toVector4D();
+ QCOMPARE(v10.x(), (qreal)1.0f);
+ QCOMPARE(v10.y(), (qreal)2.5f);
+ QCOMPARE(v10.z(), (qreal)-89.25f);
+ QCOMPARE(v10.w(), (qreal)34.0f);
+}
+
+// Test length computation for quaternions.
+void tst_QQuaternion::length_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<qreal>("w");
+ QTest::addColumn<qreal>("len");
+
+ QTest::newRow("null") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("1x") << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1y") << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1z") << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1w") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)1.0f;
+ QTest::newRow("-1x") << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1y") << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1z") << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1w") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)1.0f;
+ QTest::newRow("two") << (qreal)2.0f << (qreal)-2.0f << (qreal)2.0f << (qreal)2.0f << (qreal)qSqrt(16.0f);
+}
+void tst_QQuaternion::length()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+ QFETCH(qreal, len);
+
+ QQuaternion v(w, x, y, z);
+ QCOMPARE(v.length(), len);
+ QCOMPARE(v.lengthSquared(), x * x + y * y + z * z + w * w);
+}
+
+// Test the unit vector conversion for quaternions.
+void tst_QQuaternion::normalized_data()
+{
+ // Use the same test data as the length test.
+ length_data();
+}
+void tst_QQuaternion::normalized()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+ QFETCH(qreal, len);
+
+ QQuaternion v(w, x, y, z);
+ QQuaternion u = v.normalized();
+ if (v.isNull())
+ QVERIFY(u.isNull());
+ else
+ QCOMPARE(u.length(), qreal(1.0f));
+ QCOMPARE(u.x() * len, v.x());
+ QCOMPARE(u.y() * len, v.y());
+ QCOMPARE(u.z() * len, v.z());
+ QCOMPARE(u.scalar() * len, v.scalar());
+}
+
+// Test the unit vector conversion for quaternions.
+void tst_QQuaternion::normalize_data()
+{
+ // Use the same test data as the length test.
+ length_data();
+}
+void tst_QQuaternion::normalize()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+
+ QQuaternion v(w, x, y, z);
+ bool isNull = v.isNull();
+ v.normalize();
+ if (isNull)
+ QVERIFY(v.isNull());
+ else
+ QCOMPARE(v.length(), qreal(1.0f));
+}
+
+// Test the comparison operators for quaternions.
+void tst_QQuaternion::compare()
+{
+ QQuaternion v1(8, 1, 2, 4);
+ QQuaternion v2(8, 1, 2, 4);
+ QQuaternion v3(8, 3, 2, 4);
+ QQuaternion v4(8, 1, 3, 4);
+ QQuaternion v5(8, 1, 2, 3);
+ QQuaternion v6(3, 1, 2, 4);
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 != v3);
+ QVERIFY(v1 != v4);
+ QVERIFY(v1 != v5);
+ QVERIFY(v1 != v6);
+}
+
+// Test addition for quaternions.
+void tst_QQuaternion::add_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("w3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)8.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f << (qreal)9.0f
+ << (qreal)5.0f << (qreal)7.0f << (qreal)-3.0f << (qreal)17.0f;
+}
+void tst_QQuaternion::add()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w2, x2, y2, z2);
+ QQuaternion v3(w3, x3, y3, z3);
+
+ QVERIFY((v1 + v2) == v3);
+
+ QQuaternion v4(v1);
+ v4 += v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() + v2.x());
+ QCOMPARE(v4.y(), v1.y() + v2.y());
+ QCOMPARE(v4.z(), v1.z() + v2.z());
+ QCOMPARE(v4.scalar(), v1.scalar() + v2.scalar());
+}
+
+// Test subtraction for quaternions.
+void tst_QQuaternion::subtract_data()
+{
+ // Use the same test data as the add test.
+ add_data();
+}
+void tst_QQuaternion::subtract()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w2, x2, y2, z2);
+ QQuaternion v3(w3, x3, y3, z3);
+
+ QVERIFY((v3 - v1) == v2);
+ QVERIFY((v3 - v2) == v1);
+
+ QQuaternion v4(v3);
+ v4 -= v1;
+ QVERIFY(v4 == v2);
+
+ QCOMPARE(v4.x(), v3.x() - v1.x());
+ QCOMPARE(v4.y(), v3.y() - v1.y());
+ QCOMPARE(v4.z(), v3.z() - v1.z());
+ QCOMPARE(v4.scalar(), v3.scalar() - v1.scalar());
+
+ QQuaternion v5(v3);
+ v5 -= v2;
+ QVERIFY(v5 == v1);
+
+ QCOMPARE(v5.x(), v3.x() - v2.x());
+ QCOMPARE(v5.y(), v3.y() - v2.y());
+ QCOMPARE(v5.z(), v3.z() - v2.z());
+ QCOMPARE(v5.scalar(), v3.scalar() - v2.scalar());
+}
+
+// Test quaternion multiplication.
+void tst_QQuaternion::multiply_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("unitvec")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)7.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)6.0f << (qreal)8.0f;
+
+ for (qreal w = -1.0f; w <= 1.0f; w += 0.5f)
+ for (qreal x = -1.0f; x <= 1.0f; x += 0.5f)
+ for (qreal y = -1.0f; y <= 1.0f; y += 0.5f)
+ for (qreal z = -1.0f; z <= 1.0f; z += 0.5f) {
+ QTest::newRow("exhaustive")
+ << x << y << z << w
+ << z << w << y << x;
+ }
+}
+void tst_QQuaternion::multiply()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QQuaternion q1(w1, x1, y1, z1);
+ QQuaternion q2(w2, x2, y2, z2);
+
+ // Use the simple algorithm at:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q53
+ // to calculate the answer we expect to get.
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ qreal scalar = w1 * w2 - QVector3D::dotProduct(v1, v2);
+ QVector3D vector = w1 * v2 + w2 * v1 + QVector3D::crossProduct(v1, v2);
+ QQuaternion result(scalar, vector);
+
+ QVERIFY((q1 * q2) == result);
+}
+
+// Test multiplication by a factor for quaternions.
+void tst_QQuaternion::multiplyFactor_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)100.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)4.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)4.0f << (qreal)-6.0f << (qreal)8.0f;
+
+ QTest::newRow("allzero")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)4.0f
+ << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+}
+void tst_QQuaternion::multiplyFactor()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w2, x2, y2, z2);
+
+ QVERIFY((v1 * factor) == v2);
+ QVERIFY((factor * v1) == v2);
+
+ QQuaternion v3(v1);
+ v3 *= factor;
+ QVERIFY(v3 == v2);
+
+ QCOMPARE(v3.x(), v1.x() * factor);
+ QCOMPARE(v3.y(), v1.y() * factor);
+ QCOMPARE(v3.z(), v1.z() * factor);
+ QCOMPARE(v3.scalar(), v1.scalar() * factor);
+}
+
+// Test division by a factor for quaternions.
+void tst_QQuaternion::divide_data()
+{
+ // Use the same test data as the multiply test.
+ multiplyFactor_data();
+}
+void tst_QQuaternion::divide()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w2, x2, y2, z2);
+
+ if (factor == (qreal)0.0f)
+ return;
+
+ QVERIFY((v2 / factor) == v1);
+
+ QQuaternion v3(v2);
+ v3 /= factor;
+ QVERIFY(v3 == v1);
+
+ QCOMPARE(v3.x(), v2.x() / factor);
+ QCOMPARE(v3.y(), v2.y() / factor);
+ QCOMPARE(v3.z(), v2.z() / factor);
+ QCOMPARE(v3.scalar(), v2.scalar() / factor);
+}
+
+// Test negation for quaternions.
+void tst_QQuaternion::negate_data()
+{
+ // Use the same test data as the add test.
+ add_data();
+}
+void tst_QQuaternion::negate()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(-w1, -x1, -y1, -z1);
+
+ QVERIFY(-v1 == v2);
+}
+
+// Test quaternion conjugate calculations.
+void tst_QQuaternion::conjugate_data()
+{
+ // Use the same test data as the add test.
+ add_data();
+}
+void tst_QQuaternion::conjugate()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w1, -x1, -y1, -z1);
+
+ QVERIFY(v1.conjugate() == v2);
+}
+
+// Test quaternion creation from an axis and an angle.
+void tst_QQuaternion::fromAxisAndAngle_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("angle");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)90.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)180.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)270.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)45.0f;
+}
+void tst_QQuaternion::fromAxisAndAngle()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, angle);
+
+ // Use a straight-forward implementation of the algorithm at:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
+ // to calculate the answer we expect to get.
+ QVector3D vector = QVector3D(x1, y1, z1).normalized();
+ qreal sin_a = qSin((angle * M_PI / 180.0) / 2.0);
+ qreal cos_a = qCos((angle * M_PI / 180.0) / 2.0);
+ QQuaternion result((qreal)cos_a,
+ (qreal)(vector.x() * sin_a),
+ (qreal)(vector.y() * sin_a),
+ (qreal)(vector.z() * sin_a));
+ result = result.normalized();
+
+ QQuaternion answer = QQuaternion::fromAxisAndAngle(QVector3D(x1, y1, z1), angle);
+ QVERIFY(fuzzyCompare(answer.x(), result.x()));
+ QVERIFY(fuzzyCompare(answer.y(), result.y()));
+ QVERIFY(fuzzyCompare(answer.z(), result.z()));
+ QVERIFY(fuzzyCompare(answer.scalar(), result.scalar()));
+
+ answer = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle);
+ QVERIFY(fuzzyCompare(answer.x(), result.x()));
+ QVERIFY(fuzzyCompare(answer.y(), result.y()));
+ QVERIFY(fuzzyCompare(answer.z(), result.z()));
+ QVERIFY(fuzzyCompare(answer.scalar(), result.scalar()));
+}
+
+// Test spherical interpolation of quaternions.
+void tst_QQuaternion::slerp_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("angle1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("angle2");
+ QTest::addColumn<qreal>("t");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("angle3");
+
+ QTest::newRow("first")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)0.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f;
+ QTest::newRow("first2")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)-0.5f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f;
+ QTest::newRow("second")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)1.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f;
+ QTest::newRow("second2")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)1.5f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f;
+ QTest::newRow("middle")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)0.5f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)135.0f;
+ QTest::newRow("wide angle")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)0.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)270.0f
+ << (qreal)0.5f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)-45.0f;
+}
+void tst_QQuaternion::slerp()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, angle1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, angle2);
+ QFETCH(qreal, t);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, angle3);
+
+ QQuaternion q1 = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle1);
+ QQuaternion q2 = QQuaternion::fromAxisAndAngle(x2, y2, z2, angle2);
+ QQuaternion q3 = QQuaternion::fromAxisAndAngle(x3, y3, z3, angle3);
+
+ QQuaternion result = QQuaternion::slerp(q1, q2, t);
+
+ QVERIFY(fuzzyCompare(result.x(), q3.x()));
+ QVERIFY(fuzzyCompare(result.y(), q3.y()));
+ QVERIFY(fuzzyCompare(result.z(), q3.z()));
+ QVERIFY(fuzzyCompare(result.scalar(), q3.scalar()));
+}
+
+// Test normalized linear interpolation of quaternions.
+void tst_QQuaternion::nlerp_data()
+{
+ slerp_data();
+}
+void tst_QQuaternion::nlerp()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, angle1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, angle2);
+ QFETCH(qreal, t);
+
+ QQuaternion q1 = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle1);
+ QQuaternion q2 = QQuaternion::fromAxisAndAngle(x2, y2, z2, angle2);
+
+ QQuaternion result = QQuaternion::nlerp(q1, q2, t);
+
+ qreal resultx, resulty, resultz, resultscalar;
+ if (t <= 0.0f) {
+ resultx = q1.x();
+ resulty = q1.y();
+ resultz = q1.z();
+ resultscalar = q1.scalar();
+ } else if (t >= 1.0f) {
+ resultx = q2.x();
+ resulty = q2.y();
+ resultz = q2.z();
+ resultscalar = q2.scalar();
+ } else if (qAbs(angle1 - angle2) <= 180.f) {
+ resultx = q1.x() * (1 - t) + q2.x() * t;
+ resulty = q1.y() * (1 - t) + q2.y() * t;
+ resultz = q1.z() * (1 - t) + q2.z() * t;
+ resultscalar = q1.scalar() * (1 - t) + q2.scalar() * t;
+ } else {
+ // Angle greater than 180 degrees: negate q2.
+ resultx = q1.x() * (1 - t) - q2.x() * t;
+ resulty = q1.y() * (1 - t) - q2.y() * t;
+ resultz = q1.z() * (1 - t) - q2.z() * t;
+ resultscalar = q1.scalar() * (1 - t) - q2.scalar() * t;
+ }
+
+ QQuaternion q3 = QQuaternion(resultscalar, resultx, resulty, resultz).normalized();
+
+ QVERIFY(fuzzyCompare(result.x(), q3.x()));
+ QVERIFY(fuzzyCompare(result.y(), q3.y()));
+ QVERIFY(fuzzyCompare(result.z(), q3.z()));
+ QVERIFY(fuzzyCompare(result.scalar(), q3.scalar()));
+}
+
+class tst_QQuaternionProperties : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuaternion quaternion READ quaternion WRITE setQuaternion)
+public:
+ tst_QQuaternionProperties(QObject *parent = 0) : QObject(parent) {}
+
+ QQuaternion quaternion() const { return q; }
+ void setQuaternion(const QQuaternion& value) { q = value; }
+
+private:
+ QQuaternion q;
+};
+
+// Test getting and setting quaternion properties via the metaobject system.
+void tst_QQuaternion::properties()
+{
+ tst_QQuaternionProperties obj;
+
+ obj.setQuaternion(QQuaternion(6.0f, 7.0f, 8.0f, 9.0f));
+
+ QQuaternion q = qVariantValue<QQuaternion>(obj.property("quaternion"));
+ QCOMPARE(q.scalar(), (qreal)6.0f);
+ QCOMPARE(q.x(), (qreal)7.0f);
+ QCOMPARE(q.y(), (qreal)8.0f);
+ QCOMPARE(q.z(), (qreal)9.0f);
+
+ obj.setProperty("quaternion",
+ qVariantFromValue(QQuaternion(-6.0f, -7.0f, -8.0f, -9.0f)));
+
+ q = qVariantValue<QQuaternion>(obj.property("quaternion"));
+ QCOMPARE(q.scalar(), (qreal)-6.0f);
+ QCOMPARE(q.x(), (qreal)-7.0f);
+ QCOMPARE(q.y(), (qreal)-8.0f);
+ QCOMPARE(q.z(), (qreal)-9.0f);
+}
+
+void tst_QQuaternion::metaTypes()
+{
+ QVERIFY(QMetaType::type("QQuaternion") == QMetaType::QQuaternion);
+
+ QCOMPARE(QByteArray(QMetaType::typeName(QMetaType::QQuaternion)),
+ QByteArray("QQuaternion"));
+
+ QVERIFY(QMetaType::isRegistered(QMetaType::QQuaternion));
+
+ QVERIFY(qMetaTypeId<QQuaternion>() == QMetaType::QQuaternion);
+}
+
+QTEST_APPLESS_MAIN(tst_QQuaternion)
+
+#include "tst_qquaternion.moc"
diff --git a/tests/auto/gui/math3d/qvectornd/qvectornd.pro b/tests/auto/gui/math3d/qvectornd/qvectornd.pro
new file mode 100644
index 0000000000..6346199444
--- /dev/null
+++ b/tests/auto/gui/math3d/qvectornd/qvectornd.pro
@@ -0,0 +1,2 @@
+load(qttest_p4)
+SOURCES += tst_qvectornd.cpp
diff --git a/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp b/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp
new file mode 100644
index 0000000000..37c1949dc2
--- /dev/null
+++ b/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp
@@ -0,0 +1,2142 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qmath.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+
+class tst_QVectorND : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QVectorND() {}
+ ~tst_QVectorND() {}
+
+private slots:
+ void create2();
+ void create3();
+ void create4();
+
+ void length2_data();
+ void length2();
+ void length3_data();
+ void length3();
+ void length4_data();
+ void length4();
+
+ void normalized2_data();
+ void normalized2();
+ void normalized3_data();
+ void normalized3();
+ void normalized4_data();
+ void normalized4();
+
+ void normalize2_data();
+ void normalize2();
+ void normalize3_data();
+ void normalize3();
+ void normalize4_data();
+ void normalize4();
+
+ void compare2();
+ void compare3();
+ void compare4();
+
+ void add2_data();
+ void add2();
+ void add3_data();
+ void add3();
+ void add4_data();
+ void add4();
+
+ void subtract2_data();
+ void subtract2();
+ void subtract3_data();
+ void subtract3();
+ void subtract4_data();
+ void subtract4();
+
+ void multiply2_data();
+ void multiply2();
+ void multiply3_data();
+ void multiply3();
+ void multiply4_data();
+ void multiply4();
+
+ void multiplyFactor2_data();
+ void multiplyFactor2();
+ void multiplyFactor3_data();
+ void multiplyFactor3();
+ void multiplyFactor4_data();
+ void multiplyFactor4();
+
+ void divide2_data();
+ void divide2();
+ void divide3_data();
+ void divide3();
+ void divide4_data();
+ void divide4();
+
+ void negate2_data();
+ void negate2();
+ void negate3_data();
+ void negate3();
+ void negate4_data();
+ void negate4();
+
+ void crossProduct_data();
+ void crossProduct();
+ void normal_data();
+ void normal();
+ void distanceToPlane_data();
+ void distanceToPlane();
+ void distanceToLine_data();
+ void distanceToLine();
+
+ void dotProduct2_data();
+ void dotProduct2();
+ void dotProduct3_data();
+ void dotProduct3();
+ void dotProduct4_data();
+ void dotProduct4();
+
+ void properties();
+ void metaTypes();
+};
+
+// QVector2/3/4D use float internally, which can sometimes lead
+// to precision issues when converting to and from qreal.
+// This fuzzy compare is slightly "fuzzier" than the default
+// qFuzzyCompare for qreal to compensate.
+static bool fuzzyCompare(qreal x, qreal y)
+{
+ return qFuzzyIsNull((float)(x - y));
+}
+
+// Test the creation of QVector2D objects in various ways:
+// construct, copy, and modify.
+void tst_QVectorND::create2()
+{
+ QVector2D null;
+ QCOMPARE(null.x(), (qreal)0.0f);
+ QCOMPARE(null.y(), (qreal)0.0f);
+ QVERIFY(null.isNull());
+
+ QVector2D v1(1.0f, 2.5f);
+ QCOMPARE(v1.x(), (qreal)1.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QVERIFY(!v1.isNull());
+
+ QVector2D v1i(1, 2);
+ QCOMPARE(v1i.x(), (qreal)1.0f);
+ QCOMPARE(v1i.y(), (qreal)2.0f);
+ QVERIFY(!v1i.isNull());
+
+ QVector2D v2(v1);
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.5f);
+ QVERIFY(!v2.isNull());
+
+ QVector2D v4;
+ QCOMPARE(v4.x(), (qreal)0.0f);
+ QCOMPARE(v4.y(), (qreal)0.0f);
+ QVERIFY(v4.isNull());
+ v4 = v1;
+ QCOMPARE(v4.x(), (qreal)1.0f);
+ QCOMPARE(v4.y(), (qreal)2.5f);
+ QVERIFY(!v4.isNull());
+
+ QVector2D v5(QPoint(1, 2));
+ QCOMPARE(v5.x(), (qreal)1.0f);
+ QCOMPARE(v5.y(), (qreal)2.0f);
+ QVERIFY(!v5.isNull());
+
+ QVector2D v6(QPointF(1, 2.5));
+ QCOMPARE(v6.x(), (qreal)1.0f);
+ QCOMPARE(v6.y(), (qreal)2.5f);
+ QVERIFY(!v6.isNull());
+
+ QVector2D v7(QVector3D(1.0f, 2.5f, 54.25f));
+ QCOMPARE(v7.x(), (qreal)1.0f);
+ QCOMPARE(v7.y(), (qreal)2.5f);
+ QVERIFY(!v6.isNull());
+
+ QVector2D v8(QVector4D(1.0f, 2.5f, 54.25f, 34.0f));
+ QCOMPARE(v8.x(), (qreal)1.0f);
+ QCOMPARE(v8.y(), (qreal)2.5f);
+ QVERIFY(!v6.isNull());
+
+ v1.setX(3.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QVERIFY(!v1.isNull());
+
+ v1.setY(10.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QVERIFY(!v1.isNull());
+
+ v1.setX(0.0f);
+ v1.setY(0.0f);
+ QCOMPARE(v1.x(), (qreal)0.0f);
+ QCOMPARE(v1.y(), (qreal)0.0f);
+ QVERIFY(v1.isNull());
+
+ QPoint p1 = v8.toPoint();
+ QCOMPARE(p1.x(), 1);
+ QCOMPARE(p1.y(), 3);
+
+ QPointF p2 = v8.toPointF();
+ QCOMPARE((qreal)p2.x(), (qreal)1.0f);
+ QCOMPARE((qreal)p2.y(), (qreal)2.5f);
+
+ QVector3D v9 = v8.toVector3D();
+ QCOMPARE(v9.x(), (qreal)1.0f);
+ QCOMPARE(v9.y(), (qreal)2.5f);
+ QCOMPARE(v9.z(), (qreal)0.0f);
+
+ QVector4D v10 = v8.toVector4D();
+ QCOMPARE(v10.x(), (qreal)1.0f);
+ QCOMPARE(v10.y(), (qreal)2.5f);
+ QCOMPARE(v10.z(), (qreal)0.0f);
+ QCOMPARE(v10.w(), (qreal)0.0f);
+}
+
+// Test the creation of QVector3D objects in various ways:
+// construct, copy, and modify.
+void tst_QVectorND::create3()
+{
+ QVector3D null;
+ QCOMPARE(null.x(), (qreal)0.0f);
+ QCOMPARE(null.y(), (qreal)0.0f);
+ QCOMPARE(null.z(), (qreal)0.0f);
+ QVERIFY(null.isNull());
+
+ QVector3D v1(1.0f, 2.5f, -89.25f);
+ QCOMPARE(v1.x(), (qreal)1.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QVERIFY(!v1.isNull());
+
+ QVector3D v1i(1, 2, -89);
+ QCOMPARE(v1i.x(), (qreal)1.0f);
+ QCOMPARE(v1i.y(), (qreal)2.0f);
+ QCOMPARE(v1i.z(), (qreal)-89.0f);
+ QVERIFY(!v1i.isNull());
+
+ QVector3D v2(v1);
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.5f);
+ QCOMPARE(v2.z(), (qreal)-89.25f);
+ QVERIFY(!v2.isNull());
+
+ QVector3D v3(1.0f, 2.5f, 0.0f);
+ QCOMPARE(v3.x(), (qreal)1.0f);
+ QCOMPARE(v3.y(), (qreal)2.5f);
+ QCOMPARE(v3.z(), (qreal)0.0f);
+ QVERIFY(!v3.isNull());
+
+ QVector3D v3i(1, 2, 0);
+ QCOMPARE(v3i.x(), (qreal)1.0f);
+ QCOMPARE(v3i.y(), (qreal)2.0f);
+ QCOMPARE(v3i.z(), (qreal)0.0f);
+ QVERIFY(!v3i.isNull());
+
+ QVector3D v4;
+ QCOMPARE(v4.x(), (qreal)0.0f);
+ QCOMPARE(v4.y(), (qreal)0.0f);
+ QCOMPARE(v4.z(), (qreal)0.0f);
+ QVERIFY(v4.isNull());
+ v4 = v1;
+ QCOMPARE(v4.x(), (qreal)1.0f);
+ QCOMPARE(v4.y(), (qreal)2.5f);
+ QCOMPARE(v4.z(), (qreal)-89.25f);
+ QVERIFY(!v4.isNull());
+
+ QVector3D v5(QPoint(1, 2));
+ QCOMPARE(v5.x(), (qreal)1.0f);
+ QCOMPARE(v5.y(), (qreal)2.0f);
+ QCOMPARE(v5.z(), (qreal)0.0f);
+ QVERIFY(!v5.isNull());
+
+ QVector3D v6(QPointF(1, 2.5));
+ QCOMPARE(v6.x(), (qreal)1.0f);
+ QCOMPARE(v6.y(), (qreal)2.5f);
+ QCOMPARE(v6.z(), (qreal)0.0f);
+ QVERIFY(!v6.isNull());
+
+ QVector3D v7(QVector2D(1.0f, 2.5f));
+ QCOMPARE(v7.x(), (qreal)1.0f);
+ QCOMPARE(v7.y(), (qreal)2.5f);
+ QCOMPARE(v7.z(), (qreal)0.0f);
+ QVERIFY(!v7.isNull());
+
+ QVector3D v8(QVector2D(1.0f, 2.5f), 54.25f);
+ QCOMPARE(v8.x(), (qreal)1.0f);
+ QCOMPARE(v8.y(), (qreal)2.5f);
+ QCOMPARE(v8.z(), (qreal)54.25f);
+ QVERIFY(!v8.isNull());
+
+ QVector3D v9(QVector4D(1.0f, 2.5f, 54.25f, 34.0f));
+ QCOMPARE(v9.x(), (qreal)1.0f);
+ QCOMPARE(v9.y(), (qreal)2.5f);
+ QCOMPARE(v9.z(), (qreal)54.25f);
+ QVERIFY(!v9.isNull());
+
+ v1.setX(3.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QVERIFY(!v1.isNull());
+
+ v1.setY(10.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QVERIFY(!v1.isNull());
+
+ v1.setZ(15.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QVERIFY(!v1.isNull());
+
+ v1.setX(0.0f);
+ v1.setY(0.0f);
+ v1.setZ(0.0f);
+ QCOMPARE(v1.x(), (qreal)0.0f);
+ QCOMPARE(v1.y(), (qreal)0.0f);
+ QCOMPARE(v1.z(), (qreal)0.0f);
+ QVERIFY(v1.isNull());
+
+ QPoint p1 = v8.toPoint();
+ QCOMPARE(p1.x(), 1);
+ QCOMPARE(p1.y(), 3);
+
+ QPointF p2 = v8.toPointF();
+ QCOMPARE((qreal)p2.x(), (qreal)1.0f);
+ QCOMPARE((qreal)p2.y(), (qreal)2.5f);
+
+ QVector2D v10 = v8.toVector2D();
+ QCOMPARE(v10.x(), (qreal)1.0f);
+ QCOMPARE(v10.y(), (qreal)2.5f);
+
+ QVector4D v11 = v8.toVector4D();
+ QCOMPARE(v11.x(), (qreal)1.0f);
+ QCOMPARE(v11.y(), (qreal)2.5f);
+ QCOMPARE(v11.z(), (qreal)54.25f);
+ QCOMPARE(v11.w(), (qreal)0.0f);
+}
+
+// Test the creation of QVector4D objects in various ways:
+// construct, copy, and modify.
+void tst_QVectorND::create4()
+{
+ QVector4D null;
+ QCOMPARE(null.x(), (qreal)0.0f);
+ QCOMPARE(null.y(), (qreal)0.0f);
+ QCOMPARE(null.z(), (qreal)0.0f);
+ QCOMPARE(null.w(), (qreal)0.0f);
+ QVERIFY(null.isNull());
+
+ QVector4D v1(1.0f, 2.5f, -89.25f, 34.0f);
+ QCOMPARE(v1.x(), (qreal)1.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.w(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ QVector4D v1i(1, 2, -89, 34);
+ QCOMPARE(v1i.x(), (qreal)1.0f);
+ QCOMPARE(v1i.y(), (qreal)2.0f);
+ QCOMPARE(v1i.z(), (qreal)-89.0f);
+ QCOMPARE(v1i.w(), (qreal)34.0f);
+ QVERIFY(!v1i.isNull());
+
+ QVector4D v2(v1);
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.5f);
+ QCOMPARE(v2.z(), (qreal)-89.25f);
+ QCOMPARE(v2.w(), (qreal)34.0f);
+ QVERIFY(!v2.isNull());
+
+ QVector4D v3(1.0f, 2.5f, 0.0f, 0.0f);
+ QCOMPARE(v3.x(), (qreal)1.0f);
+ QCOMPARE(v3.y(), (qreal)2.5f);
+ QCOMPARE(v3.z(), (qreal)0.0f);
+ QCOMPARE(v3.w(), (qreal)0.0f);
+ QVERIFY(!v3.isNull());
+
+ QVector4D v3i(1, 2, 0, 0);
+ QCOMPARE(v3i.x(), (qreal)1.0f);
+ QCOMPARE(v3i.y(), (qreal)2.0f);
+ QCOMPARE(v3i.z(), (qreal)0.0f);
+ QCOMPARE(v3i.w(), (qreal)0.0f);
+ QVERIFY(!v3i.isNull());
+
+ QVector4D v3b(1.0f, 2.5f, -89.25f, 0.0f);
+ QCOMPARE(v3b.x(), (qreal)1.0f);
+ QCOMPARE(v3b.y(), (qreal)2.5f);
+ QCOMPARE(v3b.z(), (qreal)-89.25f);
+ QCOMPARE(v3b.w(), (qreal)0.0f);
+ QVERIFY(!v3b.isNull());
+
+ QVector4D v3bi(1, 2, -89, 0);
+ QCOMPARE(v3bi.x(), (qreal)1.0f);
+ QCOMPARE(v3bi.y(), (qreal)2.0f);
+ QCOMPARE(v3bi.z(), (qreal)-89.0f);
+ QCOMPARE(v3bi.w(), (qreal)0.0f);
+ QVERIFY(!v3bi.isNull());
+
+ QVector4D v4;
+ QCOMPARE(v4.x(), (qreal)0.0f);
+ QCOMPARE(v4.y(), (qreal)0.0f);
+ QCOMPARE(v4.z(), (qreal)0.0f);
+ QCOMPARE(v4.w(), (qreal)0.0f);
+ QVERIFY(v4.isNull());
+ v4 = v1;
+ QCOMPARE(v4.x(), (qreal)1.0f);
+ QCOMPARE(v4.y(), (qreal)2.5f);
+ QCOMPARE(v4.z(), (qreal)-89.25f);
+ QCOMPARE(v4.w(), (qreal)34.0f);
+ QVERIFY(!v4.isNull());
+
+ QVector4D v5(QPoint(1, 2));
+ QCOMPARE(v5.x(), (qreal)1.0f);
+ QCOMPARE(v5.y(), (qreal)2.0f);
+ QCOMPARE(v5.z(), (qreal)0.0f);
+ QCOMPARE(v5.w(), (qreal)0.0f);
+ QVERIFY(!v5.isNull());
+
+ QVector4D v6(QPointF(1, 2.5));
+ QCOMPARE(v6.x(), (qreal)1.0f);
+ QCOMPARE(v6.y(), (qreal)2.5f);
+ QCOMPARE(v6.z(), (qreal)0.0f);
+ QCOMPARE(v6.w(), (qreal)0.0f);
+ QVERIFY(!v6.isNull());
+
+ QVector4D v7(QVector2D(1.0f, 2.5f));
+ QCOMPARE(v7.x(), (qreal)1.0f);
+ QCOMPARE(v7.y(), (qreal)2.5f);
+ QCOMPARE(v7.z(), (qreal)0.0f);
+ QCOMPARE(v7.w(), (qreal)0.0f);
+ QVERIFY(!v7.isNull());
+
+ QVector4D v8(QVector3D(1.0f, 2.5f, -89.25f));
+ QCOMPARE(v8.x(), (qreal)1.0f);
+ QCOMPARE(v8.y(), (qreal)2.5f);
+ QCOMPARE(v8.z(), (qreal)-89.25f);
+ QCOMPARE(v8.w(), (qreal)0.0f);
+ QVERIFY(!v8.isNull());
+
+ QVector4D v9(QVector3D(1.0f, 2.5f, -89.25f), 34);
+ QCOMPARE(v9.x(), (qreal)1.0f);
+ QCOMPARE(v9.y(), (qreal)2.5f);
+ QCOMPARE(v9.z(), (qreal)-89.25f);
+ QCOMPARE(v9.w(), (qreal)34.0f);
+ QVERIFY(!v9.isNull());
+
+ QVector4D v10(QVector2D(1.0f, 2.5f), 23.5f, -8);
+ QCOMPARE(v10.x(), (qreal)1.0f);
+ QCOMPARE(v10.y(), (qreal)2.5f);
+ QCOMPARE(v10.z(), (qreal)23.5f);
+ QCOMPARE(v10.w(), (qreal)-8.0f);
+ QVERIFY(!v10.isNull());
+
+ v1.setX(3.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.w(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setY(10.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.w(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setZ(15.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QCOMPARE(v1.w(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setW(6.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QCOMPARE(v1.w(), (qreal)6.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setX(0.0f);
+ v1.setY(0.0f);
+ v1.setZ(0.0f);
+ v1.setW(0.0f);
+ QCOMPARE(v1.x(), (qreal)0.0f);
+ QCOMPARE(v1.y(), (qreal)0.0f);
+ QCOMPARE(v1.z(), (qreal)0.0f);
+ QCOMPARE(v1.w(), (qreal)0.0f);
+ QVERIFY(v1.isNull());
+
+ QPoint p1 = v8.toPoint();
+ QCOMPARE(p1.x(), 1);
+ QCOMPARE(p1.y(), 3);
+
+ QPointF p2 = v8.toPointF();
+ QCOMPARE((qreal)p2.x(), (qreal)1.0f);
+ QCOMPARE((qreal)p2.y(), (qreal)2.5f);
+
+ QVector2D v11 = v8.toVector2D();
+ QCOMPARE(v11.x(), (qreal)1.0f);
+ QCOMPARE(v11.y(), (qreal)2.5f);
+
+ QVector3D v12 = v8.toVector3D();
+ QCOMPARE(v12.x(), (qreal)1.0f);
+ QCOMPARE(v12.y(), (qreal)2.5f);
+ QCOMPARE(v12.z(), (qreal)-89.25f);
+
+ QVector2D v13 = v9.toVector2DAffine();
+ QVERIFY(fuzzyCompare(v13.x(), (qreal)(1.0f / 34.0f)));
+ QVERIFY(fuzzyCompare(v13.y(), (qreal)(2.5f / 34.0f)));
+
+ QVector4D zerow(1.0f, 2.0f, 3.0f, 0.0f);
+ v13 = zerow.toVector2DAffine();
+ QVERIFY(v13.isNull());
+
+ QVector3D v14 = v9.toVector3DAffine();
+ QVERIFY(fuzzyCompare(v14.x(), (qreal)(1.0f / 34.0f)));
+ QVERIFY(fuzzyCompare(v14.y(), (qreal)(2.5f / 34.0f)));
+ QVERIFY(fuzzyCompare(v14.z(), (qreal)(-89.25f / 34.0f)));
+
+ v14 = zerow.toVector3DAffine();
+ QVERIFY(v14.isNull());
+}
+
+// Test vector length computation for 2D vectors.
+void tst_QVectorND::length2_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("len");
+
+ QTest::newRow("null") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("1x") << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1y") << (qreal)0.0f << (qreal)1.0f << (qreal)1.0f;
+ QTest::newRow("-1x") << (qreal)-1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1y") << (qreal)0.0f << (qreal)-1.0f << (qreal)1.0f;
+ QTest::newRow("two") << (qreal)2.0f << (qreal)-2.0f << (qreal)qSqrt(8.0f);
+}
+void tst_QVectorND::length2()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, len);
+
+ QVector2D v(x, y);
+ QCOMPARE(v.length(), len);
+ QCOMPARE(v.lengthSquared(), x * x + y * y);
+}
+
+// Test vector length computation for 3D vectors.
+void tst_QVectorND::length3_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<qreal>("len");
+
+ QTest::newRow("null") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("1x") << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1y") << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1z") << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)1.0f;
+ QTest::newRow("-1x") << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1y") << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1z") << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)1.0f;
+ QTest::newRow("two") << (qreal)2.0f << (qreal)-2.0f << (qreal)2.0f << (qreal)qSqrt(12.0f);
+}
+void tst_QVectorND::length3()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, len);
+
+ QVector3D v(x, y, z);
+ QCOMPARE(v.length(), len);
+ QCOMPARE(v.lengthSquared(), x * x + y * y + z * z);
+}
+
+// Test vector length computation for 4D vectors.
+void tst_QVectorND::length4_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<qreal>("w");
+ QTest::addColumn<qreal>("len");
+
+ QTest::newRow("null") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("1x") << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1y") << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1z") << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1w") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)1.0f;
+ QTest::newRow("-1x") << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1y") << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1z") << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1w") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)1.0f;
+ QTest::newRow("two") << (qreal)2.0f << (qreal)-2.0f << (qreal)2.0f << (qreal)2.0f << (qreal)qSqrt(16.0f);
+}
+void tst_QVectorND::length4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+ QFETCH(qreal, len);
+
+ QVector4D v(x, y, z, w);
+ QCOMPARE(v.length(), len);
+ QCOMPARE(v.lengthSquared(), x * x + y * y + z * z + w * w);
+}
+
+// Test the unit vector conversion for 2D vectors.
+void tst_QVectorND::normalized2_data()
+{
+ // Use the same test data as the length test.
+ length2_data();
+}
+void tst_QVectorND::normalized2()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, len);
+
+ QVector2D v(x, y);
+ QVector2D u = v.normalized();
+ if (v.isNull())
+ QVERIFY(u.isNull());
+ else
+ QVERIFY(fuzzyCompare(u.length(), qreal(1.0f)));
+ QVERIFY(fuzzyCompare(u.x() * len, v.x()));
+ QVERIFY(fuzzyCompare(u.y() * len, v.y()));
+}
+
+// Test the unit vector conversion for 3D vectors.
+void tst_QVectorND::normalized3_data()
+{
+ // Use the same test data as the length test.
+ length3_data();
+}
+void tst_QVectorND::normalized3()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, len);
+
+ QVector3D v(x, y, z);
+ QVector3D u = v.normalized();
+ if (v.isNull())
+ QVERIFY(u.isNull());
+ else
+ QVERIFY(fuzzyCompare(u.length(), qreal(1.0f)));
+ QVERIFY(fuzzyCompare(u.x() * len, v.x()));
+ QVERIFY(fuzzyCompare(u.y() * len, v.y()));
+ QVERIFY(fuzzyCompare(u.z() * len, v.z()));
+}
+
+// Test the unit vector conversion for 4D vectors.
+void tst_QVectorND::normalized4_data()
+{
+ // Use the same test data as the length test.
+ length4_data();
+}
+void tst_QVectorND::normalized4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+ QFETCH(qreal, len);
+
+ QVector4D v(x, y, z, w);
+ QVector4D u = v.normalized();
+ if (v.isNull())
+ QVERIFY(u.isNull());
+ else
+ QVERIFY(fuzzyCompare(u.length(), qreal(1.0f)));
+ QVERIFY(fuzzyCompare(u.x() * len, v.x()));
+ QVERIFY(fuzzyCompare(u.y() * len, v.y()));
+ QVERIFY(fuzzyCompare(u.z() * len, v.z()));
+ QVERIFY(fuzzyCompare(u.w() * len, v.w()));
+}
+
+// Test the unit vector conversion for 2D vectors.
+void tst_QVectorND::normalize2_data()
+{
+ // Use the same test data as the length test.
+ length2_data();
+}
+void tst_QVectorND::normalize2()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+
+ QVector2D v(x, y);
+ bool isNull = v.isNull();
+ v.normalize();
+ if (isNull)
+ QVERIFY(v.isNull());
+ else
+ QVERIFY(fuzzyCompare(v.length(), qreal(1.0f)));
+}
+
+// Test the unit vector conversion for 3D vectors.
+void tst_QVectorND::normalize3_data()
+{
+ // Use the same test data as the length test.
+ length3_data();
+}
+void tst_QVectorND::normalize3()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+
+ QVector3D v(x, y, z);
+ bool isNull = v.isNull();
+ v.normalize();
+ if (isNull)
+ QVERIFY(v.isNull());
+ else
+ QVERIFY(fuzzyCompare(v.length(), qreal(1.0f)));
+}
+
+// Test the unit vector conversion for 4D vectors.
+void tst_QVectorND::normalize4_data()
+{
+ // Use the same test data as the length test.
+ length4_data();
+}
+void tst_QVectorND::normalize4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+
+ QVector4D v(x, y, z, w);
+ bool isNull = v.isNull();
+ v.normalize();
+ if (isNull)
+ QVERIFY(v.isNull());
+ else
+ QVERIFY(fuzzyCompare(v.length(), qreal(1.0f)));
+}
+
+// Test the comparison operators for 2D vectors.
+void tst_QVectorND::compare2()
+{
+ QVector2D v1(1, 2);
+ QVector2D v2(1, 2);
+ QVector2D v3(3, 2);
+ QVector2D v4(1, 3);
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 != v3);
+ QVERIFY(v1 != v4);
+}
+
+// Test the comparison operators for 3D vectors.
+void tst_QVectorND::compare3()
+{
+ QVector3D v1(1, 2, 4);
+ QVector3D v2(1, 2, 4);
+ QVector3D v3(3, 2, 4);
+ QVector3D v4(1, 3, 4);
+ QVector3D v5(1, 2, 3);
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 != v3);
+ QVERIFY(v1 != v4);
+ QVERIFY(v1 != v5);
+}
+
+// Test the comparison operators for 4D vectors.
+void tst_QVectorND::compare4()
+{
+ QVector4D v1(1, 2, 4, 8);
+ QVector4D v2(1, 2, 4, 8);
+ QVector4D v3(3, 2, 4, 8);
+ QVector4D v4(1, 3, 4, 8);
+ QVector4D v5(1, 2, 3, 8);
+ QVector4D v6(1, 2, 4, 3);
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 != v3);
+ QVERIFY(v1 != v4);
+ QVERIFY(v1 != v5);
+ QVERIFY(v1 != v6);
+}
+
+// Test vector addition for 2D vectors.
+void tst_QVectorND::add2_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f
+ << (qreal)3.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)3.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)4.0f << (qreal)5.0f
+ << (qreal)5.0f << (qreal)7.0f;
+}
+void tst_QVectorND::add2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+ QVector2D v3(x3, y3);
+
+ QVERIFY((v1 + v2) == v3);
+
+ QVector2D v4(v1);
+ v4 += v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() + v2.x());
+ QCOMPARE(v4.y(), v1.y() + v2.y());
+}
+
+// Test vector addition for 3D vectors.
+void tst_QVectorND::add3_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f
+ << (qreal)5.0f << (qreal)7.0f << (qreal)-3.0f;
+}
+void tst_QVectorND::add3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVERIFY((v1 + v2) == v3);
+
+ QVector3D v4(v1);
+ v4 += v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() + v2.x());
+ QCOMPARE(v4.y(), v1.y() + v2.y());
+ QCOMPARE(v4.z(), v1.z() + v2.z());
+}
+
+// Test vector addition for 4D vectors.
+void tst_QVectorND::add4_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("w3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)8.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f << (qreal)9.0f
+ << (qreal)5.0f << (qreal)7.0f << (qreal)-3.0f << (qreal)17.0f;
+}
+void tst_QVectorND::add4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+ QVector4D v3(x3, y3, z3, w3);
+
+ QVERIFY((v1 + v2) == v3);
+
+ QVector4D v4(v1);
+ v4 += v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() + v2.x());
+ QCOMPARE(v4.y(), v1.y() + v2.y());
+ QCOMPARE(v4.z(), v1.z() + v2.z());
+ QCOMPARE(v4.w(), v1.w() + v2.w());
+}
+
+// Test vector subtraction for 2D vectors.
+void tst_QVectorND::subtract2_data()
+{
+ // Use the same test data as the add test.
+ add2_data();
+}
+void tst_QVectorND::subtract2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+ QVector2D v3(x3, y3);
+
+ QVERIFY((v3 - v1) == v2);
+ QVERIFY((v3 - v2) == v1);
+
+ QVector2D v4(v3);
+ v4 -= v1;
+ QVERIFY(v4 == v2);
+
+ QCOMPARE(v4.x(), v3.x() - v1.x());
+ QCOMPARE(v4.y(), v3.y() - v1.y());
+
+ QVector2D v5(v3);
+ v5 -= v2;
+ QVERIFY(v5 == v1);
+
+ QCOMPARE(v5.x(), v3.x() - v2.x());
+ QCOMPARE(v5.y(), v3.y() - v2.y());
+}
+
+// Test vector subtraction for 3D vectors.
+void tst_QVectorND::subtract3_data()
+{
+ // Use the same test data as the add test.
+ add3_data();
+}
+void tst_QVectorND::subtract3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVERIFY((v3 - v1) == v2);
+ QVERIFY((v3 - v2) == v1);
+
+ QVector3D v4(v3);
+ v4 -= v1;
+ QVERIFY(v4 == v2);
+
+ QCOMPARE(v4.x(), v3.x() - v1.x());
+ QCOMPARE(v4.y(), v3.y() - v1.y());
+ QCOMPARE(v4.z(), v3.z() - v1.z());
+
+ QVector3D v5(v3);
+ v5 -= v2;
+ QVERIFY(v5 == v1);
+
+ QCOMPARE(v5.x(), v3.x() - v2.x());
+ QCOMPARE(v5.y(), v3.y() - v2.y());
+ QCOMPARE(v5.z(), v3.z() - v2.z());
+}
+
+// Test vector subtraction for 4D vectors.
+void tst_QVectorND::subtract4_data()
+{
+ // Use the same test data as the add test.
+ add4_data();
+}
+void tst_QVectorND::subtract4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+ QVector4D v3(x3, y3, z3, w3);
+
+ QVERIFY((v3 - v1) == v2);
+ QVERIFY((v3 - v2) == v1);
+
+ QVector4D v4(v3);
+ v4 -= v1;
+ QVERIFY(v4 == v2);
+
+ QCOMPARE(v4.x(), v3.x() - v1.x());
+ QCOMPARE(v4.y(), v3.y() - v1.y());
+ QCOMPARE(v4.z(), v3.z() - v1.z());
+ QCOMPARE(v4.w(), v3.w() - v1.w());
+
+ QVector4D v5(v3);
+ v5 -= v2;
+ QVERIFY(v5 == v1);
+
+ QCOMPARE(v5.x(), v3.x() - v2.x());
+ QCOMPARE(v5.y(), v3.y() - v2.y());
+ QCOMPARE(v5.z(), v3.z() - v2.z());
+ QCOMPARE(v5.w(), v3.w() - v2.w());
+}
+
+// Test component-wise vector multiplication for 2D vectors.
+void tst_QVectorND::multiply2_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)4.0f << (qreal)5.0f
+ << (qreal)4.0f << (qreal)10.0f;
+}
+void tst_QVectorND::multiply2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+ QVector2D v3(x3, y3);
+
+ QVERIFY((v1 * v2) == v3);
+
+ QVector2D v4(v1);
+ v4 *= v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() * v2.x());
+ QCOMPARE(v4.y(), v1.y() * v2.y());
+}
+
+// Test component-wise vector multiplication for 3D vectors.
+void tst_QVectorND::multiply3_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f
+ << (qreal)4.0f << (qreal)10.0f << (qreal)-18.0f;
+}
+void tst_QVectorND::multiply3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVERIFY((v1 * v2) == v3);
+
+ QVector3D v4(v1);
+ v4 *= v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() * v2.x());
+ QCOMPARE(v4.y(), v1.y() * v2.y());
+ QCOMPARE(v4.z(), v1.z() * v2.z());
+}
+
+// Test component-wise vector multiplication for 4D vectors.
+void tst_QVectorND::multiply4_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("w3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)8.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f << (qreal)9.0f
+ << (qreal)4.0f << (qreal)10.0f << (qreal)-18.0f << (qreal)72.0f;
+}
+void tst_QVectorND::multiply4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+ QVector4D v3(x3, y3, z3, w3);
+
+ QVERIFY((v1 * v2) == v3);
+
+ QVector4D v4(v1);
+ v4 *= v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() * v2.x());
+ QCOMPARE(v4.y(), v1.y() * v2.y());
+ QCOMPARE(v4.z(), v1.z() * v2.z());
+ QCOMPARE(v4.w(), v1.w() * v2.w());
+}
+
+// Test vector multiplication by a factor for 2D vectors.
+void tst_QVectorND::multiplyFactor2_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)100.0f
+ << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)4.0f;
+
+ QTest::newRow("allzero")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f;
+}
+void tst_QVectorND::multiplyFactor2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+
+ QVERIFY((v1 * factor) == v2);
+ QVERIFY((factor * v1) == v2);
+
+ QVector2D v3(v1);
+ v3 *= factor;
+ QVERIFY(v3 == v2);
+
+ QCOMPARE(v3.x(), v1.x() * factor);
+ QCOMPARE(v3.y(), v1.y() * factor);
+}
+
+// Test vector multiplication by a factor for 3D vectors.
+void tst_QVectorND::multiplyFactor3_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)100.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)4.0f << (qreal)-6.0f;
+
+ QTest::newRow("allzero")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f
+ << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+}
+void tst_QVectorND::multiplyFactor3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+
+ QVERIFY((v1 * factor) == v2);
+ QVERIFY((factor * v1) == v2);
+
+ QVector3D v3(v1);
+ v3 *= factor;
+ QVERIFY(v3 == v2);
+
+ QCOMPARE(v3.x(), v1.x() * factor);
+ QCOMPARE(v3.y(), v1.y() * factor);
+ QCOMPARE(v3.z(), v1.z() * factor);
+}
+
+// Test vector multiplication by a factor for 4D vectors.
+void tst_QVectorND::multiplyFactor4_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)100.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)4.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)4.0f << (qreal)-6.0f << (qreal)8.0f;
+
+ QTest::newRow("allzero")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)4.0f
+ << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+}
+void tst_QVectorND::multiplyFactor4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+
+ QVERIFY((v1 * factor) == v2);
+ QVERIFY((factor * v1) == v2);
+
+ QVector4D v3(v1);
+ v3 *= factor;
+ QVERIFY(v3 == v2);
+
+ QCOMPARE(v3.x(), v1.x() * factor);
+ QCOMPARE(v3.y(), v1.y() * factor);
+ QCOMPARE(v3.z(), v1.z() * factor);
+ QCOMPARE(v3.w(), v1.w() * factor);
+}
+
+// Test vector division by a factor for 2D vectors.
+void tst_QVectorND::divide2_data()
+{
+ // Use the same test data as the multiply test.
+ multiplyFactor2_data();
+}
+void tst_QVectorND::divide2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+
+ if (factor == (qreal)0.0f)
+ return;
+
+ QVERIFY((v2 / factor) == v1);
+
+ QVector2D v3(v2);
+ v3 /= factor;
+ QVERIFY(v3 == v1);
+
+ QCOMPARE(v3.x(), v2.x() / factor);
+ QCOMPARE(v3.y(), v2.y() / factor);
+}
+
+// Test vector division by a factor for 3D vectors.
+void tst_QVectorND::divide3_data()
+{
+ // Use the same test data as the multiply test.
+ multiplyFactor3_data();
+}
+void tst_QVectorND::divide3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+
+ if (factor == (qreal)0.0f)
+ return;
+
+ QVERIFY((v2 / factor) == v1);
+
+ QVector3D v3(v2);
+ v3 /= factor;
+ QVERIFY(v3 == v1);
+
+ QCOMPARE(v3.x(), v2.x() / factor);
+ QCOMPARE(v3.y(), v2.y() / factor);
+ QCOMPARE(v3.z(), v2.z() / factor);
+}
+
+// Test vector division by a factor for 4D vectors.
+void tst_QVectorND::divide4_data()
+{
+ // Use the same test data as the multiply test.
+ multiplyFactor4_data();
+}
+void tst_QVectorND::divide4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+
+ if (factor == (qreal)0.0f)
+ return;
+
+ QVERIFY((v2 / factor) == v1);
+
+ QVector4D v3(v2);
+ v3 /= factor;
+ QVERIFY(v3 == v1);
+
+ QCOMPARE(v3.x(), v2.x() / factor);
+ QCOMPARE(v3.y(), v2.y() / factor);
+ QCOMPARE(v3.z(), v2.z() / factor);
+ QCOMPARE(v3.w(), v2.w() / factor);
+}
+
+// Test vector negation for 2D vectors.
+void tst_QVectorND::negate2_data()
+{
+ // Use the same test data as the add test.
+ add2_data();
+}
+void tst_QVectorND::negate2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(-x1, -y1);
+
+ QVERIFY(-v1 == v2);
+}
+
+// Test vector negation for 3D vectors.
+void tst_QVectorND::negate3_data()
+{
+ // Use the same test data as the add test.
+ add3_data();
+}
+void tst_QVectorND::negate3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(-x1, -y1, -z1);
+
+ QVERIFY(-v1 == v2);
+}
+
+// Test vector negation for 4D vectors.
+void tst_QVectorND::negate4_data()
+{
+ // Use the same test data as the add test.
+ add4_data();
+}
+void tst_QVectorND::negate4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(-x1, -y1, -z1, -w1);
+
+ QVERIFY(-v1 == v2);
+}
+
+// Test the computation of vector cross-products.
+void tst_QVectorND::crossProduct_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("dot");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("unitvec")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)6.0f
+ << (qreal)-3.0f << (qreal)6.0f << (qreal)-3.0f
+ << (qreal)32.0f;
+}
+void tst_QVectorND::crossProduct()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVector3D v4 = QVector3D::crossProduct(v1, v2);
+ QVERIFY(v4 == v3);
+
+ // Compute the cross-product long-hand and check again.
+ qreal xres = y1 * z2 - z1 * y2;
+ qreal yres = z1 * x2 - x1 * z2;
+ qreal zres = x1 * y2 - y1 * x2;
+
+ QCOMPARE(v4.x(), xres);
+ QCOMPARE(v4.y(), yres);
+ QCOMPARE(v4.z(), zres);
+}
+
+// Test the computation of normals.
+void tst_QVectorND::normal_data()
+{
+ // Use the same test data as the crossProduct test.
+ crossProduct_data();
+}
+void tst_QVectorND::normal()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVERIFY(QVector3D::normal(v1, v2) == v3.normalized());
+ QVERIFY(QVector3D::normal(QVector3D(), v1, v2) == v3.normalized());
+
+ QVector3D point(1.0f, 2.0f, 3.0f);
+ QVERIFY(QVector3D::normal(point, v1 + point, v2 + point) == v3.normalized());
+}
+
+// Test distance to plane calculations.
+void tst_QVectorND::distanceToPlane_data()
+{
+ QTest::addColumn<qreal>("x1"); // Point on plane
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2"); // Normal to plane
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3"); // Point to test for distance
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("x4"); // Second point on plane
+ QTest::addColumn<qreal>("y4");
+ QTest::addColumn<qreal>("z4");
+ QTest::addColumn<qreal>("x5"); // Third point on plane
+ QTest::addColumn<qreal>("y5");
+ QTest::addColumn<qreal>("z5");
+ QTest::addColumn<qreal>("distance");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("above")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)2.0f;
+
+ QTest::newRow("below")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)-1.0f << (qreal)1.0f << (qreal)-2.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)-2.0f;
+}
+void tst_QVectorND::distanceToPlane()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, x4);
+ QFETCH(qreal, y4);
+ QFETCH(qreal, z4);
+ QFETCH(qreal, x5);
+ QFETCH(qreal, y5);
+ QFETCH(qreal, z5);
+ QFETCH(qreal, distance);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+ QVector3D v4(x4, y4, z4);
+ QVector3D v5(x5, y5, z5);
+
+ QCOMPARE(v3.distanceToPlane(v1, v2), distance);
+ QCOMPARE(v3.distanceToPlane(v1, v4, v5), distance);
+}
+
+// Test distance to line calculations.
+void tst_QVectorND::distanceToLine_data()
+{
+ QTest::addColumn<qreal>("x1"); // Point on line
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2"); // Direction of the line
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3"); // Point to test for distance
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("distance");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("on line")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)5.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("off line")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)1.0f;
+
+ QTest::newRow("off line 2")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)-2.0f << (qreal)0.0f
+ << (qreal)2.0f;
+
+ QTest::newRow("points")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)5.0f << (qreal)0.0f
+ << (qreal)5.0f;
+}
+void tst_QVectorND::distanceToLine()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, distance);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QCOMPARE(v3.distanceToLine(v1, v2), distance);
+}
+
+// Test the computation of dot products for 2D vectors.
+void tst_QVectorND::dotProduct2_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("dot");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("unitvec")
+ << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)4.0f << (qreal)5.0f
+ << (qreal)14.0f;
+}
+void tst_QVectorND::dotProduct2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, dot);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+
+ QVERIFY(QVector2D::dotProduct(v1, v2) == dot);
+
+ // Compute the dot-product long-hand and check again.
+ qreal d = x1 * x2 + y1 * y2;
+
+ QCOMPARE(QVector2D::dotProduct(v1, v2), d);
+}
+
+// Test the computation of dot products for 3D vectors.
+void tst_QVectorND::dotProduct3_data()
+{
+ // Use the same test data as the crossProduct test.
+ crossProduct_data();
+}
+void tst_QVectorND::dotProduct3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, dot);
+
+ Q_UNUSED(x3);
+ Q_UNUSED(y3);
+ Q_UNUSED(z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+
+ QVERIFY(QVector3D::dotProduct(v1, v2) == dot);
+
+ // Compute the dot-product long-hand and check again.
+ qreal d = x1 * x2 + y1 * y2 + z1 * z2;
+
+ QCOMPARE(QVector3D::dotProduct(v1, v2), d);
+}
+
+// Test the computation of dot products for 4D vectors.
+void tst_QVectorND::dotProduct4_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+ QTest::addColumn<qreal>("dot");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("unitvec")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)4.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)6.0f << (qreal)7.0f
+ << (qreal)60.0f;
+}
+void tst_QVectorND::dotProduct4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, dot);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+
+ QVERIFY(QVector4D::dotProduct(v1, v2) == dot);
+
+ // Compute the dot-product long-hand and check again.
+ qreal d = x1 * x2 + y1 * y2 + z1 * z2 + w1 * w2;
+
+ QCOMPARE(QVector4D::dotProduct(v1, v2), d);
+}
+
+class tst_QVectorNDProperties : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector2D vector2D READ vector2D WRITE setVector2D)
+ Q_PROPERTY(QVector3D vector3D READ vector3D WRITE setVector3D)
+ Q_PROPERTY(QVector4D vector4D READ vector4D WRITE setVector4D)
+public:
+ tst_QVectorNDProperties(QObject *parent = 0) : QObject(parent) {}
+
+ QVector2D vector2D() const { return v2; }
+ void setVector2D(const QVector2D& value) { v2 = value; }
+
+ QVector3D vector3D() const { return v3; }
+ void setVector3D(const QVector3D& value) { v3 = value; }
+
+ QVector4D vector4D() const { return v4; }
+ void setVector4D(const QVector4D& value) { v4 = value; }
+
+private:
+ QVector2D v2;
+ QVector3D v3;
+ QVector4D v4;
+};
+
+// Test getting and setting vector properties via the metaobject system.
+void tst_QVectorND::properties()
+{
+ tst_QVectorNDProperties obj;
+
+ obj.setVector2D(QVector2D(1.0f, 2.0f));
+ obj.setVector3D(QVector3D(3.0f, 4.0f, 5.0f));
+ obj.setVector4D(QVector4D(6.0f, 7.0f, 8.0f, 9.0f));
+
+ QVector2D v2 = qVariantValue<QVector2D>(obj.property("vector2D"));
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.0f);
+
+ QVector3D v3 = qVariantValue<QVector3D>(obj.property("vector3D"));
+ QCOMPARE(v3.x(), (qreal)3.0f);
+ QCOMPARE(v3.y(), (qreal)4.0f);
+ QCOMPARE(v3.z(), (qreal)5.0f);
+
+ QVector4D v4 = qVariantValue<QVector4D>(obj.property("vector4D"));
+ QCOMPARE(v4.x(), (qreal)6.0f);
+ QCOMPARE(v4.y(), (qreal)7.0f);
+ QCOMPARE(v4.z(), (qreal)8.0f);
+ QCOMPARE(v4.w(), (qreal)9.0f);
+
+ obj.setProperty("vector2D",
+ qVariantFromValue(QVector2D(-1.0f, -2.0f)));
+ obj.setProperty("vector3D",
+ qVariantFromValue(QVector3D(-3.0f, -4.0f, -5.0f)));
+ obj.setProperty("vector4D",
+ qVariantFromValue(QVector4D(-6.0f, -7.0f, -8.0f, -9.0f)));
+
+ v2 = qVariantValue<QVector2D>(obj.property("vector2D"));
+ QCOMPARE(v2.x(), (qreal)-1.0f);
+ QCOMPARE(v2.y(), (qreal)-2.0f);
+
+ v3 = qVariantValue<QVector3D>(obj.property("vector3D"));
+ QCOMPARE(v3.x(), (qreal)-3.0f);
+ QCOMPARE(v3.y(), (qreal)-4.0f);
+ QCOMPARE(v3.z(), (qreal)-5.0f);
+
+ v4 = qVariantValue<QVector4D>(obj.property("vector4D"));
+ QCOMPARE(v4.x(), (qreal)-6.0f);
+ QCOMPARE(v4.y(), (qreal)-7.0f);
+ QCOMPARE(v4.z(), (qreal)-8.0f);
+ QCOMPARE(v4.w(), (qreal)-9.0f);
+}
+
+void tst_QVectorND::metaTypes()
+{
+ QVERIFY(QMetaType::type("QVector2D") == QMetaType::QVector2D);
+ QVERIFY(QMetaType::type("QVector3D") == QMetaType::QVector3D);
+ QVERIFY(QMetaType::type("QVector4D") == QMetaType::QVector4D);
+
+ QCOMPARE(QByteArray(QMetaType::typeName(QMetaType::QVector2D)),
+ QByteArray("QVector2D"));
+ QCOMPARE(QByteArray(QMetaType::typeName(QMetaType::QVector3D)),
+ QByteArray("QVector3D"));
+ QCOMPARE(QByteArray(QMetaType::typeName(QMetaType::QVector4D)),
+ QByteArray("QVector4D"));
+
+ QVERIFY(QMetaType::isRegistered(QMetaType::QVector2D));
+ QVERIFY(QMetaType::isRegistered(QMetaType::QVector3D));
+ QVERIFY(QMetaType::isRegistered(QMetaType::QVector4D));
+
+ QVERIFY(qMetaTypeId<QVector2D>() == QMetaType::QVector2D);
+ QVERIFY(qMetaTypeId<QVector3D>() == QMetaType::QVector3D);
+ QVERIFY(qMetaTypeId<QVector4D>() == QMetaType::QVector4D);
+}
+
+QTEST_APPLESS_MAIN(tst_QVectorND)
+
+#include "tst_qvectornd.moc"
diff --git a/tests/auto/gui/painting/painting.pro b/tests/auto/gui/painting/painting.pro
new file mode 100644
index 0000000000..62230eeac7
--- /dev/null
+++ b/tests/auto/gui/painting/painting.pro
@@ -0,0 +1,21 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qpainterpath \
+ qpainterpathstroker \
+ qcolor \
+ qbrush \
+ qregion \
+ qpainter \
+ qpathclipper \
+ qprinterinfo \
+ qpen \
+ qpaintengine \
+ qtransform \
+ qwmatrix \
+ qprinter \
+ qpolygon \
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qpathclipper \
+
+
diff --git a/tests/auto/gui/painting/qbrush/.gitignore b/tests/auto/gui/painting/qbrush/.gitignore
new file mode 100644
index 0000000000..e9321a18bd
--- /dev/null
+++ b/tests/auto/gui/painting/qbrush/.gitignore
@@ -0,0 +1 @@
+tst_qbrush
diff --git a/tests/auto/gui/painting/qbrush/qbrush.pro b/tests/auto/gui/painting/qbrush/qbrush.pro
new file mode 100644
index 0000000000..1c3efd46be
--- /dev/null
+++ b/tests/auto/gui/painting/qbrush/qbrush.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qbrush.cpp
diff --git a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
new file mode 100644
index 0000000000..9ee679e0f7
--- /dev/null
+++ b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
@@ -0,0 +1,423 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include "qbrush.h"
+#include <QPainter>
+#include <QBitmap>
+
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QBrush : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QBrush();
+
+private slots:
+ void operator_eq_eq();
+ void operator_eq_eq_data();
+
+ void stream();
+ void stream_data();
+
+ void badStyles();
+
+ void testQLinearGradientSetters();
+ void testQRadialGradientSetters();
+ void testQConicalGradientSetters();
+ void testQGradientCopyConstructor();
+
+ void gradientStops();
+
+ void textures();
+
+ void swap();
+ void nullBrush();
+ void isOpaque();
+ void debug();
+};
+
+Q_DECLARE_METATYPE(QBrush)
+
+tst_QBrush::tst_QBrush()
+{
+}
+
+void tst_QBrush::operator_eq_eq_data()
+{
+ QTest::addColumn<QBrush>("brush1");
+ QTest::addColumn<QBrush>("brush2");
+ QTest::addColumn<bool>("isEqual");
+
+ QLinearGradient lg(10, 10, 100, 100);
+ lg.setColorAt(0, Qt::red);
+ lg.setColorAt(0.5, Qt::blue);
+ lg.setColorAt(1, Qt::green);
+
+ QTest::newRow("black vs black") << QBrush(Qt::black) << QBrush(Qt::black) << true;
+ QTest::newRow("black vs blue") << QBrush(Qt::black) << QBrush(Qt::blue) << false;
+
+ QTest::newRow("red vs no") << QBrush(Qt::red) << QBrush(Qt::NoBrush) << false;
+ QTest::newRow("no vs no") << QBrush(Qt::NoBrush) << QBrush(Qt::NoBrush) << true;
+
+ QTest::newRow("lg vs same lg") << QBrush(lg) << QBrush(lg) << true;
+ QTest::newRow("lg vs diff lg") << QBrush(lg) << QBrush(QLinearGradient(QPoint(0, 0), QPoint(1, 1)))
+ << false;
+
+ QTest::newRow("rad vs con") << QBrush(QRadialGradient(0, 0, 0, 0, 0)) << QBrush(QConicalGradient(0, 0, 0)) << false;
+
+ QBrush b1(lg);
+ QBrush b2(lg);
+ b1.setTransform(QTransform().scale(2, 2));
+ QTest::newRow("lg with transform vs same lg") << b1 << b2 << false;
+
+ b2.setTransform(QTransform().scale(2, 2));
+ QTest::newRow("lg w/transform vs same lg w/same transform") << b1 << b2 << true;
+
+}
+
+void tst_QBrush::operator_eq_eq()
+{
+ QFETCH(QBrush, brush1);
+ QFETCH(QBrush, brush2);
+ QFETCH(bool, isEqual);
+ QCOMPARE(brush1 == brush2, isEqual);
+}
+
+void tst_QBrush::stream_data()
+{
+ QTest::addColumn<QBrush>("brush");
+
+ QLinearGradient lg(10, 10, 100, 100);
+ lg.setColorAt(0, Qt::red);
+ lg.setColorAt(0.5, Qt::blue);
+ lg.setColorAt(1, Qt::green);
+
+ QTest::newRow("black") << QBrush(Qt::black);
+ QTest::newRow("red") << QBrush(Qt::red);
+ QTest::newRow("no") << QBrush(Qt::NoBrush);
+ QTest::newRow("lg") << QBrush(lg);
+ QTest::newRow("rad") << QBrush(QRadialGradient(0, 0, 0, 0, 0));
+ QTest::newRow("con") << QBrush(QConicalGradient(0, 0, 0));
+}
+
+void tst_QBrush::stream()
+{
+ QFETCH(QBrush, brush);
+
+ QByteArray data;
+
+ {
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream << brush;
+ }
+
+ QBrush cmp;
+ {
+ QDataStream stream(&data, QIODevice::ReadOnly);
+ stream >> cmp;
+ }
+
+ QCOMPARE(brush.style(), cmp.style());
+ QCOMPARE(brush.color(), cmp.color());
+ QCOMPARE(brush, cmp);
+}
+
+void tst_QBrush::testQLinearGradientSetters()
+{
+ QLinearGradient lg;
+
+ QCOMPARE(lg.start(), QPointF(0, 0));
+ QCOMPARE(lg.finalStop(), QPointF(1, 1));
+
+ lg.setStart(101, 102);
+ QCOMPARE(lg.start(), QPointF(101, 102));
+
+ lg.setStart(QPointF(201, 202));
+ QCOMPARE(lg.start(), QPointF(201, 202));
+
+ lg.setFinalStop(103, 104);
+ QCOMPARE(lg.finalStop(), QPointF(103, 104));
+
+ lg.setFinalStop(QPointF(203, 204));
+ QCOMPARE(lg.finalStop(), QPointF(203, 204));
+}
+
+void tst_QBrush::testQRadialGradientSetters()
+{
+ QRadialGradient rg;
+
+ QCOMPARE(rg.radius(), qreal(1.0));
+ QCOMPARE(rg.center(), QPointF(0, 0));
+ QCOMPARE(rg.focalPoint(), QPointF(0, 0));
+
+ rg.setRadius(100);
+ QCOMPARE(rg.radius(), qreal(100.0));
+
+ rg.setCenter(101, 102);
+ QCOMPARE(rg.center(), QPointF(101, 102));
+
+ rg.setCenter(QPointF(201, 202));
+ QCOMPARE(rg.center(), QPointF(201, 202));
+
+ rg.setFocalPoint(103, 104);
+ QCOMPARE(rg.focalPoint(), QPointF(103, 104));
+
+ rg.setFocalPoint(QPointF(203, 204));
+ QCOMPARE(rg.focalPoint(), QPointF(203, 204));
+}
+
+void tst_QBrush::testQConicalGradientSetters()
+{
+ QConicalGradient cg;
+
+ QCOMPARE(cg.angle(), qreal(0.0));
+ QCOMPARE(cg.center(), QPointF(0, 0));
+
+ cg.setAngle(100);
+ QCOMPARE(cg.angle(), qreal(100.0));
+
+ cg.setCenter(102, 103);
+ QCOMPARE(cg.center(), QPointF(102, 103));
+
+ cg.setCenter(QPointF(202, 203));
+ QCOMPARE(cg.center(), QPointF(202, 203));
+}
+
+void tst_QBrush::testQGradientCopyConstructor()
+{
+ {
+ QLinearGradient lg1(101, 102, 103, 104);
+
+ QLinearGradient lg2 = lg1;
+ QCOMPARE(lg1.start(), lg2.start());
+ QCOMPARE(lg1.finalStop(), lg2.finalStop());
+
+ QGradient g = lg1;
+ QCOMPARE(((QLinearGradient *) &g)->start(), lg1.start());
+ QCOMPARE(((QLinearGradient *) &g)->finalStop(), lg1.finalStop());
+ }
+
+ {
+ QRadialGradient rg1(101, 102, 103, 104, 105);
+
+ QRadialGradient rg2 = rg1;
+ QCOMPARE(rg1.center(), rg2.center());
+ QCOMPARE(rg1.focalPoint(), rg2.focalPoint());
+ QCOMPARE(rg1.radius(), rg2.radius());
+
+ QGradient g = rg1;
+ QCOMPARE(((QRadialGradient *) &g)->center(), rg1.center());
+ QCOMPARE(((QRadialGradient *) &g)->focalPoint(), rg1.focalPoint());
+ QCOMPARE(((QRadialGradient *) &g)->radius(), rg1.radius());
+ }
+
+ {
+ QConicalGradient cg1(101, 102, 103);
+
+ QConicalGradient cg2 = cg1;
+ QCOMPARE(cg1.center(), cg2.center());
+ QCOMPARE(cg1.angle(), cg2.angle());
+
+ QGradient g = cg1;
+ QCOMPARE(((QConicalGradient *) &g)->center(), cg1.center());
+ QCOMPARE(((QConicalGradient *) &g)->angle(), cg1.angle());
+ }
+
+}
+
+void tst_QBrush::badStyles()
+{
+ // QBrush(Qt::BrushStyle) constructor
+ QCOMPARE(QBrush(Qt::LinearGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(Qt::RadialGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(Qt::ConicalGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(Qt::TexturePattern).style(), Qt::NoBrush);
+
+ // QBrush(QColor, Qt::BrushStyle) constructor
+ QCOMPARE(QBrush(QColor(0, 0, 0), Qt::LinearGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(QColor(0, 0, 0), Qt::RadialGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(QColor(0, 0, 0), Qt::ConicalGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(QColor(0, 0, 0), Qt::TexturePattern).style(), Qt::NoBrush);
+
+ // QBrush(Qt::GlobalColor, Qt::BrushStyle) constructor
+ QCOMPARE(QBrush(Qt::black, Qt::LinearGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(Qt::black, Qt::RadialGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(Qt::black, Qt::ConicalGradientPattern).style(), Qt::NoBrush);
+ QCOMPARE(QBrush(Qt::black, Qt::TexturePattern).style(), Qt::NoBrush);
+
+ // Set style...
+ QBrush brush(Qt::red);
+
+ brush.setStyle(Qt::LinearGradientPattern);
+ QCOMPARE(brush.style(), Qt::SolidPattern);
+
+ brush.setStyle(Qt::RadialGradientPattern);
+ QCOMPARE(brush.style(), Qt::SolidPattern);
+
+ brush.setStyle(Qt::ConicalGradientPattern);
+ QCOMPARE(brush.style(), Qt::SolidPattern);
+
+ brush.setStyle(Qt::TexturePattern);
+ QCOMPARE(brush.style(), Qt::SolidPattern);
+
+}
+
+void tst_QBrush::gradientStops()
+{
+ QLinearGradient gradient;
+ gradient.setColorAt(0, Qt::red);
+ gradient.setColorAt(1, Qt::blue);
+
+ QCOMPARE(gradient.stops().size(), 2);
+
+ QCOMPARE(gradient.stops().at(0), QGradientStop(0, QColor(Qt::red)));
+ QCOMPARE(gradient.stops().at(1), QGradientStop(1, QColor(Qt::blue)));
+
+ gradient.setColorAt(0, Qt::blue);
+ gradient.setColorAt(1, Qt::red);
+
+ QCOMPARE(gradient.stops().size(), 2);
+
+ QCOMPARE(gradient.stops().at(0), QGradientStop(0, QColor(Qt::blue)));
+ QCOMPARE(gradient.stops().at(1), QGradientStop(1, QColor(Qt::red)));
+
+ gradient.setColorAt(0.5, Qt::green);
+
+ QCOMPARE(gradient.stops().size(), 3);
+ QCOMPARE(gradient.stops().at(1), QGradientStop(0.5, QColor(Qt::green)));
+
+ // A hack in parseStopNode() in qsvghandler.cpp depends on inserting stops at NaN.
+ gradient.setStops(QGradientStops() << QGradientStop(qQNaN(), QColor()));
+ QCOMPARE(gradient.stops().size(), 1);
+ QVERIFY(qIsNaN(gradient.stops().at(0).first));
+ QCOMPARE(gradient.stops().at(0).second, QColor());
+}
+
+void fill(QPaintDevice *pd) {
+ QPainter p(pd);
+
+ int w = pd->width();
+ int h = pd->height();
+
+ p.fillRect(0, 0, w, h, Qt::white);
+ p.fillRect(0, 0, w/3, h/3, Qt::black);
+}
+
+void tst_QBrush::textures()
+{
+ QPixmap pixmap_source(10, 10);
+ QImage image_source(10, 10, QImage::Format_RGB32);
+
+ fill(&pixmap_source);
+ fill(&image_source);
+
+ // Create a pixmap brush and compare its texture and textureImage
+ // to the expected image
+ QBrush pixmap_brush;
+ pixmap_brush.setTexture(pixmap_source);
+ QImage image = pixmap_brush.texture().toImage().convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(image, image_source);
+ image = pixmap_brush.textureImage().convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(image, image_source);
+
+ pixmap_brush = QBrush(pixmap_source);
+ image = pixmap_brush.texture().toImage().convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(image, image_source);
+ image = pixmap_brush.textureImage().convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(image, image_source);
+
+ // Create a image brush and compare its texture and textureImage
+ // to the expected image
+ QBrush image_brush;
+ image_brush.setTextureImage(image_source);
+ image = image_brush.texture().toImage().convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(image, image_source);
+ QCOMPARE(image_brush.textureImage(), image_source);
+
+ image_brush = QBrush(image_source);
+ image = image_brush.texture().toImage().convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(image, image_source);
+ QCOMPARE(image_brush.textureImage(), image_source);
+}
+
+void tst_QBrush::swap()
+{
+ QBrush b1(Qt::black), b2(Qt::white);
+ b1.swap(b2);
+ QCOMPARE(b1.color(), QColor(Qt::white));
+ QCOMPARE(b2.color(), QColor(Qt::black));
+}
+
+void tst_QBrush::nullBrush()
+{
+ QBrush brush(QColor(100,0,0), Qt::NoBrush);
+ QCOMPARE(brush.color(), QColor(100,0,0));
+}
+
+void tst_QBrush::isOpaque()
+{
+ QBitmap bm(8, 8);
+ bm.fill(Qt::black);
+
+ QBrush brush(bm);
+ QVERIFY(!brush.isOpaque());
+}
+
+void tst_QBrush::debug()
+{
+ QPixmap pixmap_source(10, 10);
+ fill(&pixmap_source);
+ QBrush pixmap_brush;
+ pixmap_brush.setTexture(pixmap_source);
+ QCOMPARE(pixmap_brush.style(), Qt::TexturePattern);
+ qDebug() << pixmap_brush; // don't crash
+}
+
+QTEST_MAIN(tst_QBrush)
+#include "tst_qbrush.moc"
diff --git a/tests/auto/gui/painting/qcolor/.gitignore b/tests/auto/gui/painting/qcolor/.gitignore
new file mode 100644
index 0000000000..92f91eb54e
--- /dev/null
+++ b/tests/auto/gui/painting/qcolor/.gitignore
@@ -0,0 +1 @@
+tst_qcolor
diff --git a/tests/auto/gui/painting/qcolor/qcolor.pro b/tests/auto/gui/painting/qcolor/qcolor.pro
new file mode 100644
index 0000000000..b9d437ef7c
--- /dev/null
+++ b/tests/auto/gui/painting/qcolor/qcolor.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qcolor.cpp
+
+
+
diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
new file mode 100644
index 0000000000..2b6896ae5d
--- /dev/null
+++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
@@ -0,0 +1,1538 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <limits.h>
+
+#include <qcolor.h>
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QColor : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QColor();
+
+private slots:
+ void getSetCheck();
+ void isValid_data();
+ void isValid();
+
+ void name_data();
+ void name();
+ void setNamedColor();
+
+ void constructNamedColorWithSpace();
+
+ void colorNames();
+
+ void spec();
+
+ void globalColors_data();
+ void globalColors();
+
+ void alpha();
+ void setAlpha();
+
+ void red();
+ void green();
+ void blue();
+
+ void setRed();
+ void setGreen();
+ void setBlue();
+
+ void getRgb();
+ void setRgb();
+
+ void rgba();
+ void setRgba();
+
+ void rgb();
+
+ void hue();
+ void saturation();
+ void value();
+
+ void getHsv();
+ void setHsv();
+
+ void cyan();
+ void magenta();
+ void yellow();
+ void black();
+
+ void getCmyk();
+ void setCmyk();
+
+ void hueHsl();
+ void saturationHsl();
+ void lightness();
+
+ void getHsl();
+ void setHsl();
+
+ void toRgb_data();
+ void toRgb();
+ void toRgbNonDestructive();
+
+ void toHsv_data();
+ void toHsv();
+ void toHsvNonDestructive();
+
+ void toCmyk_data();
+ void toCmyk();
+ void toCmykNonDestructive();
+
+ void toHsl_data();
+ void toHsl();;
+ void toHslNonDestructive();
+
+ void convertTo();
+
+ void fromRgb();
+ void fromHsv();
+ void fromCmyk();
+ void fromHsl();
+
+ void light();
+ void dark();
+
+ void assignmentOoperator();
+ void equalityOperator();
+
+ void specConstructor_data();
+ void specConstructor();
+
+ void achromaticHslHue();
+
+#ifdef Q_WS_X11
+ void allowX11ColorNames();
+ void setallowX11ColorNames();
+#endif
+};
+
+// Testing get/set functions
+void tst_QColor::getSetCheck()
+{
+ QColor obj1;
+ // int QColor::alpha()
+ // void QColor::setAlpha(int)
+ obj1.setAlpha(0);
+ QCOMPARE(obj1.alpha(), 0);
+ obj1.setAlpha(-1);
+ QCOMPARE(obj1.alpha(), 0); // range<0, 255>
+ obj1.setAlpha(INT_MIN);
+ QCOMPARE(obj1.alpha(), 0); // range<0, 255>
+ obj1.setAlpha(255);
+ QCOMPARE(obj1.alpha(), 255); // range<0, 255>
+ obj1.setAlpha(INT_MAX);
+ QCOMPARE(obj1.alpha(), 255); // range<0, 255>
+
+ // qreal QColor::alphaF()
+ // void QColor::setAlphaF(qreal)
+ obj1.setAlphaF(0.0);
+ QCOMPARE(obj1.alphaF(), qreal(0.0)); // range<0.0, 1.0>
+ obj1.setAlphaF(-0.2);
+ QCOMPARE(obj1.alphaF(), qreal(0.0)); // range<0.0, 1.0>
+ obj1.setAlphaF(1.0);
+ QCOMPARE(obj1.alphaF(), qreal(1.0)); // range<0.0, 1.0>
+ obj1.setAlphaF(1.1);
+ QCOMPARE(obj1.alphaF(), qreal(1.0)); // range<0.0, 1.0>
+
+ // int QColor::red()
+ // void QColor::setRed(int)
+ obj1.setRed(0);
+ QCOMPARE(obj1.red(), 0);
+ obj1.setRed(-1);
+ QCOMPARE(obj1.red(), 0); // range<0, 255>
+ obj1.setRed(INT_MIN);
+ QCOMPARE(obj1.red(), 0); // range<0, 255>
+ obj1.setRed(255);
+ QCOMPARE(obj1.red(), 255); // range<0, 255>
+ obj1.setRed(INT_MAX);
+ QCOMPARE(obj1.red(), 255); // range<0, 255>
+
+ // int QColor::green()
+ // void QColor::setGreen(int)
+ obj1.setGreen(0);
+ QCOMPARE(obj1.green(), 0);
+ obj1.setGreen(-1);
+ QCOMPARE(obj1.green(), 0); // range<0, 255>
+ obj1.setGreen(INT_MIN);
+ QCOMPARE(obj1.green(), 0); // range<0, 255>
+ obj1.setGreen(255);
+ QCOMPARE(obj1.green(), 255); // range<0, 255>
+ obj1.setGreen(INT_MAX);
+ QCOMPARE(obj1.green(), 255); // range<0, 255>
+
+ // int QColor::blue()
+ // void QColor::setBlue(int)
+ obj1.setBlue(0);
+ QCOMPARE(obj1.blue(), 0);
+ obj1.setBlue(-1);
+ QCOMPARE(obj1.blue(), 0); // range<0, 255>
+ obj1.setBlue(INT_MIN);
+ QCOMPARE(obj1.blue(), 0); // range<0, 255>
+ obj1.setBlue(255);
+ QCOMPARE(obj1.blue(), 255); // range<0, 255>
+ obj1.setBlue(INT_MAX);
+ QCOMPARE(obj1.blue(), 255); // range<0, 255>
+
+ // qreal QColor::redF()
+ // void QColor::setRedF(qreal)
+ obj1.setRedF(0.0);
+ QCOMPARE(obj1.redF(), qreal(0.0));
+ obj1.setRedF(-0.2);
+ QCOMPARE(obj1.redF(), qreal(0.0)); // range<0.0, 1.0
+ obj1.setRedF(1.1);
+ QCOMPARE(obj1.redF(), qreal(1.0)); // range<0.0, 1.0
+
+ // qreal QColor::greenF()
+ // void QColor::setGreenF(qreal)
+ obj1.setGreenF(0.0);
+ QCOMPARE(obj1.greenF(), qreal(0.0));
+ obj1.setGreenF(-0.2);
+ QCOMPARE(obj1.greenF(), qreal(0.0)); // range<0.0, 1.0
+ obj1.setGreenF(1.1);
+ QCOMPARE(obj1.greenF(), qreal(1.0)); // range<0.0, 1.0
+
+ // qreal QColor::blueF()
+ // void QColor::setBlueF(qreal)
+ obj1.setBlueF(0.0);
+ QCOMPARE(obj1.blueF(), qreal(0.0));
+ obj1.setBlueF(-0.2);
+ QCOMPARE(obj1.blueF(), qreal(0.0)); // range<0.0, 1.0
+ obj1.setBlueF(1.1);
+ QCOMPARE(obj1.blueF(), qreal(1.0)); // range<0.0, 1.0
+
+ // QRgb QColor::rgba()
+ // void QColor::setRgba(QRgb)
+ QRgb var9(qRgba(10, 20, 30, 40));
+ obj1.setRgba(var9);
+ QCOMPARE(obj1.rgba(), var9);
+ obj1.setRgba(QRgb(0));
+ QCOMPARE(obj1.rgba(), QRgb(0));
+
+ // QRgb QColor::rgb()
+ // void QColor::setRgb(QRgb)
+ QRgb var10(qRgb(10, 20, 30));
+ obj1.setRgb(var10);
+ QCOMPARE(obj1.rgb(), var10);
+ obj1.setRgb(QRgb(0));
+ QCOMPARE(obj1.rgb(), qRgb(0, 0, 0));
+}
+
+Q_DECLARE_METATYPE(QColor)
+
+
+tst_QColor::tst_QColor()
+
+{ }
+
+void tst_QColor::isValid_data()
+{
+ QTest::addColumn<QColor>("color");
+ QTest::addColumn<bool>("isValid");
+
+ QTest::newRow("defaultConstructor") << QColor() << false;
+ QTest::newRow("rgbConstructor-valid") << QColor(2,5,7) << true;
+ QTest::newRow("rgbConstructor-invalid") << QColor(2,5,999) << false;
+ QTest::newRow("nameQStringConstructor-valid") << QColor(QString("#ffffff")) << true;
+ QTest::newRow("nameQStringConstructor-invalid") << QColor(QString("#ffffgg")) << false;
+ QTest::newRow("nameQStringConstructor-empty") << QColor(QString("")) << false;
+ QTest::newRow("nameQStringConstructor-named") << QColor(QString("red")) << true;
+ QTest::newRow("nameCharConstructor-valid") << QColor("#ffffff") << true;
+ QTest::newRow("nameCharConstructor-invalid") << QColor("#ffffgg") << false;
+ QTest::newRow("nameCharConstructor-invalid-2") << QColor("#fffffg") << false;
+}
+
+void tst_QColor::isValid()
+{
+ QFETCH(QColor, color);
+ QFETCH(bool, isValid);
+ QVERIFY(color.isValid() == isValid);
+}
+
+void tst_QColor::name_data()
+{
+ QTest::addColumn<QColor>("color");
+ QTest::addColumn<QString>("name");
+
+ QTest::newRow("invalid") << QColor() << "#000000";
+ QTest::newRow("global color black") << QColor(Qt::black) << "#000000";
+ QTest::newRow("global color white") << QColor(Qt::white) << "#ffffff";
+ QTest::newRow("global color darkGray") << QColor(Qt::darkGray) << "#808080";
+ QTest::newRow("global color gray") << QColor(Qt::gray) << "#a0a0a4";
+ QTest::newRow("global color lightGray") << QColor(Qt::lightGray) << "#c0c0c0";
+ QTest::newRow("global color red") << QColor(Qt::red) << "#ff0000";
+ QTest::newRow("global color green") << QColor(Qt::green) << "#00ff00";
+ QTest::newRow("global color blue") << QColor(Qt::blue) << "#0000ff";
+ QTest::newRow("global color cyan") << QColor(Qt::cyan) << "#00ffff";
+ QTest::newRow("global color magenta") << QColor(Qt::magenta) << "#ff00ff";
+ QTest::newRow("global color yellow") << QColor(Qt::yellow) << "#ffff00";
+ QTest::newRow("global color darkRed") << QColor(Qt::darkRed) << "#800000";
+ QTest::newRow("global color darkGreen") << QColor(Qt::darkGreen) << "#008000";
+ QTest::newRow("global color darkBlue") << QColor(Qt::darkBlue) << "#000080";
+ QTest::newRow("global color darkCyan") << QColor(Qt::darkCyan) << "#008080";
+ QTest::newRow("global color darkMagenta") << QColor(Qt::darkMagenta) << "#800080";
+ QTest::newRow("global color darkYellow") << QColor(Qt::darkYellow) << "#808000";
+}
+
+void tst_QColor::name()
+{
+ QFETCH(QColor, color);
+ QFETCH(QString, name);
+ QCOMPARE(color.name(), name);
+}
+
+void tst_QColor::globalColors_data()
+{
+ QTest::addColumn<QColor>("color");
+ QTest::addColumn<uint>("argb");
+
+ QTest::newRow("invalid") << QColor() << 0xff000000;
+ QTest::newRow("global color black") << QColor(Qt::black) << 0xff000000;
+ QTest::newRow("global color white") << QColor(Qt::white) << 0xffffffff;
+ QTest::newRow("global color darkGray") << QColor(Qt::darkGray) << 0xff808080;
+ QTest::newRow("global color gray") << QColor(Qt::gray) << 0xffa0a0a4;
+ QTest::newRow("global color lightGray") << QColor(Qt::lightGray) << 0xffc0c0c0;
+ QTest::newRow("global color red") << QColor(Qt::red) << 0xffff0000;
+ QTest::newRow("global color green") << QColor(Qt::green) << 0xff00ff00;
+ QTest::newRow("global color blue") << QColor(Qt::blue) << 0xff0000ff;
+ QTest::newRow("global color cyan") << QColor(Qt::cyan) << 0xff00ffff;
+ QTest::newRow("global color magenta") << QColor(Qt::magenta) << 0xffff00ff;
+ QTest::newRow("global color yellow") << QColor(Qt::yellow) << 0xffffff00;
+ QTest::newRow("global color darkRed") << QColor(Qt::darkRed) << 0xff800000;
+ QTest::newRow("global color darkGreen") << QColor(Qt::darkGreen) << 0xff008000;
+ QTest::newRow("global color darkBlue") << QColor(Qt::darkBlue) << 0xff000080;
+ QTest::newRow("global color darkCyan") << QColor(Qt::darkCyan) << 0xff008080;
+ QTest::newRow("global color darkMagenta") << QColor(Qt::darkMagenta) << 0xff800080;
+ QTest::newRow("global color darkYellow") << QColor(Qt::darkYellow) << 0xff808000;
+ QTest::newRow("global color transparent") << QColor(Qt::transparent) << 0x00000000u;
+}
+
+
+void tst_QColor::globalColors()
+{
+ QFETCH(QColor, color);
+ QFETCH(uint, argb);
+ QCOMPARE(color.rgba(), argb);
+}
+
+/*
+ CSS color names = SVG 1.0 color names + transparent (rgba(0,0,0,0))
+*/
+
+#ifdef rgb
+# undef rgb
+#endif
+#define rgb(r,g,b) (0xff000000 | r << 16 | g << 8 | b)
+
+static const struct RGBData {
+ const char *name;
+ uint value;
+} rgbTbl[] = {
+ { "aliceblue", rgb(240, 248, 255) },
+ { "antiquewhite", rgb(250, 235, 215) },
+ { "aqua", rgb( 0, 255, 255) },
+ { "aquamarine", rgb(127, 255, 212) },
+ { "azure", rgb(240, 255, 255) },
+ { "beige", rgb(245, 245, 220) },
+ { "bisque", rgb(255, 228, 196) },
+ { "black", rgb( 0, 0, 0) },
+ { "blanchedalmond", rgb(255, 235, 205) },
+ { "blue", rgb( 0, 0, 255) },
+ { "blueviolet", rgb(138, 43, 226) },
+ { "brown", rgb(165, 42, 42) },
+ { "burlywood", rgb(222, 184, 135) },
+ { "cadetblue", rgb( 95, 158, 160) },
+ { "chartreuse", rgb(127, 255, 0) },
+ { "chocolate", rgb(210, 105, 30) },
+ { "coral", rgb(255, 127, 80) },
+ { "cornflowerblue", rgb(100, 149, 237) },
+ { "cornsilk", rgb(255, 248, 220) },
+ { "crimson", rgb(220, 20, 60) },
+ { "cyan", rgb( 0, 255, 255) },
+ { "darkblue", rgb( 0, 0, 139) },
+ { "darkcyan", rgb( 0, 139, 139) },
+ { "darkgoldenrod", rgb(184, 134, 11) },
+ { "darkgray", rgb(169, 169, 169) },
+ { "darkgreen", rgb( 0, 100, 0) },
+ { "darkgrey", rgb(169, 169, 169) },
+ { "darkkhaki", rgb(189, 183, 107) },
+ { "darkmagenta", rgb(139, 0, 139) },
+ { "darkolivegreen", rgb( 85, 107, 47) },
+ { "darkorange", rgb(255, 140, 0) },
+ { "darkorchid", rgb(153, 50, 204) },
+ { "darkred", rgb(139, 0, 0) },
+ { "darksalmon", rgb(233, 150, 122) },
+ { "darkseagreen", rgb(143, 188, 143) },
+ { "darkslateblue", rgb( 72, 61, 139) },
+ { "darkslategray", rgb( 47, 79, 79) },
+ { "darkslategrey", rgb( 47, 79, 79) },
+ { "darkturquoise", rgb( 0, 206, 209) },
+ { "darkviolet", rgb(148, 0, 211) },
+ { "deeppink", rgb(255, 20, 147) },
+ { "deepskyblue", rgb( 0, 191, 255) },
+ { "dimgray", rgb(105, 105, 105) },
+ { "dimgrey", rgb(105, 105, 105) },
+ { "dodgerblue", rgb( 30, 144, 255) },
+ { "firebrick", rgb(178, 34, 34) },
+ { "floralwhite", rgb(255, 250, 240) },
+ { "forestgreen", rgb( 34, 139, 34) },
+ { "fuchsia", rgb(255, 0, 255) },
+ { "gainsboro", rgb(220, 220, 220) },
+ { "ghostwhite", rgb(248, 248, 255) },
+ { "gold", rgb(255, 215, 0) },
+ { "goldenrod", rgb(218, 165, 32) },
+ { "gray", rgb(128, 128, 128) },
+ { "green", rgb( 0, 128, 0) },
+ { "greenyellow", rgb(173, 255, 47) },
+ { "grey", rgb(128, 128, 128) },
+ { "honeydew", rgb(240, 255, 240) },
+ { "hotpink", rgb(255, 105, 180) },
+ { "indianred", rgb(205, 92, 92) },
+ { "indigo", rgb( 75, 0, 130) },
+ { "ivory", rgb(255, 255, 240) },
+ { "khaki", rgb(240, 230, 140) },
+ { "lavender", rgb(230, 230, 250) },
+ { "lavenderblush", rgb(255, 240, 245) },
+ { "lawngreen", rgb(124, 252, 0) },
+ { "lemonchiffon", rgb(255, 250, 205) },
+ { "lightblue", rgb(173, 216, 230) },
+ { "lightcoral", rgb(240, 128, 128) },
+ { "lightcyan", rgb(224, 255, 255) },
+ { "lightgoldenrodyellow", rgb(250, 250, 210) },
+ { "lightgray", rgb(211, 211, 211) },
+ { "lightgreen", rgb(144, 238, 144) },
+ { "lightgrey", rgb(211, 211, 211) },
+ { "lightpink", rgb(255, 182, 193) },
+ { "lightsalmon", rgb(255, 160, 122) },
+ { "lightseagreen", rgb( 32, 178, 170) },
+ { "lightskyblue", rgb(135, 206, 250) },
+ { "lightslategray", rgb(119, 136, 153) },
+ { "lightslategrey", rgb(119, 136, 153) },
+ { "lightsteelblue", rgb(176, 196, 222) },
+ { "lightyellow", rgb(255, 255, 224) },
+ { "lime", rgb( 0, 255, 0) },
+ { "limegreen", rgb( 50, 205, 50) },
+ { "linen", rgb(250, 240, 230) },
+ { "magenta", rgb(255, 0, 255) },
+ { "maroon", rgb(128, 0, 0) },
+ { "mediumaquamarine", rgb(102, 205, 170) },
+ { "mediumblue", rgb( 0, 0, 205) },
+ { "mediumorchid", rgb(186, 85, 211) },
+ { "mediumpurple", rgb(147, 112, 219) },
+ { "mediumseagreen", rgb( 60, 179, 113) },
+ { "mediumslateblue", rgb(123, 104, 238) },
+ { "mediumspringgreen", rgb( 0, 250, 154) },
+ { "mediumturquoise", rgb( 72, 209, 204) },
+ { "mediumvioletred", rgb(199, 21, 133) },
+ { "midnightblue", rgb( 25, 25, 112) },
+ { "mintcream", rgb(245, 255, 250) },
+ { "mistyrose", rgb(255, 228, 225) },
+ { "moccasin", rgb(255, 228, 181) },
+ { "navajowhite", rgb(255, 222, 173) },
+ { "navy", rgb( 0, 0, 128) },
+ { "oldlace", rgb(253, 245, 230) },
+ { "olive", rgb(128, 128, 0) },
+ { "olivedrab", rgb(107, 142, 35) },
+ { "orange", rgb(255, 165, 0) },
+ { "orangered", rgb(255, 69, 0) },
+ { "orchid", rgb(218, 112, 214) },
+ { "palegoldenrod", rgb(238, 232, 170) },
+ { "palegreen", rgb(152, 251, 152) },
+ { "paleturquoise", rgb(175, 238, 238) },
+ { "palevioletred", rgb(219, 112, 147) },
+ { "papayawhip", rgb(255, 239, 213) },
+ { "peachpuff", rgb(255, 218, 185) },
+ { "peru", rgb(205, 133, 63) },
+ { "pink", rgb(255, 192, 203) },
+ { "plum", rgb(221, 160, 221) },
+ { "powderblue", rgb(176, 224, 230) },
+ { "purple", rgb(128, 0, 128) },
+ { "red", rgb(255, 0, 0) },
+ { "rosybrown", rgb(188, 143, 143) },
+ { "royalblue", rgb( 65, 105, 225) },
+ { "saddlebrown", rgb(139, 69, 19) },
+ { "salmon", rgb(250, 128, 114) },
+ { "sandybrown", rgb(244, 164, 96) },
+ { "seagreen", rgb( 46, 139, 87) },
+ { "seashell", rgb(255, 245, 238) },
+ { "sienna", rgb(160, 82, 45) },
+ { "silver", rgb(192, 192, 192) },
+ { "skyblue", rgb(135, 206, 235) },
+ { "slateblue", rgb(106, 90, 205) },
+ { "slategray", rgb(112, 128, 144) },
+ { "slategrey", rgb(112, 128, 144) },
+ { "snow", rgb(255, 250, 250) },
+ { "springgreen", rgb( 0, 255, 127) },
+ { "steelblue", rgb( 70, 130, 180) },
+ { "tan", rgb(210, 180, 140) },
+ { "teal", rgb( 0, 128, 128) },
+ { "thistle", rgb(216, 191, 216) },
+ { "tomato", rgb(255, 99, 71) },
+ { "transparent", 0 },
+ { "turquoise", rgb( 64, 224, 208) },
+ { "violet", rgb(238, 130, 238) },
+ { "wheat", rgb(245, 222, 179) },
+ { "white", rgb(255, 255, 255) },
+ { "whitesmoke", rgb(245, 245, 245) },
+ { "yellow", rgb(255, 255, 0) },
+ { "yellowgreen", rgb(154, 205, 50) }
+};
+static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData);
+
+#undef rgb
+
+void tst_QColor::setNamedColor()
+{
+ for (int i = 0; i < rgbTblSize; ++i) {
+ QColor color;
+ color.setNamedColor(QLatin1String(rgbTbl[i].name));
+ QColor expected;
+ expected.setRgba(rgbTbl[i].value);
+ QCOMPARE(color, expected);
+ }
+}
+
+void tst_QColor::constructNamedColorWithSpace()
+{
+ QColor whiteSmoke("white smoke");
+ QCOMPARE(whiteSmoke, QColor(245, 245, 245));
+}
+
+void tst_QColor::colorNames()
+{
+ DEPENDS_ON("setNamedColor()");
+
+ QStringList all = QColor::colorNames();
+ QCOMPARE(all.size(), rgbTblSize);
+ for (int i = 0; i < all.size(); ++i)
+ QCOMPARE(all.at(i), QString::fromLatin1(rgbTbl[i].name));
+}
+
+void tst_QColor::spec()
+{
+ QColor invalid;
+ QCOMPARE(invalid.spec(), QColor::Invalid);
+
+ QColor rgb = QColor::fromRgb(0, 0, 0);
+ QCOMPARE(rgb.spec(), QColor::Rgb);
+
+ QColor hsv = QColor::fromHsv(0, 0, 0);
+ QCOMPARE(hsv.spec(), QColor::Hsv);
+
+ QColor cmyk = QColor::fromCmyk(0, 0, 0, 0);
+ QCOMPARE(cmyk.spec(), QColor::Cmyk);
+
+ QColor hsl = QColor::fromHsl(0, 0, 0, 0);
+ QCOMPARE(hsl.spec(), QColor::Hsl);
+
+}
+
+void tst_QColor::alpha()
+{ DEPENDS_ON(setRgb()); }
+
+void tst_QColor::red()
+{ DEPENDS_ON(setRgb()); }
+
+void tst_QColor::green()
+{ DEPENDS_ON(setRgb()); }
+
+void tst_QColor::blue()
+{ DEPENDS_ON(setRgb()); }
+
+void tst_QColor::getRgb()
+{ DEPENDS_ON(setRgb()); }
+
+void tst_QColor::setAlpha()
+{ DEPENDS_ON(setRgb()); }
+
+bool veryFuzzyCompare(double a, double b)
+{
+ return qAbs(a - b) < 0.01;
+}
+
+void tst_QColor::setRed()
+{
+ DEPENDS_ON(setRgb());
+
+ QColor c = QColor(Qt::blue).toHsv();
+ c.setRed(127);
+ QCOMPARE(c.red(), 127);
+ QCOMPARE(c.green(), 0);
+ QCOMPARE(c.blue(), 255);
+
+ c = QColor(Qt::blue).toHsv();
+ c.setRedF(0.5);
+ QVERIFY(veryFuzzyCompare(c.redF(), 0.5));
+ QCOMPARE(c.greenF(), qreal(0.0));
+ QCOMPARE(c.blueF(), qreal(1.0));
+}
+
+void tst_QColor::setGreen()
+{
+ DEPENDS_ON(setRgb());
+
+ QColor c = QColor(Qt::blue).toHsv();
+ c.setGreen(127);
+ QCOMPARE(c.red(), 0);
+ QCOMPARE(c.green(), 127);
+ QCOMPARE(c.blue(), 255);
+
+ c = QColor(Qt::blue).toHsv();
+ c.setGreenF(0.5);
+ QCOMPARE(c.redF(), qreal(0.0));
+ QVERIFY(veryFuzzyCompare(c.greenF(), 0.5));
+ QCOMPARE(c.blueF(), qreal(1.0));
+}
+
+void tst_QColor::setBlue()
+{
+ DEPENDS_ON(setRgb());
+
+ QColor c = QColor(Qt::red).toHsv();
+ c.setBlue(127);
+ QCOMPARE(c.red(), 255);
+ QCOMPARE(c.green(), 0);
+ QCOMPARE(c.blue(), 127);
+
+ c = QColor(Qt::red).toHsv();
+ c.setBlueF(0.5);
+ QCOMPARE(c.redF(), qreal(1.0));
+ QCOMPARE(c.greenF(), qreal(0.0));
+ QVERIFY(veryFuzzyCompare(c.blueF(), 0.5));
+}
+
+
+void tst_QColor::setRgb()
+{
+ QColor color;
+
+ for (int A = 0; A <= USHRT_MAX; ++A) {
+ {
+ // 0-255
+ int a = A >> 8;
+ QRgb rgb = qRgba(0, 0, 0, a);
+
+ color.setRgb(0, 0, 0, a);
+ QCOMPARE(color.alpha(), a);
+ QCOMPARE(color.rgb(), qRgb(0, 0, 0));
+
+ color.setRgb(rgb);
+ QCOMPARE(color.alpha(), 255);
+ QCOMPARE(color.rgb(), qRgb(0, 0, 0));
+
+ int r, g, b, a2;
+ color.setRgb(0, 0, 0, a);
+ color.getRgb(&r, &g, &b, &a2);
+ QCOMPARE(a2, a);
+
+ QColor c(0, 0, 0);
+ c.setAlpha(a);
+ QCOMPARE(c.alpha(), a);
+ }
+
+ {
+ // 0.0-1.0
+ qreal a = A / qreal(USHRT_MAX);
+ color.setRgbF(0.0, 0.0, 0.0, a);
+ QCOMPARE(color.alphaF(), a);
+
+ qreal r, g, b, a2;
+ color.getRgbF(&r, &g, &b, &a2);
+ QCOMPARE(a2, a);
+
+ QColor c(0, 0, 0);
+ c.setAlphaF(a);
+
+ QCOMPARE(c.alphaF(), a);
+ }
+ }
+
+ for (int R = 0; R <= USHRT_MAX; ++R) {
+ {
+ // 0-255
+ int r = R >> 8;
+ QRgb rgb = qRgb(r, 0, 0);
+
+ color.setRgb(r, 0, 0);
+ QCOMPARE(color.red(), r);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.red(), r);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r2, g, b, a;
+ color.getRgb(&r2, &g, &b, &a);
+ QCOMPARE(r2, r);
+ }
+
+ {
+ // 0.0-1.0
+ qreal r = R / qreal(USHRT_MAX);
+ color.setRgbF(r, 0.0, 0.0);
+ QCOMPARE(color.redF(), r);
+
+ qreal r2, g, b, a;
+ color.getRgbF(&r2, &g, &b, &a);
+ QCOMPARE(r2, r);
+ }
+ }
+
+ for (int G = 0; G <= USHRT_MAX; ++G) {
+ {
+ // 0-255
+ int g = G >> 8;
+ QRgb rgb = qRgb(0, g, 0);
+
+ color.setRgb(0, g, 0);
+ QCOMPARE(color.green(), g);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.green(), g);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r, g2, b, a;
+ color.getRgb(&r, &g2, &b, &a);
+ QCOMPARE(g2, g);
+ }
+
+ {
+ // 0.0-1.0
+ qreal g = G / qreal(USHRT_MAX);
+ color.setRgbF(0.0, g, 0.0);
+ QCOMPARE(color.greenF(), g);
+
+ qreal r, g2, b, a;
+ color.getRgbF(&r, &g2, &b, &a);
+ QCOMPARE(g2, g);
+ }
+ }
+
+ for (int B = 0; B <= USHRT_MAX; ++B) {
+ {
+ // 0-255
+ int b = B >> 8;
+ QRgb rgb = qRgb(0, 0, b);
+
+ color.setRgb(0, 0, b);
+ QCOMPARE(color.blue(), b);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.blue(), b);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r, g, b2, a;
+ color.getRgb(&r, &g, &b2, &a);
+ QCOMPARE(b2, b);
+ }
+
+ {
+ // 0.0-1.0
+ qreal b = B / qreal(USHRT_MAX);
+ color.setRgbF(0.0, 0.0, b);
+ QCOMPARE(color.blueF(), b);
+
+ qreal r, g, b2, a;
+ color.getRgbF(&r, &g, &b2, &a);
+ QCOMPARE(b2, b);
+ }
+ }
+}
+
+void tst_QColor::rgba()
+{ DEPENDS_ON("setRgba()"); }
+
+void tst_QColor::setRgba()
+{
+ for (int a = 0; a < 255; ++a) {
+ const QRgb rgba1 = qRgba(a, a, a, a);
+ QColor color;
+ color.setRgba(rgba1);
+ QCOMPARE(color.alpha(), a);
+ const QRgb rgba2 = color.rgba();
+ QCOMPARE(rgba2, rgba1);
+ QCOMPARE(qAlpha(rgba2), a);
+ }
+}
+
+void tst_QColor::rgb()
+{ DEPENDS_ON(setRgb()); }
+
+void tst_QColor::hue()
+{ DEPENDS_ON(setHsv()); }
+
+void tst_QColor::saturation()
+{ DEPENDS_ON(setHsv()); }
+
+void tst_QColor::value()
+{ DEPENDS_ON(setHsv()); }
+
+void tst_QColor::getHsv()
+{ DEPENDS_ON(setHsv()); }
+
+void tst_QColor::setHsv()
+{
+ QColor color;
+
+ for (int A = 0; A <= USHRT_MAX; ++A) {
+ {
+ // 0-255
+ int a = A >> 8;
+ color.setHsv(0, 0, 0, a);
+ QCOMPARE(color.alpha(), a);
+
+ int h, s, v, a2;
+ color.getHsv(&h, &s, &v, &a2);
+ QCOMPARE(a2, a);
+ }
+
+ {
+ // 0.0-1.0
+ qreal a = A / qreal(USHRT_MAX);
+ color.setHsvF(0.0, 0.0, 0.0, a); QCOMPARE(color.alphaF(), a);
+
+ qreal h, s, v, a2;
+ color.getHsvF(&h, &s, &v, &a2);
+ QCOMPARE(a2, a);
+ }
+ }
+
+ for (int H = 0; H < 36000; ++H) {
+ {
+ // 0-255
+ int h = H / 100;
+
+ color.setHsv(h, 0, 0, 0);
+ QCOMPARE(color.hue(), h);
+
+ int h2, s, v, a;
+ color.getHsv(&h2, &s, &v, &a);
+ QCOMPARE(h2, h);
+ }
+
+ {
+ // 0.0-1.0
+ qreal h = H / 36000.0;
+ color.setHsvF(h, 0.0, 0.0, 0.0);
+ QCOMPARE(color.hueF(), h);
+
+ qreal h2, s, v, a;
+ color.getHsvF(&h2, &s, &v, &a);
+ QCOMPARE(h2, h);
+ }
+ }
+
+ for (int S = 0; S <= USHRT_MAX; ++S) {
+ {
+ // 0-255
+ int s = S >> 8;
+ color.setHsv(0, s, 0, 0);
+ QCOMPARE(color.saturation(), s);
+
+ int h, s2, v, a;
+ color.getHsv(&h, &s2, &v, &a);
+ QCOMPARE(s2, s);
+ }
+
+ {
+ // 0.0-1.0
+ qreal s = S / qreal(USHRT_MAX);
+ color.setHsvF(0.0, s, 0.0, 0.0);
+ QCOMPARE(color.saturationF(), s);
+
+ qreal h, s2, v, a;
+ color.getHsvF(&h, &s2, &v, &a);
+ QCOMPARE(s2, s);
+ }
+ }
+
+ for (int V = 0; V <= USHRT_MAX; ++V) {
+ {
+ // 0-255
+ int v = V >> 8;
+ color.setHsv(0, 0, v, 0);
+ QCOMPARE(color.value(), v);
+
+ int h, s, v2, a;
+ color.getHsv(&h, &s, &v2, &a);
+ QCOMPARE(v2, v);
+ }
+
+ {
+ // 0.0-1.0
+ qreal v = V / qreal(USHRT_MAX);
+ color.setHsvF(0.0, 0.0, v, 0.0);
+ QCOMPARE(color.valueF(), v);
+
+ qreal h, s, v2, a;
+ color.getHsvF(&h, &s, &v2, &a);
+ QCOMPARE(v2, v);
+ }
+ }
+}
+
+void tst_QColor::cyan()
+{ DEPENDS_ON(setCmyk()); }
+
+void tst_QColor::magenta()
+{ DEPENDS_ON(setCmyk()); }
+
+void tst_QColor::yellow()
+{ DEPENDS_ON(setCmyk()); }
+
+void tst_QColor::black()
+{ DEPENDS_ON(setCmyk()); }
+
+void tst_QColor::getCmyk()
+{ DEPENDS_ON(setCmyk()); }
+
+void tst_QColor::setCmyk()
+{
+ QColor color;
+
+ for (int A = 0; A <= USHRT_MAX; ++A) {
+ {
+ // 0-255
+ int a = A >> 8;
+ color.setCmyk(0, 0, 0, 0, a);
+ QCOMPARE(color.alpha(), a);
+
+ int c, m, y, k, a2;
+ color.getCmyk(&c, &m, &y, &k, &a2);
+ QCOMPARE(a2, a);
+ }
+
+ {
+ // 0.0-1.0
+ qreal a = A / qreal(USHRT_MAX);
+ color.setCmykF(0.0, 0.0, 0.0, 0.0, a);
+ QCOMPARE(color.alphaF(), a);
+
+ qreal c, m, y, k, a2;
+ color.getCmykF(&c, &m, &y, &k, &a2);
+ QCOMPARE(a2, a);
+ }
+ }
+
+ for (int C = 0; C <= USHRT_MAX; ++C) {
+ {
+ // 0-255
+ int c = C >> 8;
+ color.setCmyk(c, 0, 0, 0, 0);
+ QCOMPARE(color.cyan(), c);
+
+ int c2, m, y, k, a;
+ color.getCmyk(&c2, &m, &y, &k, &a);
+ QCOMPARE(c2, c);
+ }
+
+ {
+ // 0.0-1.0
+ qreal c = C / qreal(USHRT_MAX);
+ color.setCmykF(c, 0.0, 0.0, 0.0, 0.0);
+ QCOMPARE(color.cyanF(), c);
+
+ qreal c2, m, y, k, a;
+ color.getCmykF(&c2, &m, &y, &k, &a);
+ QCOMPARE(c2, c);
+ }
+ }
+
+ for (int M = 0; M <= USHRT_MAX; ++M) {
+ {
+ // 0-255
+ int m = M >> 8;
+ color.setCmyk(0, m, 0, 0, 0);
+ QCOMPARE(color.magenta(), m);
+
+ int c, m2, y, k, a;
+ color.getCmyk(&c, &m2, &y, &k, &a);
+ QCOMPARE(m2, m);
+ }
+
+ {
+ // 0.0-1.0
+ qreal m = M / qreal(USHRT_MAX);
+ color.setCmykF(0.0, m, 0.0, 0.0, 0.0);
+ QCOMPARE(color.magentaF(), m);
+
+ qreal c, m2, y, k, a;
+ color.getCmykF(&c, &m2, &y, &k, &a);
+ QCOMPARE(m2, m);
+ }
+ }
+
+ for (int Y = 0; Y <= USHRT_MAX; ++Y) {
+ {
+ // 0-255
+ int y = Y >> 8;
+ color.setCmyk(0, 0, y, 0, 0);
+ QCOMPARE(color.yellow(), y);
+
+ int c, m, y2, k, a;
+ color.getCmyk(&c, &m, &y2, &k, &a);
+ QCOMPARE(y2, y);
+ }
+
+ {
+ // 0.0-1.0
+ qreal y = Y / qreal(USHRT_MAX);
+ color.setCmykF(0.0, 0.0, y, 0.0, 0.0);
+ QCOMPARE(color.yellowF(), y);
+
+ qreal c, m, y2, k, a;
+ color.getCmykF(&c, &m, &y2, &k, &a);
+ QCOMPARE(y2, y);
+ }
+ }
+
+ for (int K = 0; K <= USHRT_MAX; ++K) {
+ {
+ // 0-255
+ int k = K >> 8;
+ color.setCmyk(0, 0, 0, k, 0);
+ QCOMPARE(color.black(), k);
+
+ int c, m, y, k2, a;
+ color.getCmyk(&c, &m, &y, &k2, &a);
+ QCOMPARE(k2, k);
+ }
+
+ {
+ // 0.0-1.0
+ qreal k = K / qreal(USHRT_MAX);
+ color.setCmykF(0.0, 0.0, 0.0, k, 0.0);
+ QCOMPARE(color.blackF(), k);
+
+ qreal c, m, y, k2, a;
+ color.getCmykF(&c, &m, &y, &k2, &a);
+ QCOMPARE(k2, k);
+ }
+ }
+}
+
+void tst_QColor::hueHsl()
+{ DEPENDS_ON(setHsl()); }
+
+void tst_QColor::saturationHsl()
+{ DEPENDS_ON(setHsl()); }
+
+void tst_QColor::lightness()
+{ DEPENDS_ON(setHsl()); }
+
+void tst_QColor::getHsl()
+{ DEPENDS_ON(setHsl()); }
+
+void tst_QColor::setHsl()
+{
+ QColor color;
+
+ for (int A = 0; A <= USHRT_MAX; ++A) {
+ {
+ // 0-255
+ int a = A >> 8;
+ color.setHsl(0, 0, 0, a);
+ QCOMPARE(color.alpha(), a);
+
+ int h, s, l, a2;
+ color.getHsv(&h, &s, &l, &a2);
+ QCOMPARE(a2, a);
+ }
+
+ {
+ // 0.0-1.0
+ qreal a = A / qreal(USHRT_MAX);
+ color.setHslF(0.0, 0.0, 0.0, a); QCOMPARE(color.alphaF(), a);
+
+ qreal h, s, l, a2;
+ color.getHslF(&h, &s, &l, &a2);
+ QCOMPARE(a2, a);
+ }
+ }
+
+ for (int H = 0; H < 36000; ++H) {
+ {
+ // 0-255
+ int h = H / 100;
+
+ color.setHsl(h, 0, 0, 0);
+ QCOMPARE(color.hslHue(), h);
+
+ int h2, s, l, a;
+ color.getHsl(&h2, &s, &l, &a);
+ QCOMPARE(h2, h);
+ }
+
+ {
+ // 0.0-1.0
+ qreal h = H / 36000.0;
+ color.setHslF(h, 0.0, 0.0, 0.0);
+ QCOMPARE(color.hslHueF(), h);
+
+ qreal h2, s, l, a;
+ color.getHslF(&h2, &s, &l, &a);
+ QCOMPARE(h2, h);
+ }
+ }
+
+ for (int S = 0; S <= USHRT_MAX; ++S) {
+ {
+ // 0-255
+ int s = S >> 8;
+ color.setHsl(0, s, 0, 0);
+ QCOMPARE(color.hslSaturation(), s);
+
+ int h, s2, l, a;
+ color.getHsl(&h, &s2, &l, &a);
+ QCOMPARE(s2, s);
+ }
+
+ {
+ // 0.0-1.0
+ qreal s = S / qreal(USHRT_MAX);
+ color.setHslF(0.0, s, 0.0, 0.0);
+ QCOMPARE(color.hslSaturationF(), s);
+
+ qreal h, s2, l, a;
+ color.getHslF(&h, &s2, &l, &a);
+ QCOMPARE(s2, s);
+ }
+ }
+
+ for (int L = 0; L <= USHRT_MAX; ++L) {
+ {
+ // 0-255
+ int l = L >> 8;
+ color.setHsl(0, 0, l, 0);
+ QCOMPARE(color.lightness(), l);
+
+ int h, s, l2, a;
+ color.getHsl(&h, &s, &l2, &a);
+ QCOMPARE(l2, l);
+ }
+
+ {
+ // 0.0-1.0
+ qreal l = L / qreal(USHRT_MAX);
+ color.setHslF(0.0, 0.0, l, 0.0);
+ QCOMPARE(color.lightnessF(), l);
+
+ qreal h, s, l2, a;
+ color.getHslF(&h, &s, &l2, &a);
+ QCOMPARE(l2, l);
+ }
+ }
+}
+
+void tst_QColor::toRgb_data()
+{
+ QTest::addColumn<QColor>("expectedColor");
+ QTest::addColumn<QColor>("hsvColor");
+ QTest::addColumn<QColor>("cmykColor");
+ QTest::addColumn<QColor>("hslColor");
+
+ QTest::newRow("black")
+ << QColor::fromRgbF(0.0, 0.0, 0.0)
+ << QColor::fromHsvF(-1.0, 0.0, 0.0)
+ << QColor::fromCmykF(0.0, 0.0, 0.0, 1.0)
+ << QColor::fromHslF(-1.0, 0.0, 0.0);
+
+ QTest::newRow("white")
+ << QColor::fromRgbF(1.0, 1.0, 1.0)
+ << QColor::fromHsvF(-1.0, 0.0, 1.0)
+ << QColor::fromCmykF(0.0, 0.0, 0.0, 0.0)
+ << QColor::fromHslF(-1.0, 0.0, 1.0);
+
+ QTest::newRow("red")
+ << QColor::fromRgbF(1.0, 0.0, 0.0)
+ << QColor::fromHsvF(0.0, 1.0, 1.0)
+ << QColor::fromCmykF(0.0, 1.0, 1.0, 0.0)
+ << QColor::fromHslF(0.0, 1.0, 0.5, 1.0);
+
+ QTest::newRow("green")
+ << QColor::fromRgbF(0.0, 1.0, 0.0)
+ << QColor::fromHsvF(0.33333, 1.0, 1.0)
+ << QColor::fromCmykF(1.0, 0.0, 1.0, 0.0)
+ << QColor::fromHslF(0.33333, 1.0, 0.5);
+
+ QTest::newRow("blue")
+ << QColor::fromRgbF(0.0, 0.0, 1.0)
+ << QColor::fromHsvF(0.66667, 1.0, 1.0)
+ << QColor::fromCmykF(1.0, 1.0, 0.0, 0.0)
+ << QColor::fromHslF(0.66667, 1.0, 0.5);
+
+ QTest::newRow("cyan")
+ << QColor::fromRgbF(0.0, 1.0, 1.0)
+ << QColor::fromHsvF(0.5, 1.0, 1.0)
+ << QColor::fromCmykF(1.0, 0.0, 0.0, 0.0)
+ << QColor::fromHslF(0.5, 1.0, 0.5);
+
+ QTest::newRow("magenta")
+ << QColor::fromRgbF(1.0, 0.0, 1.0)
+ << QColor::fromHsvF(0.83333, 1.0, 1.0)
+ << QColor::fromCmykF(0.0, 1.0, 0.0, 0.0)
+ << QColor::fromHslF(0.83333, 1.0, 0.5);
+
+ QTest::newRow("yellow")
+ << QColor::fromRgbF(1.0, 1.0, 0.0)
+ << QColor::fromHsvF(0.16667, 1.0, 1.0)
+ << QColor::fromCmykF(0.0, 0.0, 1.0, 0.0)
+ << QColor::fromHslF(0.16667, 1.0, 0.5);
+
+ QTest::newRow("gray")
+ << QColor::fromRgbF(0.6431375, 0.6431375, 0.6431375)
+ << QColor::fromHsvF(-1.0, 0.0, 0.6431375)
+ << QColor::fromCmykF(0.0, 0.0, 0.0, 0.356863)
+ << QColor::fromHslF(-1.0, 0.0, 0.6431375);
+
+ // ### add colors using the 0-255 functions
+}
+
+void tst_QColor::toRgb()
+{
+ // invalid should remain invalid
+ QVERIFY(!QColor().toRgb().isValid());
+
+ QFETCH(QColor, expectedColor);
+ QFETCH(QColor, hsvColor);
+ QFETCH(QColor, cmykColor);
+ QFETCH(QColor, hslColor);
+ QCOMPARE(hsvColor.toRgb(), expectedColor);
+ QCOMPARE(cmykColor.toRgb(), expectedColor);
+ QCOMPARE(hslColor.toRgb(), expectedColor);
+
+}
+
+void tst_QColor::toHsv_data()
+{
+ QTest::addColumn<QColor>("expectedColor");
+ QTest::addColumn<QColor>("rgbColor");
+ QTest::addColumn<QColor>("cmykColor");
+ QTest::addColumn<QColor>("hslColor");
+
+ QTest::newRow("data0")
+ << QColor::fromHsv(300, 255, 255)
+ << QColor(255, 0, 255)
+ << QColor::fromCmyk(0, 255, 0, 0)
+ << QColor::fromHslF(300./360., 1., 0.5, 1.0);
+
+ QTest::newRow("data1")
+ << QColor::fromHsvF(1., 1., 1., 1.)
+ << QColor(255, 0, 0, 255)
+ << QColor::fromCmykF(0., 1., 1., 0.)
+ << QColor::fromHsvF(1., 1., 1., 1.);
+}
+
+void tst_QColor::toRgbNonDestructive()
+{
+ QColor aColor = QColor::fromRgbF(0.11, 0.22, 0.33, 0.44);
+ QCOMPARE(aColor, aColor.toRgb());
+}
+
+void tst_QColor::toHsv()
+{
+ // invalid should remain invalid
+ QVERIFY(!QColor().toHsv().isValid());
+
+ QFETCH(QColor, expectedColor);
+ QFETCH(QColor, rgbColor);
+ QFETCH(QColor, cmykColor);
+ QFETCH(QColor, hslColor);
+ QCOMPARE(rgbColor.toHsv(), expectedColor);
+ QCOMPARE(cmykColor.toHsv(), expectedColor);
+ QCOMPARE(hslColor.toHsv(), expectedColor);
+}
+
+void tst_QColor::toHsvNonDestructive()
+{
+ QColor aColor = QColor::fromHsvF(0.11, 0.22, 0.33, 0.44);
+ QCOMPARE(aColor, aColor.toHsv());
+}
+
+void tst_QColor::toCmyk_data()
+{
+ QTest::addColumn<QColor>("expectedColor");
+ QTest::addColumn<QColor>("rgbColor");
+ QTest::addColumn<QColor>("hsvColor");
+ QTest::addColumn<QColor>("hslColor");
+
+ QTest::newRow("data0")
+ << QColor::fromCmykF(1.0, 0.0, 0.0, 0.0)
+ << QColor(0, 255, 255)
+ << QColor::fromHsv(180, 255, 255)
+ << QColor::fromHslF(180./360., 1., 0.5, 1.0);
+
+ QTest::newRow("data1")
+ << QColor::fromCmyk(255, 255, 255, 255)
+ << QColor::fromRgb(0, 0, 0)
+ << QColor::fromRgb(0, 0, 0).toHsv()
+ << QColor::fromRgb(0, 0, 0).toHsl();
+}
+
+void tst_QColor::toCmyk()
+{
+ // invalid should remain invalid
+ QVERIFY(!QColor().toCmyk().isValid());
+
+ QFETCH(QColor, expectedColor);
+ QFETCH(QColor, rgbColor);
+ QFETCH(QColor, hsvColor);
+ QFETCH(QColor, hslColor);
+ QCOMPARE(rgbColor.toHsv().toCmyk(), expectedColor);
+ QCOMPARE(hsvColor.toCmyk(), expectedColor);
+ QCOMPARE(hslColor.toCmyk(), expectedColor);
+}
+
+void tst_QColor::toCmykNonDestructive()
+{
+ QColor aColor = QColor::fromCmykF(0.11, 0.22, 0.33, 0.44);
+ QCOMPARE(aColor, aColor.toCmyk());
+}
+
+void tst_QColor::toHsl_data()
+{
+ QTest::addColumn<QColor>("expectedColor");
+ QTest::addColumn<QColor>("hsvColor");
+ QTest::addColumn<QColor>("rgbColor");
+ QTest::addColumn<QColor>("cmykColor");
+
+
+ QTest::newRow("data0")
+ << QColor::fromHslF(300./360., 1., 0.5, 1.0)
+ << QColor::fromHsv(300, 255, 255)
+ << QColor(255, 0, 255)
+ << QColor::fromCmyk(0, 255, 0, 0);
+
+ QTest::newRow("data1")
+ << QColor::fromHslF(1., 1., 0.5, 1.0)
+ << QColor::fromHsvF(1., 1., 1., 1.)
+ << QColor(255, 0, 0, 255)
+ << QColor::fromCmykF(0., 1., 1., 0.);
+}
+
+void tst_QColor::toHsl()
+{
+ // invalid should remain invalid
+ QVERIFY(!QColor().toHsl().isValid());
+
+ QFETCH(QColor, expectedColor);
+ QFETCH(QColor, rgbColor);
+ QFETCH(QColor, cmykColor);
+ QFETCH(QColor, hsvColor);
+
+ QCOMPARE(rgbColor.toHsl(), expectedColor);
+ QCOMPARE(cmykColor.toHsl(), expectedColor);
+ QCOMPARE(hsvColor.toHsl(), expectedColor);
+
+}
+
+
+void tst_QColor::toHslNonDestructive()
+{
+ QColor aColor = QColor::fromHslF(0.11, 0.22, 0.33, 0.44);
+ QCOMPARE(aColor, aColor.toHsl());
+}
+
+
+void tst_QColor::convertTo()
+{
+ QColor color(Qt::black);
+
+ QColor rgb = color.convertTo(QColor::Rgb);
+ QVERIFY(rgb.spec() == QColor::Rgb);
+
+ QColor hsv = color.convertTo(QColor::Hsv);
+ QVERIFY(hsv.spec() == QColor::Hsv);
+
+ QColor cmyk = color.convertTo(QColor::Cmyk);
+ QVERIFY(cmyk.spec() == QColor::Cmyk);
+
+ QColor hsl = color.convertTo(QColor::Hsl);
+ QVERIFY(hsl.spec() == QColor::Hsl);
+
+ QColor invalid = color.convertTo(QColor::Invalid);
+ QVERIFY(invalid.spec() == QColor::Invalid);
+
+ DEPENDS_ON(toRgb());
+ DEPENDS_ON(toHsv());
+ DEPENDS_ON(toCmyk());
+ DEPENDS_ON(toHsl());
+}
+
+void tst_QColor::fromRgb()
+{ DEPENDS_ON(convertTo()); }
+
+void tst_QColor::fromHsv()
+{ DEPENDS_ON(convertTo()); }
+
+void tst_QColor::fromCmyk()
+{ DEPENDS_ON(convertTo()); }
+
+void tst_QColor::fromHsl()
+{ DEPENDS_ON(convertTo()); }
+
+void tst_QColor::light()
+{
+ QColor gray(Qt::gray);
+ QColor lighter = gray.light();
+ QVERIFY(lighter.value() > gray.value());
+}
+
+void tst_QColor::dark()
+{
+ QColor gray(Qt::gray);
+ QColor darker = gray.dark();
+ QVERIFY(darker.value() < gray.value());
+}
+
+void tst_QColor::assignmentOoperator()
+{ DEPENDS_ON(convertTo()); }
+
+void tst_QColor::equalityOperator()
+{ DEPENDS_ON(convertTo()); }
+
+Q_DECLARE_METATYPE(QColor::Spec);
+
+void tst_QColor::specConstructor_data()
+{
+ QTest::addColumn<QColor::Spec>("spec");
+
+ QTest::newRow("Invalid") << QColor::Invalid;
+ QTest::newRow("Rgb") << QColor::Rgb;
+ QTest::newRow("Hsv") << QColor::Hsv;
+ QTest::newRow("Cmyk") << QColor::Cmyk;
+}
+
+void tst_QColor::specConstructor()
+{
+ QFETCH(QColor::Spec, spec);
+ QColor color = spec;
+ QCOMPARE(color.spec(), spec);
+}
+
+void tst_QColor::achromaticHslHue()
+{
+ QColor color = Qt::black;
+
+ QColor hsl = color.toHsl();
+ QCOMPARE(hsl.hslHue(), -1);
+}
+
+#ifdef Q_WS_X11
+void tst_QColor::allowX11ColorNames()
+{
+ DEPENDS_ON(setallowX11ColorNames());
+}
+
+void tst_QColor::setallowX11ColorNames()
+{
+#if defined(Q_OS_IRIX)
+ QSKIP("This fails due to the gamma settings in the SGI X server", SkipAll);
+#else
+ RGBData x11RgbTbl[] = {
+ // a few standard X11 color names
+ { "DodgerBlue1", qRgb(30, 144, 255) },
+ { "DodgerBlue2", qRgb(28, 134, 238) },
+ { "DodgerBlue3", qRgb(24, 116, 205) },
+ { "DodgerBlue4", qRgb(16, 78, 139) },
+ { "SteelBlue1", qRgb(99, 184, 255) },
+ { "SteelBlue2", qRgb(92, 172, 238) },
+ { "SteelBlue3", qRgb(79, 148, 205) },
+ { "SteelBlue4", qRgb(54, 100, 139) },
+ { "DeepSkyBlue1", qRgb(0, 191, 255) },
+ { "DeepSkyBlue2", qRgb(0, 178, 238) },
+ { "DeepSkyBlue3", qRgb(0, 154, 205) },
+ { "DeepSkyBlue4", qRgb(0, 104, 139) },
+ { "SkyBlue1", qRgb(135, 206, 255) },
+ { "SkyBlue2", qRgb(126, 192, 238) },
+ { "SkyBlue3", qRgb(108, 166, 205) },
+ { "SkyBlue4", qRgb(74, 112, 139) }
+ };
+ static const int x11RgbTblSize = sizeof(x11RgbTbl) / sizeof(RGBData);
+
+ // X11 color names should not work by default
+ QVERIFY(!QColor::allowX11ColorNames());
+ for (int i = 0; i < x11RgbTblSize; ++i) {
+ QString colorName = QLatin1String(x11RgbTbl[i].name);
+ QColor color;
+ color.setNamedColor(colorName);
+ QVERIFY(!color.isValid());
+ }
+
+ // enable X11 color names
+ QColor::setAllowX11ColorNames(true);
+ QVERIFY(QColor::allowX11ColorNames());
+ for (int i = 0; i < x11RgbTblSize; ++i) {
+ QString colorName = QLatin1String(x11RgbTbl[i].name);
+ QColor color;
+ color.setNamedColor(colorName);
+ QColor expected(x11RgbTbl[i].value);
+ QCOMPARE(color, expected);
+ }
+
+ // should be able to turn off X11 color names
+ QColor::setAllowX11ColorNames(false);
+ QVERIFY(!QColor::allowX11ColorNames());
+ for (int i = 0; i < x11RgbTblSize; ++i) {
+ QString colorName = QLatin1String(x11RgbTbl[i].name);
+ QColor color;
+ color.setNamedColor(colorName);
+ QVERIFY(!color.isValid());
+ }
+#endif // Q_OS_IRIX
+}
+#endif // Q_WS_X11
+
+QTEST_MAIN(tst_QColor)
+#include "tst_qcolor.moc"
diff --git a/tests/auto/gui/painting/qpaintengine/.gitignore b/tests/auto/gui/painting/qpaintengine/.gitignore
new file mode 100644
index 0000000000..e55942ea9f
--- /dev/null
+++ b/tests/auto/gui/painting/qpaintengine/.gitignore
@@ -0,0 +1 @@
+tst_qpaintengine
diff --git a/tests/auto/gui/painting/qpaintengine/qpaintengine.pro b/tests/auto/gui/painting/qpaintengine/qpaintengine.pro
new file mode 100644
index 0000000000..e37c1668ac
--- /dev/null
+++ b/tests/auto/gui/painting/qpaintengine/qpaintengine.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qpaintengine.h
+############################################################
+
+load(qttest_p4)
+
+SOURCES += tst_qpaintengine.cpp
+
+
diff --git a/tests/auto/gui/painting/qpaintengine/tst_qpaintengine.cpp b/tests/auto/gui/painting/qpaintengine/tst_qpaintengine.cpp
new file mode 100644
index 0000000000..ba9cc62a3d
--- /dev/null
+++ b/tests/auto/gui/painting/qpaintengine/tst_qpaintengine.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qpaintengine.h>
+#include <qpixmap.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPaintEngine : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QPaintEngine();
+ virtual ~tst_QPaintEngine();
+
+private slots:
+ void getSetCheck();
+};
+
+tst_QPaintEngine::tst_QPaintEngine()
+{
+}
+
+tst_QPaintEngine::~tst_QPaintEngine()
+{
+}
+
+class MyPaintEngine : public QPaintEngine
+{
+public:
+ MyPaintEngine() : QPaintEngine() {}
+ bool begin(QPaintDevice *) { return true; }
+ bool end() { return true; }
+ void updateState(const QPaintEngineState &) {}
+ void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
+ Type type() const { return Raster; }
+};
+
+// Testing get/set functions
+void tst_QPaintEngine::getSetCheck()
+{
+ MyPaintEngine obj1;
+ // QPaintDevice * QPaintEngine::paintDevice()
+ // void QPaintEngine::setPaintDevice(QPaintDevice *)
+ QPixmap *var1 = new QPixmap;
+ obj1.setPaintDevice(var1);
+ QCOMPARE((QPaintDevice *)var1, obj1.paintDevice());
+ obj1.setPaintDevice((QPaintDevice *)0);
+ QCOMPARE((QPaintDevice *)0, obj1.paintDevice());
+ delete var1;
+}
+
+QTEST_MAIN(tst_QPaintEngine)
+#include "tst_qpaintengine.moc"
diff --git a/tests/auto/gui/painting/qpainter/.gitignore b/tests/auto/gui/painting/qpainter/.gitignore
new file mode 100644
index 0000000000..33e0dbe945
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/.gitignore
@@ -0,0 +1,2 @@
+tst_qpainter
+foo.png
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.png b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.png
new file mode 100644
index 0000000000..f2ab9a776d
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.png b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.png
new file mode 100644
index 0000000000..b1c755b5b0
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.png b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.png
new file mode 100644
index 0000000000..0e30498da5
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.png b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.png
new file mode 100644
index 0000000000..f00796a3ad
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.png b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.png
new file mode 100644
index 0000000000..a9a1a8a536
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.png b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.png
new file mode 100644
index 0000000000..0e30498da5
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.png b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.png
new file mode 100644
index 0000000000..67db116b90
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.png b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.png
new file mode 100644
index 0000000000..7d32afa4a8
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.png b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.png
new file mode 100644
index 0000000000..0e30498da5
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/dst.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/dst.xbm
new file mode 100644
index 0000000000..e645a0b86b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/dst.xbm
@@ -0,0 +1,6 @@
+#define dst_width 8
+#define dst_height 8
+static char dst_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x30,0x00,0x30,0x00,
+ 0x11,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x10,0x00,0x00,
+ 0x00,0x11 };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm
new file mode 100644
index 0000000000..303c799264
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm
@@ -0,0 +1,6 @@
+#define res_AndNotROP_width 8
+#define res_AndNotROP_height 8
+static char res_AndNotROP_bits[] = {
+ 0xf0,0xf0,0xcc,0xcc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm
new file mode 100644
index 0000000000..31333de879
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm
@@ -0,0 +1,6 @@
+#define res_AndROP_width 8
+#define res_AndROP_height 8
+static char res_AndROP_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm
new file mode 100644
index 0000000000..9cc25ea147
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm
@@ -0,0 +1,6 @@
+#define res_ClearROP_width 8
+#define res_ClearROP_height 8
+static char res_ClearROP_bits[] = {
+ 0xf0,0xf0,0xc0,0xc0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm
new file mode 100644
index 0000000000..869844dcee
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm
@@ -0,0 +1,6 @@
+#define res_CopyROP_width 8
+#define res_CopyROP_height 8
+static char res_CopyROP_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0x35,0x00,0x5a,0x00,
+ 0x41,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc0,0x5b,0x2f,
+ 0x2b,0x50 };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm
new file mode 100644
index 0000000000..d058484fa8
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm
@@ -0,0 +1,6 @@
+#define res_NandROP_width 8
+#define res_NandROP_height 8
+static char res_NandROP_bits[] = {
+ 0xf0,0xf0,0xcc,0xcc,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm
new file mode 100644
index 0000000000..3a2bc23468
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm
@@ -0,0 +1,6 @@
+#define res_NopROP_width 8
+#define res_NopROP_height 8
+static char res_NopROP_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm
new file mode 100644
index 0000000000..c74be41bbd
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm
@@ -0,0 +1,6 @@
+#define res_NorROP_width 8
+#define res_NorROP_height 8
+static char res_NorROP_bits[] = {
+ 0xf0,0xf0,0xc0,0xc0,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm
new file mode 100644
index 0000000000..0cf8c3a82c
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotAndROP_width 8
+#define res_NotAndROP_height 8
+static char res_NotAndROP_bits[] = {
+ 0xf0,0xf0,0xc0,0xc0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm
new file mode 100644
index 0000000000..65474e16c5
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotCopyROP_width 8
+#define res_NotCopyROP_height 8
+static char res_NotCopyROP_bits[] = {
+ 0xf0,0xf0,0xc0,0xc0,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm
new file mode 100644
index 0000000000..144d8995b6
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotOrROP_width 8
+#define res_NotOrROP_height 8
+static char res_NotOrROP_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm
new file mode 100644
index 0000000000..ccb3d36fb4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotROP_width 8
+#define res_NotROP_height 8
+static char res_NotROP_bits[] = {
+ 0xf0,0xf0,0xcc,0xcc,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm
new file mode 100644
index 0000000000..4be8f51a80
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotXorROP_width 8
+#define res_NotXorROP_height 8
+static char res_NotXorROP_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm
new file mode 100644
index 0000000000..d53fbe00e1
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm
@@ -0,0 +1,6 @@
+#define res_OrNotROP_width 8
+#define res_OrNotROP_height 8
+static char res_OrNotROP_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm
new file mode 100644
index 0000000000..06b51fcc68
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm
@@ -0,0 +1,6 @@
+#define res_OrROP_width 8
+#define res_OrROP_height 8
+static char res_OrROP_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm
new file mode 100644
index 0000000000..ab42472bb0
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm
@@ -0,0 +1,6 @@
+#define res_SetROP_width 8
+#define res_SetROP_height 8
+static char res_SetROP_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm
new file mode 100644
index 0000000000..5ac892dd0b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm
@@ -0,0 +1,6 @@
+#define res_XorROP_width 8
+#define res_XorROP_height 8
+static char res_XorROP_bits[] = {
+ 0xf0,0xf0,0xcc,0xcc,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.png
new file mode 100644
index 0000000000..8a3d28f3ed
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.png
new file mode 100644
index 0000000000..fe017ac1ab
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.png
new file mode 100644
index 0000000000..82d938c023
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.png
new file mode 100644
index 0000000000..2b67b928e4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.png
new file mode 100644
index 0000000000..c95b5a10ba
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.png
new file mode 100644
index 0000000000..bbe2a24530
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.png
new file mode 100644
index 0000000000..0158278b84
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.png
new file mode 100644
index 0000000000..aa1f403075
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.png
new file mode 100644
index 0000000000..ebf8244eee
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.png
new file mode 100644
index 0000000000..88568bc330
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.png
new file mode 100644
index 0000000000..0ed6de2865
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.png
new file mode 100644
index 0000000000..c2ff341e6b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.png
new file mode 100644
index 0000000000..e08c9acbe2
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.png
new file mode 100644
index 0000000000..e9d7a57333
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.png
new file mode 100644
index 0000000000..01438a195c
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.png
new file mode 100644
index 0000000000..587623d3e8
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.png
new file mode 100644
index 0000000000..10e7ae59d5
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.png
new file mode 100644
index 0000000000..5c14136eb4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.png
new file mode 100644
index 0000000000..207f52564b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.png
new file mode 100644
index 0000000000..6981cee080
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.png
new file mode 100644
index 0000000000..8b8de9892a
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.png
new file mode 100644
index 0000000000..9825c0539f
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.png
new file mode 100644
index 0000000000..8d26638c03
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.png
new file mode 100644
index 0000000000..f5b33589ba
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.png
new file mode 100644
index 0000000000..adc4ee3701
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.png
new file mode 100644
index 0000000000..dccc94c43b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.png
new file mode 100644
index 0000000000..4d207e7968
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.png
new file mode 100644
index 0000000000..aa93d4d4a4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.png
new file mode 100644
index 0000000000..ad320f950b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.png
new file mode 100644
index 0000000000..3e33bb1078
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.png
new file mode 100644
index 0000000000..ce2b6f4e15
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.png
new file mode 100644
index 0000000000..9eddc9840b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.png
new file mode 100644
index 0000000000..4ea9669dd3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.png
new file mode 100644
index 0000000000..c64e0a5630
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.png
new file mode 100644
index 0000000000..1fe3def383
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.png
new file mode 100644
index 0000000000..9c294b04d9
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.png
new file mode 100644
index 0000000000..01c694cdcc
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.png
new file mode 100644
index 0000000000..4b11aa9c41
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.png
new file mode 100644
index 0000000000..accbe42112
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.png
new file mode 100644
index 0000000000..3c58d4fac7
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.png
new file mode 100644
index 0000000000..3b0a41c396
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.png
new file mode 100644
index 0000000000..045ef33012
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.png
new file mode 100644
index 0000000000..3a83725938
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png
new file mode 100644
index 0000000000..7c51fc16fa
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png
new file mode 100644
index 0000000000..8f519e8c52
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png
new file mode 100644
index 0000000000..a0f9f60653
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png
new file mode 100644
index 0000000000..95931a4317
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png
new file mode 100644
index 0000000000..f825d523b0
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png
new file mode 100644
index 0000000000..245a27ea2f
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png
new file mode 100644
index 0000000000..b32020675b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png
new file mode 100644
index 0000000000..cff8926587
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.png
new file mode 100644
index 0000000000..3622f3a2b1
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.png
new file mode 100644
index 0000000000..e31793e4a3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.png
new file mode 100644
index 0000000000..8e8237548b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.png
new file mode 100644
index 0000000000..f4b98914b4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.png
new file mode 100644
index 0000000000..b14fdba341
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.png
new file mode 100644
index 0000000000..129d7f3dc6
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.png
new file mode 100644
index 0000000000..d894c5cb68
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.png
new file mode 100644
index 0000000000..b1e61504cd
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.png
new file mode 100644
index 0000000000..8cf29cde81
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.png
new file mode 100644
index 0000000000..99fedf8c04
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.png
new file mode 100644
index 0000000000..bc220f546e
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.png
new file mode 100644
index 0000000000..f48e8b9f4d
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.png
new file mode 100644
index 0000000000..c5e3c0fc63
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.png
new file mode 100644
index 0000000000..13bb69f91b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.png
new file mode 100644
index 0000000000..4a7ca7f9b3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.png
new file mode 100644
index 0000000000..85b964301d
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.png
new file mode 100644
index 0000000000..d92bf16044
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.png
new file mode 100644
index 0000000000..bb81c5abe8
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.png
new file mode 100644
index 0000000000..9378f166cd
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.png
new file mode 100644
index 0000000000..2ea026eb6c
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.png
new file mode 100644
index 0000000000..8366d37eda
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.png
new file mode 100644
index 0000000000..39c36d1b52
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.png
new file mode 100644
index 0000000000..beb2bc35b8
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.png
new file mode 100644
index 0000000000..6ed17a72ed
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.png
new file mode 100644
index 0000000000..9e0b63c220
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.png
new file mode 100644
index 0000000000..6471b4aaa4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.png
new file mode 100644
index 0000000000..c158ea0d01
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.png
new file mode 100644
index 0000000000..eb3deacc86
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.png
new file mode 100644
index 0000000000..51948b0ac9
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.png
new file mode 100644
index 0000000000..00968ffd06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.png
new file mode 100644
index 0000000000..c2b009cac3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.png
new file mode 100644
index 0000000000..42b0b3c308
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.png
new file mode 100644
index 0000000000..bc43614ab3
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.png
new file mode 100644
index 0000000000..7486d4b3f4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.png
new file mode 100644
index 0000000000..8098634be4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.png
new file mode 100644
index 0000000000..8c5b9feb7c
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.png
new file mode 100644
index 0000000000..c7e51a1410
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.png
new file mode 100644
index 0000000000..8605b64d93
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/src1.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src1.xbm
new file mode 100644
index 0000000000..f088d28c8c
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src1.xbm
@@ -0,0 +1,12 @@
+#define src1_width 32
+#define src1_height 32
+static char src1_bits[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2-mask.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2-mask.xbm
new file mode 100644
index 0000000000..bd73f9433c
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2-mask.xbm
@@ -0,0 +1,16 @@
+#define src2_width 32
+#define src2_height 48
+static char src2_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,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2.xbm
new file mode 100644
index 0000000000..40126a9d17
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2.xbm
@@ -0,0 +1,16 @@
+#define src2_width 32
+#define src2_height 48
+static char src2_bits[] = {
+ 0xa7,0x01,0xc0,0x03,0x40,0x9b,0x80,0x08,0x18,0x00,0x00,0x00,0x48,0x00,0x00,
+ 0x00,0xbb,0xbb,0xbb,0xbb,0xee,0xee,0xee,0xee,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0x0d,0x00,0x0d,0x00,0x20,0x00,0x20,0x00,0x80,0xed,0xb7,0x08,0xe8,
+ 0x61,0x54,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x68,0xa2,0x02,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/src3.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src3.xbm
new file mode 100644
index 0000000000..2f2d5472a4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src3.xbm
@@ -0,0 +1,12 @@
+#define src3_width 32
+#define src3_height 32
+static char src3_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,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/dst.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/dst.xbm
new file mode 100644
index 0000000000..45543c8ebf
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/dst.xbm
@@ -0,0 +1,6 @@
+#define dst_width 8
+#define dst_height 8
+static char dst_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xb1,0x00,0x00,0x00,0x70,0xe6,0x6e,0x2b,0x70,0xe6,0x6e,0x2b,0x24,0x00,0x00,
+ 0x00,0x81 };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm
new file mode 100644
index 0000000000..303c799264
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm
@@ -0,0 +1,6 @@
+#define res_AndNotROP_width 8
+#define res_AndNotROP_height 8
+static char res_AndNotROP_bits[] = {
+ 0xf0,0xf0,0xcc,0xcc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm
new file mode 100644
index 0000000000..31333de879
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm
@@ -0,0 +1,6 @@
+#define res_AndROP_width 8
+#define res_AndROP_height 8
+static char res_AndROP_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm
new file mode 100644
index 0000000000..9cc25ea147
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm
@@ -0,0 +1,6 @@
+#define res_ClearROP_width 8
+#define res_ClearROP_height 8
+static char res_ClearROP_bits[] = {
+ 0xf0,0xf0,0xc0,0xc0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm
new file mode 100644
index 0000000000..869844dcee
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm
@@ -0,0 +1,6 @@
+#define res_CopyROP_width 8
+#define res_CopyROP_height 8
+static char res_CopyROP_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0x35,0x00,0x5a,0x00,
+ 0x41,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc0,0x5b,0x2f,
+ 0x2b,0x50 };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm
new file mode 100644
index 0000000000..d058484fa8
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm
@@ -0,0 +1,6 @@
+#define res_NandROP_width 8
+#define res_NandROP_height 8
+static char res_NandROP_bits[] = {
+ 0xf0,0xf0,0xcc,0xcc,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm
new file mode 100644
index 0000000000..3a2bc23468
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm
@@ -0,0 +1,6 @@
+#define res_NopROP_width 8
+#define res_NopROP_height 8
+static char res_NopROP_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm
new file mode 100644
index 0000000000..c74be41bbd
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm
@@ -0,0 +1,6 @@
+#define res_NorROP_width 8
+#define res_NorROP_height 8
+static char res_NorROP_bits[] = {
+ 0xf0,0xf0,0xc0,0xc0,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm
new file mode 100644
index 0000000000..0cf8c3a82c
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotAndROP_width 8
+#define res_NotAndROP_height 8
+static char res_NotAndROP_bits[] = {
+ 0xf0,0xf0,0xc0,0xc0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm
new file mode 100644
index 0000000000..65474e16c5
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotCopyROP_width 8
+#define res_NotCopyROP_height 8
+static char res_NotCopyROP_bits[] = {
+ 0xf0,0xf0,0xc0,0xc0,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm
new file mode 100644
index 0000000000..144d8995b6
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotOrROP_width 8
+#define res_NotOrROP_height 8
+static char res_NotOrROP_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm
new file mode 100644
index 0000000000..ccb3d36fb4
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotROP_width 8
+#define res_NotROP_height 8
+static char res_NotROP_bits[] = {
+ 0xf0,0xf0,0xcc,0xcc,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm
new file mode 100644
index 0000000000..4be8f51a80
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm
@@ -0,0 +1,6 @@
+#define res_NotXorROP_width 8
+#define res_NotXorROP_height 8
+static char res_NotXorROP_bits[] = {
+ 0xf0,0xf0,0xf0,0xf0,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm
new file mode 100644
index 0000000000..d53fbe00e1
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm
@@ -0,0 +1,6 @@
+#define res_OrNotROP_width 8
+#define res_OrNotROP_height 8
+static char res_OrNotROP_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm
new file mode 100644
index 0000000000..06b51fcc68
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm
@@ -0,0 +1,6 @@
+#define res_OrROP_width 8
+#define res_OrROP_height 8
+static char res_OrROP_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff,
+ 0x7f,0xff };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm
new file mode 100644
index 0000000000..ab42472bb0
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm
@@ -0,0 +1,6 @@
+#define res_SetROP_width 8
+#define res_SetROP_height 8
+static char res_SetROP_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm
new file mode 100644
index 0000000000..5ac892dd0b
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm
@@ -0,0 +1,6 @@
+#define res_XorROP_width 8
+#define res_XorROP_height 8
+static char res_XorROP_bits[] = {
+ 0xf0,0xf0,0xcc,0xcc,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00,
+ 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53,
+ 0x59,0x3a };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm
new file mode 100644
index 0000000000..ac9031f1f1
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm
@@ -0,0 +1,6 @@
+#define src1_width 8
+#define src1_height 8
+static char src1_bits[] = {
+ 0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,
+ 0x59,0x00,0x00,0x00,0x18,0xe6,0x6e,0x2b,0x18,0xe6,0x6e,0x2b,0x00,0x00,0x00,
+ 0x00,0x49 };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1.xbm
new file mode 100644
index 0000000000..d883569db2
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1.xbm
@@ -0,0 +1,6 @@
+#define src1_width 8
+#define src1_height 8
+static char src1_bits[] = {
+ 0xf0,0xf0,0xfc,0xfc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xe0,0xe5,0x6e,0x2b,
+ 0x29,0x00,0x00,0x00,0xe8,0xe5,0x6e,0x2b,0xe8,0xe5,0x6e,0x2b,0x3c,0x00,0x00,
+ 0x05,0x3c };
diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src2.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src2.xbm
new file mode 100644
index 0000000000..fb203df28a
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src2.xbm
@@ -0,0 +1,5 @@
+#define src2_width 4
+#define src2_height 4
+static char src2_bits[] = {
+ 0x0f,0x5f,0x40,0x00,0x00,0x00,0x00,0x2d,0x00,0x39,0x00,0x5f,0x00,0x5d,0x00,
+ 0x30 };
diff --git a/tests/auto/gui/painting/qpainter/qpainter.pro b/tests/auto/gui/painting/qpainter/qpainter.pro
new file mode 100644
index 0000000000..00307d3e58
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/qpainter.pro
@@ -0,0 +1,20 @@
+load(qttest_p4)
+
+QT += widgets widgets-private printsupport
+
+SOURCES += tst_qpainter.cpp
+wince*|symbian: {
+ addFiles.files = drawEllipse drawLine_rop_bitmap drawPixmap_rop drawPixmap_rop_bitmap task217400.png
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+}
+
+wince* {
+ DEFINES += SRCDIR=\\\".\\\"
+} else:!symbian {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
+
+
+mac*:CONFIG+=insignificant_test
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/gui/painting/qpainter/task217400.png b/tests/auto/gui/painting/qpainter/task217400.png
new file mode 100644
index 0000000000..c12a602ba6
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/task217400.png
Binary files differ
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
new file mode 100644
index 0000000000..c2c9002023
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -0,0 +1,4697 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "../../../../shared/util.h"
+
+#include <qpainter.h>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qfontmetrics.h>
+#include <qbitmap.h>
+#include <qimage.h>
+#include <qthread.h>
+#include <limits.h>
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
+#include <qprinter.h>
+#include <math.h>
+#endif
+#include <qpaintengine.h>
+#include <qdesktopwidget.h>
+#include <qpixmap.h>
+
+#include <qpainter.h>
+
+#include <qlabel.h>
+
+#include <qqueue.h>
+
+#include <qgraphicsview.h>
+#include <qgraphicsscene.h>
+#include <qgraphicsproxywidget.h>
+#include <qlayout.h>
+#include <qfontdatabase.h>
+
+#if defined(Q_OS_SYMBIAN)
+# define SRCDIR "."
+#endif
+
+Q_DECLARE_METATYPE(QGradientStops)
+Q_DECLARE_METATYPE(QLine)
+Q_DECLARE_METATYPE(QRect)
+Q_DECLARE_METATYPE(QSize)
+Q_DECLARE_METATYPE(QPoint)
+Q_DECLARE_METATYPE(QPainterPath)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPainter : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QPainter();
+ virtual ~tst_QPainter();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void qt_format_text_clip();
+ void qt_format_text_boundingRect();
+ void drawPixmap_comp_data();
+ void drawPixmap_comp();
+ void saveAndRestore_data();
+ void saveAndRestore();
+
+ void drawBorderPixmap();
+ void drawPixmapFragments();
+
+ void drawLine_data();
+ void drawLine();
+ void drawLine_clipped();
+ void drawLine_task121143();
+ void drawLine_task216948();
+
+ void drawLine_task190634();
+ void drawLine_task229459();
+ void drawLine_task234891();
+
+ void drawRect_data() { fillData(); }
+ void drawRect();
+ void drawRect2();
+
+ void fillRect();
+ void fillRect2();
+ void fillRect3();
+ void fillRect4();
+
+ void drawEllipse_data();
+ void drawEllipse();
+ void drawClippedEllipse_data();
+ void drawClippedEllipse();
+
+ void drawPath_data();
+ void drawPath();
+ void drawPath2();
+ void drawPath3();
+
+ void drawRoundRect_data() { fillData(); }
+ void drawRoundRect();
+
+ void qimageFormats_data();
+ void qimageFormats();
+ void textOnTransparentImage();
+
+ void initFrom();
+
+ void setWindow();
+
+ void combinedMatrix();
+ void renderHints();
+
+ void disableEnableClipping();
+ void setClipRect();
+ void setEqualClipRegionAndPath_data();
+ void setEqualClipRegionAndPath();
+
+ void clipRectSaveRestore();
+
+ void clippedFillPath_data();
+ void clippedFillPath();
+ void clippedLines_data();
+ void clippedLines();
+ void clippedPolygon_data();
+ void clippedPolygon();
+
+ void clippedText();
+
+ void clipBoundingRect();
+
+ void setOpacity_data();
+ void setOpacity();
+
+ void drawhelper_blend_untransformed_data();
+ void drawhelper_blend_untransformed();
+ void drawhelper_blend_tiled_untransformed_data();
+ void drawhelper_blend_tiled_untransformed();
+
+ void porterDuff_warning();
+
+ void drawhelper_blend_color();
+
+ void childWidgetViewport();
+
+ void fillRect_objectBoundingModeGradient();
+ void fillRect_stretchToDeviceMode();
+ void monoImages();
+
+ void linearGradientSymmetry_data();
+ void linearGradientSymmetry();
+ void gradientInterpolation();
+
+ void fpe_pixmapTransform();
+ void fpe_zeroLengthLines();
+ void fpe_divByZero();
+
+ void fpe_steepSlopes_data();
+ void fpe_steepSlopes();
+ void fpe_rasterizeLine_task232012();
+
+ void fpe_radialGradients();
+
+ void rasterizer_asserts();
+ void rasterizer_negativeCoords();
+
+ void blendOverFlow_data();
+ void blendOverFlow();
+
+ void largeImagePainting_data();
+ void largeImagePainting();
+
+ void imageScaling_task206785();
+
+ void outlineFillConsistency();
+
+ void drawImage_task217400_data();
+ void drawImage_task217400();
+ void drawImage_1x1();
+ void drawImage_task258776();
+ void drawRect_task215378();
+ void drawRect_task247505();
+
+ void drawText_subPixelPositionsInRaster_qtbug5053();
+
+ void drawImage_data();
+ void drawImage();
+
+ void clippedImage();
+
+ void stateResetBetweenQPainters();
+
+ void imageCoordinateLimit();
+ void imageBlending_data();
+ void imageBlending();
+ void imageBlending_clipped();
+
+ void paintOnNullPixmap();
+ void checkCompositionMode();
+
+ void drawPolygon();
+
+ void inactivePainter();
+
+ void extendedBlendModes();
+
+ void zeroOpacity();
+ void clippingBug();
+ void emptyClip();
+
+ void taskQT4444_dontOverflowDashOffset();
+
+ void painterBegin();
+ void setPenColorOnImage();
+ void setPenColorOnPixmap();
+
+ void QTBUG5939_attachPainterPrivate();
+
+ void drawPointScaled();
+
+ void QTBUG14614_gradientCacheRaceCondition();
+ void drawTextOpacity();
+
+ void QTBUG17053_zeroDashPattern();
+
+ void drawTextOutsideGuiThread();
+
+private:
+ void fillData();
+ void setPenColor(QPainter& p);
+ QColor baseColor( int k, int intensity=255 );
+ QImage getResImage( const QString &dir, const QString &addition, const QString &extension );
+ QBitmap getBitmap( const QString &dir, const QString &filename, bool mask );
+};
+
+// Testing get/set functions
+void tst_QPainter::getSetCheck()
+{
+ QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied);
+ QPainter obj1;
+ obj1.begin(&img);
+ // CompositionMode QPainter::compositionMode()
+ // void QPainter::setCompositionMode(CompositionMode)
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Clear));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Clear), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Source));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Source), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Destination));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Destination), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop), obj1.compositionMode());
+ obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Xor));
+ QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Xor), obj1.compositionMode());
+
+ // const QPen & QPainter::pen()
+ // void QPainter::setPen(const QPen &)
+ QPen var3(Qt::red);
+ obj1.setPen(var3);
+ QCOMPARE(var3, obj1.pen());
+ obj1.setPen(QPen());
+ QCOMPARE(QPen(), obj1.pen());
+
+ // const QBrush & QPainter::brush()
+ // void QPainter::setBrush(const QBrush &)
+ QBrush var4(Qt::red);
+ obj1.setBrush(var4);
+ QCOMPARE(var4, obj1.brush());
+ obj1.setBrush(QBrush());
+ QCOMPARE(QBrush(), obj1.brush());
+
+ // const QBrush & QPainter::background()
+ // void QPainter::setBackground(const QBrush &)
+ QBrush var5(Qt::yellow);
+ obj1.setBackground(var5);
+ QCOMPARE(var5, obj1.background());
+ obj1.setBackground(QBrush());
+ QCOMPARE(QBrush(), obj1.background());
+
+ // bool QPainter::matrixEnabled()
+ // void QPainter::setMatrixEnabled(bool)
+ obj1.setMatrixEnabled(false);
+ QCOMPARE(false, obj1.matrixEnabled());
+ obj1.setMatrixEnabled(true);
+ QCOMPARE(true, obj1.matrixEnabled());
+
+ // bool QPainter::viewTransformEnabled()
+ // void QPainter::setViewTransformEnabled(bool)
+ obj1.setViewTransformEnabled(false);
+ QCOMPARE(false, obj1.viewTransformEnabled());
+ obj1.setViewTransformEnabled(true);
+ QCOMPARE(true, obj1.viewTransformEnabled());
+}
+
+Q_DECLARE_METATYPE(QPixmap)
+Q_DECLARE_METATYPE(QPolygon)
+Q_DECLARE_METATYPE(QBrush)
+Q_DECLARE_METATYPE(QPen)
+Q_DECLARE_METATYPE(QFont)
+Q_DECLARE_METATYPE(QColor)
+Q_DECLARE_METATYPE(QRegion)
+
+tst_QPainter::tst_QPainter()
+{
+ // QtTestCase sets this to false, but this turns off alpha pixmaps on Unix.
+ QApplication::setDesktopSettingsAware(TRUE);
+}
+
+tst_QPainter::~tst_QPainter()
+{
+}
+
+void tst_QPainter::init()
+{
+}
+
+void tst_QPainter::cleanup()
+{
+}
+
+/* tests the clipping operations in qt_format_text, making sure
+ the clip rectangle after the call is the same as before
+*/
+void tst_QPainter::qt_format_text_clip()
+{
+ QVERIFY(1);
+ QSKIP( "Needs fixing...", SkipAll);
+
+ QWidget *w = new QWidget( 0 );
+
+ int modes[] = { Qt::AlignVCenter|Qt::TextSingleLine,
+ Qt::AlignVCenter|Qt::TextSingleLine|Qt::TextDontClip,
+ Qt::AlignVCenter|Qt::TextWordWrap,
+ Qt::AlignVCenter|Qt::TextWordWrap|Qt::TextDontClip,
+ 0
+ };
+
+ int *m = modes;
+ while( *m ) {
+ {
+ QPainter p( w );
+ QRegion clipreg = p.clipRegion();
+ bool hasClipping = p.hasClipping();
+ qreal tx = p.matrix().dx();
+ qreal ty = p.matrix().dy();
+
+ p.drawText( 10, 10, 100, 100, *m,
+ "fooo" );
+
+ QVERIFY( clipreg == p.clipRegion() );
+ QVERIFY( hasClipping == p.hasClipping() );
+ QCOMPARE( tx, p.matrix().dx() );
+ QCOMPARE( ty, p.matrix().dy() );
+
+ p.setClipRect( QRect( 5, 5, 50, 50 ) );
+ clipreg = p.clipRegion();
+ hasClipping = p.hasClipping();
+
+ p.drawText( 10, 10, 100, 100, *m,
+ "fooo" );
+
+ QVERIFY( clipreg == p.clipRegion() );
+ QVERIFY( hasClipping == p.hasClipping() );
+ QCOMPARE( tx, p.matrix().dx() );
+ QCOMPARE( ty, p.matrix().dy() );
+ }
+ {
+ QPainter p( w );
+ p.setMatrix( QMatrix( 2, 1, 3, 4, 5, 6 ) );
+ QRegion clipreg = p.clipRegion();
+ bool hasClipping = p.hasClipping();
+ qreal tx = p.matrix().dx();
+ qreal ty = p.matrix().dy();
+
+ p.drawText( 10, 10, 100, 100, *m,
+ "fooo" );
+
+ QVERIFY( clipreg == p.clipRegion() );
+ QVERIFY( hasClipping == p.hasClipping() );
+ QCOMPARE( tx, p.matrix().dx() );
+ QCOMPARE( ty, p.matrix().dy() );
+
+ p.setClipRect( QRect( 5, 5, 50, 50 ) );
+ clipreg = p.clipRegion();
+ hasClipping = p.hasClipping();
+
+ p.drawText( 10, 10, 100, 100, *m,
+ "fooo" );
+
+ QVERIFY( clipreg == p.clipRegion() );
+ QVERIFY( hasClipping == p.hasClipping() );
+ QCOMPARE( tx, p.matrix().dx() );
+ QCOMPARE( ty, p.matrix().dy() );
+ }
+ {
+ QPainter p( w );
+ QRegion clipreg = p.clipRegion();
+ bool hasClipping = p.hasClipping();
+ qreal tx = p.matrix().dx();
+ qreal ty = p.matrix().dy();
+
+ p.drawText( 10, 10, 100, 100, *m,
+ "fooo" );
+
+ QVERIFY( clipreg == p.clipRegion() );
+ QVERIFY( hasClipping == p.hasClipping() );
+ QCOMPARE( tx, p.matrix().dx() );
+ QCOMPARE( ty, p.matrix().dy() );
+
+ p.setClipRect( QRect( 5, 5, 50, 50 ));
+ clipreg = p.clipRegion();
+ hasClipping = p.hasClipping();
+
+ p.drawText( 10, 10, 100, 100, *m,
+ "fooo" );
+
+ QVERIFY( clipreg == p.clipRegion() );
+ QVERIFY( hasClipping == p.hasClipping() );
+ QCOMPARE( tx, p.matrix().dx() );
+ QCOMPARE( ty, p.matrix().dy() );
+ }
+ {
+ QPainter p( w );
+ p.setMatrix( QMatrix( 2, 1, 3, 4, 5, 6 ) );
+ QRegion clipreg = p.clipRegion();
+ bool hasClipping = p.hasClipping();
+ qreal tx = p.matrix().dx();
+ qreal ty = p.matrix().dy();
+
+ p.drawText( 10, 10, 100, 100, *m,
+ "fooo" );
+
+ QVERIFY( clipreg == p.clipRegion() );
+ QVERIFY( hasClipping == p.hasClipping() );
+ QCOMPARE( tx, p.matrix().dx() );
+ QCOMPARE( ty, p.matrix().dy() );
+
+ p.setClipRect(QRect( 5, 5, 50, 50 ));
+ clipreg = p.clipRegion();
+ hasClipping = p.hasClipping();
+
+ p.drawText( 10, 10, 100, 100, *m,
+ "fooo" );
+
+ QVERIFY( clipreg == p.clipRegion() );
+ QVERIFY( hasClipping == p.hasClipping() );
+ QCOMPARE( tx, p.matrix().dx() );
+ QCOMPARE( ty, p.matrix().dy() );
+ }
+ ++m;
+ }
+ delete w;
+}
+
+/* tests the bounding rect calculations in qt_format_text, making sure
+ the bounding rect has a reasonable value.
+*/
+void tst_QPainter::qt_format_text_boundingRect()
+{
+ QVERIFY(1);
+ QSKIP( "Needs fixing...", SkipAll);
+
+ {
+ const char * strings[] = {
+ "a\n\nb",
+ "abc",
+ "a\n \nb",
+ "this is a longer string",
+ "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233",
+ "aa\327\222\327\233aa",
+ "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233",
+ "\327\222\327\233aa",
+ "linebreakatend\n",
+ "some text longer than 30 chars with a line break at the end\n",
+ "some text\nwith line breaks\nin the middle\nand at the end\n",
+ "foo\n\n\nfoo",
+ 0
+ };
+
+ int modes[] = { Qt::AlignVCenter|Qt::TextSingleLine,
+ Qt::AlignVCenter|Qt::TextSingleLine|Qt::TextDontClip,
+ Qt::AlignVCenter|Qt::TextWordWrap,
+ Qt::AlignVCenter|Qt::TextWordWrap|Qt::TextDontClip,
+ Qt::AlignLeft,
+ Qt::AlignCenter,
+ Qt::AlignRight,
+ 0
+ };
+
+ QFont f;
+ for(int i = 5; i < 15; ++i) {
+ f.setPointSize(i);
+ QFontMetrics fm(f);
+ const char **str = strings;
+ while( *str ) {
+ int *m = modes;
+ while( *m ) {
+ QRect br = fm.boundingRect( 0, 0, 2000, 100, *m, QString::fromUtf8( *str ) );
+ QVERIFY( br.width() < 800 );
+
+ QRect br2 = fm.boundingRect( br.x(), br.y(), br.width(), br.height(), *m, QString::fromUtf8( *str ) );
+ QCOMPARE( br, br2 );
+#if 0
+ {
+ QPrinter printer;
+ printer.setOutputToFile(TRUE);
+ printer.setOutputFileName("tmp.prn");
+ QPainter p(&printer);
+ QRect pbr = p.fontMetrics().boundingRect( 0, 0, 2000, 100, *m, QString::fromUtf8( *str ) );
+ QCOMPARE(pbr, br);
+ }
+#endif
+#if !defined(QT_NO_PRINTER) && !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
+ {
+ QPrinter printer(QPrinter::HighResolution);
+ if (printer.printerName().isEmpty()) {
+ QSKIP( "No printers installed, skipping bounding rect test",
+ SkipSingle );
+ break;
+ }
+
+ printer.setOutputFileName("tmp.prn");
+ QPainter p(&printer);
+ QRect pbr = p.fontMetrics().boundingRect( 0, 0, 12000, 600, *m, QString::fromUtf8( *str ) );
+ QVERIFY(pbr.width() > 2*br.width());
+ QVERIFY(pbr.height() > 2*br.height());
+ }
+#endif
+ ++m;
+ }
+ ++str;
+ }
+ }
+ }
+
+ {
+ const char * strings[] = {
+ "a",
+ "a\nb",
+ "a\n\nb",
+ "abc",
+// "a\n \nb",
+ "this is a longer string",
+// "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233",
+// "aa\327\222\327\233aa",
+// "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233",
+// "\327\222\327\233aa",
+// "linebreakatend\n",
+// "some text longer than 30 chars with a line break at the end\n",
+// "some text\nwith line breaks\nin the middle\nand at the end\n",
+ "foo\n\n\nfoo",
+ "a\n\n\n\n\nb",
+ "a\n\n\n\n\n\nb",
+// "\347\231\273\351\214\262\346\203\205\345\240\261\343\201\214\350\246\213\343\201\244\343\201\213\343\202\211\343\201\252\343\201\204\343\201\213\347\204\241\345\212\271\343\201\252\343\201\237\343\202\201\343\200\201\nPhotoshop Album \343\202\222\350\265\267\345\213\225\343\201\247\343\201\215\343\201\276\343\201\233\343\202\223\343\200\202\345\206\215\343\202\244\343\203\263\343\202\271\343\203\210\343\203\274\343\203\253\343\201\227\343\201\246\343\201\217\343\201\240\343\201\225\343\201\204\343\200\202"
+// "\347\231\273\351\214\262\346\203\205\345\240\261\343\201\214\350\246\213\343\201\244\343\201\213\343\202\211\343\201\252\343\201\204\343\201\213\347\204\241\345\212\271\343\201\252\343\201\237\343\202\201\343\200\201\n\343\202\222\350\265\267\345\213\225\343\201\247\343\201\215\343\201\276\343\201\233\343\202\223\343\200\202\345\206\215\343\202\244\343\203\263\343\202\271\343\203\210\343\203\274\343\203\253\343\201\227\343\201\246\343\201\217\343\201\240\343\201\225\343\201\204\343\200\202",
+ 0
+ };
+
+ int modes[] = { Qt::AlignVCenter,
+ Qt::AlignLeft,
+ Qt::AlignCenter,
+ Qt::AlignRight,
+ 0
+ };
+
+
+ QFont f;
+ for(int i = 5; i < 15; ++i) {
+ f.setPointSize(i);
+ QFontMetrics fm(f);
+ const char **str = strings;
+ while( *str ) {
+ int *m = modes;
+ while( *m ) {
+ QString s = QString::fromUtf8(*str);
+ QRect br = fm.boundingRect(0, 0, 1000, 1000, *m, s );
+ int lines =
+ s.count("\n");
+ int expectedHeight = fm.height()+lines*fm.lineSpacing();
+ QCOMPARE(br.height(), expectedHeight);
+ ++m;
+ }
+ ++str;
+ }
+ QRect br = fm.boundingRect(0, 0, 100, 0, Qt::TextWordWrap,
+ "A paragraph with gggggggggggggggggggggggggggggggggggg in the middle.");
+ QVERIFY(br.height() >= fm.height()+2*fm.lineSpacing());
+ }
+ }
+}
+
+
+static const char* const maskSource_data[] = {
+"16 13 6 1",
+". c None",
+"d c #000000",
+"# c #999999",
+"c c #cccccc",
+"b c #ffff00",
+"a c #ffffff",
+"...#####........",
+"..#aaaaa#.......",
+".#abcbcba######.",
+".#acbcbcaaaaaa#d",
+".#abcbcbcbcbcb#d",
+"#############b#d",
+"#aaaaaaaaaa##c#d",
+"#abcbcbcbcbbd##d",
+".#abcbcbcbcbcd#d",
+".#acbcbcbcbcbd#d",
+"..#acbcbcbcbb#dd",
+"..#############d",
+"...ddddddddddddd"};
+
+static const char* const maskResult_data[] = {
+"16 13 6 1",
+". c #ff0000",
+"d c #000000",
+"# c #999999",
+"c c #cccccc",
+"b c #ffff00",
+"a c #ffffff",
+"...#####........",
+"..#aaaaa#.......",
+".#abcbcba######.",
+".#acbcbcaaaaaa#d",
+".#abcbcbcbcbcb#d",
+"#############b#d",
+"#aaaaaaaaaa##c#d",
+"#abcbcbcbcbbd##d",
+".#abcbcbcbcbcd#d",
+".#acbcbcbcbcbd#d",
+"..#acbcbcbcbb#dd",
+"..#############d",
+"...ddddddddddddd"};
+
+
+void tst_QPainter::drawPixmap_comp_data()
+{
+ if (qApp->desktop()->depth() < 24) {
+ QSKIP("Test only works on 32 bit displays", SkipAll);
+ return;
+ }
+
+ QTest::addColumn<uint>("dest");
+ QTest::addColumn<uint>("source");
+
+ QTest::newRow("0% on 0%, 1") << 0x00000000u<< 0x00000000u;
+ QTest::newRow("0% on 0%, 2") << 0x00007fffu << 0x00ff007fu;
+
+ QTest::newRow("50% on a=0%") << 0x00000000u << 0x7fff0000u;
+ QTest::newRow("50% on a=50%") << 0x7f000000u << 0x7fff0000u;
+ QTest::newRow("50% on deadbeef") << 0xdeafbeefu << 0x7fff0000u;
+ QTest::newRow("deadbeef on a=0%") << 0x00000000u << 0xdeadbeefu;
+ QTest::newRow("deadbeef on a=50%") << 0x7f000000u << 0xdeadbeefu;
+ QTest::newRow("50% blue on 50% red") << 0x7fff0000u << 0x7f0000ffu;
+ QTest::newRow("50% blue on 50% green") << 0x7f00ff00u << 0x7f0000ffu;
+ QTest::newRow("50% red on 50% green") << 0x7f00ff00u << 0x7fff0000u;
+ QTest::newRow("0% on 50%") << 0x7fff00ffu << 0x00ffffffu;
+ QTest::newRow("100% on deadbeef") << 0xdeafbeefu << 0xffabcdefu;
+ QTest::newRow("100% on a=0%") << 0x00000000u << 0xffabcdefu;
+}
+
+QRgb qt_compose_alpha(QRgb source, QRgb dest)
+{
+ int r1 = qRed(dest), g1 = qGreen(dest), b1 = qBlue(dest), a1 = qAlpha(dest);
+ int r2 = qRed(source), g2 = qGreen(source), b2 = qBlue(source), a2 = qAlpha(source);
+
+ int alpha = qMin(a2 + ((255 - a2) * a1 + 127) / 255, 255);
+ if (alpha == 0)
+ return qRgba(0, 0, 0, 0);
+
+ return qRgba(
+ qMin((r2 * a2 + (255 - a2) * r1 * a1 / 255) / alpha, 255),
+ qMin((g2 * a2 + (255 - a2) * g1 * a1 / 255) / alpha, 255),
+ qMin((b2 * a2 + (255 - a2) * b1 * a1 / 255) / alpha, 255),
+ alpha);
+}
+
+/* Tests that drawing masked pixmaps works
+*/
+void tst_QPainter::drawPixmap_comp()
+{
+#ifdef Q_WS_MAC
+ QSKIP("Mac has other ideas about alpha composition", SkipAll);
+#endif
+
+ QFETCH(uint, dest);
+ QFETCH(uint, source);
+
+ QRgb expected = qt_compose_alpha(source, dest);
+
+ QColor c1(qRed(dest), qGreen(dest), qBlue(dest), qAlpha(dest));
+ QColor c2(qRed(source), qGreen(source), qBlue(source), qAlpha(source));
+
+ QPixmap destPm(10, 10), srcPm(10, 10);
+ destPm.fill(c1);
+ srcPm.fill(c2);
+
+#if defined(Q_WS_X11)
+ if (!destPm.x11PictureHandle())
+ QSKIP("Requires XRender support", SkipAll);
+#endif
+
+ QPainter p(&destPm);
+ p.drawPixmap(0, 0, srcPm);
+ p.end();
+
+ QImage result = destPm.toImage().convertToFormat(QImage::Format_ARGB32);
+ bool different = false;
+ for (int y=0; y<result.height(); ++y)
+ for (int x=0; x<result.width(); ++x) {
+ bool diff;
+ if (qAlpha(expected) == 0) {
+ diff = qAlpha(result.pixel(x, y)) != 0;
+ } else {
+ // Compensate for possible roundoff / platform fudge
+ int off = 1;
+ QRgb pix = result.pixel(x, y);
+ diff = (qAbs(qRed(pix) - qRed(expected)) > off)
+ || (qAbs(qGreen(pix) - qGreen(expected)) > off)
+ || (qAbs(qBlue(pix) - qBlue(expected)) > off)
+ || (qAbs(qAlpha(pix) - qAlpha(expected)) > off);
+ }
+ if (diff && !different)
+ qDebug( "Different at %d,%d pixel [%d,%d,%d,%d] expected [%d,%d,%d,%d]", x, y,
+ qRed(result.pixel(x, y)), qGreen(result.pixel(x, y)),
+ qBlue(result.pixel(x, y)), qAlpha(result.pixel(x, y)),
+ qRed(expected), qGreen(expected), qBlue(expected), qAlpha(expected));
+ different |= diff;
+ }
+
+ QVERIFY(!different);
+}
+
+void tst_QPainter::saveAndRestore_data()
+{
+ QVERIFY(1);
+
+ QTest::addColumn<QFont>("font");
+ QTest::addColumn<QPen>("pen");
+ QTest::addColumn<QBrush>("brush");
+ QTest::addColumn<QColor>("backgroundColor");
+ QTest::addColumn<int>("backgroundMode");
+ QTest::addColumn<QPoint>("brushOrigin");
+ QTest::addColumn<QRegion>("clipRegion");
+ QTest::addColumn<QRect>("window");
+ QTest::addColumn<QRect>("viewport");
+
+ QPixmap pixmap(1, 1);
+ QPainter p(&pixmap);
+ QFont font = p.font();
+ QPen pen = p.pen();
+ QBrush brush = p.brush();
+ QColor backgroundColor = p.background().color();
+ Qt::BGMode backgroundMode = p.backgroundMode();
+ QPoint brushOrigin = p.brushOrigin();
+ QRegion clipRegion = p.clipRegion();
+ QRect window = p.window();
+ QRect viewport = p.viewport();
+
+ QTest::newRow("Original") << font << pen << brush << backgroundColor << int(backgroundMode)
+ << brushOrigin << clipRegion << window << viewport;
+
+ QFont font2 = font;
+ font2.setPointSize( 24 );
+ QTest::newRow("Modified font.pointSize, brush, backgroundColor, backgroundMode")
+ << font2 << pen << QBrush(Qt::red) << QColor(Qt::blue) << int(Qt::TransparentMode)
+ << brushOrigin << clipRegion << window << viewport;
+
+ font2 = font;
+ font2.setPixelSize( 20 );
+ QTest::newRow("Modified font.pixelSize, brushOrigin, pos")
+ << font2 << pen << brush << backgroundColor << int(backgroundMode)
+ << QPoint( 50, 32 ) << clipRegion << window << viewport;
+
+ QTest::newRow("Modified clipRegion, window, viewport")
+ << font << pen << brush << backgroundColor << int(backgroundMode)
+ << brushOrigin << clipRegion.subtracted(QRect(10,10,50,30))
+ << QRect(-500, -500, 500, 500 ) << QRect( 0, 0, 50, 50 );
+}
+
+void tst_QPainter::saveAndRestore()
+{
+ QFETCH( QFont, font );
+ QFETCH( QPen, pen );
+ QFETCH( QBrush, brush );
+ QFETCH( QColor, backgroundColor );
+ QFETCH( int, backgroundMode );
+ QFETCH( QPoint, brushOrigin );
+ QFETCH( QRegion, clipRegion );
+ QFETCH( QRect, window );
+ QFETCH( QRect, viewport );
+
+ QPixmap pixmap(1, 1);
+ QPainter painter(&pixmap);
+
+ QFont font_org = painter.font();
+ QPen pen_org = painter.pen();
+ QBrush brush_org = painter.brush();
+ QColor backgroundColor_org = painter.background().color();
+ Qt::BGMode backgroundMode_org = painter.backgroundMode();
+ QPoint brushOrigin_org = painter.brushOrigin();
+ QRegion clipRegion_org = painter.clipRegion();
+ QRect window_org = painter.window();
+ QRect viewport_org = painter.viewport();
+
+ painter.save();
+ painter.setFont( font );
+ painter.setPen( QPen(pen) );
+ painter.setBrush( brush );
+ painter.setBackground( backgroundColor );
+ painter.setBackgroundMode( (Qt::BGMode)backgroundMode );
+ painter.setBrushOrigin( brushOrigin );
+ painter.setClipRegion( clipRegion );
+ painter.setWindow( window );
+ painter.setViewport( viewport );
+ painter.restore();
+
+ QCOMPARE( painter.font(), font_org );
+ QCOMPARE( painter.font().pointSize(), font_org.pointSize() );
+ QCOMPARE( painter.font().pixelSize(), font_org.pixelSize() );
+ QCOMPARE( painter.pen(), pen_org );
+ QCOMPARE( painter.brush(), brush_org );
+ QCOMPARE( painter.background().color(), backgroundColor_org );
+ QCOMPARE( painter.backgroundMode(), backgroundMode_org );
+ QCOMPARE( painter.brushOrigin(), brushOrigin_org );
+ QCOMPARE( painter.clipRegion(), clipRegion_org );
+ QCOMPARE( painter.window(), window_org );
+ QCOMPARE( painter.viewport(), viewport_org );
+}
+
+/*
+ Helper functions
+*/
+
+QColor tst_QPainter::baseColor( int k, int intensity )
+{
+ int r = ( k & 1 ) * intensity;
+ int g = ( (k>>1) & 1 ) * intensity;
+ int b = ( (k>>2) & 1 ) * intensity;
+ return QColor( r, g, b );
+}
+
+QImage tst_QPainter::getResImage( const QString &dir, const QString &addition, const QString &extension )
+{
+ QImage res;
+ QString resFilename = dir + QString( "/res_%1." ).arg( addition ) + extension;
+ if ( !res.load( resFilename ) ) {
+ QWARN(QString("Could not load result data %s %1").arg(resFilename).toLatin1());
+ return QImage();
+ }
+ return res;
+}
+
+QBitmap tst_QPainter::getBitmap( const QString &dir, const QString &filename, bool mask )
+{
+ QBitmap bm;
+ QString bmFilename = dir + QString( "/%1.xbm" ).arg( filename );
+ if ( !bm.load( bmFilename ) ) {
+ QWARN(QString("Could not load bitmap '%1'").arg(bmFilename).toLatin1());
+ return QBitmap();
+ }
+ if ( mask ) {
+ QBitmap mask;
+ QString maskFilename = dir + QString( "/%1-mask.xbm" ).arg( filename );
+ if ( !mask.load( maskFilename ) ) {
+ QWARN(QString("Could not load mask '%1'").arg(maskFilename).toLatin1());
+ return QBitmap();
+ }
+ bm.setMask( mask );
+ }
+ return bm;
+}
+
+static int getPaintedPixels(const QImage &image, const QColor &background)
+{
+ uint color = background.rgba();
+
+ int pixels = 0;
+
+ for (int y = 0; y < image.height(); ++y)
+ for (int x = 0; x < image.width(); ++x)
+ if (image.pixel(x, y) != color)
+ ++pixels;
+
+ return pixels;
+}
+
+static QRect getPaintedSize(const QImage &image, const QColor &background)
+{
+ // not the fastest but at least it works..
+ int xmin = image.width() + 1;
+ int xmax = -1;
+ int ymin = image.height() +1;
+ int ymax = -1;
+
+ uint color = background.rgba();
+
+ for ( int y = 0; y < image.height(); ++y ) {
+ for ( int x = 0; x < image.width(); ++x ) {
+ QRgb pixel = image.pixel( x, y );
+ if ( pixel != color && x < xmin )
+ xmin = x;
+ if ( pixel != color && x > xmax )
+ xmax = x;
+ if ( pixel != color && y < ymin )
+ ymin = y;
+ if ( pixel != color && y > ymax )
+ ymax = y;
+ }
+ }
+
+ return QRect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
+}
+
+static QRect getPaintedSize(const QPixmap &pm, const QColor &background)
+{
+ return getPaintedSize(pm.toImage(), background);
+}
+
+void tst_QPainter::initFrom()
+{
+ QWidget *widget = new QWidget();
+ QPalette pal = widget->palette();
+ pal.setColor(QPalette::Foreground, QColor(255, 0, 0));
+ pal.setBrush(QPalette::Background, QColor(0, 255, 0));
+ widget->setPalette(pal);
+
+ QFont font = widget->font();
+ font.setPointSize(26);
+ font.setItalic(true);
+ widget->setFont(font);
+
+ QPixmap pm(100, 100);
+ QPainter p(&pm);
+ p.initFrom(widget);
+
+ QCOMPARE(p.font(), font);
+ QCOMPARE(p.pen().color(), pal.color(QPalette::Foreground));
+ QCOMPARE(p.background(), pal.background());
+
+ delete widget;
+}
+
+void tst_QPainter::drawBorderPixmap()
+{
+ QPixmap src(79,79);
+ src.fill(Qt::transparent);
+
+ QImage pm(200,200,QImage::Format_RGB32);
+ QPainter p(&pm);
+ p.setTransform(QTransform(-1,0,0,-1,173.5,153.5));
+ qDrawBorderPixmap(&p, QRect(0,0,75,105), QMargins(39,39,39,39), src, QRect(0,0,79,79), QMargins(39,39,39,39),
+ QTileRules(Qt::StretchTile,Qt::StretchTile), 0);
+}
+
+void tst_QPainter::drawPixmapFragments()
+{
+ QPixmap origPixmap(20, 20);
+ QPixmap resPixmap(20, 20);
+ QPainter::PixmapFragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1},
+ { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1},
+ {15, 5, 0, 10, 10, 10, 1, 1, 0, 1},
+ { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} };
+ {
+ QPainter p(&origPixmap);
+ p.fillRect(0, 0, 10, 10, Qt::red);
+ p.fillRect(10, 0, 10, 10, Qt::green);
+ p.fillRect(0, 10, 10, 10, Qt::blue);
+ p.fillRect(10, 10, 10, 10, Qt::yellow);
+ }
+ {
+ QPainter p(&resPixmap);
+ p.drawPixmapFragments(fragments, 4, origPixmap);
+ }
+
+ QImage origImage = origPixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ QImage resImage = resPixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+
+ QVERIFY(resImage.size() == resPixmap.size());
+ QVERIFY(resImage.pixel(5, 5) == origImage.pixel(15, 15));
+ QVERIFY(resImage.pixel(5, 15) == origImage.pixel(15, 5));
+ QVERIFY(resImage.pixel(15, 5) == origImage.pixel(5, 15));
+ QVERIFY(resImage.pixel(15, 15) == origImage.pixel(5, 5));
+
+
+ QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2));
+ QVERIFY(fragment.x == 20);
+ QVERIFY(fragment.y == 20);
+ QVERIFY(fragment.sourceLeft == 30);
+ QVERIFY(fragment.sourceTop == 30);
+ QVERIFY(fragment.width == 2);
+ QVERIFY(fragment.height == 2);
+ QVERIFY(fragment.scaleX == 1);
+ QVERIFY(fragment.scaleY == 1);
+ QVERIFY(fragment.rotation == 0);
+ QVERIFY(fragment.opacity == 1);
+}
+
+void tst_QPainter::drawLine_data()
+{
+ QTest::addColumn<QLine>("line");
+
+ QTest::newRow("0-45") << QLine(0, 20, 100, 0);
+ QTest::newRow("45-90") << QLine(0, 100, 20, 0);
+ QTest::newRow("90-135") << QLine(20, 100, 0, 0);
+ QTest::newRow("135-180") << QLine(100, 20, 0, 0);
+ QTest::newRow("180-225") << QLine(100, 0, 0, 20);
+ QTest::newRow("225-270") << QLine(20, 0, 0, 100);
+ QTest::newRow("270-315") << QLine(0, 0, 20, 100);
+ QTest::newRow("315-360") << QLine(0, 0, 100, 20);
+}
+
+void tst_QPainter::drawLine()
+{
+ const int offset = 5;
+ const int epsilon = 1; // allow for one pixel difference
+
+ QFETCH(QLine, line);
+
+ QPixmap pixmapUnclipped(qMin(line.x1(), line.x2())
+ + 2*offset + qAbs(line.dx()),
+ qMin(line.y1(), line.y2())
+ + 2*offset + qAbs(line.dy()));
+
+ { // unclipped
+ pixmapUnclipped.fill(Qt::white);
+ QPainter p(&pixmapUnclipped);
+ p.translate(offset, offset);
+ p.setPen(QPen(Qt::black));
+ p.drawLine(line);
+ p.end();
+
+ const QRect painted = getPaintedSize(pixmapUnclipped, Qt::white);
+
+ QLine l = line;
+ l.translate(offset, offset);
+ QVERIFY(qAbs(painted.width() - qAbs(l.dx())) <= epsilon);
+ QVERIFY(qAbs(painted.height() - qAbs(l.dy())) <= epsilon);
+ QVERIFY(qAbs(painted.top() - qMin(l.y1(), l.y2())) <= epsilon);
+ QVERIFY(qAbs(painted.left() - qMin(l.x1(), l.x2())) <= epsilon);
+ QVERIFY(qAbs(painted.bottom() - qMax(l.y1(), l.y2())) <= epsilon);
+ QVERIFY(qAbs(painted.right() - qMax(l.x1(), l.x2())) <= epsilon);
+ }
+
+ QPixmap pixmapClipped(qMin(line.x1(), line.x2())
+ + 2*offset + qAbs(line.dx()),
+ qMin(line.y1(), line.y2())
+ + 2*offset + qAbs(line.dy()));
+ { // clipped
+ const QRect clip = QRect(line.p1(), line.p2()).normalized();
+
+ pixmapClipped.fill(Qt::white);
+ QPainter p(&pixmapClipped);
+ p.translate(offset, offset);
+ p.setClipRect(clip);
+ p.setPen(QPen(Qt::black));
+ p.drawLine(line);
+ p.end();
+ }
+
+ const QImage unclipped = pixmapUnclipped.toImage();
+ const QImage clipped = pixmapClipped.toImage();
+ QCOMPARE(unclipped, clipped);
+}
+
+void tst_QPainter::drawLine_clipped()
+{
+ QImage image(16, 1, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0x0);
+
+ QPainter p(&image);
+ p.setPen(QPen(Qt::black, 10));
+
+ // this should fill the whole image
+ p.drawLine(-1, -1, 17, 1);
+ p.end();
+
+ for (int x = 0; x < 16; ++x)
+ QCOMPARE(image.pixel(x, 0), 0xff000000);
+}
+
+void tst_QPainter::drawLine_task121143()
+{
+ QPen pen(Qt::black);
+
+ QImage image(5, 5, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0xffffffff);
+ QPainter p(&image);
+ p.setPen(pen);
+ p.drawLine(QLine(0, 0+4, 0+4, 0));
+ p.end();
+
+ QImage expected(5, 5, QImage::Format_ARGB32_Premultiplied);
+ expected.fill(0xffffffff);
+ for (int x = 0; x < 5; ++x)
+ expected.setPixel(x, 5-x-1, pen.color().rgb());
+
+ QCOMPARE(image, expected);
+}
+
+void tst_QPainter::drawLine_task190634()
+{
+ QPen pen(Qt::black, 3);
+
+ QImage image(32, 32, QImage::Format_ARGB32_Premultiplied);
+ QPainter p(&image);
+ p.fillRect(0, 0, image.width(), image.height(), Qt::white);
+
+ p.setPen(pen);
+ p.drawLine(QLineF(2, -1.6, 10, -1.6));
+ p.end();
+
+ const uint *data = reinterpret_cast<uint *>(image.bits());
+
+ for (int i = 0; i < image.width() * image.height(); ++i)
+ QCOMPARE(data[i], 0xffffffff);
+
+ p.begin(&image);
+ p.fillRect(0, 0, image.width(), image.height(), Qt::white);
+
+ p.setPen(pen);
+ p.drawLine(QLineF(-1.6, 2, -1.6, 10));
+ p.end();
+
+ data = reinterpret_cast<uint *>(image.bits());
+
+ for (int i = 0; i < image.width() * image.height(); ++i)
+ QCOMPARE(data[i], 0xffffffff);
+
+ p.begin(&image);
+ p.fillRect(0, 0, image.width(), image.height(), Qt::white);
+
+ p.setPen(pen);
+ p.drawLine( QPoint(2,-2), QPoint(3,-5) );
+ p.end();
+
+ data = reinterpret_cast<uint *>(image.bits());
+
+ for (int i = 0; i < image.width() * image.height(); ++i)
+ QCOMPARE(data[i], 0xffffffff);
+}
+
+void tst_QPainter::drawLine_task229459()
+{
+ QImage image(32, 32, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0x0);
+ QPen pen(Qt::black, 64);
+
+ QPainter p(&image);
+ p.setPen(pen);
+ p.drawLine(-8, -8, 10000000, 10000000);
+ p.end();
+
+ QImage expected = image;
+ expected.fill(0xff000000);
+
+ QCOMPARE(image, expected);
+}
+
+void tst_QPainter::drawLine_task234891()
+{
+ QImage img(100, 1000, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+ QImage expected = img;
+
+ QPainter p(&img);
+ p.setPen(QPen(QBrush(QColor(255,0,0)), 6));
+ p.drawLine(QPointF(25000,100),QPointF(30000,105));
+
+ p.setPen(QPen(QBrush(QColor(0,255,0)), 6));
+ p.drawLine(QPointF(30000,150),QPointF(35000,155));
+
+ p.setPen(QPen(QBrush(QColor(0,0,255)), 6));
+ p.drawLine(QPointF(65000,200),QPointF(66000,205));
+
+ QCOMPARE(expected, img);
+}
+
+void tst_QPainter::drawLine_task216948()
+{
+ QImage img(1, 10, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+
+ QPainter p(&img);
+ QLine line(10, 0, 10, 10);
+ p.translate(-10, 0);
+ p.drawLine(line);
+ p.end();
+
+ for (int i = 0; i < img.height(); ++i)
+ QCOMPARE(img.pixel(0, i), QColor(Qt::black).rgba());
+}
+
+void tst_QPainter::drawRect()
+{
+ QFETCH(QRect, rect);
+ QFETCH(bool, usePen);
+
+ QPixmap pixmap(rect.x() + rect.width() + 10,
+ rect.y() + rect.height() + 10);
+ {
+ pixmap.fill(Qt::white);
+ QPainter p(&pixmap);
+ p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
+ p.setBrush(Qt::black);
+ p.drawRect(rect);
+ p.end();
+
+ int increment = usePen ? 1 : 0;
+
+ const QRect painted = getPaintedSize(pixmap, Qt::white);
+ QCOMPARE(painted.width(), rect.width() + increment);
+ QCOMPARE(painted.height(), rect.height() + increment);
+ }
+}
+
+void tst_QPainter::drawRect2()
+{
+ QImage image(64, 64, QImage::Format_ARGB32_Premultiplied);
+ {
+ image.fill(0xffffffff);
+
+ QTransform transform(0.368567, 0, 0, 0, 0.368567, 0, 0.0289, 0.0289, 1);
+
+ QPainter p(&image);
+ p.setTransform(transform);
+ p.setBrush(Qt::red);
+ p.setPen(Qt::NoPen);
+ p.drawRect(QRect(14, 14, 39, 39));
+ p.end();
+
+ QRect fill = getPaintedSize(image, Qt::white);
+ image.fill(0xffffffff);
+
+ p.begin(&image);
+ p.setTransform(transform);
+ p.drawRect(QRect(14, 14, 39, 39));
+ p.end();
+
+ QRect stroke = getPaintedSize(image, Qt::white);
+ QCOMPARE(stroke.adjusted(1, 1, 0, 0), fill.adjusted(0, 0, 1, 1));
+ }
+}
+
+void tst_QPainter::fillRect()
+{
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ image.fill(QColor(0, 0, 0, 0).rgba());
+
+ QPainter p(&image);
+
+ p.fillRect(0, 0, 100, 100, QColor(255, 0, 0, 127));
+
+// pixmap.save("bla1.png", "PNG");
+ QCOMPARE(getPaintedSize(image, QColor(0, 0, 0, 0)),
+ QRect(0, 0, 100, 100));
+ QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)).isValid(),
+ QRect().isValid());
+
+ p.setCompositionMode(QPainter::CompositionMode_SourceIn);
+ p.fillRect(50, 0, 50, 100, QColor(0, 0, 255, 255));
+
+ QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)),
+ QRect(50, 0, 50, 100));
+ QCOMPARE(getPaintedSize(image, QColor(0, 0, 127, 127)),
+ QRect(0, 0, 50, 100));
+}
+
+void tst_QPainter::fillRect2()
+{
+ QRgb background = 0x0;
+
+ QImage img(1, 20, QImage::Format_ARGB32_Premultiplied);
+ img.fill(background);
+
+ QPainter p(&img);
+
+ QRectF rect(0, 1, 1.2, 18);
+ p.fillRect(rect, Qt::black);
+
+ p.end();
+
+ QCOMPARE(img.pixel(0, 0), background);
+ QCOMPARE(img.pixel(0, img.height() - 1), background);
+
+ QCOMPARE(img.pixel(0, 1), img.pixel(0, 2));
+ QCOMPARE(img.pixel(0, img.height() - 2), img.pixel(0, img.height() - 3));
+}
+
+void tst_QPainter::fillRect3()
+{
+ QImage img(1, 1, QImage::Format_ARGB32_Premultiplied);
+ img.fill(QColor(Qt::black).rgba());
+
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(img.rect(), Qt::transparent);
+ p.end();
+
+ QCOMPARE(img.pixel(0, 0), 0U);
+}
+
+void tst_QPainter::fillRect4()
+{
+ QImage image(100, 1, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0x0);
+
+ QImage expected = image;
+ expected.fill(0xffffffff);
+
+ QPainter p(&image);
+ p.scale(1.1, 1);
+ p.setPen(Qt::NoPen);
+
+ for (int i = 0; i < 33; ++i)
+ p.fillRect(QRectF(3 * i, 0, 3, 1), Qt::white);
+
+ p.end();
+
+ QCOMPARE(image, expected);
+}
+
+void tst_QPainter::drawPath_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<QRect>("expectedBounds");
+ QTest::addColumn<int>("expectedPixels");
+
+ {
+ QPainterPath p;
+ p.addRect(2, 2, 10, 10);
+ QTest::newRow("int-aligned rect") << p << QRect(2, 2, 10, 10) << 10 * 10;
+ }
+
+ {
+ QPainterPath p;
+ p.addRect(2.25, 2.25, 10, 10);
+ QTest::newRow("non-aligned rect") << p << QRect(3, 3, 10, 10) << 10 * 10;
+ }
+
+ {
+ QPainterPath p;
+ p.addRect(2.25, 2.25, 10.5, 10.5);
+ QTest::newRow("non-aligned rect 2") << p << QRect(3, 3, 10, 10) << 10 * 10;
+ }
+
+ {
+ QPainterPath p;
+ p.addRect(2.5, 2.5, 10, 10);
+ QTest::newRow("non-aligned rect 3") << p << QRect(3, 3, 10, 10) << 10 * 10;
+ }
+
+ {
+ QPainterPath p;
+ p.addRect(2, 2, 10, 10);
+ p.addRect(4, 4, 6, 6);
+ QTest::newRow("rect-in-rect") << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6;
+ }
+
+ {
+ QPainterPath p;
+ p.addRect(2, 2, 10, 10);
+ p.addRect(4, 4, 6, 6);
+ p.addRect(6, 6, 2, 2);
+ QTest::newRow("rect-in-rect-in-rect") << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6 + 2 * 2;
+ }
+}
+
+void tst_QPainter::drawPath()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(QRect, expectedBounds);
+ QFETCH(int, expectedPixels);
+
+ const int offset = 2;
+
+ QImage image(expectedBounds.width() + 2 * offset, expectedBounds.height() + 2 * offset,
+ QImage::Format_ARGB32_Premultiplied);
+ image.fill(QColor(Qt::white).rgb());
+
+ QPainter p(&image);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::black);
+ p.translate(offset - expectedBounds.left(), offset - expectedBounds.top());
+ p.drawPath(path);
+ p.end();
+
+ const QRect paintedBounds = getPaintedSize(image, Qt::white);
+
+ QCOMPARE(paintedBounds.x(), offset);
+ QCOMPARE(paintedBounds.y(), offset);
+ QCOMPARE(paintedBounds.width(), expectedBounds.width());
+ QCOMPARE(paintedBounds.height(), expectedBounds.height());
+
+ if (expectedPixels != -1) {
+ int paintedPixels = getPaintedPixels(image, Qt::white);
+ QCOMPARE(paintedPixels, expectedPixels);
+ }
+}
+
+void tst_QPainter::drawPath2()
+{
+ const int w = 50;
+
+ for (int h = 5; h < 200; ++h) {
+ QPainterPath p1, p2;
+ p1.lineTo(w, 0);
+ p1.lineTo(w, h);
+
+ p2.lineTo(w, h);
+ p2.lineTo(0, h);
+
+ const int offset = 2;
+
+ QImage image(w + 2 * offset, h + 2 * offset,
+ QImage::Format_ARGB32_Premultiplied);
+ image.fill(QColor(Qt::white).rgb());
+
+ QPainter p(&image);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::black);
+ p.translate(offset, offset);
+ p.drawPath(p1);
+ p.end();
+
+ const int p1Pixels = getPaintedPixels(image, Qt::white);
+
+ image.fill(QColor(Qt::white).rgb());
+ p.begin(&image);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::black);
+ p.translate(offset, offset);
+ p.drawPath(p2);
+ p.end();
+
+ const int p2Pixels = getPaintedPixels(image, Qt::white);
+
+ QCOMPARE(p1Pixels + p2Pixels, w * h);
+ }
+}
+
+void tst_QPainter::drawPath3()
+{
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
+ QImage imgA(400, 400, QImage::Format_RGB32);
+#else
+ QImage imgA(100, 100, QImage::Format_RGB32);
+#endif
+ imgA.fill(0xffffff);
+ QImage imgB = imgA;
+
+ QPainterPath path;
+ for (int y = 0; y < imgA.height(); ++y) {
+ for (int x = 0; x < imgA.width(); ++x) {
+ if ((x + y) & 1) {
+ imgA.setPixel(x, y, 0);
+ path.addRect(x, y, 1, 1);
+ }
+ }
+ }
+
+ QPainter p(&imgB);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::black);
+
+ p.drawPath(path);
+ p.end();
+
+ QVERIFY(imgA == imgB);
+
+ imgA.invertPixels();
+ imgB.fill(0xffffff);
+
+ p.begin(&imgB);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::black);
+
+ QRectF rect(0, 0, imgA.width(), imgA.height());
+ path.addRect(rect.adjusted(-10, -10, 10, 10));
+ p.drawPath(path);
+ p.end();
+
+ QVERIFY(imgA == imgB);
+
+ path.setFillRule(Qt::WindingFill);
+ imgB.fill(0xffffff);
+
+ p.begin(&imgB);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::black);
+ QRect clip = rect.adjusted(10, 10, -10, -10).toRect();
+ p.setClipRect(clip);
+ p.drawPath(path);
+ p.end();
+
+ QCOMPARE(getPaintedPixels(imgB, Qt::white), clip.width() * clip.height());
+}
+
+void tst_QPainter::drawEllipse_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<bool>("usePen");
+
+ // The current drawEllipse algorithm (drawEllipse_midpoint_i in
+ // qpaintengine_raster.cpp) draws ellipses that are too wide if the
+ // ratio between width and hight is too large/small (task 114874). Those
+ // ratios are therefore currently avoided.
+ for (int w = 10; w < 128; w += 7) {
+ for (int h = w/2; h < qMin(2*w, 128); h += 13) {
+ QString s = QString("%1x%2").arg(w).arg(h);
+ QTest::newRow(QString("%1 with pen").arg(s).toLatin1()) << QSize(w, h) << true;
+ QTest::newRow(QString("%1 no pen").arg(s).toLatin1()) << QSize(w, h) << false;
+ }
+ }
+}
+
+void tst_QPainter::drawEllipse()
+{
+ QFETCH(QSize, size);
+ QFETCH(bool, usePen);
+
+ const int offset = 10;
+ QRect rect(QPoint(offset, offset), size);
+
+ QImage image(size.width() + 2 * offset, size.height() + 2 * offset,
+ QImage::Format_ARGB32_Premultiplied);
+ image.fill(QColor(Qt::white).rgb());
+
+ QPainter p(&image);
+ p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
+ p.setBrush(Qt::black);
+ p.drawEllipse(rect);
+ p.end();
+
+ QPixmap pixmap = QPixmap::fromImage(image);
+
+ const QRect painted = getPaintedSize(pixmap, Qt::white);
+
+ QCOMPARE(painted.x(), rect.x());
+ QCOMPARE(painted.y(), rect.y() + (usePen ? 0 : 1));
+ QCOMPARE(painted.width(), size.width() + (usePen ? 1 : 0));
+ QCOMPARE(painted.height(), size.height() + (usePen ? 1 : -1));
+}
+
+void tst_QPainter::drawClippedEllipse_data()
+{
+ QTest::addColumn<QRect>("rect");
+
+ for (int w = 20; w < 128; w += 7) {
+ for (int h = w/2; h < qMin(2*w, 128); h += 13) {
+ QString s = QString("%1x%2").arg(w).arg(h);
+ QTest::newRow(QString("%1 top").arg(s).toLatin1()) << QRect(0, -h/2, w, h);
+ QTest::newRow(QString("%1 topright").arg(s).toLatin1()) << QRect(w/2, -h/2, w, h);
+ QTest::newRow(QString("%1 right").arg(s).toLatin1()) << QRect(w/2, 0, w, h);
+ QTest::newRow(QString("%1 bottomright").arg(s).toLatin1()) << QRect(w/2, h/2, w, h);
+ QTest::newRow(QString("%1 bottom").arg(s).toLatin1()) << QRect(0, h/2, w, h);
+ QTest::newRow(QString("%1 bottomleft").arg(s).toLatin1()) << QRect(-w/2, h/2, w, h);
+ QTest::newRow(QString("%1 left").arg(s).toLatin1()) << QRect(-w/2, 0, w, h);
+ QTest::newRow(QString("%1 topleft").arg(s).toLatin1()) << QRect(-w/2, -h/2, w, h);
+ }
+ }
+}
+
+void tst_QPainter::drawClippedEllipse()
+{
+ QFETCH(QRect, rect);
+ if (sizeof(qreal) != sizeof(double))
+ QSKIP("Test only works for qreal==double", SkipAll);
+ QImage image(rect.width() + 1, rect.height() + 1,
+ QImage::Format_ARGB32_Premultiplied);
+ QRect expected = QRect(rect.x(), rect.y(), rect.width()+1, rect.height()+1)
+ & QRect(0, 0, image.width(), image.height());
+
+
+ image.fill(QColor(Qt::white).rgb());
+ QPainter p(&image);
+ p.drawEllipse(rect);
+ p.end();
+
+ QPixmap pixmap = QPixmap::fromImage(image);
+ const QRect painted = getPaintedSize(pixmap, Qt::white);
+
+ QCOMPARE(painted.x(), expected.x());
+ QCOMPARE(painted.y(), expected.y());
+ QCOMPARE(painted.width(), expected.width());
+ QCOMPARE(painted.height(), expected.height());
+
+}
+
+void tst_QPainter::drawRoundRect()
+{
+ QFETCH(QRect, rect);
+ QFETCH(bool, usePen);
+
+#ifdef Q_WS_MAC
+ if (QTest::currentDataTag() == QByteArray("rect(6, 12, 3, 14) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(6, 17, 3, 25) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(10, 6, 10, 3) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(10, 12, 10, 14) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(13, 45, 17, 80) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(13, 50, 17, 91) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(17, 6, 24, 3) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(24, 12, 38, 14) with pen"))
+ QSKIP("The Mac paint engine is off-by-one on certain rect sizes", SkipSingle);
+#endif
+ QPixmap pixmap(rect.x() + rect.width() + 10,
+ rect.y() + rect.height() + 10);
+ {
+ pixmap.fill(Qt::white);
+ QPainter p(&pixmap);
+ p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
+ p.setBrush(Qt::black);
+ p.drawRoundRect(rect);
+ p.end();
+
+ int increment = usePen ? 1 : 0;
+
+ const QRect painted = getPaintedSize(pixmap, Qt::white);
+ QCOMPARE(painted.width(), rect.width() + increment);
+ QCOMPARE(painted.height(), rect.height() + increment);
+ }
+}
+
+Q_DECLARE_METATYPE(QImage::Format)
+
+void tst_QPainter::qimageFormats_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::newRow("QImage::Format_RGB32") << QImage::Format_RGB32;
+ QTest::newRow("QImage::Format_ARGB32") << QImage::Format_ARGB32;
+ QTest::newRow("QImage::Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("QImage::Format_RGB16") << QImage::Format_RGB16;
+ QTest::newRow("Qimage::Format_ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied;
+ QTest::newRow("Qimage::Format_RGB666") << QImage::Format_RGB666;
+ QTest::newRow("Qimage::Format_RGB555") << QImage::Format_RGB555;
+ QTest::newRow("Qimage::Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied;
+ QTest::newRow("Qimage::Format_RGB888") << QImage::Format_RGB888;
+}
+
+/*
+ Tests that QPainter can paint on various QImage formats.
+*/
+void tst_QPainter::qimageFormats()
+{
+ QFETCH(QImage::Format, format);
+
+ const QSize size(100, 100);
+ QImage image(size, format);
+ image.fill(0);
+
+ const QColor testColor(Qt::red);
+ QPainter p(&image);
+ QVERIFY(p.isActive());
+ p.setBrush(QBrush(testColor));
+ p.drawRect(QRect(QPoint(0,0), size));
+ QCOMPARE(image.pixel(50, 50), testColor.rgb());
+}
+
+void tst_QPainter::fillData()
+{
+ QTest::addColumn<QRect>("rect");
+ QTest::addColumn<bool>("usePen");
+
+ for (int w = 3; w < 50; w += 7) {
+ for (int h = 3; h < 50; h += 11) {
+ int x = w/2 + 5;
+ int y = h/2 + 5;
+ QTest::newRow(QString("rect(%1, %2, %3, %4) with pen").arg(x).arg(y).arg(w).arg(h).toLatin1())
+ << QRect(x, y, w, h) << true;
+ QTest::newRow(QString("rect(%1, %2, %3, %4) no pen").arg(x).arg(y).arg(w).arg(h).toLatin1())
+ << QRect(x, y, w, h) << false;
+ }
+ }
+}
+
+/*
+ Test that drawline works properly after setWindow has been called.
+*/
+void tst_QPainter::setWindow()
+{
+ QPixmap pixmap(600, 600);
+ pixmap.fill(QColor(Qt::white));
+
+ QPainter painter(&pixmap);
+ painter.setWindow(0, 0, 3, 3);
+ painter.drawLine(1, 1, 2, 2);
+
+ const QRect painted = getPaintedSize(pixmap, Qt::white);
+ QVERIFY(195 < painted.y() && painted.y() < 205); // correct value is around 200
+ QVERIFY(195 < painted.height() && painted.height() < 205); // correct value is around 200
+}
+
+void tst_QPainter::combinedMatrix()
+{
+ QPixmap pm(64, 64);
+
+ QPainter p(&pm);
+ p.setWindow(0, 0, 1, 1);
+ p.setViewport(32, 0, 32, 32);
+
+ p.translate(0.5, 0.5);
+
+ QMatrix cm = p.combinedMatrix();
+
+ QPointF pt = QPointF(0, 0) * cm;
+
+ QCOMPARE(pt.x(), 48.0);
+ QCOMPARE(pt.y(), 16.0);
+}
+
+void tst_QPainter::textOnTransparentImage()
+{
+ bool foundPixel = false;
+ QImage image(10, 10, QImage::Format_ARGB32_Premultiplied);
+ image.fill(qRgba(0, 0, 0, 0)); // transparent
+ {
+ QPainter painter(&image);
+ painter.setPen(QColor(255, 255, 255));
+ painter.drawText(0, 10, "W");
+ }
+ for (int x = 0; x < image.width(); ++x)
+ for (int y = 0; y < image.height(); ++y)
+ if (image.pixel(x, y) != 0)
+ foundPixel = true;
+ QVERIFY(foundPixel);
+}
+
+void tst_QPainter::renderHints()
+{
+ QImage img(1, 1, QImage::Format_RGB32);
+
+ QPainter p(&img);
+
+ // Turn off all...
+ p.setRenderHints(QPainter::RenderHints(0xffffffff), false);
+ QCOMPARE(p.renderHints(), QPainter::RenderHints(0));
+
+ // Single set/get
+ p.setRenderHint(QPainter::Antialiasing);
+ QVERIFY(p.renderHints() & QPainter::Antialiasing);
+
+ p.setRenderHint(QPainter::Antialiasing, false);
+ QVERIFY(!(p.renderHints() & QPainter::Antialiasing));
+
+ // Multi set/get
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+ QVERIFY(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform));
+
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
+ QVERIFY(!(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform)));
+}
+
+int countPixels(const QImage &img, const QRgb &color)
+{
+ int count = 0;
+ for (int y = 0; y < img.height(); ++y) {
+ for (int x = 0; x < img.width(); ++x) {
+ count += ((img.pixel(x, y) & 0xffffff) == color);
+ }
+ }
+ return count;
+}
+
+template <typename T>
+void testClipping(QImage &img)
+{
+ QPainterPath a, b;
+ a.addRect(QRect(2, 2, 4, 4));
+ b.addRect(QRect(4, 4, 4, 4));
+ QPainter p(&img);
+
+ p.end();
+ img.fill(0x0);
+ p.begin(&img);
+ p.setClipPath(a);
+ p.setClipPath(b, Qt::IntersectClip);
+
+ p.setClipping(false);
+ p.setPen(Qt::NoPen);
+ p.setBrush(QColor(0xff0000));
+ p.drawRect(T(0, 0, 10, 10));
+
+ p.setClipping(true);
+ p.setBrush(QColor(0x00ff00));
+ p.drawRect(T(0, 0, 10, 10));
+
+ QCOMPARE(countPixels(img, 0xff0000), 96);
+ QCOMPARE(countPixels(img, 0x00ff00), 4);
+}
+
+void tst_QPainter::disableEnableClipping()
+{
+ QImage img(10, 10, QImage::Format_RGB32);
+
+ testClipping<QRectF>(img);
+ testClipping<QRect>(img);
+}
+
+void tst_QPainter::setClipRect()
+{
+ QImage img(10, 10, QImage::Format_RGB32);
+ // simple test to let valgrind check for buffer overflow
+ {
+ QPainter p(&img);
+ p.setClipRect(-10, -10, 100, 100);
+ p.fillRect(-10, -10, 100, 100, QBrush(QColor(Qt::red)));
+ }
+
+ // rects with negative width/height
+ {
+ QPainter p(&img);
+ p.setClipRect(QRect(10, 10, -10, 10));
+ QVERIFY(p.clipRegion().isEmpty());
+ p.setClipRect(QRect(10, 10, 10, -10));
+ QVERIFY(p.clipRegion().isEmpty());
+ p.setClipRect(QRectF(10.5, 10.5, -10.5, 10.5));
+ QVERIFY(p.clipRegion().isEmpty());
+ p.setClipRect(QRectF(10.5, 10.5, 10.5, -10.5));
+ QVERIFY(p.clipRegion().isEmpty());
+ }
+}
+
+/*
+ This tests the two different clipping approaches in QRasterPaintEngine,
+ one when using a QRegion and one when using a QPainterPath. They should
+ give equal results.
+*/
+void tst_QPainter::setEqualClipRegionAndPath_data()
+{
+ QTest::addColumn<QSize>("deviceSize");
+ QTest::addColumn<QRegion>("region");
+
+ QTest::newRow("empty") << QSize(100, 100) << QRegion();
+ QTest::newRow("simple rect") << QSize(100, 100)
+ << QRegion(QRect(5, 5, 10, 10));
+
+ QVector<QRect> rects;
+ QRegion region;
+
+ rects << QRect(5, 5, 10, 10) << QRect(20, 20, 10, 10);
+ region.setRects(rects.constData(), rects.size());
+ QTest::newRow("two rects") << QSize(100, 100) << region;
+
+ rects.clear();
+ rects << QRect(5, 5, 10, 10) << QRect(20, 5, 10, 10);
+ region.setRects(rects.constData(), rects.size());
+ QTest::newRow("two x-adjacent rects") << QSize(100, 100) << region;
+
+ rects.clear();
+ rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
+ region.setRects(rects.constData(), rects.size());
+ QTest::newRow("two x-adjacent rects 2") << QSize(100, 100) << region;
+
+ rects.clear();
+ rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
+ region.setRects(rects.constData(), rects.size());
+ QTest::newRow("two x-adjacent rects 3") << QSize(50, 50) << region;
+
+ rects.clear();
+ rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
+ region.setRects(rects.constData(), rects.size());
+ QTest::newRow("two x-adjacent rects 4") << QSize(101, 101) << region;
+
+ region = QRegion(QRect(0, 0, 200, 200), QRegion::Ellipse);
+
+ QTest::newRow("ellipse") << QSize(190, 200) << region;
+
+ region ^= QRect(50, 50, 50, 50);
+ QTest::newRow("ellipse 2") << QSize(200, 200) << region;
+}
+
+void tst_QPainter::setEqualClipRegionAndPath()
+{
+ QFETCH(QSize, deviceSize);
+ QFETCH(QRegion, region);
+
+ QPainterPath path;
+ path.addRegion(region);
+
+ QImage img1(deviceSize.width(), deviceSize.height(),
+ QImage::Format_ARGB32);
+ QImage img2(deviceSize.width(), deviceSize.height(),
+ QImage::Format_ARGB32);
+ img1.fill(0x12345678);
+ img2.fill(0x12345678);
+
+ {
+ QPainter p(&img1);
+ p.setClipRegion(region);
+ p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
+ }
+ {
+ QPainter p(&img2);
+ p.setClipPath(path);
+ p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
+ }
+
+#if 0
+ if (img1 != img2) {
+ img1.save("setEqualClipRegionAndPath_1.xpm", "XPM");
+ img2.save("setEqualClipRegionAndPath_2.xpm", "XPM");
+ }
+#endif
+ QCOMPARE(img1, img2);
+
+#if 0
+ // rotated
+ img1.fill(0x12345678);
+ img2.fill(0x12345678);
+
+ {
+ QPainter p(&img1);
+ p.rotate(25);
+ p.setClipRegion(region);
+ p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
+ }
+ {
+ QPainter p(&img2);
+ p.rotate(25);
+ p.setClipPath(path);
+ p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
+ }
+
+#if 1
+ if (img1 != img2) {
+ img1.save("setEqualClipRegionAndPath_1.xpm", "XPM");
+ img2.save("setEqualClipRegionAndPath_2.xpm", "XPM");
+ }
+#endif
+ QCOMPARE(img1, img2);
+#endif
+
+ img1.fill(0x12345678);
+ img2.fill(0x12345678);
+
+ // simple intersectclip
+ img1.fill(0x12345678);
+ img2.fill(0x12345678);
+ {
+ QPainter p(&img1);
+ p.setClipRegion(region);
+ p.setClipRegion(region, Qt::IntersectClip);
+ p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
+ }
+ {
+ QPainter p(&img2);
+ p.setClipPath(path);
+ p.setClipPath(path, Qt::IntersectClip);
+ p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
+ }
+#if 0
+ if (img1 != img2) {
+ img1.save("setEqualClipRegionAndPath_1.png", "PNG");
+ img2.save("setEqualClipRegionAndPath_2.png", "PNG");
+ }
+#endif
+ QCOMPARE(img1, img2);
+
+ img1.fill(0x12345678);
+ img2.fill(0x12345678);
+ {
+ QPainter p(&img1);
+ p.setClipPath(path);
+ p.setClipRegion(region, Qt::IntersectClip);
+ p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
+ }
+ {
+ QPainter p(&img2);
+ p.setClipRegion(region);
+ p.setClipPath(path, Qt::IntersectClip);
+ p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
+ }
+#if 0
+ if (img1 != img2) {
+ img1.save("setEqualClipRegionAndPath_1.xpm", "XPM");
+ img2.save("setEqualClipRegionAndPath_2.xpm", "XPM");
+ }
+#endif
+ QCOMPARE(img1, img2);
+
+}
+
+void tst_QPainter::clippedFillPath_data()
+{
+ QTest::addColumn<QSize>("imageSize");
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<QRect>("clipRect");
+ QTest::addColumn<QBrush>("brush");
+ QTest::addColumn<QPen>("pen");
+
+ QLinearGradient gradient(QPoint(0, 0), QPoint(100, 100));
+ gradient.setColorAt(0, Qt::red);
+ gradient.setColorAt(1, Qt::blue);
+
+
+ QPen pen2(QColor(223, 223, 0, 223));
+ pen2.setWidth(2);
+
+ QPainterPath path;
+ path.addRect(QRect(15, 15, 50, 50));
+ QTest::newRow("simple rect 0") << QSize(100, 100) << path
+ << QRect(15, 15, 49, 49)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("simple rect 1") << QSize(100, 100) << path
+ << QRect(15, 15, 50, 50)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("simple rect 2") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("simple rect 3") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(QColor(Qt::blue))
+ << QPen(Qt::NoPen);
+ QTest::newRow("simple rect 4") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(gradient)
+ << pen2;
+
+ path = QPainterPath();
+ path.addEllipse(QRect(15, 15, 50, 50));
+ QTest::newRow("ellipse 0") << QSize(100, 100) << path
+ << QRect(15, 15, 49, 49)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("ellipse 1") << QSize(100, 100) << path
+ << QRect(15, 15, 50, 50)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("ellipse 2") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("ellipse 3") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(QColor(Qt::blue))
+ << QPen(Qt::NoPen);
+ QTest::newRow("ellipse 4") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(gradient)
+ << pen2;
+
+ path = QPainterPath();
+ path.addRoundRect(QRect(15, 15, 50, 50), 20);
+ QTest::newRow("round rect 0") << QSize(100, 100) << path
+ << QRect(15, 15, 49, 49)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("round rect 1") << QSize(100, 100) << path
+ << QRect(15, 15, 50, 50)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("round rect 2") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("round rect 3") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(QColor(Qt::blue))
+ << QPen(Qt::NoPen);
+ QTest::newRow("round rect 4") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(gradient)
+ << pen2;
+
+ path = QPainterPath();
+ path.moveTo(15, 50);
+ path.cubicTo(40, 50, 40, 15, 65, 50);
+ path.lineTo(15, 50);
+ QTest::newRow("cubic 0") << QSize(100, 100) << path
+ << QRect(15, 15, 49, 49)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("cubic 1") << QSize(100, 100) << path
+ << QRect(15, 15, 50, 50)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("cubic 2") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(Qt::NoBrush)
+ << QPen(Qt::black);
+ QTest::newRow("cubic 3") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(QColor(Qt::blue))
+ << QPen(Qt::NoPen);
+ QTest::newRow("cubic 4") << QSize(100, 100) << path
+ << QRect(15, 15, 51, 51)
+ << QBrush(gradient)
+ << pen2;
+}
+
+void tst_QPainter::clippedFillPath()
+{
+ QFETCH(QSize, imageSize);
+ QFETCH(QPainterPath, path);
+ QFETCH(QRect, clipRect);
+ QPainterPath clipPath;
+ clipPath.addRect(clipRect);
+ QFETCH(QBrush, brush);
+ QFETCH(QPen, pen);
+
+ const int width = imageSize.width();
+ const int height = imageSize.height();
+
+ QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
+ clippedRect.fill(0x12345678);
+ {
+ QPainter painter(&clippedRect);
+ painter.setPen(pen);
+ painter.setBrush(brush);
+ painter.setClipRect(clipRect);
+ painter.drawPath(path);
+ }
+
+ QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
+ clippedPath.fill(0x12345678);
+ {
+ QPainter painter(&clippedPath);
+ painter.setPen(pen);
+ painter.setBrush(brush);
+ painter.setClipPath(clipPath);
+ painter.drawPath(path);
+ }
+
+#if 0
+ if (clippedRect != clippedPath) {
+ clippedRect.save(QString("clippedRect.png"), "PNG");
+ clippedPath.save(QString("clippedPath.png"), "PNG");
+ }
+#endif
+ QCOMPARE(clippedRect, clippedPath);
+
+ // repeat with antialiasing
+
+ clippedRect.fill(0x12345678);
+ {
+ QPainter painter(&clippedRect);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(pen);
+ painter.setBrush(brush);
+ painter.setClipRect(clipRect);
+ painter.drawPath(path);
+ }
+
+ clippedPath.fill(0x12345678);
+ {
+ QPainter painter(&clippedPath);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(pen);
+ painter.setBrush(brush);
+ painter.setClipPath(clipPath);
+ painter.drawPath(path);
+ }
+
+#if 1
+ if (clippedRect != clippedPath) {
+ clippedRect.save(QString("clippedRect.png"), "PNG");
+ clippedPath.save(QString("clippedPath.png"), "PNG");
+ }
+#endif
+ QCOMPARE(clippedRect, clippedPath);
+
+}
+
+void tst_QPainter::clippedLines_data()
+{
+ QTest::addColumn<QSize>("imageSize");
+ QTest::addColumn<QLineF>("line");
+ QTest::addColumn<QRect>("clipRect");
+ QTest::addColumn<QPen>("pen");
+
+ QPen pen2(QColor(223, 223, 0, 223));
+ pen2.setWidth(2);
+
+ QVector<QLineF> lines;
+ lines << QLineF(15, 15, 65, 65)
+ << QLineF(14, 14, 66, 66)
+ << QLineF(16, 16, 64, 64)
+ << QLineF(65, 65, 15, 15)
+ << QLineF(66, 66, 14, 14)
+ << QLineF(64, 64, 14, 14)
+ << QLineF(15, 50, 15, 64)
+ << QLineF(15, 50, 15, 65)
+ << QLineF(15, 50, 15, 66)
+ << QLineF(15, 50, 64, 50)
+ << QLineF(15, 50, 65, 50)
+ << QLineF(15, 50, 66, 50);
+
+ foreach (QLineF line, lines) {
+ QString desc = QString("line (%1, %2, %3, %4) %5").arg(line.x1())
+ .arg(line.y1()).arg(line.x2()).arg(line.y2());
+ QTest::newRow(qPrintable(desc.arg(0))) << QSize(100, 100) << line
+ << QRect(15, 15, 49, 49)
+ << QPen(Qt::black);
+ QTest::newRow(qPrintable(desc.arg(1))) << QSize(100, 100) << line
+ << QRect(15, 15, 50, 50)
+ << QPen(Qt::black);
+ QTest::newRow(qPrintable(desc.arg(2))) << QSize(100, 100) << line
+ << QRect(15, 15, 51, 51)
+ << QPen(Qt::black);
+ QTest::newRow(qPrintable(desc.arg(3))) << QSize(100, 100) << line
+ << QRect(15, 15, 51, 51)
+ << QPen(Qt::NoPen);
+ QTest::newRow(qPrintable(desc.arg(4))) << QSize(100, 100) << line
+ << QRect(15, 15, 51, 51)
+ << pen2;
+ }
+}
+
+void tst_QPainter::clippedLines()
+{
+ QFETCH(QSize, imageSize);
+ QFETCH(QLineF, line);
+ QFETCH(QRect, clipRect);
+ QPainterPath clipPath;
+ clipPath.addRect(clipRect);
+ QFETCH(QPen, pen);
+
+ const int width = imageSize.width();
+ const int height = imageSize.height();
+
+ QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
+ clippedRect.fill(0x12345678);
+ {
+ QPainter painter(&clippedRect);
+ painter.setPen(pen);
+ painter.setClipRect(clipRect);
+ painter.drawLine(line);
+ painter.drawLine(line.toLine());
+ }
+
+ QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
+ clippedPath.fill(0x12345678);
+ {
+ QPainter painter(&clippedPath);
+ painter.setPen(pen);
+ painter.setClipPath(clipPath);
+ painter.drawLine(line);
+ painter.drawLine(line.toLine());
+ }
+
+#if 0
+ if (clippedRect != clippedPath) {
+ clippedRect.save(QString("clippedRect.png"), "PNG");
+ clippedPath.save(QString("clippedPath.png"), "PNG");
+ }
+#endif
+ QCOMPARE(clippedRect, clippedPath);
+
+ // repeat with antialiasing
+ clippedRect.fill(0x12345678);
+ {
+ QPainter painter(&clippedRect);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(pen);
+ painter.setClipRect(clipRect);
+ painter.drawLine(line);
+ painter.drawLine(line.toLine());
+ }
+
+ clippedPath.fill(0x12345678);
+ {
+ QPainter painter(&clippedPath);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(pen);
+ painter.setClipPath(clipPath);
+ painter.drawLine(line);
+ painter.drawLine(line.toLine());
+ }
+
+#if 0
+ if (clippedRect != clippedPath) {
+ clippedRect.save(QString("clippedRect.png"), "PNG");
+ clippedPath.save(QString("clippedPath.png"), "PNG");
+ }
+#endif
+ QCOMPARE(clippedRect, clippedPath);
+}
+
+void tst_QPainter::clippedPolygon_data()
+{
+ clippedFillPath_data();
+};
+
+void tst_QPainter::clippedPolygon()
+{
+ QFETCH(QSize, imageSize);
+ QFETCH(QPainterPath, path);
+ QPolygonF polygon = path.toFillPolygon();
+ QFETCH(QRect, clipRect);
+ QPainterPath clipPath;
+ clipPath.addRect(clipRect);
+ QFETCH(QPen, pen);
+ QFETCH(QBrush, brush);
+
+ const int width = imageSize.width();
+ const int height = imageSize.height();
+
+ QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
+ clippedRect.fill(0x12345678);
+ {
+ QPainter painter(&clippedRect);
+ painter.setPen(pen);
+ painter.setBrush(brush);
+ painter.setClipRect(clipRect);
+ painter.drawPolygon(polygon);
+ painter.drawPolygon(polygon.toPolygon());
+ }
+
+ QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
+ clippedPath.fill(0x12345678);
+ {
+ QPainter painter(&clippedPath);
+ painter.setPen(pen);
+ painter.setBrush(brush);
+ painter.setClipRect(clipRect);
+ painter.drawPolygon(polygon);
+ painter.drawPolygon(polygon.toPolygon());
+ }
+
+#if 0
+ if (clippedRect != clippedPath) {
+ clippedRect.save(QString("clippedRect.png"), "PNG");
+ clippedPath.save(QString("clippedPath.png"), "PNG");
+ }
+#endif
+ QCOMPARE(clippedRect, clippedPath);
+
+ // repeat with antialiasing
+
+ clippedRect.fill(0x12345678);
+ {
+ QPainter painter(&clippedRect);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(pen);
+ painter.setBrush(brush);
+ painter.setClipRect(clipRect);
+ painter.drawPolygon(polygon);
+ painter.drawPolygon(polygon.toPolygon());
+ }
+
+ clippedPath.fill(0x12345678);
+ {
+ QPainter painter(&clippedPath);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(pen);
+ painter.setBrush(brush);
+ painter.setClipRect(clipRect);
+ painter.drawPolygon(polygon);
+ painter.drawPolygon(polygon.toPolygon());
+ }
+
+#if 0
+ if (clippedRect != clippedPath) {
+ clippedRect.save(QString("clippedRect.png"), "PNG");
+ clippedPath.save(QString("clippedPath.png"), "PNG");
+ }
+#endif
+ QCOMPARE(clippedRect, clippedPath);
+}
+
+// this just draws some text that should be clipped in the raster
+// paint engine.
+void tst_QPainter::clippedText()
+{
+ for (char ch = 'A'; ch < 'Z'; ++ch) {
+ //qDebug() << ch;
+ QFont f;
+ f.setPixelSize(24);
+ QFontMetrics metrics(f);
+ QRect textRect = metrics.boundingRect(QChar(ch));
+
+ if (textRect.width() <= 8)
+ continue;
+ if (textRect.height() <= 8)
+ continue;
+
+ QRect imageRect = textRect.adjusted(4, 4, -4, -4);
+
+ QImage image(imageRect.size(), QImage::Format_ARGB32_Premultiplied);
+
+ image.fill(qRgba(255, 255, 255, 255));
+ {
+ QPainter painter(&image);
+ painter.setFont(f);
+ painter.setPen(Qt::black);
+
+ painter.drawText(0, 0, QChar(ch));
+ }
+
+ image.fill(qRgba(255, 255, 255, 255));
+ {
+ QPainter painter(&image);
+ painter.setFont(f);
+ painter.setPen(Qt::black);
+
+ painter.drawText(-imageRect.topLeft(), QChar(ch));
+ }
+
+ bool foundPixel = false;
+ for (int x = 0; x < image.width(); ++x)
+ for (int y = 0; y < image.height(); ++y)
+ if (image.pixel(x, y) != 0)
+ foundPixel = true;
+ // can't QVERIFY(foundPixel) as sometimes all pixels are clipped
+ // away. For example for 'O'
+ // just call /some/ function to prevent the compiler from optimizing
+ // foundPixel away
+ QString::number(foundPixel);
+
+ //image.save(QString("debug") + ch + ".xpm");
+ }
+
+ QVERIFY(true); // reached, don't trigger any valgrind errors
+}
+
+void tst_QPainter::setOpacity_data()
+{
+ QTest::addColumn<QImage::Format>("destFormat");
+ QTest::addColumn<QImage::Format>("srcFormat");
+
+ QTest::newRow("ARGB32P on ARGB32P") << QImage::Format_ARGB32_Premultiplied
+ << QImage::Format_ARGB32_Premultiplied;
+
+ QTest::newRow("ARGB32 on ARGB32") << QImage::Format_ARGB32
+ << QImage::Format_ARGB32;
+
+ QTest::newRow("RGB32 on RGB32") << QImage::Format_RGB32
+ << QImage::Format_RGB32;
+
+ QTest::newRow("RGB16 on RGB16") << QImage::Format_RGB16
+ << QImage::Format_RGB16;
+
+ QTest::newRow("ARGB8565_Premultiplied on ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied
+ << QImage::Format_ARGB8565_Premultiplied;
+
+ QTest::newRow("RGB555 on RGB555") << QImage::Format_RGB555
+ << QImage::Format_RGB555;
+
+ QTest::newRow("RGB666 on RGB666") << QImage::Format_RGB666
+ << QImage::Format_RGB666;
+
+ QTest::newRow("ARGB8555_Premultiplied on ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied
+ << QImage::Format_ARGB8555_Premultiplied;
+
+ QTest::newRow("RGB888 on RGB888") << QImage::Format_RGB888
+ << QImage::Format_RGB888;
+
+ QTest::newRow("RGB32 on RGB16") << QImage::Format_RGB16
+ << QImage::Format_RGB32;
+
+ QTest::newRow("RGB32 on ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied
+ << QImage::Format_RGB32;
+
+ QTest::newRow("RGB32 on RGB666") << QImage::Format_RGB666
+ << QImage::Format_RGB32;
+
+ QTest::newRow("RGB32 on RGB555") << QImage::Format_RGB555
+ << QImage::Format_RGB32;
+
+ QTest::newRow("RGB32 on ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied
+ << QImage::Format_RGB32;
+
+ QTest::newRow("RGB32 on RGB888") << QImage::Format_RGB888
+ << QImage::Format_RGB32;
+
+ QTest::newRow("RGB16 on RGB32") << QImage::Format_RGB32
+ << QImage::Format_RGB16;
+
+ QTest::newRow("ARGB8565_Premultiplied on RGB32") << QImage::Format_RGB32
+ << QImage::Format_ARGB8565_Premultiplied;
+
+ QTest::newRow("RGB666 on RGB32") << QImage::Format_RGB32
+ << QImage::Format_RGB666;
+
+ QTest::newRow("RGB555 on RGB32") << QImage::Format_RGB32
+ << QImage::Format_RGB555;
+
+ QTest::newRow("ARGB8555_Premultiplied on RGB32") << QImage::Format_RGB32
+ << QImage::Format_ARGB8555_Premultiplied;
+
+ QTest::newRow("RGB888 on RGB32") << QImage::Format_RGB32
+ << QImage::Format_RGB888;
+
+ QTest::newRow("RGB555 on RGB888") << QImage::Format_RGB888
+ << QImage::Format_RGB555;
+
+ QTest::newRow("RGB666 on RGB888") << QImage::Format_RGB888
+ << QImage::Format_RGB666;
+
+ QTest::newRow("RGB444 on RGB444") << QImage::Format_RGB444
+ << QImage::Format_RGB444;
+}
+
+void tst_QPainter::setOpacity()
+{
+ QFETCH(QImage::Format, destFormat);
+ QFETCH(QImage::Format, srcFormat);
+
+ const QSize imageSize(12, 12);
+ const QRect imageRect(QPoint(0, 0), imageSize);
+ QColor destColor = Qt::black;
+ QColor srcColor = Qt::white;
+
+ QImage dest(imageSize, destFormat);
+ QImage src(imageSize, srcFormat);
+
+ QPainter p;
+ p.begin(&dest);
+ p.fillRect(imageRect, destColor);
+ p.end();
+
+ p.begin(&src);
+ p.fillRect(imageRect, srcColor);
+ p.end();
+
+ p.begin(&dest);
+ p.setOpacity(0.5);
+ p.drawImage(imageRect, src, imageRect);
+ p.end();
+
+ QImage actual = dest.convertToFormat(QImage::Format_RGB32);
+
+ for (int y = 0; y < actual.height(); ++y) {
+ QRgb *p = (QRgb *)actual.scanLine(y);
+ for (int x = 0; x < actual.width(); ++x) {
+ QVERIFY(qAbs(qRed(p[x]) - 127) <= 0xf);
+ QVERIFY(qAbs(qGreen(p[x]) - 127) <= 0xf);
+ QVERIFY(qAbs(qBlue(p[x]) - 127) <= 0xf);
+ }
+ }
+}
+
+void tst_QPainter::drawhelper_blend_untransformed_data()
+{
+ setOpacity_data();
+}
+
+void tst_QPainter::drawhelper_blend_untransformed()
+{
+ QFETCH(QImage::Format, destFormat);
+ QFETCH(QImage::Format, srcFormat);
+
+ const int size = 128;
+ const QSize imageSize(size, size);
+ const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing
+
+ QColor destColor(127, 127, 127);
+ QColor srcColor(Qt::white);
+
+ QImage dest(imageSize, destFormat);
+ QImage src(imageSize, srcFormat);
+
+ QPainter p;
+ p.begin(&src);
+ p.fillRect(paintRect, srcColor);
+ p.end();
+
+ QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1 << 0.01 << 0.4
+ << 0.5 << 0.6 << 0.9 << 1.0);
+ foreach (qreal opacity, opacities) {
+ p.begin(&dest);
+ p.fillRect(paintRect, destColor);
+
+ p.setOpacity(opacity);
+ p.drawImage(paintRect, src, paintRect);
+ p.end();
+
+ // sanity check: make sure all pixels are equal
+ QImage expected(size - 2, size, destFormat);
+ p.begin(&expected);
+ p.fillRect(0, 0, expected.width(), expected.height(),
+ QColor(dest.pixel(1, 0)));
+ p.end();
+
+ const QImage subDest(dest.bits() + dest.depth() / 8,
+ dest.width() - 2, dest.height(),
+ dest.bytesPerLine(), dest.format());
+
+ if (dest.format() == QImage::Format_ARGB8565_Premultiplied ||
+ dest.format() == QImage::Format_ARGB8555_Premultiplied) {
+ // Test skipped due to rounding errors...
+ continue;
+ }
+#if 0
+ if (subDest != expected) {
+ qDebug() << "size" << size << "opacity" << opacity;
+ for (int j = 0; j < expected.height(); ++j) {
+ for (int i = 0; i < expected.width(); ++i) {
+ if (expected.pixel(i,j) != subDest.pixel(i,j))
+ qDebug() << i << j << hex << expected.pixel(i, j)
+ << subDest.pixel(i, j);
+ }
+ }
+ }
+#endif
+ QCOMPARE(subDest, expected);
+ }
+}
+
+void tst_QPainter::drawhelper_blend_tiled_untransformed_data()
+{
+ setOpacity_data();
+}
+
+void tst_QPainter::drawhelper_blend_tiled_untransformed()
+{
+ QFETCH(QImage::Format, destFormat);
+ QFETCH(QImage::Format, srcFormat);
+
+ const int size = 128;
+ const QSize imageSize(size, size);
+ const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing
+
+ QColor destColor(127, 127, 127);
+ QColor srcColor(Qt::white);
+
+ QImage dest(imageSize, destFormat);
+ QImage src(imageSize / 2, srcFormat);
+
+ QPainter p;
+ p.begin(&src);
+ p.fillRect(QRect(QPoint(0, 0), imageSize/ 2), srcColor);
+ p.end();
+
+ const QBrush brush(src);
+
+ QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1 << 0.01 << 0.4
+ << 0.5 << 0.6 << 0.9 << 1.0);
+ foreach (qreal opacity, opacities) {
+ p.begin(&dest);
+ p.fillRect(paintRect, destColor);
+
+ p.setOpacity(opacity);
+ p.fillRect(paintRect, brush);
+ p.end();
+
+ // sanity check: make sure all pixels are equal
+ QImage expected(size - 2, size, destFormat);
+ p.begin(&expected);
+ p.fillRect(0, 0, expected.width(), expected.height(),
+ QColor(dest.pixel(1, 0)));
+ p.end();
+
+ const QImage subDest(dest.bits() + dest.depth() / 8,
+ dest.width() - 2, dest.height(),
+ dest.bytesPerLine(), dest.format());
+
+ if (dest.format() == QImage::Format_ARGB8565_Premultiplied ||
+ dest.format() == QImage::Format_ARGB8555_Premultiplied) {
+ // Skipping test due to rounding errors. Test needs rewrite
+ continue;
+ }
+#if 0
+ if (subDest != expected) {
+ qDebug() << "size" << size << "opacity" << opacity;
+ for (int j = 0; j < expected.height(); ++j) {
+ for (int i = 0; i < expected.width(); ++i) {
+ if (expected.pixel(i,j) != subDest.pixel(i,j))
+ qDebug() << i << j << hex << expected.pixel(i, j)
+ << subDest.pixel(i, j);
+ }
+ }
+ }
+#endif
+ QCOMPARE(subDest, expected);
+ }
+}
+
+static QPaintEngine::PaintEngineFeatures no_porter_duff()
+{
+ QPaintEngine::PaintEngineFeatures features = QPaintEngine::AllFeatures;
+ return features & ~QPaintEngine::PorterDuff;
+}
+
+class DummyPaintEngine : public QPaintEngine, public QPaintDevice
+{
+public:
+ DummyPaintEngine() : QPaintEngine(no_porter_duff()) {}
+ virtual bool begin(QPaintDevice *) { return true; }
+ virtual bool end() { return true; }
+
+ virtual void updateState(const QPaintEngineState &) {}
+ virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
+
+ virtual Type type() const { return User; }
+
+ virtual QPaintEngine *paintEngine() const { return (QPaintEngine *)this; }
+
+ virtual int metric(PaintDeviceMetric metric) const { Q_UNUSED(metric); return 0; };
+};
+
+static bool success;
+
+void porterDuff_warningChecker(QtMsgType type, const char *msg)
+{
+ if (type == QtWarningMsg && msg == QLatin1String("QPainter::setCompositionMode: PorterDuff modes not supported on device"))
+ success = false;
+}
+
+void tst_QPainter::porterDuff_warning()
+{
+ QtMsgHandler old = qInstallMsgHandler(porterDuff_warningChecker);
+ DummyPaintEngine dummy;
+ QPainter p(&dummy);
+
+ success = true;
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ QVERIFY(success);
+
+ success = true;
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ QVERIFY(success);
+
+ success = true;
+ p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
+ QVERIFY(!success);
+
+ QVERIFY(qInstallMsgHandler(old) == porterDuff_warningChecker);
+}
+
+class quint24
+{
+public:
+ inline quint24(quint32 v)
+ {
+ data[0] = qBlue(v);
+ data[1] = qGreen(v);
+ data[2] = qRed(v);
+ }
+
+ inline operator quint32 ()
+ {
+ return qRgb(data[2], data[1], data[0]);
+ }
+
+ inline bool operator==(const quint24 &v) const {
+ return (data[0] == v.data[0] && data[1] == v.data[1] && data[2] == v.data[2]);
+ }
+
+ uchar data[3];
+} Q_PACKED;
+
+void tst_QPainter::drawhelper_blend_color()
+{
+ QImage dest(32, 32, QImage::Format_ARGB8555_Premultiplied);
+ dest.fill(0xff000000);
+
+ {
+ QPainter p(&dest);
+ p.fillRect(0, 0, dest.width(), dest.height(), QColor(255, 0, 0, 127));
+ }
+
+ QImage expected(32, 32, QImage::Format_ARGB8555_Premultiplied);
+ expected.fill(0xff3c007f);
+
+ QCOMPARE(dest.pixel(1, 1), expected.pixel(1, 1));
+ QCOMPARE(dest, expected);
+}
+
+class ViewportTestWidget : public QWidget
+{
+public:
+ ViewportTestWidget(QWidget *parent = 0) : QWidget(parent), hasPainted(false) {}
+ QSize sizeHint() const {
+ return QSize(100, 100);
+ }
+
+ QRect viewport;
+ bool hasPainted;
+
+protected:
+ void paintEvent(QPaintEvent *) {
+ hasPainted = true;
+ QPainter p(this);
+ viewport = p.viewport();
+ }
+};
+
+void tst_QPainter::childWidgetViewport()
+{
+ QWidget parent;
+ parent.setAutoFillBackground(true);
+ parent.resize(200, 200);
+ ViewportTestWidget child(&parent);
+ child.setAutoFillBackground(true);
+ parent.show();
+ parent.update();
+ qApp->processEvents();
+
+ if (child.hasPainted) {
+ QCOMPARE(child.viewport, QRect(QPoint(0, 0), child.sizeHint()));
+ } else {
+ qWarning("Failed to ensure that paintEvent has been run. Could not run test.");
+ }
+}
+
+void tst_QPainter::fillRect_objectBoundingModeGradient()
+{
+ QImage a(10, 10, QImage::Format_ARGB32_Premultiplied);
+ a.fill(0x0);
+ QImage b = a;
+
+ QLinearGradient g(QPoint(0, 0), QPoint(0, 1));
+ g.setColorAt(0, Qt::red);
+ g.setColorAt(1, Qt::blue);
+ g.setCoordinateMode(QGradient::ObjectBoundingMode);
+
+ QPainter p(&a);
+ p.fillRect(QRect(0, 0, a.width(), a.height()), g);
+ p.end();
+
+ QPainterPath path;
+ path.addRect(0, 0, a.width(), a.height());
+
+ p.begin(&b);
+ p.fillPath(path, g);
+ p.end();
+
+ QCOMPARE(a, b);
+}
+
+void tst_QPainter::fillRect_stretchToDeviceMode()
+{
+ QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
+
+ QLinearGradient g(QPoint(0, 0), QPoint(0, 1));
+ g.setCoordinateMode(QGradient::StretchToDeviceMode);
+
+ QPainter p(&img);
+ p.fillRect(img.rect(), g);
+ p.end();
+
+ for (int i = 1; i < img.height(); ++i)
+ QVERIFY(img.pixel(0, i) != img.pixel(0, i-1));
+}
+
+void tst_QPainter::monoImages()
+{
+ Qt::GlobalColor colorPairs[][2] = {
+ { Qt::white, Qt::black },
+ { Qt::color0, Qt::color1 },
+ { Qt::red, Qt::blue }
+ };
+
+ const int numColorPairs = sizeof(colorPairs) / sizeof(QRgb[2]);
+
+ QImage transparent(2, 2, QImage::Format_ARGB32_Premultiplied);
+ transparent.fill(0x0);
+
+ for (int i = 1; i < QImage::NImageFormats; ++i) {
+ for (int j = 0; j < numColorPairs; ++j) {
+ const QImage::Format format = QImage::Format(i);
+ if (format == QImage::Format_Indexed8)
+ continue;
+
+ QImage img(2, 2, format);
+
+ if (img.colorCount() > 0) {
+ img.setColor(0, QColor(colorPairs[j][0]).rgba());
+ img.setColor(1, QColor(colorPairs[j][1]).rgba());
+ }
+
+ img.fill(0x0);
+ QPainter p(&img);
+ p.fillRect(0, 0, 2, 2, colorPairs[j][0]);
+ p.fillRect(0, 0, 1, 1, colorPairs[j][1]);
+ p.fillRect(1, 1, 1, 1, colorPairs[j][1]);
+ p.end();
+
+ QImage original = img;
+
+ p.begin(&img);
+ p.drawImage(0, 0, transparent);
+ p.end();
+
+ // drawing a transparent image on top of another image
+ // should not change the image
+ QCOMPARE(original, img);
+
+ if (img.colorCount() == 0)
+ continue;
+
+ for (int k = 0; k < 2; ++k) {
+ QPainter p(&img);
+ p.fillRect(0, 0, 2, 2, colorPairs[j][k]);
+ p.end();
+
+ QImage argb32p(2, 2, QImage::Format_ARGB32_Premultiplied);
+ p.begin(&argb32p);
+ p.fillRect(0, 0, 2, 2, colorPairs[j][k]);
+ p.end();
+
+ QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
+
+ // drawing argb32p image on mono image
+ p.begin(&img);
+ p.drawImage(0, 0, argb32p);
+ p.end();
+
+ QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
+
+ // drawing mono image on argb32p image
+ p.begin(&argb32p);
+ p.drawImage(0, 0, img);
+ p.end();
+
+ QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
+ }
+ }
+ }
+}
+
+#if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_CC_MSVC) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_SYMBIAN)
+#include <fenv.h>
+
+static const QString fpeExceptionString(int exception)
+{
+#ifdef FE_INEXACT
+ if (exception & FE_INEXACT)
+ return QLatin1String("Inexact result");
+#endif
+ if (exception & FE_UNDERFLOW)
+ return QLatin1String("Underflow");
+ if (exception & FE_OVERFLOW)
+ return QLatin1String("Overflow");
+ if (exception & FE_DIVBYZERO)
+ return QLatin1String("Divide by zero");
+ if (exception & FE_INVALID)
+ return QLatin1String("Invalid operation");
+ return QLatin1String("No exception");
+}
+
+class FpExceptionChecker
+{
+public:
+ FpExceptionChecker(int exceptionMask)
+ : m_exceptionMask(exceptionMask)
+ {
+ feclearexcept(m_exceptionMask);
+ }
+
+ ~FpExceptionChecker()
+ {
+ const int exceptions = fetestexcept(m_exceptionMask);
+ QVERIFY2(!exceptions, qPrintable(QLatin1String("Floating point exception: ") + fpeExceptionString(exceptions)));
+ }
+
+private:
+ int m_exceptionMask;
+};
+
+void fpe_rasterizeLine_task232012()
+{
+ FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
+ QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+ QPainter p(&img);
+
+ p.setBrush(Qt::black);
+ p.drawRect(QRectF(0, 0, 5, 0));
+ p.drawRect(QRectF(0, 0, 0, 5));
+}
+
+void fpe_pixmapTransform()
+{
+ FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
+
+ QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
+
+ QPainter p(&img);
+
+ const qreal scaleFactor = 0.001;
+ const int translateDistance = 1000000;
+
+ p.setPen(Qt::red);
+ p.setBrush(QBrush(Qt::red,Qt::Dense6Pattern));
+
+ for (int i = 0; i < 2; ++i) {
+ p.setRenderHint(QPainter::SmoothPixmapTransform, i);
+
+ p.resetTransform();
+ p.scale(1.1, 1.1);
+ p.translate(translateDistance, 0);
+ p.drawRect(-translateDistance, 0, 100, 100);
+
+ p.resetTransform();
+ p.scale(scaleFactor, scaleFactor);
+ p.drawRect(QRectF(0, 0, 1 / scaleFactor, 1 / scaleFactor));
+ }
+}
+
+void fpe_zeroLengthLines()
+{
+ FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
+
+ QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
+
+ QPainter p(&img);
+
+ p.setPen(QPen(Qt::black, 3));
+ p.drawLine(64, 64, 64, 64);
+}
+
+void fpe_divByZero()
+{
+ FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
+
+ QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
+
+ QPainter p(&img);
+
+ p.setRenderHint(QPainter::Antialiasing);
+
+ p.drawRect(QRectF(10, 10, 100, 0));
+ p.drawRect(QRectF(10, 10, 0, 100));
+
+ p.drawRect(QRect(10, 10, 100, 0));
+ p.drawRect(QRect(10, 10, 0, 100));
+
+ p.fillRect(QRectF(10, 10, 100, 0), Qt::black);
+ p.fillRect(QRectF(10, 10, 0, 100), Qt::black);
+
+ p.fillRect(QRect(10, 10, 100, 0), Qt::black);
+ p.fillRect(QRect(10, 10, 0, 100), Qt::black);
+}
+
+void fpe_steepSlopes()
+{
+ FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
+
+ QImage img(1024, 1024, QImage::Format_ARGB32_Premultiplied);
+
+ QFETCH(QTransform, transform);
+ QFETCH(QLineF, line);
+ QFETCH(bool, antialiased);
+
+ QPainter p(&img);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setRenderHint(QPainter::Antialiasing, antialiased);
+ p.setTransform(transform);
+
+ p.drawLine(line);
+}
+
+void fpe_radialGradients()
+{
+ FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
+
+ QImage img(21, 21, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+
+ double m = img.width() * 0.5;
+
+ QPainter p(&img);
+ p.setRenderHints(QPainter::Antialiasing);
+ p.setPen(Qt::NoPen);
+ p.setBrush(QRadialGradient(m, m, m));
+ p.drawEllipse(img.rect());
+}
+
+#define FPE_TEST(x) \
+void tst_QPainter::x() \
+{ \
+ ::x(); \
+}
+#else
+#define FPE_TEST(x) \
+void tst_QPainter::x() \
+{ \
+ QSKIP("Floating point exception checking (fenv.h) not available", SkipAll); \
+}
+#endif
+
+FPE_TEST(fpe_rasterizeLine_task232012)
+FPE_TEST(fpe_pixmapTransform)
+FPE_TEST(fpe_zeroLengthLines)
+FPE_TEST(fpe_divByZero)
+FPE_TEST(fpe_steepSlopes)
+FPE_TEST(fpe_radialGradients)
+
+void tst_QPainter::fpe_steepSlopes_data()
+{
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<QLineF>("line");
+ QTest::addColumn<bool>("antialiased");
+
+ {
+ const qreal dsin = 0.000014946676875461832484392500630665523431162000633776187896728515625;
+ const qreal dcos = 0.9999999998882984630910186751862056553363800048828125;
+
+ const QTransform transform = QTransform(QMatrix(dcos, dsin, -dsin, dcos, 64, 64));
+ const QLineF line(2, 2, 2, 6);
+
+ QTest::newRow("task 207147 aa") << transform << line << true;
+ QTest::newRow("task 207147 no aa") << transform << line << false;
+ }
+
+ {
+ QTransform transform;
+ transform.rotate(0.0000001);
+ const QLineF line(5, 5, 10, 5);
+
+ QTest::newRow("task 166702 aa") << transform << line << true;
+ QTest::newRow("task 166702 no aa") << transform << line << false;
+ }
+
+ {
+ const QTransform transform;
+ const QLineF line(2.5, 2.5, 2.5 + 1/256., 60000.5);
+
+ QTest::newRow("steep line aa") << transform << line << true;
+ QTest::newRow("steep line no aa") << transform << line << false;
+ }
+
+ {
+ const QTransform transform;
+ const QLineF line(2.5, 2.5, 2.5 + 1/256., 1024);
+
+ QTest::newRow("steep line 2 aa") << transform << line << true;
+ QTest::newRow("steep line 2 no aa") << transform << line << false;
+ }
+
+ {
+ const QTransform transform;
+ const QLineF line(2.5, 2.5, 2.5 + 1/64., 1024);
+
+ QTest::newRow("steep line 3 aa") << transform << line << true;
+ QTest::newRow("steep line 3 no aa") << transform << line << false;
+ }
+}
+
+qreal randf()
+{
+ return rand() / (RAND_MAX + 1.0);
+}
+
+QPointF randInRect(const QRectF &rect)
+{
+ const qreal x = rect.left() + rect.width() * randf();
+ const qreal y = rect.top() + rect.height() * randf();
+
+ return QPointF(x, y);
+}
+
+void tst_QPainter::rasterizer_asserts()
+{
+ QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
+
+ QRectF middle(QPointF(0, 0), img.size());
+ QRectF left = middle.translated(-middle.width(), 0);
+ QRectF right = middle.translated(middle.width(), 0);
+
+ QPainter p(&img);
+ img.fill(Qt::white);
+ p.setCompositionMode(QPainter::CompositionMode_Destination);
+ for (int i = 0; i < 100000; ++i) {
+ QPainterPath path;
+ path.moveTo(randInRect(middle));
+ path.lineTo(randInRect(left));
+ path.lineTo(randInRect(right));
+
+ p.fillPath(path, Qt::black);
+ }
+}
+
+void tst_QPainter::rasterizer_negativeCoords()
+{
+ QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+
+ QImage original = img;
+
+ QPainter p(&img);
+ p.rotate(90);
+ p.fillRect(0, 0, 70, 50, Qt::black);
+
+ // image should not have changed
+ QCOMPARE(img.pixel(0, 0), 0x0U);
+ QCOMPARE(img, original);
+}
+
+void tst_QPainter::blendOverFlow_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<int>("width");
+ QTest::addColumn<int>("height");
+
+ QImage::Format format = QImage::Format_ARGB8555_Premultiplied;
+ QTest::newRow("555,1,1") << format << 1 << 1;
+ QTest::newRow("555,2,2") << format << 2 << 2;
+ QTest::newRow("555,10,10") << format << 10 << 10;
+
+ format = QImage::Format_ARGB8565_Premultiplied;
+ QTest::newRow("565,1,1") << format << 1 << 1;
+ QTest::newRow("565,2,2") << format << 2 << 2;
+ QTest::newRow("565,10,10") << format << 10 << 10;
+}
+
+void tst_QPainter::blendOverFlow()
+{
+ QFETCH(QImage::Format, format);
+ QFETCH(int, width);
+ QFETCH(int, height);
+
+ QImage dest(width, height, format);
+ QImage src(width, height, format);
+
+ {
+ QPainter p(&dest);
+ p.fillRect(0, 0, width, height, Qt::green);
+ }
+ QImage expected = dest;
+
+ {
+ QPainter p(&src);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(0, 0, width, height, QColor(0, 255, 0, 6));
+ }
+
+ {
+ QPainter p(&dest);
+ p.drawImage(0, 0, src);
+ }
+
+ QCOMPARE(dest.pixel(0, 0), expected.pixel(0, 0));
+ QCOMPARE(dest, expected);
+}
+
+void tst_QPainter::largeImagePainting_data()
+{
+ QTest::addColumn<int>("width");
+ QTest::addColumn<int>("height");
+ QTest::addColumn<bool>("antialiased");
+
+ QTest::newRow("tall") << 1 << 32767 << false;
+ QTest::newRow("tall aa") << 1 << 32767 << true;
+ QTest::newRow("wide") << 32767 << 1 << false;
+ QTest::newRow("wide aa") << 32767 << 1 << true;
+}
+
+void tst_QPainter::largeImagePainting()
+{
+ QPainterPath path;
+ path.addRect(0, 0, 1, 1);
+ path.addRect(2, 0, 1, 1);
+ path.addRect(0, 2, 1, 1);
+
+ QFETCH(int, width);
+ QFETCH(int, height);
+ QFETCH(bool, antialiased);
+
+ QImage img(width, height, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+
+ QPainter p(&img);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::white);
+
+ p.setRenderHint(QPainter::Antialiasing, antialiased);
+
+ for (int i = 0; i < img.width(); i += 4) {
+ p.drawPath(path);
+ p.translate(4, 0);
+ }
+
+ p.resetMatrix();
+
+ for (int i = 4; i < img.height(); i += 4) {
+ p.translate(0, 4);
+ p.drawPath(path);
+ }
+
+ for (int i = 0; i < img.width(); ++i) {
+ if (i % 2)
+ QCOMPARE(img.pixel(i, 0), 0x0U);
+ else
+ QCOMPARE(img.pixel(i, 0), 0xffffffffU);
+ }
+
+ for (int i = 1; i < img.height(); ++i) {
+ if (i % 2)
+ QCOMPARE(img.pixel(0, i), 0x0U);
+ else
+ QCOMPARE(img.pixel(0, i), 0xffffffffU);
+ }
+}
+
+void tst_QPainter::imageScaling_task206785()
+{
+ QImage src(32, 2, QImage::Format_ARGB32_Premultiplied);
+ src.fill(0xffffffff);
+
+ QImage dst(128, 128, QImage::Format_ARGB32_Premultiplied);
+
+ QImage expected(128, 128, QImage::Format_ARGB32_Premultiplied);
+ expected.fill(0xffffffff);
+
+ for (int i = 1; i < 5; ++i) {
+ qreal scale = i / qreal(5);
+
+ dst.fill(0xff000000);
+
+ QPainter p(&dst);
+ p.scale(dst.width() / qreal(src.width()), scale);
+
+ for (int y = 0; y * scale < dst.height(); ++y)
+ p.drawImage(0, y, src);
+
+ p.end();
+
+ QCOMPARE(dst, expected);
+ }
+}
+
+#define FOR_EACH_NEIGHBOR_8 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if (dx != 0 || dy != 0)
+#define FOR_EACH_NEIGHBOR_4 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if ((dx == 0) != (dy == 0))
+
+uint qHash(const QPoint &point)
+{
+ return qHash(qMakePair(point.x(), point.y()));
+}
+
+bool verifyOutlineFillConsistency(const QImage &img, QRgb outside, QRgb inside, QRgb outline)
+{
+ if (img.pixel(img.width() / 2, img.height() / 2) != inside)
+ return false;
+
+ int x = img.width() / 2;
+ int y = img.height() / 2;
+
+ while (img.pixel(++x, y) == inside)
+ ;
+
+ if (img.pixel(x, y) != outline)
+ return false;
+
+ QQueue<QPoint> discovered;
+ discovered.enqueue(QPoint(x, y));
+
+ QVector<bool> visited(img.width() * img.height());
+ visited.fill(false);
+
+ while (!discovered.isEmpty()) {
+ QPoint p = discovered.dequeue();
+ QRgb pixel = img.pixel(p.x(), p.y());
+
+ bool &v = visited[p.y() * img.width() + p.x()];
+ if (v)
+ continue;
+ v = true;
+
+ if (pixel == outline) {
+ FOR_EACH_NEIGHBOR_8 {
+ QPoint x(p.x() + dx, p.y() + dy);
+ discovered.enqueue(x);
+ }
+ } else {
+ FOR_EACH_NEIGHBOR_4 {
+ if ((dx == 0) == (dy == 0))
+ continue;
+ QRgb neighbor = img.pixel(p.x() + dx, p.y() + dy);
+ if ((pixel == inside && neighbor == outside) ||
+ (pixel == outside && neighbor == inside))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+#undef FOR_EACH_NEIGHBOR_8
+#undef FOR_EACH_NEIGHBOR_4
+
+void tst_QPainter::outlineFillConsistency()
+{
+ QSKIP("currently broken...", SkipAll);
+ return;
+
+ QImage dst(256, 256, QImage::Format_ARGB32_Premultiplied);
+
+ QPolygonF poly;
+ poly << QPointF(5, -100) << QPointF(-70, 20) << QPointF(95, 25);
+
+ QPen pen(Qt::red);
+ QBrush brush(Qt::black);
+
+ QRgb background = 0xffffffff;
+ for (int i = 0; i < 360; ++i) {
+ dst.fill(background);
+
+ QPainter p(&dst);
+ p.translate(dst.width() / 2, dst.height() / 2);
+
+ QPolygonF copy = poly;
+ for (int j = 0; j < copy.size(); ++j)
+ copy[j] = QTransform().rotate(i).map(copy[j]);
+
+ p.setPen(pen);
+ p.setBrush(brush);
+ p.drawPolygon(copy);
+ p.end();
+
+#if 0
+ if (!verifyOutlineFillConsistency(dst, background, p.brush().color().rgba(), p.pen().color().rgba()))
+ dst.save(QString("outlineFillConsistency-%1.png").arg(i));
+#endif
+
+ QVERIFY(verifyOutlineFillConsistency(dst, background, brush.color().rgba(), pen.color().rgba()));
+ }
+}
+
+void tst_QPainter::drawImage_task217400_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+
+ QTest::newRow("444") << QImage::Format_ARGB4444_Premultiplied;
+ QTest::newRow("555") << QImage::Format_ARGB8555_Premultiplied;
+ QTest::newRow("565") << QImage::Format_ARGB8565_Premultiplied;
+// QTest::newRow("666") << QImage::Format_ARGB6666_Premultiplied;
+ QTest::newRow("888p") << QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("888") << QImage::Format_ARGB32;
+}
+
+void tst_QPainter::drawImage_task217400()
+{
+ QFETCH(QImage::Format, format);
+
+ const QImage src = QImage(QString(SRCDIR) + "/task217400.png")
+ .convertToFormat(format);
+ QVERIFY(!src.isNull());
+
+ QImage expected(src.size(), format);
+ {
+ QPainter p(&expected);
+ p.fillRect(0, 0, expected.width(), expected.height(), Qt::white);
+ p.drawImage(0, 0, src);
+ }
+
+ for (int i = 1; i <= 4; ++i) {
+ QImage dest(src.width() + i, src.height(), format);
+ {
+ QPainter p(&dest);
+ p.fillRect(0, 0, dest.width(), dest.height(), Qt::white);
+ p.drawImage(i, 0, src);
+ }
+
+ const QImage result = dest.copy(i, 0, src.width(), src.height());
+
+#if 0
+ if (result != expected) {
+ qDebug("i=%i", i);
+ result.save("result.png");
+ expected.save("expected.png");
+ }
+#endif
+ QCOMPARE(result, expected);
+ }
+}
+
+void tst_QPainter::drawImage_task258776()
+{
+ QImage src(16, 16, QImage::Format_RGB888);
+ QImage dest(33, 33, QImage::Format_RGB888);
+ src.fill(0x00ff00);
+ dest.fill(0x0000ff);
+
+ QPainter painter(&dest);
+ painter.drawImage(QRectF(0.499, 0.499, 32, 32), src, QRectF(0, 0, 16, 16));
+ painter.end();
+
+ QImage expected(33, 33, QImage::Format_RGB32);
+ expected.fill(0xff0000);
+
+ painter.begin(&expected);
+ painter.drawImage(QRectF(0, 0, 32, 32), src);
+ painter.end();
+
+ dest = dest.convertToFormat(QImage::Format_RGB32);
+
+ dest.save("dest.png");
+ expected.save("expected.png");
+ QCOMPARE(dest, expected);
+}
+
+void tst_QPainter::clipRectSaveRestore()
+{
+ QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+
+ QPainter p(&img);
+ p.setClipRect(QRect(0, 0, 10, 10));
+ p.save();
+ p.setClipRect(QRect(5, 5, 5, 5), Qt::IntersectClip);
+ p.restore();
+ p.fillRect(0, 0, 64, 64, Qt::black);
+ p.end();
+
+ QCOMPARE(img.pixel(0, 0), QColor(Qt::black).rgba());
+}
+
+void tst_QPainter::clippedImage()
+{
+ QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+
+ QImage src(16, 16, QImage::Format_RGB32);
+ src.fill(QColor(Qt::red).rgba());
+
+ QPainter p(&img);
+ p.setClipRect(QRect(1, 1, 14, 14));
+ p.drawImage(0, 0, src);
+ p.end();
+
+ QCOMPARE(img.pixel(0, 0), 0x0U);
+ QCOMPARE(img.pixel(1, 1), src.pixel(1, 1));
+}
+
+void tst_QPainter::stateResetBetweenQPainters()
+{
+ QImage img(16, 16, QImage::Format_ARGB32);
+
+ {
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(0, 0, 16, 16, Qt::red);
+ }
+
+ {
+ QPainter p2(&img);
+ p2.fillRect(0, 0, 16, 16, QColor(0, 0, 255, 63));
+ }
+
+ img.save("foo.png");
+
+ QVERIFY(img.pixel(0, 0) != qRgba(0, 0, 255, 63));
+ QVERIFY(qRed(img.pixel(0, 0)) > 0); // We didn't erase the red channel...
+ QVERIFY(qBlue(img.pixel(0, 0)) < 255); // We blended the blue channel
+}
+
+void tst_QPainter::drawRect_task215378()
+{
+ QImage img(11, 11, QImage::Format_ARGB32_Premultiplied);
+ img.fill(QColor(Qt::white).rgba());
+
+ QPainter p(&img);
+ p.setPen(QColor(127, 127, 127, 127));
+ p.drawRect(0, 0, 10, 10);
+ p.end();
+
+ QCOMPARE(img.pixel(0, 0), img.pixel(1, 0));
+ QCOMPARE(img.pixel(0, 0), img.pixel(0, 1));
+ QVERIFY(img.pixel(0, 0) != img.pixel(1, 1));
+}
+
+void tst_QPainter::drawRect_task247505()
+{
+ QImage a(10, 10, QImage::Format_ARGB32_Premultiplied);
+ a.fill(0);
+ QImage b = a;
+
+ QPainter p(&a);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::black);
+ p.drawRect(QRectF(10, 0, -10, 10));
+ p.end();
+ p.begin(&b);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::black);
+ p.drawRect(QRectF(0, 0, 10, 10));
+ p.end();
+
+ QCOMPARE(a, b);
+}
+
+void tst_QPainter::drawImage_data()
+{
+ QTest::addColumn<int>("x");
+ QTest::addColumn<int>("y");
+ QTest::addColumn<int>("w");
+ QTest::addColumn<int>("h");
+ QTest::addColumn<QImage::Format>("srcFormat");
+ QTest::addColumn<QImage::Format>("dstFormat");
+
+ for (int srcFormat = QImage::Format_Mono; srcFormat < QImage::NImageFormats; ++srcFormat) {
+ for (int dstFormat = QImage::Format_Mono; dstFormat < QImage::NImageFormats; ++dstFormat) {
+ if (dstFormat == QImage::Format_Indexed8)
+ continue;
+ for (int odd_x = 0; odd_x <= 1; ++odd_x) {
+ for (int odd_width = 0; odd_width <= 1; ++odd_width) {
+ QString description =
+ QString("srcFormat %1, dstFormat %2, odd x: %3, odd width: %4")
+ .arg(srcFormat).arg(dstFormat).arg(odd_x).arg(odd_width);
+
+ QTest::newRow(qPrintable(description)) << (10 + odd_x) << 10 << (20 + odd_width) << 20
+ << QImage::Format(srcFormat)
+ << QImage::Format(dstFormat);
+ }
+ }
+ }
+ }
+}
+
+bool verifyImage(const QImage &img, int x, int y, int w, int h, uint background)
+{
+ int imgWidth = img.width();
+ int imgHeight = img.height();
+ for (int i = 0; i < imgHeight; ++i) {
+ for (int j = 0; j < imgWidth; ++j) {
+ uint pixel = img.pixel(j, i);
+ bool outside = j < x || j >= (x + w) || i < y || i >= (y + h);
+ if (outside != (pixel == background)) {
+ //printf("%d %d, expected %x, got %x, outside: %d\n", x, y, background, pixel, outside);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void tst_QPainter::drawImage()
+{
+ QFETCH(int, x);
+ QFETCH(int, y);
+ QFETCH(int, w);
+ QFETCH(int, h);
+ QFETCH(QImage::Format, srcFormat);
+ QFETCH(QImage::Format, dstFormat);
+
+ QImage dst(40, 40, QImage::Format_RGB32);
+ dst.fill(0xffffffff);
+
+ dst = dst.convertToFormat(dstFormat);
+ uint background = dst.pixel(0, 0);
+
+ QImage src(w, h, QImage::Format_RGB32);
+ src.fill(0xff000000);
+ src = src.convertToFormat(srcFormat);
+
+ QPainter p(&dst);
+ p.drawImage(x, y, src);
+ p.end();
+
+ QVERIFY(verifyImage(dst, x, y, w, h, background));
+}
+
+void tst_QPainter::imageCoordinateLimit()
+{
+ QImage img(64, 40000, QImage::Format_MonoLSB);
+ QPainter p(&img);
+ p.drawText(10, 36000, QLatin1String("foo"));
+ p.setPen(QPen(Qt::black, 2));
+ p.drawLine(10, 0, 60, 40000);
+
+ p.setRenderHint(QPainter::Antialiasing);
+ p.drawLine(10, 0, 60, 40000);
+}
+
+
+void tst_QPainter::imageBlending_data()
+{
+ QTest::addColumn<QImage::Format>("sourceFormat");
+ QTest::addColumn<QImage::Format>("destFormat");
+ QTest::addColumn<int>("error");
+
+ int error_rgb565 = ((1<<3) + (1<<2) + (1<<3));
+ QTest::newRow("rgb565_on_rgb565") << QImage::Format_RGB16
+ << QImage::Format_RGB16
+ << 0;
+ QTest::newRow("argb8565_on_rgb565") << QImage::Format_ARGB8565_Premultiplied
+ << QImage::Format_RGB16
+ << error_rgb565;
+
+ QTest::newRow("rgb32_on_rgb565") << QImage::Format_RGB32
+ << QImage::Format_RGB16
+ << error_rgb565;
+
+ QTest::newRow("argb32pm_on_rgb565") << QImage::Format_ARGB32_Premultiplied
+ << QImage::Format_RGB16
+ << error_rgb565;
+}
+
+int diffColor(quint32 ap, quint32 bp)
+{
+ int a = qAlpha(ap) - qAlpha(bp);
+ int r = qRed(ap) - qRed(bp);
+ int b = qBlue(ap) - qBlue(bp);
+ int g = qBlue(ap) - qBlue(bp);
+
+ return qAbs(a) + qAbs(r) + qAbs(g) + qAbs(b);
+}
+
+// this test assumes premultiplied pixels...
+
+void tst_QPainter::imageBlending()
+{
+ QFETCH(QImage::Format, sourceFormat);
+ QFETCH(QImage::Format, destFormat);
+ QFETCH(int, error);
+
+ QImage dest;
+ {
+ QImage orig_dest(6, 6, QImage::Format_ARGB32_Premultiplied);
+ orig_dest.fill(0);
+ QPainter p(&orig_dest);
+ p.fillRect(0, 0, 6, 3, QColor::fromRgbF(1, 0, 0));
+ p.fillRect(3, 0, 3, 6, QColor::fromRgbF(0, 0, 1, 0.5));
+ p.end();
+ dest = orig_dest.convertToFormat(destFormat);
+
+ // An image like this: (r = red, m = magenta, b = light alpha blue, 0 = transparent)
+ // r r r m m m
+ // r r r m m m
+ // r r r m m m
+ // 0 0 0 b b b
+ // 0 0 0 b b b
+ // 0 0 0 b b b
+ }
+
+ QImage source;
+ {
+ QImage orig_source(6, 6, QImage::Format_ARGB32_Premultiplied);
+ orig_source.fill(0);
+ QPainter p(&orig_source);
+ p.fillRect(1, 1, 4, 4, QColor::fromRgbF(0, 1, 0, 0.5));
+ p.fillRect(2, 2, 2, 2, QColor::fromRgbF(0, 1, 0));
+ p.end();
+ source = orig_source.convertToFormat(sourceFormat);
+
+ // An image like this: (0 = transparent, . = green at 0.5 alpha, g = opaque green.
+ // 0 0 0 0 0 0
+ // 0 . . . . 0
+ // 0 . g g . 0
+ // 0 . g g . 0
+ // 0 . . . . 0
+ // 0 0 0 0 0 0
+ }
+
+ QPainter p(&dest);
+ p.drawImage(0, 0, source);
+ p.end();
+
+ // resulting image:
+ // r r r m m m
+ // r r. r. m. m. m
+ // r r. g g m. m
+ // 0 . g g b. b
+ // 0 . . b. b. b
+ // 0 0 0 b b b
+
+ // the g pixels, always green..
+ QVERIFY(diffColor(dest.pixel(2, 2), 0xff00ff00) <= error); // g
+
+ if (source.hasAlphaChannel()) {
+ QVERIFY(diffColor(dest.pixel(0, 0), 0xffff0000) <= error); // r
+ QVERIFY(diffColor(dest.pixel(5, 0), 0xff7f007f) <= error); // m
+ QVERIFY(diffColor(dest.pixel(1, 1), 0xff7f7f00) <= error); // r.
+ QVERIFY(diffColor(dest.pixel(4, 1), 0xff3f7f3f) <= error); // m.
+ if (dest.hasAlphaChannel()) {
+ QVERIFY(diffColor(dest.pixel(1, 3), 0x7f007f00) <= error); // .
+ QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b.
+ QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b.
+ QVERIFY(diffColor(dest.pixel(4, 4), 0x7f00007f) <= error); // b
+ QVERIFY(diffColor(dest.pixel(4, 0), 0) <= 0); // 0
+ }
+ } else {
+ QVERIFY(diffColor(dest.pixel(0, 0), 0xff000000) <= 0);
+ QVERIFY(diffColor(dest.pixel(1, 1), 0xff007f00) <= error);
+ }
+}
+
+void tst_QPainter::imageBlending_clipped()
+{
+ QImage src(20, 20, QImage::Format_RGB16);
+ QPainter p(&src);
+ p.fillRect(src.rect(), Qt::red);
+ p.end();
+
+ QImage dst(40, 20, QImage::Format_RGB16);
+ p.begin(&dst);
+ p.fillRect(dst.rect(), Qt::white);
+ p.end();
+
+ QImage expected = dst;
+
+ p.begin(&dst);
+ p.setClipRect(QRect(23, 0, 20, 20));
+
+ // should be completely clipped
+ p.drawImage(QRectF(3, 0, 20, 20), src);
+ p.end();
+
+ // dst should be left unchanged
+ QCOMPARE(dst, expected);
+}
+
+void tst_QPainter::paintOnNullPixmap()
+{
+ QPixmap pix(16, 16);
+
+ QPixmap textPixmap;
+ QPainter p(&textPixmap);
+ p.drawPixmap(10, 10, pix);
+ p.end();
+
+ QPixmap textPixmap2(16,16);
+ p.begin(&textPixmap2);
+ p.end();
+}
+
+void tst_QPainter::checkCompositionMode()
+{
+ QImage refImage(50,50,QImage::Format_ARGB32);
+ QPainter painter(&refImage);
+ painter.fillRect(QRect(0,0,50,50),Qt::blue);
+
+ QImage testImage(50,50,QImage::Format_ARGB32);
+ QPainter p(&testImage);
+ p.fillRect(QRect(0,0,50,50),Qt::red);
+ p.save();
+ p.setCompositionMode(QPainter::CompositionMode_SourceOut);
+ p.restore();
+ p.fillRect(QRect(0,0,50,50),Qt::blue);
+
+ QCOMPARE(refImage.pixel(20,20),testImage.pixel(20,20));
+}
+
+static QLinearGradient inverseGradient(QLinearGradient g)
+{
+ QLinearGradient g2 = g;
+
+ QGradientStops stops = g.stops();
+
+ QGradientStops inverse;
+ foreach (QGradientStop stop, stops)
+ inverse << QGradientStop(1 - stop.first, stop.second);
+
+ g2.setStops(inverse);
+ return g2;
+}
+
+void tst_QPainter::linearGradientSymmetry_data()
+{
+ QTest::addColumn<QGradientStops>("stops");
+
+ if (sizeof(qreal) != sizeof(float)) {
+ QGradientStops stops;
+ stops << qMakePair(qreal(0.0), QColor(Qt::blue));
+ stops << qMakePair(qreal(0.2), QColor(220, 220, 220, 0));
+ stops << qMakePair(qreal(0.6), QColor(Qt::red));
+ stops << qMakePair(qreal(0.9), QColor(220, 220, 220, 255));
+ stops << qMakePair(qreal(1.0), QColor(Qt::black));
+ QTest::newRow("multiple stops") << stops;
+ }
+
+ {
+ QGradientStops stops;
+ stops << qMakePair(qreal(0.0), QColor(Qt::blue));
+ stops << qMakePair(qreal(1.0), QColor(Qt::black));
+ QTest::newRow("two stops") << stops;
+ }
+
+ if (sizeof(qreal) != sizeof(float)) {
+ QGradientStops stops;
+ stops << qMakePair(qreal(0.3), QColor(Qt::blue));
+ stops << qMakePair(qreal(0.6), QColor(Qt::black));
+ QTest::newRow("two stops 2") << stops;
+ }
+}
+
+void tst_QPainter::linearGradientSymmetry()
+{
+#ifdef Q_WS_QWS
+ QSKIP("QWS has limited resolution in the gradient color table", SkipAll);
+#else
+ QFETCH(QGradientStops, stops);
+
+ QImage a(64, 8, QImage::Format_ARGB32_Premultiplied);
+ QImage b(64, 8, QImage::Format_ARGB32_Premultiplied);
+
+ a.fill(0);
+ b.fill(0);
+
+ QLinearGradient gradient(QRectF(b.rect()).topLeft(), QRectF(b.rect()).topRight());
+ gradient.setStops(stops);
+
+ QPainter pa(&a);
+ pa.fillRect(a.rect(), gradient);
+ pa.end();
+
+ QPainter pb(&b);
+ pb.fillRect(b.rect(), inverseGradient(gradient));
+ pb.end();
+
+ b = b.mirrored(true);
+ QCOMPARE(a, b);
+#endif
+}
+
+void tst_QPainter::gradientInterpolation()
+{
+ QImage image(256, 8, QImage::Format_ARGB32_Premultiplied);
+ QPainter painter;
+
+ QLinearGradient gradient(QRectF(image.rect()).topLeft(), QRectF(image.rect()).topRight());
+ gradient.setColorAt(0.0, QColor(255, 0, 0, 0));
+ gradient.setColorAt(1.0, Qt::blue);
+
+ image.fill(0);
+ painter.begin(&image);
+ painter.fillRect(image.rect(), gradient);
+ painter.end();
+
+ const QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(3));
+
+ for (int i = 0; i < 256; ++i) {
+ QCOMPARE(qAlpha(line[i]), qBlue(line[i])); // bright blue
+ QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha
+ QCOMPARE(qRed(line[i]), 0); // no red component
+ QCOMPARE(qGreen(line[i]), 0); // no green component
+ }
+
+ gradient.setInterpolationMode(QGradient::ComponentInterpolation);
+
+ image.fill(0);
+ painter.begin(&image);
+ painter.fillRect(image.rect(), gradient);
+ painter.end();
+
+ for (int i = 1; i < 256; ++i) {
+ if (i < 128) {
+ QVERIFY(qRed(line[i]) >= qBlue(line[i])); // red is dominant
+ } else {
+ QVERIFY(qRed(line[i]) <= qBlue(line[i])); // blue is dominant
+ }
+ QVERIFY((qRed(line[i]) - 0.5) * (qAlpha(line[i - 1]) - 0.5) <= (qRed(line[i - 1]) + 0.5) * (qAlpha(line[i]) + 0.5)); // decreasing red
+ QVERIFY((qBlue(line[i]) + 0.5) * (qAlpha(line[i - 1]) + 0.5) >= (qBlue(line[i - 1]) - 0.5) * (qAlpha(line[i]) - 0.5)); // increasing blue
+ QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha
+ QCOMPARE(qGreen(line[i]), 0); // no green component
+ }
+}
+
+void tst_QPainter::drawPolygon()
+{
+ QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
+
+ QPainterPathStroker stroker;
+ stroker.setWidth(1.5);
+
+ QPainterPath path;
+ path.moveTo(2, 34);
+ path.lineTo(34, 2);
+
+ QPolygonF poly = stroker.createStroke(path).toFillPolygon();
+
+ img.fill(0xffffffff);
+ QPainter p(&img);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setBrush(Qt::red);
+ p.setPen(Qt::NoPen);
+ p.drawPolygon(poly);
+ p.translate(64, 64);
+ p.drawPolygon(poly);
+ p.end();
+
+ QImage a = img.copy();
+
+ img.fill(0xffffffff);
+ p.begin(&img);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setBrush(Qt::red);
+ p.setPen(Qt::NoPen);
+ p.translate(64, 64);
+ p.drawPolygon(poly);
+ p.resetTransform();
+ p.drawPolygon(poly);
+ p.end();
+
+ QCOMPARE(a, img);
+}
+
+void tst_QPainter::inactivePainter()
+{
+ // This test succeeds if it doesn't segfault.
+
+ QPainter p;
+ QPainterPath path;
+ QRegion region(QRect(20, 20, 60, 40));
+ QPolygonF polygon(QVector<QPointF>() << QPointF(0, 0) << QPointF(12, 0) << QPointF(8, 6));
+ path.addPolygon(polygon);
+
+ p.save();
+ p.restore();
+
+ p.background();
+ p.setBackground(QBrush(Qt::blue));
+
+ p.brush();
+ p.setBrush(Qt::red);
+ p.setBrush(Qt::NoBrush);
+ p.setBrush(QBrush(Qt::white, Qt::DiagCrossPattern));
+
+ p.backgroundMode();
+ p.setBackgroundMode(Qt::OpaqueMode);
+
+ p.boundingRect(QRectF(0, 0, 100, 20), Qt::AlignCenter, QLatin1String("Hello, World!"));
+ p.boundingRect(QRect(0, 0, 100, 20), Qt::AlignCenter, QLatin1String("Hello, World!"));
+
+ p.brushOrigin();
+ p.setBrushOrigin(QPointF(12, 34));
+ p.setBrushOrigin(QPoint(12, 34));
+
+ p.clipPath();
+ p.clipRegion();
+ p.hasClipping();
+ p.setClipPath(path);
+ p.setClipRect(QRectF(42, 42, 42, 42));
+ p.setClipRect(QRect(42, 42, 42, 42));
+ p.setClipRegion(region);
+ p.setClipping(true);
+
+ p.combinedMatrix();
+ p.combinedTransform();
+
+ p.compositionMode();
+ p.setCompositionMode(QPainter::CompositionMode_Plus);
+
+ p.device();
+ p.deviceMatrix();
+ p.deviceTransform();
+
+ p.font();
+ p.setFont(QFont(QLatin1String("Times"), 24));
+
+ p.fontInfo();
+ p.fontMetrics();
+
+ p.layoutDirection();
+ p.setLayoutDirection(Qt::RightToLeft);
+
+ p.opacity();
+ p.setOpacity(0.75);
+
+ p.pen();
+ p.setPen(QPen(Qt::red));
+ p.setPen(Qt::green);
+ p.setPen(Qt::NoPen);
+
+ p.renderHints();
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
+
+ p.resetMatrix();
+ p.resetTransform();
+ p.rotate(1);
+ p.scale(2, 2);
+ p.shear(-1, 1);
+ p.translate(3, 14);
+
+ p.viewTransformEnabled();
+ p.setViewTransformEnabled(true);
+
+ p.viewport();
+ p.setViewport(QRect(10, 10, 620, 460));
+
+ p.window();
+ p.setWindow(QRect(10, 10, 620, 460));
+
+ p.worldMatrix();
+ p.setWorldMatrix(QMatrix().translate(43, 21), true);
+ p.setWorldMatrixEnabled(true);
+
+ p.transform();
+ p.setTransform(QTransform().translate(12, 34), true);
+
+ p.worldTransform();
+ p.setWorldTransform(QTransform().scale(0.5, 0.5), true);
+}
+
+bool testCompositionMode(int src, int dst, int expected, QPainter::CompositionMode op, qreal opacity = 1.0)
+{
+ // The test image needs to be large enough to test SIMD code
+ const QSize imageSize(100, 100);
+
+ QImage actual(imageSize, QImage::Format_ARGB32_Premultiplied);
+ actual.fill(QColor(dst, dst, dst).rgb());
+
+ QPainter p(&actual);
+ p.setCompositionMode(op);
+ p.setOpacity(opacity);
+ p.fillRect(QRect(QPoint(), imageSize), QColor(src, src, src));
+ p.end();
+
+ if (qRed(actual.pixel(0, 0)) != expected) {
+ qDebug("Fail: mode %d, src[%d] dst [%d] actual [%d] expected [%d]", op,
+ src, dst, qRed(actual.pixel(0, 0)), expected);
+ return false;
+ } else {
+ QImage refImage(imageSize, QImage::Format_ARGB32_Premultiplied);
+ refImage.fill(QColor(expected, expected, expected).rgb());
+ return actual == refImage;
+ }
+}
+
+void tst_QPainter::extendedBlendModes()
+{
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Plus));
+ QVERIFY(testCompositionMode(127, 128, 255, QPainter::CompositionMode_Plus));
+ QVERIFY(testCompositionMode(127, 0, 127, QPainter::CompositionMode_Plus));
+ QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Plus));
+ QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Plus));
+ QVERIFY(testCompositionMode( 0, 255, 255, QPainter::CompositionMode_Plus));
+ QVERIFY(testCompositionMode(128, 128, 255, QPainter::CompositionMode_Plus));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus, 0.3));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Plus, 0.3));
+ QVERIFY(testCompositionMode(127, 128, 165, QPainter::CompositionMode_Plus, 0.3));
+ QVERIFY(testCompositionMode(127, 0, 37, QPainter::CompositionMode_Plus, 0.3));
+ QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Plus, 0.3));
+ QVERIFY(testCompositionMode(255, 0, 75, QPainter::CompositionMode_Plus, 0.3));
+ QVERIFY(testCompositionMode( 0, 255, 255, QPainter::CompositionMode_Plus, 0.3));
+ QVERIFY(testCompositionMode(128, 128, 166, QPainter::CompositionMode_Plus, 0.3));
+ QVERIFY(testCompositionMode(186, 200, 255, QPainter::CompositionMode_Plus, 0.3));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Multiply));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Multiply));
+ QVERIFY(testCompositionMode(127, 255, 127, QPainter::CompositionMode_Multiply));
+ QVERIFY(testCompositionMode(255, 127, 127, QPainter::CompositionMode_Multiply));
+ QVERIFY(testCompositionMode( 63, 255, 63, QPainter::CompositionMode_Multiply));
+ QVERIFY(testCompositionMode(255, 63, 63, QPainter::CompositionMode_Multiply));
+ QVERIFY(testCompositionMode(127, 127, 63, QPainter::CompositionMode_Multiply));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Screen));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Screen));
+ QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Screen));
+ QVERIFY(testCompositionMode(255, 63, 255, QPainter::CompositionMode_Screen));
+ QVERIFY(testCompositionMode( 63, 0, 63, QPainter::CompositionMode_Screen));
+ QVERIFY(testCompositionMode( 0, 63, 63, QPainter::CompositionMode_Screen));
+ QVERIFY(testCompositionMode(127, 127, 191, QPainter::CompositionMode_Screen));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Overlay));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Overlay));
+ QVERIFY(testCompositionMode( 63, 63, 31, QPainter::CompositionMode_Overlay));
+ QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Overlay));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Darken));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Darken));
+ QVERIFY(testCompositionMode( 63, 63, 63, QPainter::CompositionMode_Darken));
+ QVERIFY(testCompositionMode( 63, 255, 63, QPainter::CompositionMode_Darken));
+ QVERIFY(testCompositionMode(255, 63, 63, QPainter::CompositionMode_Darken));
+ QVERIFY(testCompositionMode( 63, 127, 63, QPainter::CompositionMode_Darken));
+ QVERIFY(testCompositionMode(127, 63, 63, QPainter::CompositionMode_Darken));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Lighten));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Lighten));
+ QVERIFY(testCompositionMode( 63, 63, 63, QPainter::CompositionMode_Lighten));
+ QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Lighten));
+ QVERIFY(testCompositionMode(255, 63, 255, QPainter::CompositionMode_Lighten));
+ QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Lighten));
+ QVERIFY(testCompositionMode(127, 63, 127, QPainter::CompositionMode_Lighten));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorDodge));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_ColorDodge));
+ QVERIFY(testCompositionMode( 63, 127, 169, QPainter::CompositionMode_ColorDodge));
+ QVERIFY(testCompositionMode(191, 127, 255, QPainter::CompositionMode_ColorDodge));
+ QVERIFY(testCompositionMode(127, 191, 255, QPainter::CompositionMode_ColorDodge));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorBurn));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_ColorBurn));
+ QVERIFY(testCompositionMode(127, 127, 0, QPainter::CompositionMode_ColorBurn));
+ QVERIFY(testCompositionMode(128, 128, 2, QPainter::CompositionMode_ColorBurn));
+ QVERIFY(testCompositionMode(191, 127, 84, QPainter::CompositionMode_ColorBurn));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_HardLight));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_HardLight));
+ QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_HardLight));
+ QVERIFY(testCompositionMode( 63, 63, 31, QPainter::CompositionMode_HardLight));
+ QVERIFY(testCompositionMode(127, 63, 63, QPainter::CompositionMode_HardLight));
+
+ QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_SoftLight));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_SoftLight));
+ QVERIFY(testCompositionMode(127, 127, 126, QPainter::CompositionMode_SoftLight));
+ QVERIFY(testCompositionMode( 63, 63, 39, QPainter::CompositionMode_SoftLight));
+ QVERIFY(testCompositionMode(127, 63, 62, QPainter::CompositionMode_SoftLight));
+
+ QVERIFY(testCompositionMode(255, 255, 0, QPainter::CompositionMode_Difference));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Difference));
+ QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Difference));
+ QVERIFY(testCompositionMode(127, 127, 0, QPainter::CompositionMode_Difference));
+ QVERIFY(testCompositionMode(127, 128, 1, QPainter::CompositionMode_Difference));
+ QVERIFY(testCompositionMode(127, 63, 64, QPainter::CompositionMode_Difference));
+ QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Difference));
+
+ QVERIFY(testCompositionMode(255, 255, 0, QPainter::CompositionMode_Exclusion));
+ QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Exclusion));
+ QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Exclusion));
+ QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_Exclusion));
+ QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Exclusion));
+ QVERIFY(testCompositionMode( 63, 63, 95, QPainter::CompositionMode_Exclusion));
+ QVERIFY(testCompositionMode(191, 191, 96, QPainter::CompositionMode_Exclusion));
+}
+
+void tst_QPainter::zeroOpacity()
+{
+ QImage source(1, 1, QImage::Format_ARGB32_Premultiplied);
+ source.fill(0xffffffff);
+
+ QImage target(1, 1, QImage::Format_RGB32);
+ target.fill(0xff000000);
+
+ QPainter p(&target);
+ p.setOpacity(0.0);
+ p.drawImage(0, 0, source);
+ p.end();
+
+ QCOMPARE(target.pixel(0, 0), 0xff000000);
+}
+
+void tst_QPainter::clippingBug()
+{
+ QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+
+ QImage expected = img;
+ QPainter p(&expected);
+ p.fillRect(1, 1, 30, 30, Qt::red);
+ p.end();
+
+ QPainterPath path;
+ path.addRect(1, 1, 30, 30);
+ path.addRect(1, 1, 30, 30);
+ path.addRect(1, 1, 30, 30);
+
+ p.begin(&img);
+ p.setClipPath(path);
+ p.fillRect(0, 0, 32, 32, Qt::red);
+ p.end();
+
+ QCOMPARE(img, expected);
+}
+
+void tst_QPainter::emptyClip()
+{
+ QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
+ QPainter p(&img);
+ p.setRenderHints(QPainter::Antialiasing);
+ p.setClipRect(0, 32, 64, 0);
+ p.fillRect(0, 0, 64, 64, Qt::white);
+
+ QPainterPath path;
+ path.lineTo(64, 0);
+ path.lineTo(64, 64);
+ path.lineTo(40, 64);
+ path.lineTo(40, 80);
+ path.lineTo(0, 80);
+
+ p.fillPath(path, Qt::green);
+}
+
+void tst_QPainter::drawImage_1x1()
+{
+ QImage source(1, 1, QImage::Format_ARGB32_Premultiplied);
+ source.fill(0xffffffff);
+
+ QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0xff000000);
+ QPainter p(&img);
+ p.drawImage(QRectF(0.9, 0.9, 32, 32), source);
+ p.end();
+
+ QImage expected = img;
+ expected.fill(0xff000000);
+ p.begin(&expected);
+ p.fillRect(1, 1, 31, 31, Qt::white);
+ p.end();
+
+ QCOMPARE(img, expected);
+}
+
+void tst_QPainter::taskQT4444_dontOverflowDashOffset()
+{
+ QPainter p;
+
+ QPen pen;
+ pen.setWidth(2);
+ pen.setStyle(Qt::DashDotLine);
+
+ QPointF point[4];
+ point[0] = QPointF(182.50868749707968,347.78457234212630);
+ point[1] = QPointF(182.50868749707968,107.22501998401277);
+ point[2] = QPointF(182.50868749707968,107.22501998401277);
+ point[3] = QPointF(520.46600762283651,107.22501998401277);
+
+ QImage crashImage(QSize(1000, 120), QImage::Format_ARGB32_Premultiplied);
+ p.begin(&crashImage);
+ p.setPen(pen);
+ p.drawLines(point, 2);
+ p.end();
+
+ QVERIFY(true); // Don't crash
+}
+
+void tst_QPainter::painterBegin()
+{
+ QImage nullImage;
+ QImage indexed8Image(16, 16, QImage::Format_Indexed8);
+ QImage rgb32Image(16, 16, QImage::Format_RGB32);
+ QImage argb32Image(16, 16, QImage::Format_ARGB32_Premultiplied);
+
+ QPainter p;
+
+ // Painting on null image should fail.
+ QVERIFY(!p.begin(&nullImage));
+
+ // Check that the painter is not messed up by using it on another image.
+ QVERIFY(p.begin(&rgb32Image));
+ QVERIFY(p.end());
+
+ // If painting on indexed8 image fails, the painter state should still be OK.
+ if (p.begin(&indexed8Image))
+ QVERIFY(p.end());
+ QVERIFY(p.begin(&rgb32Image));
+ QVERIFY(p.end());
+
+ // Try opening a painter on the two different images.
+ QVERIFY(p.begin(&rgb32Image));
+ QVERIFY(!p.begin(&argb32Image));
+ QVERIFY(p.end());
+
+ // Try opening two painters on the same image.
+ QVERIFY(p.begin(&rgb32Image));
+ QPainter q;
+ QVERIFY(!q.begin(&rgb32Image));
+ QVERIFY(!q.end());
+ QVERIFY(p.end());
+
+ // Try ending an inactive painter.
+ QVERIFY(!p.end());
+}
+
+void tst_QPainter::setPenColor(QPainter& p)
+{
+ p.setPen(Qt::NoPen);
+
+ // Setting color, then style
+ // Should work even though the pen is "NoPen with color", temporarily.
+ QPen newPen(p.pen());
+ newPen.setColor(Qt::red);
+ QCOMPARE(p.pen().style(), newPen.style());
+ QCOMPARE(p.pen().style(), Qt::NoPen);
+ p.setPen(newPen);
+
+ QCOMPARE(p.pen().color().name(), QString("#ff0000"));
+
+ QPen newPen2(p.pen());
+ newPen2.setStyle(Qt::SolidLine);
+ p.setPen(newPen2);
+
+ QCOMPARE(p.pen().color().name(), QString("#ff0000"));
+}
+
+void tst_QPainter::setPenColorOnImage()
+{
+ QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied);
+ QPainter p(&img);
+ setPenColor(p);
+}
+
+void tst_QPainter::setPenColorOnPixmap()
+{
+ QPixmap pix(10, 10);
+ QPainter p(&pix);
+ setPenColor(p);
+}
+
+class TestProxy : public QGraphicsProxyWidget
+{
+public:
+ TestProxy() : QGraphicsProxyWidget() {}
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsProxyWidget::paint(painter, option, widget);
+ deviceTransform = painter->deviceTransform();
+ }
+ QTransform deviceTransform;
+};
+
+class TestWidget : public QWidget
+{
+Q_OBJECT
+public:
+ TestWidget() : QWidget(), painted(false) {}
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter p(this);
+ deviceTransform = p.deviceTransform();
+ worldTransform = p.worldTransform();
+ painted = true;
+ }
+ QTransform deviceTransform;
+ QTransform worldTransform;
+ bool painted;
+};
+
+void tst_QPainter::QTBUG5939_attachPainterPrivate()
+{
+ QWidget *w = new QWidget();
+ QGraphicsScene *scene = new QGraphicsScene();
+ QGraphicsView *view = new QGraphicsView(scene, w);
+ view->move(50 ,50);
+ TestProxy *proxy = new TestProxy();
+ TestWidget *widget = new TestWidget();
+ proxy->setWidget(widget);
+ scene->addItem(proxy);
+ proxy->rotate(45);
+ w->resize(scene->sceneRect().size().toSize());
+
+ w->show();
+ QTRY_VERIFY(widget->painted);
+
+ QVERIFY(widget->worldTransform.isIdentity());
+ QCOMPARE(widget->deviceTransform, proxy->deviceTransform);
+}
+
+void tst_QPainter::clipBoundingRect()
+{
+ QPixmap pix(500, 500);
+
+ QPainter p(&pix);
+
+ // Test a basic rectangle
+ p.setClipRect(100, 100, 200, 100);
+ QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
+ p.setClipRect(120, 120, 20, 20, Qt::IntersectClip);
+ QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+
+ // Test a basic float rectangle
+ p.setClipRect(QRectF(100, 100, 200, 100));
+ QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
+ p.setClipRect(QRectF(120, 120, 20, 20), Qt::IntersectClip);
+ QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+
+ // Test a basic path + region
+ QPainterPath path;
+ path.addRect(100, 100, 200, 100);
+ p.setClipPath(path);
+ QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
+ p.setClipRegion(QRegion(120, 120, 20, 20), Qt::IntersectClip);
+ QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+
+ p.setClipRect(0, 0, 500, 500);
+ p.translate(250, 250);
+ for (int i=0; i<360; ++i) {
+ p.rotate(1);
+ p.setClipRect(-100, -100, 200, 200, Qt::IntersectClip);
+ }
+ QVERIFY(p.clipBoundingRect().contains(QRectF(-100, -100, 200, 200)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(-250, -250, 500, 500)));
+
+}
+
+void tst_QPainter::drawText_subPixelPositionsInRaster_qtbug5053()
+{
+#if !defined(Q_WS_MAC) || !defined(QT_MAC_USE_COCOA)
+ QSKIP("Only Mac/Cocoa supports sub pixel positions in raster engine currently", SkipAll);
+#endif
+ QFontMetricsF fm(qApp->font());
+
+ QImage baseLine(fm.width(QChar::fromLatin1('e')), fm.height(), QImage::Format_RGB32);
+ baseLine.fill(Qt::white);
+ {
+ QPainter p(&baseLine);
+ p.drawText(0, fm.ascent(), QString::fromLatin1("e"));
+ }
+
+ bool foundDifferentRasterization = false;
+ for (int i=1; i<12; ++i) {
+ QImage comparison(baseLine.size(), QImage::Format_RGB32);
+ comparison.fill(Qt::white);
+
+ {
+ QPainter p(&comparison);
+ p.drawText(QPointF(i / 12.0, fm.ascent()), QString::fromLatin1("e"));
+ }
+
+ if (comparison != baseLine) {
+ foundDifferentRasterization = true;
+ break;
+ }
+ }
+
+ QVERIFY(foundDifferentRasterization);
+}
+
+void tst_QPainter::drawPointScaled()
+{
+ QImage image(32, 32, QImage::Format_RGB32);
+ image.fill(0xffffffff);
+
+ QPainter p(&image);
+
+ p.scale(0.1, 0.1);
+
+ QPen pen;
+ pen.setWidth(1000);
+ pen.setColor(Qt::red);
+
+ p.setPen(pen);
+ p.drawPoint(0, 0);
+ p.end();
+
+ QCOMPARE(image.pixel(16, 16), 0xffff0000);
+}
+
+class GradientProducer : public QThread
+{
+protected:
+ void run();
+};
+
+void GradientProducer::run()
+{
+ QImage image(1, 1, QImage::Format_RGB32);
+ QPainter p(&image);
+
+ for (int i = 0; i < 1000; ++i) {
+ QLinearGradient g;
+ g.setColorAt(0, QColor(i % 256, 0, 0));
+ g.setColorAt(1, Qt::white);
+
+ p.fillRect(image.rect(), g);
+ }
+}
+
+void tst_QPainter::QTBUG14614_gradientCacheRaceCondition()
+{
+ const int threadCount = 16;
+ GradientProducer producers[threadCount];
+ for (int i = 0; i < threadCount; ++i)
+ producers[i].start();
+ for (int i = 0; i < threadCount; ++i)
+ producers[i].wait();
+}
+
+void tst_QPainter::drawTextOpacity()
+{
+ QImage image(32, 32, QImage::Format_RGB32);
+ image.fill(0xffffffff);
+
+ QPainter p(&image);
+ p.setPen(QColor("#6F6F6F"));
+ p.setOpacity(0.5);
+ p.drawText(5, 30, QLatin1String("Qt"));
+ p.end();
+
+ QImage copy = image;
+ image.fill(0xffffffff);
+
+ p.begin(&image);
+ p.setPen(QColor("#6F6F6F"));
+ p.drawLine(-10, -10, -1, -1);
+ p.setOpacity(0.5);
+ p.drawText(5, 30, QLatin1String("Qt"));
+ p.end();
+
+ QCOMPARE(image, copy);
+}
+
+void tst_QPainter::QTBUG17053_zeroDashPattern()
+{
+ QImage image(32, 32, QImage::Format_RGB32);
+ image.fill(0xffffffff);
+
+ QImage original = image;
+
+ QVector<qreal> pattern;
+ pattern << qreal(0) << qreal(0);
+
+ QPainter p(&image);
+ QPen pen(Qt::black, 2.0);
+ pen.setDashPattern(pattern);
+
+ p.setPen(pen);
+ p.drawLine(0, 0, image.width(), image.height());
+
+ QCOMPARE(image, original);
+}
+
+class TextDrawerThread : public QThread
+{
+public:
+ void run();
+ QImage rendering;
+};
+
+void TextDrawerThread::run()
+{
+ rendering = QImage(100, 100, QImage::Format_ARGB32_Premultiplied);
+ rendering.fill(0);
+ QPainter p(&rendering);
+ p.fillRect(10, 10, 100, 100, Qt::blue);
+ p.setPen(Qt::green);
+ p.drawText(20, 20, "some text");
+ p.end();
+}
+
+void tst_QPainter::drawTextOutsideGuiThread()
+{
+ if (!QFontDatabase::supportsThreadedFontRendering())
+ QSKIP("No threaded font rendering", SkipAll);
+
+ QImage referenceRendering(100, 100, QImage::Format_ARGB32_Premultiplied);
+ referenceRendering.fill(0);
+ QPainter p(&referenceRendering);
+ p.fillRect(10, 10, 100, 100, Qt::blue);
+ p.setPen(Qt::green);
+ p.drawText(20, 20, "some text");
+ p.end();
+
+ TextDrawerThread t;
+ t.start();
+ t.wait();
+
+ QCOMPARE(referenceRendering, t.rendering);
+}
+
+QTEST_MAIN(tst_QPainter)
+
+#include "tst_qpainter.moc"
diff --git a/tests/auto/gui/painting/qpainter/utils/createImages/createImages.pro b/tests/auto/gui/painting/qpainter/utils/createImages/createImages.pro
new file mode 100644
index 0000000000..ce2d341e92
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/utils/createImages/createImages.pro
@@ -0,0 +1,11 @@
+######################################################################
+# Automatically generated by qmake (1.02a) Thu Apr 18 18:56:53 2002
+######################################################################
+
+TEMPLATE = app
+CONFIG -= moc
+
+# Input
+SOURCES += main.cpp
+
+
diff --git a/tests/auto/gui/painting/qpainter/utils/createImages/main.cpp b/tests/auto/gui/painting/qpainter/utils/createImages/main.cpp
new file mode 100644
index 0000000000..418c385717
--- /dev/null
+++ b/tests/auto/gui/painting/qpainter/utils/createImages/main.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <qapplication.h>
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qbitmap.h>
+
+static QColor baseColor( int k, int intensity )
+{
+ int r = ( k & 1 ) * intensity;
+ int g = ( (k>>1) & 1 ) * intensity;
+ int b = ( (k>>2) & 1 ) * intensity;
+ return QColor( r, g, b );
+}
+
+static QPixmap createDestPixmap()
+{
+ const int colorbands = 3;
+ const int intensities = 4;
+ QPixmap pm( 32, colorbands*intensities*4 );
+ QPainter painter;
+ painter.begin( &pm );
+ for ( int i=0; i<colorbands; i++ ) {
+ for ( int j=0; j<intensities; j++ ) {
+ int intensity = 255 * (j+1) / intensities; // 25%, 50%, 75% and 100%
+ for ( int k=0; k<8; k++ ) {
+ QColor col = baseColor( k, intensity );
+ painter.setPen( QPen( col, 1 ) );
+ painter.setBrush( col );
+ painter.drawRect( k*4, j*4 + i*intensities*4, 4, 4 );
+ }
+ }
+ }
+ painter.end();
+ return pm;
+}
+
+static QBitmap createDestBitmap()
+{
+ // create a bitmap that looks like:
+ // (0 is color0 and 1 is color1)
+ // 00001111
+ // 00001111
+ // 00001111
+ // 00001111
+ // 00001111
+ // 00001111
+ // 00001111
+ // 00001111
+ QBitmap bm( 8, 8 );
+ QPainter painter;
+ painter.begin( &bm );
+ painter.setPen( QPen( Qt::color0, 4 ) );
+ painter.drawLine( 2, 0, 2, 8 );
+ painter.setPen( QPen( Qt::color1, 4 ) );
+ painter.drawLine( 6, 0, 6, 8 );
+ painter.end();
+ return bm;
+}
+
+static QBitmap createSrcBitmap( int size, int border )
+{
+ // create the source bitmap that looks like
+ // (for size=4 and border=2):
+ //
+ //
+ // 1111
+ // 1111
+ // 0000
+ // 0000
+ //
+ //
+ // If \a border is 0, the bitmap does not have a mask, otherwise the inner
+ // part is masked.
+ // \a size specifies the size of the inner (i.e. masked) part. It should be
+ // a multiple of 2.
+ int size2 = size/2;
+ int totalSize = 2 * ( size2 + border );
+ QBitmap bm( totalSize, totalSize );
+ QPainter painter;
+ painter.begin( &bm );
+ painter.setPen( QPen( Qt::color0, 1 ) );
+ painter.setBrush( Qt::color0 );
+ painter.drawRect( border, size2+border, size, size2 );
+ painter.setPen( QPen( Qt::color1, 1 ) );
+ painter.setBrush( Qt::color1 );
+ painter.drawRect( border, border, size, size2 );
+ painter.end();
+ if ( border > 0 ) {
+ QBitmap mask( totalSize, totalSize, TRUE );
+ QPainter painter;
+ painter.begin( &mask );
+ painter.setPen( QPen( Qt::color1, 1 ) );
+ painter.setBrush( Qt::color1 );
+ painter.drawRect( border, border, size, size );
+ painter.end();
+ bm.setMask( mask );
+ }
+ return bm;
+}
+
+
+int main( int argc, char **argv )
+{
+ QApplication a( argc, argv );
+
+ // input for tst_QPainter::drawLine_rop_bitmap()
+ {
+ QBitmap dst = createDestBitmap();
+ dst.save( "../../drawLine_rop_bitmap/dst.xbm", "XBM" );
+ }
+
+ // input for tst_QPainter::drawPixmap_rop_bitmap()
+ {
+ QBitmap dst = createDestBitmap();
+ QBitmap src1 = createSrcBitmap( 4, 2 );
+ QBitmap src2 = createSrcBitmap( 4, 0 );
+ dst.save( "../../drawPixmap_rop_bitmap/dst.xbm", "XBM" );
+ src1.save( "../../drawPixmap_rop_bitmap/src1.xbm", "XBM" );
+ src1.mask()->save( "../../drawPixmap_rop_bitmap/src1-mask.xbm", "XBM" );
+ src2.save( "../../drawPixmap_rop_bitmap/src2.xbm", "XBM" );
+ }
+
+ // input for tst_QPainter::drawPixmap_rop()
+ {
+ QPixmap dst1 = createDestPixmap();
+ QPixmap dst2 = createDestPixmap();
+ dst2.resize( 32, 32 );
+ QBitmap src1 = createSrcBitmap( 32, 0 );
+
+ QBitmap src_tmp = createSrcBitmap( 32, 0 ).xForm( QWMatrix( 1, 0, 0, -1, 0, 0 ) );
+ src_tmp.resize( 32, 48 );
+ QBitmap src2 = src_tmp.xForm( QWMatrix( 1, 0, 0, -1, 0, 0 ) );
+ QBitmap mask( 32, 48, TRUE );
+ {
+ QPainter painter;
+ painter.begin( &mask );
+ painter.setPen( QPen( Qt::color1, 1 ) );
+ painter.setBrush( Qt::color1 );
+ painter.drawRect( 0, 16, 32, 32 );
+ painter.end();
+ }
+ src2.setMask( mask );
+
+ QBitmap src3 = createSrcBitmap( 32, 0 ).xForm( QWMatrix( 1, 0, 0, -1, 0, 0 ) );
+
+ dst1.save( "../../drawPixmap_rop/dst1.png", "PNG" );
+ dst2.save( "../../drawPixmap_rop/dst2.png", "PNG" );
+ src1.save( "../../drawPixmap_rop/src1.xbm", "XBM" );
+ src2.save( "../../drawPixmap_rop/src2.xbm", "XBM" );
+ src2.mask()->save( "../../drawPixmap_rop/src2-mask.xbm", "XBM" );
+ src3.save( "../../drawPixmap_rop/src3.xbm", "XBM" );
+ }
+}
diff --git a/tests/auto/gui/painting/qpainterpath/.gitignore b/tests/auto/gui/painting/qpainterpath/.gitignore
new file mode 100644
index 0000000000..4e0e797989
--- /dev/null
+++ b/tests/auto/gui/painting/qpainterpath/.gitignore
@@ -0,0 +1,2 @@
+tst_qpainterpath
+data
diff --git a/tests/auto/gui/painting/qpainterpath/qpainterpath.pro b/tests/auto/gui/painting/qpainterpath/qpainterpath.pro
new file mode 100644
index 0000000000..9708222c99
--- /dev/null
+++ b/tests/auto/gui/painting/qpainterpath/qpainterpath.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qpainterpath.cpp
+
+
+
diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
new file mode 100644
index 0000000000..33315adc06
--- /dev/null
+++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
@@ -0,0 +1,1332 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qfile.h>
+#include <qpainterpath.h>
+#include <qpen.h>
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPainterPath : public QObject
+{
+ Q_OBJECT
+
+public:
+
+private slots:
+ void getSetCheck();
+ void swap();
+
+ void contains_QPointF_data();
+ void contains_QPointF();
+
+ void contains_QRectF_data();
+ void contains_QRectF();
+
+ void intersects_QRectF_data();
+ void intersects_QRectF();
+
+ void testContainsAndIntersects_data();
+ void testContainsAndIntersects();
+
+ void testSimplified_data();
+ void testSimplified();
+
+ void testStroker_data();
+ void testStroker();
+
+ void currentPosition();
+
+ void testOperatorEquals();
+ void testOperatorEquals_fuzzy();
+ void testOperatorDatastream();
+
+ void testArcMoveTo_data();
+ void testArcMoveTo();
+ void setElementPositionAt();
+
+ void testOnPath_data();
+ void testOnPath();
+
+ void pointAtPercent_data();
+ void pointAtPercent();
+
+ void angleAtPercent();
+
+ void arcWinding_data();
+ void arcWinding();
+
+ void testToFillPolygons();
+
+ void testNaNandInfinites();
+
+ void closing();
+
+ void operators_data();
+ void operators();
+
+ void connectPathDuplicatePoint();
+ void connectPathMoveTo();
+
+ void translate();
+
+ void lineWithinBounds();
+};
+
+// Testing get/set functions
+void tst_QPainterPath::getSetCheck()
+{
+ QPainterPathStroker obj1;
+ // qreal QPainterPathStroker::width()
+ // void QPainterPathStroker::setWidth(qreal)
+ obj1.setWidth(0.0);
+ QCOMPARE(qreal(1.0), obj1.width()); // Pathstroker sets with to 1 if <= 0
+ obj1.setWidth(0.5);
+ QCOMPARE(qreal(0.5), obj1.width());
+ obj1.setWidth(1.1);
+ QCOMPARE(qreal(1.1), obj1.width());
+
+ // qreal QPainterPathStroker::miterLimit()
+ // void QPainterPathStroker::setMiterLimit(qreal)
+ obj1.setMiterLimit(0.0);
+ QCOMPARE(qreal(0.0), obj1.miterLimit());
+ obj1.setMiterLimit(1.1);
+ QCOMPARE(qreal(1.1), obj1.miterLimit());
+
+ // qreal QPainterPathStroker::curveThreshold()
+ // void QPainterPathStroker::setCurveThreshold(qreal)
+ obj1.setCurveThreshold(0.0);
+ QCOMPARE(qreal(0.0), obj1.curveThreshold());
+ obj1.setCurveThreshold(1.1);
+ QCOMPARE(qreal(1.1), obj1.curveThreshold());
+}
+
+void tst_QPainterPath::swap()
+{
+ QPainterPath p1;
+ p1.addRect( 0, 0,10,10);
+ QPainterPath p2;
+ p2.addRect(10,10,10,10);
+ p1.swap(p2);
+ QCOMPARE(p1.boundingRect().toRect(), QRect(10,10,10,10));
+ QCOMPARE(p2.boundingRect().toRect(), QRect( 0, 0,10,10));
+}
+
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QRectF)
+
+void tst_QPainterPath::currentPosition()
+{
+ QPainterPath p;
+
+ QCOMPARE(p.currentPosition(), QPointF());
+
+ p.moveTo(100, 100);
+ QCOMPARE(p.currentPosition(), QPointF(100, 100));
+
+ p.lineTo(200, 200);
+ QCOMPARE(p.currentPosition(), QPointF(200, 200));
+
+ p.cubicTo(300, 200, 200, 300, 500, 500);
+ QCOMPARE(p.currentPosition(), QPointF(500, 500));
+}
+
+void tst_QPainterPath::contains_QPointF_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<QPointF>("pt");
+ QTest::addColumn<bool>("contained");
+
+ QPainterPath path;
+ path.addRect(0, 0, 100, 100);
+
+ // #####
+ // # #
+ // # #
+ // # #
+ // #####
+
+ QTest::newRow("[0,0] in [0,0,100,100]") << path << QPointF(0, 0) << true;
+
+ QTest::newRow("[99,0] in [0,0,100,100]") << path << QPointF(99, 0) << true;
+ QTest::newRow("[0,99] in [0,0,100,100]") << path << QPointF(0, 99) << true;
+ QTest::newRow("[99,99] in [0,0,100,100]") << path << QPointF(99, 99) << true;
+
+ QTest::newRow("[99.99,0] in [0,0,100,100]") << path << QPointF(99.99, 0) << true;
+ QTest::newRow("[0,99.99] in [0,0,100,100]") << path << QPointF(0, 99.99) << true;
+ QTest::newRow("[99.99,99.99] in [0,0,100,100]") << path << QPointF(99.99, 99.99) << true;
+
+ QTest::newRow("[0.01,0.01] in [0,0,100,100]") << path << QPointF(0.01, 0.01) << true;
+ QTest::newRow("[0,0.01] in [0,0,100,100]") << path << QPointF(0, 0.01) << true;
+ QTest::newRow("[0.01,0] in [0,0,100,100]") << path << QPointF(0.01, 0) << true;
+
+ QTest::newRow("[-0.01,-0.01] in [0,0,100,100]") << path << QPointF(-0.01, -0.01) << false;
+ QTest::newRow("[-0,-0.01] in [0,0,100,100]") << path << QPointF(0, -0.01) << false;
+ QTest::newRow("[-0.01,0] in [0,0,100,100]") << path << QPointF(-0.01, 0) << false;
+
+
+ QTest::newRow("[-10,0] in [0,0,100,100]") << path << QPointF(-10, 0) << false;
+ QTest::newRow("[100,0] in [0,0,100,100]") << path << QPointF(100, 0) << false;
+
+ QTest::newRow("[0,-10] in [0,0,100,100]") << path << QPointF(0, -10) << false;
+ QTest::newRow("[0,100] in [0,0,100,100]") << path << QPointF(0, 100) << false;
+
+ QTest::newRow("[100.1,0] in [0,0,100,100]") << path << QPointF(100.1, 0) << false;
+ QTest::newRow("[0,100.1] in [0,0,100,100]") << path << QPointF(0, 100.1) << false;
+
+ path.addRect(50, 50, 100, 100);
+
+ // #####
+ // # #
+ // # #####
+ // # # # #
+ // ##### #
+ // # #
+ // #####
+
+ QTest::newRow("[49,49] in 2 rects") << path << QPointF(49,49) << true;
+ QTest::newRow("[50,50] in 2 rects") << path << QPointF(50,50) << false;
+ QTest::newRow("[100,100] in 2 rects") << path << QPointF(100,100) << true;
+
+ path.setFillRule(Qt::WindingFill);
+ QTest::newRow("[50,50] in 2 rects (winding)") << path << QPointF(50,50) << true;
+
+ path.addEllipse(0, 0, 150, 150);
+
+ // #####
+ // ## ##
+ // # #####
+ // # # # #
+ // ##### #
+ // ## ##
+ // #####
+
+ QTest::newRow("[50,50] in complex (winding)") << path << QPointF(50, 50) << true;
+
+ path.setFillRule(Qt::OddEvenFill);
+ QTest::newRow("[50,50] in complex (windinf)") << path << QPointF(50, 50) << true;
+ QTest::newRow("[49,49] in complex") << path << QPointF(49,49) << false;
+ QTest::newRow("[100,100] in complex") << path << QPointF(49,49) << false;
+
+
+ // unclosed triangle
+ path = QPainterPath();
+ path.moveTo(100, 100);
+ path.lineTo(130, 70);
+ path.lineTo(150, 110);
+
+ QTest::newRow("[100,100] in triangle") << path << QPointF(100, 100) << true;
+ QTest::newRow("[140,100] in triangle") << path << QPointF(140, 100) << true;
+ QTest::newRow("[130,80] in triangle") << path << QPointF(130, 80) << true;
+
+ QTest::newRow("[110,80] in triangle") << path << QPointF(110, 80) << false;
+ QTest::newRow("[150,100] in triangle") << path << QPointF(150, 100) << false;
+ QTest::newRow("[120,110] in triangle") << path << QPointF(120, 110) << false;
+
+ QRectF base_rect(0, 0, 20, 20);
+
+ path = QPainterPath();
+ path.addEllipse(base_rect);
+
+ // not strictly precise, but good enougth to verify fair precision.
+ QPainterPath inside;
+ inside.addEllipse(base_rect.adjusted(5, 5, -5, -5));
+ QPolygonF inside_poly = inside.toFillPolygon();
+ for (int i=0; i<inside_poly.size(); ++i)
+ QTest::newRow("inside_ellipse") << path << inside_poly.at(i) << true;
+
+ QPainterPath outside;
+ outside.addEllipse(base_rect.adjusted(-5, -5, 5, 5));
+ QPolygonF outside_poly = outside.toFillPolygon();
+ for (int i=0; i<outside_poly.size(); ++i)
+ QTest::newRow("outside_ellipse") << path << outside_poly.at(i) << false;
+
+ path = QPainterPath();
+ base_rect = QRectF(50, 50, 200, 200);
+ path.addEllipse(base_rect);
+ path.setFillRule(Qt::WindingFill);
+
+ QTest::newRow("topleft outside ellipse") << path << base_rect.topLeft() << false;
+ QTest::newRow("topright outside ellipse") << path << base_rect.topRight() << false;
+ QTest::newRow("bottomright outside ellipse") << path << base_rect.bottomRight() << false;
+ QTest::newRow("bottomleft outside ellipse") << path << base_rect.bottomLeft() << false;
+
+ // Test horizontal curve segment
+ path = QPainterPath();
+ path.moveTo(100, 100);
+ path.cubicTo(120, 100, 180, 100, 200, 100);
+ path.lineTo(150, 200);
+ path.closeSubpath();
+
+ QTest::newRow("horizontal cubic, out left") << path << QPointF(0, 100) << false;
+ QTest::newRow("horizontal cubic, out right") << path << QPointF(300, 100) <<false;
+ QTest::newRow("horizontal cubic, in mid") << path << QPointF(150, 100) << true;
+
+ path = QPainterPath();
+ path.addEllipse(QRectF(-5000.0, -5000.0, 1500000.0, 1500000.0));
+ QTest::newRow("huge ellipse, qreal=float crash") << path << QPointF(1100000.35, 1098000.2) << true;
+
+}
+
+void tst_QPainterPath::contains_QPointF()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(QPointF, pt);
+ QFETCH(bool, contained);
+
+ QCOMPARE(path.contains(pt), contained);
+}
+
+void tst_QPainterPath::contains_QRectF_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<QRectF>("rect");
+ QTest::addColumn<bool>("contained");
+
+ QPainterPath path;
+ path.addRect(0, 0, 100, 100);
+
+ QTest::newRow("same rect") << path << QRectF(0.1, 0.1, 99, 99) << true; // ###
+ QTest::newRow("outside") << path << QRectF(-1, -1, 100, 100) << false;
+ QTest::newRow("covers") << path << QRectF(-1, -1, 102, 102) << false;
+ QTest::newRow("left") << path << QRectF(-10, 50, 5, 5) << false;
+ QTest::newRow("top") << path << QRectF(50, -10, 5, 5) << false;
+ QTest::newRow("right") << path << QRectF(110, 50, 5, 5) << false;
+ QTest::newRow("bottom") << path << QRectF(50, 110, 5, 5) << false;
+
+ path.addRect(50, 50, 100, 100);
+
+ QTest::newRow("r1 top") << path << QRectF(0.1, 0.1, 99, 49) << true;
+ QTest::newRow("r1 left") << path << QRectF(0.1, 0.1, 49, 99) << true;
+ QTest::newRow("r2 right") << path << QRectF(100.01, 50.1, 49, 99) << true;
+ QTest::newRow("r2 bottom") << path << QRectF(50.1, 100.1, 99, 49) << true;
+ QTest::newRow("inside 2 rects") << path << QRectF(51, 51, 48, 48) << false;
+ QTest::newRow("topRight 2 rects") << path << QRectF(100, 0, 49, 49) << false;
+ QTest::newRow("bottomLeft 2 rects") << path << QRectF(0, 100, 49, 49) << false;
+
+ path.setFillRule(Qt::WindingFill);
+ QTest::newRow("inside 2 rects (winding)") << path << QRectF(51, 51, 48, 48) << true;
+
+ path.addEllipse(0, 0, 150, 150);
+ QTest::newRow("topRight 2 rects") << path << QRectF(100, 25, 24, 24) << true;
+ QTest::newRow("bottomLeft 2 rects") << path << QRectF(25, 100, 24, 24) << true;
+
+ path.setFillRule(Qt::OddEvenFill);
+ QTest::newRow("inside 2 rects") << path << QRectF(50, 50, 49, 49) << false;
+}
+
+void tst_QPainterPath::contains_QRectF()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(QRectF, rect);
+ QFETCH(bool, contained);
+
+ QCOMPARE(path.contains(rect), contained);
+}
+
+static inline QPainterPath rectPath(qreal x, qreal y, qreal w, qreal h)
+{
+ QPainterPath path;
+ path.addRect(x, y, w, h);
+ path.closeSubpath();
+ return path;
+}
+
+static inline QPainterPath ellipsePath(qreal x, qreal y, qreal w, qreal h)
+{
+ QPainterPath path;
+ path.addEllipse(x, y, w, h);
+ path.closeSubpath();
+ return path;
+}
+
+static inline QPainterPath linePath(qreal x1, qreal y1, qreal x2, qreal y2)
+{
+ QPainterPath path;
+ path.moveTo(x1, y1);
+ path.lineTo(x2, y2);
+ return path;
+}
+
+void tst_QPainterPath::intersects_QRectF_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<QRectF>("rect");
+ QTest::addColumn<bool>("intersects");
+
+ QPainterPath path;
+ path.addRect(0, 0, 100, 100);
+
+ QTest::newRow("same rect") << path << QRectF(0.1, 0.1, 99, 99) << true; // ###
+ QTest::newRow("outside") << path << QRectF(-1, -1, 100, 100) << true;
+ QTest::newRow("covers") << path << QRectF(-1, -1, 102, 102) << true;
+ QTest::newRow("left") << path << QRectF(-10, 50, 5, 5) << false;
+ QTest::newRow("top") << path << QRectF(50, -10, 5, 5) << false;
+ QTest::newRow("right") << path << QRectF(110, 50, 5, 5) << false;
+ QTest::newRow("bottom") << path << QRectF(50, 110, 5, 5) << false;
+
+ path.addRect(50, 50, 100, 100);
+
+ QTest::newRow("r1 top") << path << QRectF(0.1, 0.1, 99, 49) << true;
+ QTest::newRow("r1 left") << path << QRectF(0.1, 0.1, 49, 99) << true;
+ QTest::newRow("r2 right") << path << QRectF(100.01, 50.1, 49, 99) << true;
+ QTest::newRow("r2 bottom") << path << QRectF(50.1, 100.1, 99, 49) << true;
+ QTest::newRow("inside 2 rects") << path << QRectF(51, 51, 48, 48) << false;
+
+ path.setFillRule(Qt::WindingFill);
+ QTest::newRow("inside 2 rects (winding)") << path << QRectF(51, 51, 48, 48) << true;
+
+ path.addEllipse(0, 0, 150, 150);
+ QTest::newRow("topRight 2 rects") << path << QRectF(100, 25, 24, 24) << true;
+ QTest::newRow("bottomLeft 2 rects") << path << QRectF(25, 100, 24, 24) << true;
+
+ QTest::newRow("horizontal line") << linePath(0, 0, 10, 0) << QRectF(1, -1, 2, 2) << true;
+ QTest::newRow("vertical line") << linePath(0, 0, 0, 10) << QRectF(-1, 1, 2, 2) << true;
+
+ path = QPainterPath();
+ path.addEllipse(QRectF(-5000.0, -5000.0, 1500000.0, 1500000.0));
+ QTest::newRow("huge ellipse, qreal=float crash") << path << QRectF(1100000.35, 1098000.2, 1500000.0, 1500000.0) << true;
+}
+
+void tst_QPainterPath::intersects_QRectF()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(QRectF, rect);
+ QFETCH(bool, intersects);
+
+ QCOMPARE(path.intersects(rect), intersects);
+}
+
+
+void tst_QPainterPath::testContainsAndIntersects_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<QPainterPath>("candidate");
+ QTest::addColumn<bool>("contained");
+ QTest::addColumn<bool>("intersects");
+
+ QTest::newRow("rect vs small ellipse (upper left)") << rectPath(0, 0, 100, 100) << ellipsePath(0, 0, 50, 50) << false << true;
+ QTest::newRow("rect vs small ellipse (upper right)") << rectPath(0, 0, 100, 100) << ellipsePath(50, 0, 50, 50) << false << true;
+ QTest::newRow("rect vs small ellipse (lower right)") << rectPath(0, 0, 100, 100) << ellipsePath(50, 50, 50, 50) << false << true;
+ QTest::newRow("rect vs small ellipse (lower left)") << rectPath(0, 0, 100, 100) << ellipsePath(0, 50, 50, 50) << false << true;
+ QTest::newRow("rect vs small ellipse (centered)") << rectPath(0, 0, 100, 100) << ellipsePath(25, 25, 50, 50) << true << true;
+ QTest::newRow("rect vs equal ellipse") << rectPath(0, 0, 100, 100) << ellipsePath(0, 0, 100, 100) << false << true;
+ QTest::newRow("rect vs big ellipse") << rectPath(0, 0, 100, 100) << ellipsePath(-10, -10, 120, 120) << false << true;
+
+ QPainterPath twoEllipses = ellipsePath(0, 0, 100, 100).united(ellipsePath(200, 0, 100, 100));
+
+ QTest::newRow("rect vs two small ellipses") << rectPath(0, 0, 100, 100) << ellipsePath(25, 25, 50, 50).united(ellipsePath(225, 25, 50, 50)) << false << true;
+ QTest::newRow("rect vs two equal ellipses") << rectPath(0, 0, 100, 100) << twoEllipses << false << true;
+
+ QTest::newRow("rect vs self") << rectPath(0, 0, 100, 100) << rectPath(0, 0, 100, 100) << false << true;
+ QTest::newRow("ellipse vs self") << ellipsePath(0, 0, 100, 100) << ellipsePath(0, 0, 100, 100) << false << true;
+
+ QPainterPath twoRects = rectPath(0, 0, 100, 100).united(rectPath(200, 0, 100, 100));
+ QTest::newRow("two rects vs small ellipse (upper left)") << twoRects << ellipsePath(0, 0, 50, 50) << false << true;
+ QTest::newRow("two rects vs small ellipse (upper right)") << twoRects << ellipsePath(50, 0, 50, 50) << false << true;
+ QTest::newRow("two rects vs small ellipse (lower right)") << twoRects << ellipsePath(50, 50, 50, 50) << false << true;
+ QTest::newRow("two rects vs small ellipse (lower left)") << twoRects << ellipsePath(0, 50, 50, 50) << false << true;
+ QTest::newRow("two rects vs small ellipse (centered)") << twoRects << ellipsePath(25, 25, 50, 50) << true << true;
+ QTest::newRow("two rects vs equal ellipse") << twoRects << ellipsePath(0, 0, 100, 100) << false << true;
+ QTest::newRow("two rects vs big ellipse") << twoRects << ellipsePath(-10, -10, 120, 120) << false << true;
+
+ QTest::newRow("two rects vs two small ellipses") << twoRects << ellipsePath(25, 25, 50, 50).united(ellipsePath(225, 25, 50, 50)) << true << true;
+ QTest::newRow("two rects vs two equal ellipses") << twoRects << ellipsePath(0, 0, 100, 100).united(ellipsePath(200, 0, 100, 100)) << false << true;
+
+ QTest::newRow("two rects vs self") << twoRects << twoRects << false << true;
+ QTest::newRow("two ellipses vs self") << twoEllipses << twoEllipses << false << true;
+
+ QPainterPath windingRect = rectPath(0, 0, 100, 100);
+ windingRect.addRect(25, 25, 100, 50);
+ windingRect.setFillRule(Qt::WindingFill);
+
+ QTest::newRow("rect with winding rule vs tall rect") << windingRect << rectPath(40, 20, 20, 60) << true << true;
+ QTest::newRow("rect with winding rule vs self") << windingRect << windingRect << false << true;
+
+ QPainterPath thickFrame = rectPath(0, 0, 100, 100).subtracted(rectPath(25, 25, 50, 50));
+ QPainterPath thinFrame = rectPath(10, 10, 80, 80).subtracted(rectPath(15, 15, 70, 70));
+
+ QTest::newRow("thin frame in thick frame") << thickFrame << thinFrame << true << true;
+ QTest::newRow("rect in thick frame") << thickFrame << rectPath(40, 40, 20, 20) << false << false;
+ QTest::newRow("rect in thin frame") << thinFrame << rectPath(40, 40, 20, 20) << false << false;
+
+ QPainterPath ellipses;
+ ellipses.addEllipse(0, 0, 10, 10);
+ ellipses.addEllipse(4, 4, 2, 2);
+ ellipses.setFillRule(Qt::WindingFill);
+
+ // the definition of QPainterPath::intersects() and contains() is fill-area based,
+ QTest::newRow("line in rect") << rectPath(0, 0, 100, 100) << linePath(10, 10, 90, 90) << true << true;
+ QTest::newRow("horizontal line in rect") << rectPath(0, 0, 100, 100) << linePath(10, 50, 90, 50) << true << true;
+ QTest::newRow("vertical line in rect") << rectPath(0, 0, 100, 100) << linePath(50, 10, 50, 90) << true << true;
+
+ QTest::newRow("line through rect") << rectPath(0, 0, 100, 100) << linePath(-10, -10, 110, 110) << false << true;
+ QTest::newRow("line through rect 2") << rectPath(0, 0, 100, 100) << linePath(-10, 0, 110, 100) << false << true;
+ QTest::newRow("line through rect 3") << rectPath(0, 0, 100, 100) << linePath(5, 10, 110, 100) << false << true;
+ QTest::newRow("line through rect 4") << rectPath(0, 0, 100, 100) << linePath(-10, 0, 90, 90) << false << true;
+
+ QTest::newRow("horizontal line through rect") << rectPath(0, 0, 100, 100) << linePath(-10, 50, 110, 50) << false << true;
+ QTest::newRow("vertical line through rect") << rectPath(0, 0, 100, 100) << linePath(50, -10, 50, 110) << false << true;
+
+ QTest::newRow("line vs line") << linePath(0, 0, 10, 10) << linePath(10, 0, 0, 10) << false << true;
+
+ QTest::newRow("line in rect with hole") << rectPath(0, 0, 10, 10).subtracted(rectPath(2, 2, 6, 6)) << linePath(4, 4, 6, 6) << false << false;
+ QTest::newRow("line in ellipse") << ellipses << linePath(3, 5, 7, 5) << false << true;
+ QTest::newRow("line in ellipse 2") << ellipses << linePath(4.5, 5, 5.5, 5) << true << true;
+
+ QTest::newRow("winding ellipse") << ellipses << ellipsePath(4, 4, 2, 2) << false << true;
+ QTest::newRow("winding ellipse 2") << ellipses << ellipsePath(4.5, 4.5, 1, 1) << true << true;
+ ellipses.setFillRule(Qt::OddEvenFill);
+ QTest::newRow("odd even ellipse") << ellipses << ellipsePath(4, 4, 2, 2) << false << true;
+ QTest::newRow("odd even ellipse 2") << ellipses << ellipsePath(4.5, 4.5, 1, 1) << false << false;
+}
+
+void tst_QPainterPath::testContainsAndIntersects()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(QPainterPath, candidate);
+ QFETCH(bool, contained);
+ QFETCH(bool, intersects);
+
+ QCOMPARE(path.intersects(candidate), intersects);
+ QCOMPARE(path.contains(candidate), contained);
+}
+
+void tst_QPainterPath::testSimplified_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<int>("elements");
+
+ QTest::newRow("rect") << rectPath(0, 0, 10, 10) << 5;
+
+ QPainterPath twoRects = rectPath(0, 0, 10, 10);
+ twoRects.addPath(rectPath(5, 0, 10, 10));
+ QTest::newRow("two rects (odd)") << twoRects << 10;
+
+ twoRects.setFillRule(Qt::WindingFill);
+ QTest::newRow("two rects (winding)") << twoRects << 5;
+
+ QPainterPath threeSteps = rectPath(0, 0, 10, 10);
+ threeSteps.addPath(rectPath(0, 10, 20, 10));
+ threeSteps.addPath(rectPath(0, 20, 30, 10));
+
+ QTest::newRow("three rects (steps)") << threeSteps << 9;
+}
+
+void tst_QPainterPath::testSimplified()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(int, elements);
+
+ QPainterPath simplified = path.simplified();
+
+ QCOMPARE(simplified.elementCount(), elements);
+
+ QVERIFY(simplified.subtracted(path).isEmpty());
+ QVERIFY(path.subtracted(simplified).isEmpty());
+}
+
+void tst_QPainterPath::testStroker_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<QPen>("pen");
+ QTest::addColumn<QPainterPath>("stroke");
+
+ QTest::newRow("line 1") << linePath(2, 2, 10, 2) << QPen(Qt::black, 2, Qt::SolidLine, Qt::FlatCap) << rectPath(2, 1, 8, 2);
+ QTest::newRow("line 2") << linePath(2, 2, 10, 2) << QPen(Qt::black, 2, Qt::SolidLine, Qt::SquareCap) << rectPath(1, 1, 10, 2);
+
+ QTest::newRow("rect") << rectPath(1, 1, 8, 8) << QPen(Qt::black, 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin) << rectPath(0, 0, 10, 10).subtracted(rectPath(2, 2, 6, 6));
+
+ QTest::newRow("dotted line") << linePath(0, 0, 10, 0) << QPen(Qt::black, 2, Qt::DotLine) << rectPath(-1, -1, 4, 2).united(rectPath(5, -1, 4, 2));
+}
+
+void tst_QPainterPath::testStroker()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(QPen, pen);
+ QFETCH(QPainterPath, stroke);
+
+ QPainterPathStroker stroker;
+ stroker.setWidth(pen.widthF());
+ stroker.setCapStyle(pen.capStyle());
+ stroker.setJoinStyle(pen.joinStyle());
+ stroker.setMiterLimit(pen.miterLimit());
+ stroker.setDashPattern(pen.style());
+ stroker.setDashOffset(pen.dashOffset());
+
+ QPainterPath result = stroker.createStroke(path);
+
+ // check if stroke == result
+ QVERIFY(result.subtracted(stroke).isEmpty());
+ QVERIFY(stroke.subtracted(result).isEmpty());
+}
+
+void tst_QPainterPath::testOperatorEquals()
+{
+ QPainterPath empty1;
+ QPainterPath empty2;
+ QVERIFY(empty1 == empty2);
+
+ QPainterPath rect1;
+ rect1.addRect(100, 100, 100, 100);
+ QVERIFY(rect1 == rect1);
+ QVERIFY(rect1 != empty1);
+
+ QPainterPath rect2;
+ rect2.addRect(100, 100, 100, 100);
+ QVERIFY(rect1 == rect2);
+
+ rect2.setFillRule(Qt::WindingFill);
+ QVERIFY(rect1 != rect2);
+
+ QPainterPath ellipse1;
+ ellipse1.addEllipse(50, 50, 100, 100);
+ QVERIFY(rect1 != ellipse1);
+
+ QPainterPath ellipse2;
+ ellipse2.addEllipse(50, 50, 100, 100);
+ QVERIFY(ellipse1 == ellipse2);
+}
+
+void tst_QPainterPath::testOperatorEquals_fuzzy()
+{
+ // if operator== returns true for two paths it should
+ // also return true when the same transform is applied to both paths
+ {
+ QRectF a(100, 100, 100, 50);
+ QRectF b = a.translated(1e-14, 1e-14);
+
+ QPainterPath pa;
+ pa.addRect(a);
+ QPainterPath pb;
+ pb.addRect(b);
+
+ QVERIFY(pa == pb);
+
+ QTransform transform;
+ transform.translate(-100, -100);
+
+ QVERIFY(transform.map(pa) == transform.map(pb));
+ }
+
+ // higher tolerance for error when path's bounding rect is big
+ {
+ QRectF a(1, 1, 1e6, 0.5e6);
+ QRectF b = a.translated(1e-7, 1e-7);
+
+ QPainterPath pa;
+ pa.addRect(a);
+ QPainterPath pb;
+ pb.addRect(b);
+
+ QVERIFY(pa == pb);
+
+ QTransform transform;
+ transform.translate(-1, -1);
+
+ QVERIFY(transform.map(pa) == transform.map(pb));
+ }
+
+ // operator== should return true for a path that has
+ // been transformed and then inverse transformed
+ {
+ QPainterPath a;
+ a.addRect(0, 0, 100, 100);
+
+ QTransform transform;
+ transform.translate(100, 20);
+ transform.scale(1.5, 1.5);
+
+ QPainterPath b = transform.inverted().map(transform.map(a));
+
+ QVERIFY(a == b);
+ }
+
+ {
+ QPainterPath a;
+ a.lineTo(10, 0);
+ a.lineTo(10, 10);
+ a.lineTo(0, 10);
+
+ QPainterPath b;
+ b.lineTo(10, 0);
+ b.moveTo(10, 10);
+ b.lineTo(0, 10);
+
+ QVERIFY(a != b);
+ }
+}
+
+void tst_QPainterPath::testOperatorDatastream()
+{
+ QPainterPath path;
+ path.addEllipse(0, 0, 100, 100);
+ path.addRect(0, 0, 100, 100);
+ path.setFillRule(Qt::WindingFill);
+
+ // Write out
+ {
+ QFile data("data");
+ bool ok = data.open(QFile::WriteOnly);
+ QVERIFY(ok);
+ QDataStream stream(&data);
+ stream << path;
+ }
+
+ QPainterPath other;
+ // Read in
+ {
+ QFile data("data");
+ bool ok = data.open(QFile::ReadOnly);
+ QVERIFY(ok);
+ QDataStream stream(&data);
+ stream >> other;
+ }
+
+ QVERIFY(other == path);
+}
+
+void tst_QPainterPath::closing()
+{
+ // lineto's
+ {
+ QPainterPath triangle(QPoint(100, 100));
+
+ triangle.lineTo(200, 100);
+ triangle.lineTo(200, 200);
+ QCOMPARE(triangle.elementCount(), 3);
+
+ triangle.closeSubpath();
+ QCOMPARE(triangle.elementCount(), 4);
+ QCOMPARE(triangle.elementAt(3).type, QPainterPath::LineToElement);
+
+ triangle.moveTo(300, 300);
+ QCOMPARE(triangle.elementCount(), 5);
+ QCOMPARE(triangle.elementAt(4).type, QPainterPath::MoveToElement);
+
+ triangle.lineTo(400, 300);
+ triangle.lineTo(400, 400);
+ QCOMPARE(triangle.elementCount(), 7);
+
+ triangle.closeSubpath();
+ QCOMPARE(triangle.elementCount(), 8);
+
+ // this will should trigger implicit moveto...
+ triangle.lineTo(600, 300);
+ QCOMPARE(triangle.elementCount(), 10);
+ QCOMPARE(triangle.elementAt(8).type, QPainterPath::MoveToElement);
+ QCOMPARE(triangle.elementAt(9).type, QPainterPath::LineToElement);
+
+ triangle.lineTo(600, 700);
+ QCOMPARE(triangle.elementCount(), 11);
+ }
+
+ // curveto's
+ {
+ QPainterPath curves(QPoint(100, 100));
+
+ curves.cubicTo(200, 100, 100, 200, 200, 200);
+ QCOMPARE(curves.elementCount(), 4);
+
+ curves.closeSubpath();
+ QCOMPARE(curves.elementCount(), 5);
+ QCOMPARE(curves.elementAt(4).type, QPainterPath::LineToElement);
+
+ curves.moveTo(300, 300);
+ QCOMPARE(curves.elementCount(), 6);
+ QCOMPARE(curves.elementAt(5).type, QPainterPath::MoveToElement);
+
+ curves.cubicTo(400, 300, 300, 400, 400, 400);
+ QCOMPARE(curves.elementCount(), 9);
+
+ curves.closeSubpath();
+ QCOMPARE(curves.elementCount(), 10);
+
+ // should trigger implicit moveto..
+ curves.cubicTo(100, 800, 800, 100, 800, 800);
+ QCOMPARE(curves.elementCount(), 14);
+ QCOMPARE(curves.elementAt(10).type, QPainterPath::MoveToElement);
+ QCOMPARE(curves.elementAt(11).type, QPainterPath::CurveToElement);
+ }
+
+ {
+ QPainterPath rects;
+ rects.addRect(100, 100, 100, 100);
+
+ QCOMPARE(rects.elementCount(), 5);
+ QCOMPARE(rects.elementAt(0).type, QPainterPath::MoveToElement);
+ QCOMPARE(rects.elementAt(4).type, QPainterPath::LineToElement);
+
+ rects.addRect(300, 100, 100,100);
+ QCOMPARE(rects.elementCount(), 10);
+ QCOMPARE(rects.elementAt(5).type, QPainterPath::MoveToElement);
+ QCOMPARE(rects.elementAt(9).type, QPainterPath::LineToElement);
+
+ rects.lineTo(0, 0);
+ QCOMPARE(rects.elementCount(), 12);
+ QCOMPARE(rects.elementAt(10).type, QPainterPath::MoveToElement);
+ QCOMPARE(rects.elementAt(11).type, QPainterPath::LineToElement);
+ }
+
+ {
+ QPainterPath ellipses;
+ ellipses.addEllipse(100, 100, 100, 100);
+
+ QCOMPARE(ellipses.elementCount(), 13);
+ QCOMPARE(ellipses.elementAt(0).type, QPainterPath::MoveToElement);
+ QCOMPARE(ellipses.elementAt(10).type, QPainterPath::CurveToElement);
+
+ ellipses.addEllipse(300, 100, 100,100);
+ QCOMPARE(ellipses.elementCount(), 26);
+ QCOMPARE(ellipses.elementAt(13).type, QPainterPath::MoveToElement);
+ QCOMPARE(ellipses.elementAt(23).type, QPainterPath::CurveToElement);
+
+ ellipses.lineTo(0, 0);
+ QCOMPARE(ellipses.elementCount(), 28);
+ QCOMPARE(ellipses.elementAt(26).type, QPainterPath::MoveToElement);
+ QCOMPARE(ellipses.elementAt(27).type, QPainterPath::LineToElement);
+ }
+
+ {
+ QPainterPath path;
+ path.moveTo(10, 10);
+ path.lineTo(40, 10);
+ path.lineTo(25, 20);
+ path.lineTo(10 + 1e-13, 10 + 1e-13);
+ QCOMPARE(path.elementCount(), 4);
+ path.closeSubpath();
+ QCOMPARE(path.elementCount(), 4);
+ }
+}
+
+void tst_QPainterPath::testArcMoveTo_data()
+{
+ QTest::addColumn<QRectF>("rect");
+ QTest::addColumn<qreal>("angle");
+
+ QList<QRectF> rects;
+ rects << QRectF(100, 100, 100, 100)
+ << QRectF(100, 100, -100, 100)
+ << QRectF(100, 100, 100, -100)
+ << QRectF(100, 100, -100, -100);
+
+ for (int domain=0; domain<rects.size(); ++domain) {
+ for (int i=-360; i<=360; ++i) {
+ QTest::newRow("test") << rects.at(domain) << (qreal) i;
+ }
+
+ // test low angles
+ QTest::newRow("test") << rects.at(domain) << (qreal) 1e-10;
+ QTest::newRow("test") << rects.at(domain) << (qreal)-1e-10;
+ }
+}
+
+void tst_QPainterPath::operators_data()
+{
+ QTest::addColumn<QPainterPath>("test");
+ QTest::addColumn<QPainterPath>("expected");
+
+ QPainterPath a;
+ QPainterPath b;
+ a.addRect(0, 0, 100, 100);
+ b.addRect(50, 50, 100, 100);
+
+ QTest::newRow("a & b") << (a & b) << a.intersected(b);
+ QTest::newRow("a | b") << (a | b) << a.united(b);
+ QTest::newRow("a + b") << (a + b) << a.united(b);
+ QTest::newRow("a - b") << (a - b) << a.subtracted(b);
+
+ QPainterPath c = a;
+ QTest::newRow("a &= b") << (a &= b) << a.intersected(b);
+ c = a;
+ QTest::newRow("a |= b") << (a |= b) << a.united(b);
+ c = a;
+ QTest::newRow("a += b") << (a += b) << a.united(b);
+ c = a;
+ QTest::newRow("a -= b") << (a -= b) << a.subtracted(b);
+}
+
+void tst_QPainterPath::operators()
+{
+ QFETCH(QPainterPath, test);
+ QFETCH(QPainterPath, expected);
+
+ QCOMPARE(test, expected);
+}
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#define ANGLE(t) ((t) * 2 * M_PI / 360.0)
+
+
+static inline bool pathFuzzyCompare(double p1, double p2)
+{
+ return qAbs(p1 - p2) < 0.001;
+}
+
+
+static inline bool pathFuzzyCompare(float p1, float p2)
+{
+ return qAbs(p1 - p2) < 0.001;
+}
+
+
+void tst_QPainterPath::testArcMoveTo()
+{
+ QFETCH(QRectF, rect);
+ QFETCH(qreal, angle);
+
+ QPainterPath path;
+ path.arcMoveTo(rect, angle);
+ path.arcTo(rect, angle, 30);
+ path.arcTo(rect, angle + 30, 30);
+
+ QPointF pos = path.elementAt(0);
+
+ QVERIFY((path.elementCount()-1) % 3 == 0);
+
+ qreal x_radius = rect.width() / 2.0;
+ qreal y_radius = rect.height() / 2.0;
+
+ QPointF shouldBe = rect.center()
+ + QPointF(x_radius * cos(ANGLE(angle)), -y_radius * sin(ANGLE(angle)));
+
+ qreal iw = 1 / rect.width();
+ qreal ih = 1 / rect.height();
+
+ QVERIFY(pathFuzzyCompare(pos.x() * iw, shouldBe.x() * iw));
+ QVERIFY(pathFuzzyCompare(pos.y() * ih, shouldBe.y() * ih));
+}
+
+void tst_QPainterPath::testOnPath_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<qreal>("start");
+ QTest::addColumn<qreal>("middle");
+ QTest::addColumn<qreal>("end");
+
+ QPainterPath path = QPainterPath(QPointF(153, 199));
+ path.cubicTo(QPointF(147, 61), QPointF(414, 18),
+ QPointF(355, 201));
+
+ QTest::newRow("First case") << path
+ << qreal(93.0)
+ << qreal(4.0)
+ << qreal(252.13);
+
+ path = QPainterPath(QPointF(328, 197));
+ path.cubicTo(QPointF(150, 50), QPointF(401, 50),
+ QPointF(225, 197));
+ QTest::newRow("Second case") << path
+ << qreal(140.0)
+ << qreal(0.0)
+ << qreal(220.0);
+
+ path = QPainterPath(QPointF(328, 197));
+ path.cubicTo(QPointF(101 , 153), QPointF(596, 151),
+ QPointF(353, 197));
+ QTest::newRow("Third case") << path
+ << qreal(169.0)
+ << qreal(0.22)
+ << qreal(191.0);
+
+ path = QPainterPath(QPointF(153, 199));
+ path.cubicTo(QPointF(59, 53), QPointF(597, 218),
+ QPointF(355, 201));
+ QTest::newRow("Fourth case") << path
+ << qreal(122.0)
+ << qreal(348.0)
+ << qreal(175.0);
+
+}
+
+#define SIGN(x) ((x < 0)?-1:1)
+void tst_QPainterPath::testOnPath()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(qreal, start);
+ QFETCH(qreal, middle);
+ QFETCH(qreal, end);
+
+ int signStart = SIGN(start);
+ int signMid = SIGN(middle);
+ int signEnd = SIGN(end);
+
+ static const qreal diff = 3;
+
+ qreal angle = path.angleAtPercent(0);
+ QCOMPARE(SIGN(angle), signStart);
+ QVERIFY(qAbs(angle-start) < diff);
+
+ angle = path.angleAtPercent(0.5);
+ QCOMPARE(SIGN(angle), signMid);
+ QVERIFY(qAbs(angle-middle) < diff);
+
+ angle = path.angleAtPercent(1);
+ QCOMPARE(SIGN(angle), signEnd);
+ QVERIFY(qAbs(angle-end) < diff);
+}
+
+void tst_QPainterPath::pointAtPercent_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<qreal>("percent");
+ QTest::addColumn<QPointF>("point");
+
+ QPainterPath path;
+ path.lineTo(100, 0);
+
+ QTest::newRow("Case 1") << path << qreal(0.2) << QPointF(20, 0);
+ QTest::newRow("Case 2") << path << qreal(0.5) << QPointF(50, 0);
+ QTest::newRow("Case 3") << path << qreal(0.0) << QPointF(0, 0);
+ QTest::newRow("Case 4") << path << qreal(1.0) << QPointF(100, 0);
+
+ path = QPainterPath();
+ path.lineTo(0, 100);
+
+ QTest::newRow("Case 5") << path << qreal(0.2) << QPointF(0, 20);
+ QTest::newRow("Case 6") << path << qreal(0.5) << QPointF(0, 50);
+ QTest::newRow("Case 7") << path << qreal(0.0) << QPointF(0, 0);
+ QTest::newRow("Case 8") << path << qreal(1.0) << QPointF(0, 100);
+
+ path.lineTo(300, 100);
+
+ QTest::newRow("Case 9") << path << qreal(0.25) << QPointF(0, 100);
+ QTest::newRow("Case 10") << path << qreal(0.5) << QPointF(100, 100);
+ QTest::newRow("Case 11") << path << qreal(0.75) << QPointF(200, 100);
+
+ path = QPainterPath();
+ path.addEllipse(0, 0, 100, 100);
+
+ QTest::newRow("Case 12") << path << qreal(0.0) << QPointF(100, 50);
+ QTest::newRow("Case 13") << path << qreal(0.25) << QPointF(50, 100);
+ QTest::newRow("Case 14") << path << qreal(0.5) << QPointF(0, 50);
+ QTest::newRow("Case 15") << path << qreal(0.75) << QPointF(50, 0);
+ QTest::newRow("Case 16") << path << qreal(1.0) << QPointF(100, 50);
+
+ path = QPainterPath();
+ QRectF rect(241, 273, 185, 228);
+ path.addEllipse(rect);
+ QTest::newRow("Case 17") << path << qreal(1.0) << QPointF(rect.right(), qreal(0.5) * (rect.top() + rect.bottom()));
+
+ path = QPainterPath();
+ path.moveTo(100, 100);
+ QTest::newRow("Case 18") << path << qreal(0.0) << QPointF(100, 100);
+ QTest::newRow("Case 19") << path << qreal(1.0) << QPointF(100, 100);
+}
+
+void tst_QPainterPath::pointAtPercent()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(qreal, percent);
+ QFETCH(QPointF, point);
+
+ QPointF result = path.pointAtPercent(percent);
+ QVERIFY(pathFuzzyCompare(point.x() , result.x()));
+ QVERIFY(pathFuzzyCompare(point.y() , result.y()));
+}
+
+void tst_QPainterPath::setElementPositionAt()
+{
+ QPainterPath path(QPointF(42., 42.));
+ QCOMPARE(path.elementCount(), 1);
+ QVERIFY(path.elementAt(0).type == QPainterPath::MoveToElement);
+ QCOMPARE(path.elementAt(0).x, qreal(42.));
+ QCOMPARE(path.elementAt(0).y, qreal(42.));
+
+ QPainterPath copy = path;
+ copy.setElementPositionAt(0, qreal(0), qreal(0));
+ QCOMPARE(copy.elementCount(), 1);
+ QVERIFY(copy.elementAt(0).type == QPainterPath::MoveToElement);
+ QCOMPARE(copy.elementAt(0).x, qreal(0));
+ QCOMPARE(copy.elementAt(0).y, qreal(0));
+
+ QCOMPARE(path.elementCount(), 1);
+ QVERIFY(path.elementAt(0).type == QPainterPath::MoveToElement);
+ QCOMPARE(path.elementAt(0).x, qreal(42.));
+ QCOMPARE(path.elementAt(0).y, qreal(42.));
+}
+
+void tst_QPainterPath::angleAtPercent()
+{
+ for (int angle = 0; angle < 360; ++angle) {
+ QLineF line = QLineF::fromPolar(100, angle);
+ QPainterPath path;
+ path.moveTo(line.p1());
+ path.lineTo(line.p2());
+
+ QCOMPARE(path.angleAtPercent(0.5), line.angle());
+ }
+}
+
+void tst_QPainterPath::arcWinding_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ QTest::addColumn<QPointF>("point");
+ QTest::addColumn<bool>("inside");
+
+ QPainterPath a;
+ a.addEllipse(0, 0, 100, 100);
+ a.addRect(50, 50, 100, 100);
+
+ QTest::newRow("Case A (oddeven)") << a << QPointF(55, 55) << false;
+ a.setFillRule(Qt::WindingFill);
+ QTest::newRow("Case A (winding)") << a << QPointF(55, 55) << true;
+
+ QPainterPath b;
+ b.arcMoveTo(0, 0, 100, 100, 10);
+ b.arcTo(0, 0, 100, 100, 10, 360);
+ b.addRect(50, 50, 100, 100);
+
+ QTest::newRow("Case B (oddeven)") << b << QPointF(55, 55) << false;
+ b.setFillRule(Qt::WindingFill);
+ QTest::newRow("Case B (winding)") << b << QPointF(55, 55) << false;
+
+ QPainterPath c;
+ c.arcMoveTo(0, 0, 100, 100, 0);
+ c.arcTo(0, 0, 100, 100, 0, 360);
+ c.addRect(50, 50, 100, 100);
+
+ QTest::newRow("Case C (oddeven)") << c << QPointF(55, 55) << false;
+ c.setFillRule(Qt::WindingFill);
+ QTest::newRow("Case C (winding)") << c << QPointF(55, 55) << false;
+
+ QPainterPath d;
+ d.arcMoveTo(0, 0, 100, 100, 10);
+ d.arcTo(0, 0, 100, 100, 10, -360);
+ d.addRect(50, 50, 100, 100);
+
+ QTest::newRow("Case D (oddeven)") << d << QPointF(55, 55) << false;
+ d.setFillRule(Qt::WindingFill);
+ QTest::newRow("Case D (winding)") << d << QPointF(55, 55) << true;
+
+ QPainterPath e;
+ e.arcMoveTo(0, 0, 100, 100, 0);
+ e.arcTo(0, 0, 100, 100, 0, -360);
+ e.addRect(50, 50, 100, 100);
+
+ QTest::newRow("Case E (oddeven)") << e << QPointF(55, 55) << false;
+ e.setFillRule(Qt::WindingFill);
+ QTest::newRow("Case E (winding)") << e << QPointF(55, 55) << true;
+}
+
+void tst_QPainterPath::arcWinding()
+{
+ QFETCH(QPainterPath, path);
+ QFETCH(QPointF, point);
+ QFETCH(bool, inside);
+
+ QCOMPARE(path.contains(point), inside);
+}
+
+void tst_QPainterPath::testToFillPolygons()
+{
+ QPainterPath path;
+ path.lineTo(QPointF(0, 50));
+ path.lineTo(QPointF(50, 50));
+
+ path.moveTo(QPointF(70, 50));
+ path.lineTo(QPointF(70, 100));
+ path.lineTo(QPointF(40, 100));
+
+ const QList<QPolygonF> polygons = path.toFillPolygons();
+ QCOMPARE(polygons.size(), 2);
+ QCOMPARE(polygons.first().count(QPointF(70, 50)), 0);
+}
+
+void tst_QPainterPath::testNaNandInfinites()
+{
+ QPainterPath path1;
+ QPainterPath path2 = path1;
+
+ QPointF p1 = QPointF(qSNaN(), 1);
+ QPointF p2 = QPointF(qQNaN(), 1);
+ QPointF p3 = QPointF(qQNaN(), 1);
+ QPointF pInf = QPointF(qInf(), 1);
+
+ // all these operations with NaN/Inf should be ignored
+ // can't test operator>> reliably, as we can't create a path with NaN to << later
+
+ path1.moveTo(p1);
+ path1.moveTo(qSNaN(), qQNaN());
+ path1.moveTo(pInf);
+
+ path1.lineTo(p1);
+ path1.lineTo(qSNaN(), qQNaN());
+ path1.lineTo(pInf);
+
+ path1.cubicTo(p1, p2, p3);
+ path1.cubicTo(p1, QPointF(1, 1), QPointF(2, 2));
+ path1.cubicTo(pInf, QPointF(10, 10), QPointF(5, 1));
+
+ path1.quadTo(p1, p2);
+ path1.quadTo(QPointF(1, 1), p3);
+ path1.quadTo(QPointF(1, 1), pInf);
+
+ path1.arcTo(QRectF(p1, p2), 5, 5);
+ path1.arcTo(QRectF(pInf, QPointF(1, 1)), 5, 5);
+
+ path1.addRect(QRectF(p1, p2));
+ path1.addRect(QRectF(pInf, QPointF(1, 1)));
+
+ path1.addEllipse(QRectF(p1, p2));
+ path1.addEllipse(QRectF(pInf, QPointF(1, 1)));
+
+ QCOMPARE(path1, path2);
+
+ path1.lineTo(QPointF(1, 1));
+ QVERIFY(path1 != path2);
+}
+
+void tst_QPainterPath::connectPathDuplicatePoint()
+{
+ QPainterPath a;
+ a.moveTo(10, 10);
+ a.lineTo(20, 20);
+
+ QPainterPath b;
+ b.moveTo(20, 20);
+ b.lineTo(30, 10);
+
+ a.connectPath(b);
+
+ QPainterPath c;
+ c.moveTo(10, 10);
+ c.lineTo(20, 20);
+ c.lineTo(30, 10);
+
+ QCOMPARE(c, a);
+}
+
+void tst_QPainterPath::connectPathMoveTo()
+{
+ QPainterPath path1;
+ QPainterPath path2;
+ QPainterPath path3;
+ QPainterPath path4;
+
+ path1.moveTo(1,1);
+
+ path2.moveTo(4,4);
+ path2.lineTo(5,6);
+ path2.lineTo(6,7);
+
+ path3.connectPath(path2);
+
+ path4.lineTo(5,5);
+
+ path1.connectPath(path2);
+
+ QVERIFY(path1.elementAt(0).type == QPainterPath::MoveToElement);
+ QVERIFY(path2.elementAt(0).type == QPainterPath::MoveToElement);
+ QVERIFY(path3.elementAt(0).type == QPainterPath::MoveToElement);
+ QVERIFY(path4.elementAt(0).type == QPainterPath::MoveToElement);
+}
+
+void tst_QPainterPath::translate()
+{
+ QPainterPath path;
+
+ // Path with no elements.
+ QCOMPARE(path.currentPosition(), QPointF());
+ path.translate(50.5, 50.5);
+ QCOMPARE(path.currentPosition(), QPointF());
+ QCOMPARE(path.translated(50.5, 50.5).currentPosition(), QPointF());
+
+ // path.isEmpty(), but we have one MoveTo element that should be translated.
+ path.moveTo(50, 50);
+ QCOMPARE(path.currentPosition(), QPointF(50, 50));
+ path.translate(99.9, 99.9);
+ QCOMPARE(path.currentPosition(), QPointF(149.9, 149.9));
+ path.translate(-99.9, -99.9);
+ QCOMPARE(path.currentPosition(), QPointF(50, 50));
+ QCOMPARE(path.translated(-50, -50).currentPosition(), QPointF(0, 0));
+
+ // Complex path.
+ QRegion shape(100, 100, 300, 200, QRegion::Ellipse);
+ shape -= QRect(225, 175, 50, 50);
+ QPainterPath complexPath;
+ complexPath.addRegion(shape);
+ QVector<QPointF> untranslatedElements;
+ for (int i = 0; i < complexPath.elementCount(); ++i)
+ untranslatedElements.append(QPointF(complexPath.elementAt(i)));
+
+ const QPainterPath untranslatedComplexPath(complexPath);
+ const QPointF offset(100, 100);
+ complexPath.translate(offset);
+
+ for (int i = 0; i < complexPath.elementCount(); ++i)
+ QCOMPARE(QPointF(complexPath.elementAt(i)) - offset, untranslatedElements.at(i));
+
+ QCOMPARE(complexPath.translated(-offset), untranslatedComplexPath);
+}
+
+
+void tst_QPainterPath::lineWithinBounds()
+{
+ const int iteration_count = 3;
+ volatile const qreal yVal = 0.5;
+ QPointF a(0.0, yVal);
+ QPointF b(1000.0, yVal);
+ QPointF c(2000.0, yVal);
+ QPointF d(3000.0, yVal);
+ QPainterPath path;
+ path.moveTo(QPointF(0, yVal));
+ path.cubicTo(QPointF(1000.0, yVal), QPointF(2000.0, yVal), QPointF(3000.0, yVal));
+ for(int i=0; i<=iteration_count; i++) {
+ qreal actual = path.pointAtPercent(qreal(i) / iteration_count).y();
+ QVERIFY(actual == yVal); // don't use QCOMPARE, don't want fuzzy comparison
+ }
+}
+
+
+QTEST_APPLESS_MAIN(tst_QPainterPath)
+
+#include "tst_qpainterpath.moc"
diff --git a/tests/auto/gui/painting/qpainterpathstroker/.gitignore b/tests/auto/gui/painting/qpainterpathstroker/.gitignore
new file mode 100644
index 0000000000..e171c5da31
--- /dev/null
+++ b/tests/auto/gui/painting/qpainterpathstroker/.gitignore
@@ -0,0 +1 @@
+tst_qpainterpathstroker
diff --git a/tests/auto/gui/painting/qpainterpathstroker/qpainterpathstroker.pro b/tests/auto/gui/painting/qpainterpathstroker/qpainterpathstroker.pro
new file mode 100644
index 0000000000..b6f62a2eee
--- /dev/null
+++ b/tests/auto/gui/painting/qpainterpathstroker/qpainterpathstroker.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qpainterpathstroker.cpp
+
+
+
diff --git a/tests/auto/gui/painting/qpainterpathstroker/tst_qpainterpathstroker.cpp b/tests/auto/gui/painting/qpainterpathstroker/tst_qpainterpathstroker.cpp
new file mode 100644
index 0000000000..288263e5d7
--- /dev/null
+++ b/tests/auto/gui/painting/qpainterpathstroker/tst_qpainterpathstroker.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qfile.h>
+#include <QPainterPathStroker>
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPainterPathStroker : public QObject
+{
+ Q_OBJECT
+
+public:
+
+private slots:
+ void strokeEmptyPath();
+};
+
+void tst_QPainterPathStroker::strokeEmptyPath()
+{
+ QPainterPath path;
+ path.moveTo(10, 10);
+ path.lineTo(10, 10);
+ QPainterPathStroker stroker;
+ QCOMPARE(stroker.createStroke(path), path);
+}
+
+QTEST_APPLESS_MAIN(tst_QPainterPathStroker)
+
+#include "tst_qpainterpathstroker.moc"
diff --git a/tests/auto/gui/painting/qpathclipper/.gitignore b/tests/auto/gui/painting/qpathclipper/.gitignore
new file mode 100644
index 0000000000..a689eef0f6
--- /dev/null
+++ b/tests/auto/gui/painting/qpathclipper/.gitignore
@@ -0,0 +1 @@
+tst_qpathclipper
diff --git a/tests/auto/gui/painting/qpathclipper/pathcompare.h b/tests/auto/gui/painting/qpathclipper/pathcompare.h
new file mode 100644
index 0000000000..d80c189665
--- /dev/null
+++ b/tests/auto/gui/painting/qpathclipper/pathcompare.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PATHCOMPARE_H
+#define PATHCOMPARE_H
+
+#include <qmath.h>
+
+namespace QPathCompare {
+
+static const int precision = 8;
+static const qreal epsilon = qPow(0.1, precision);
+
+static inline bool fuzzyIsZero(qreal x, qreal relative)
+{
+ if (qAbs(relative) < epsilon)
+ return qAbs(x) < epsilon;
+ else
+ return qAbs(x / relative) < epsilon;
+}
+
+static bool fuzzyCompare(const QPointF &a, const QPointF &b)
+{
+ const QPointF delta = a - b;
+
+ const qreal x = qMax(qAbs(a.x()), qAbs(b.x()));
+ const qreal y = qMax(qAbs(a.y()), qAbs(b.y()));
+
+ return fuzzyIsZero(delta.x(), x) && fuzzyIsZero(delta.y(), y);
+}
+
+static bool isClosed(const QPainterPath &path)
+{
+ if (path.elementCount() == 0)
+ return false;
+
+ QPointF first = path.elementAt(0);
+ QPointF last = path.elementAt(path.elementCount() - 1);
+
+ return fuzzyCompare(first, last);
+}
+
+// rotation and direction independent path comparison
+// allows paths to be shifted or reversed relative to each other
+static bool comparePaths(const QPainterPath &actual, const QPainterPath &expected)
+{
+ const int endActual = isClosed(actual) ? actual.elementCount() - 1 : actual.elementCount();
+ const int endExpected = isClosed(expected) ? expected.elementCount() - 1 : expected.elementCount();
+
+ if (endActual != endExpected)
+ return false;
+
+ for (int i = 0; i < endActual; ++i) {
+ int k = 0;
+ for (k = 0; k < endActual; ++k) {
+ int i1 = k;
+ int i2 = (i + k) % endActual;
+
+ QPointF a = actual.elementAt(i1);
+ QPointF b = expected.elementAt(i2);
+
+ if (!fuzzyCompare(a, b))
+ break;
+ }
+
+ if (k == endActual)
+ return true;
+
+ for (k = 0; k < endActual; ++k) {
+ int i1 = k;
+ int i2 = (i + endActual - k) % endActual;
+
+ QPointF a = actual.elementAt(i1);
+ QPointF b = expected.elementAt(i2);
+
+ if (!fuzzyCompare(a, b))
+ break;
+ }
+
+ if (k == endActual)
+ return true;
+ }
+
+ return false;
+}
+
+}
+
+#endif
diff --git a/tests/auto/gui/painting/qpathclipper/paths.cpp b/tests/auto/gui/painting/qpathclipper/paths.cpp
new file mode 100644
index 0000000000..950c34614e
--- /dev/null
+++ b/tests/auto/gui/painting/qpathclipper/paths.cpp
@@ -0,0 +1,734 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "paths.h"
+
+QPainterPath Paths::rect()
+{
+ QPainterPath path;
+
+ path.moveTo(45.885571, 62.857143);
+ path.lineTo(154.11442, 62.857143);
+ path.cubicTo(162.1236, 62.857143,
+ 168.57142, 70.260744,
+ 168.57142, 79.457144);
+ path.lineTo(168.57142, 123.4);
+ path.cubicTo(168.57142, 132.5964,
+ 162.1236, 140,
+ 154.11442, 140);
+ path.lineTo(45.885571, 140);
+ path.cubicTo(37.876394, 140,
+ 31.428572, 132.5964,
+ 31.428572, 123.4);
+ path.lineTo(31.428572, 79.457144);
+ path.cubicTo(31.428572,70.260744,
+ 37.876394,62.857143,
+ 45.885571,62.857143);
+ path.closeSubpath();
+ return path;
+}
+
+QPainterPath Paths::rect6()
+{
+ QPainterPath path;
+
+ path.moveTo(45.885571, 62.857143);
+ path.lineTo(154.11442, 62.857143);
+ path.cubicTo(162.1236, 62.857143,
+ 168.57142, 70.260744,
+ 168.57142, 79.457144);
+ path.lineTo(168.57142, 123.4);
+ path.cubicTo(168.57142, 132.5964,
+ 162.1236, 140,
+ 154.11442, 140);
+ path.lineTo(45.885571, 140);
+ path.closeSubpath();
+ return path;
+}
+
+
+QPainterPath Paths::heart()
+{
+ QPainterPath path;
+ path.moveTo(263.41570, 235.14588);
+ path.cubicTo(197.17570,235.14588,
+ 143.41575,288.90587,
+ 143.41575,355.14588);
+ path.cubicTo(143.41575, 489.90139,
+ 279.34890, 525.23318,
+ 371.97820, 658.45392);
+ path.cubicTo(459.55244,526.05056,
+ 600.54070,485.59932,
+ 600.54070,355.14588);
+ path.cubicTo(600.54070,288.90588, 546.78080,235.14587, 480.54070,235.14588);
+ path.cubicTo(432.49280,235.14588, 391.13910,263.51631, 371.97820,304.33338);
+ path.cubicTo(352.81740,263.51630, 311.46370,235.14587, 263.41570,235.14588);
+ path.closeSubpath();
+ return path;
+}
+
+
+QPainterPath Paths::body()
+{
+ QPainterPath path;
+ path.moveTo(62.500000,15.531250);
+ path.cubicTo(48.633197,15.531250, 37.374999,26.789445, 37.375000,40.656250);
+ path.cubicTo(37.375000,54.523053, 48.633195,65.781252, 62.500000,65.781250);
+ path.cubicTo(76.366803,65.781250, 87.624998,54.523052, 87.625000,40.656250);
+ path.cubicTo(87.625000,26.789447, 76.366802,15.531250, 62.500000,15.531250);
+ path.closeSubpath();
+ path.moveTo(54.437500,65.812500);
+ path.cubicTo(35.184750,65.812499, 19.687500,81.341002, 19.687500,100.59375);
+ path.lineTo(19.687500,155.68750);
+ path.cubicTo(19.687501,167.50351, 25.539122,177.88308, 34.500000,184.15625);
+ path.lineTo(34.500000,254.03125);
+ path.cubicTo(34.499999,257.03306, 46.990615,259.43748, 62.500000,259.43750);
+ path.cubicTo(78.009381,259.43751, 90.468750,257.03307, 90.468750,254.03125);
+ path.lineTo(90.468750,184.15625);
+ path.cubicTo(99.429633,177.88307, 105.28125,167.50352, 105.28125,155.68750);
+ path.lineTo(105.28125,100.59375);
+ path.cubicTo(105.28125,81.341000, 89.784000,65.812500, 70.531250,65.812500);
+ path.lineTo(54.437500,65.812500);
+ path.closeSubpath();
+
+ return path;
+}
+
+
+QPainterPath Paths::mailbox()
+{
+ QPainterPath path;
+ path.moveTo(355.22951,136.82424);
+ path.lineTo(332.03629,112.56585);
+ path.lineTo(325.71086,57.501867);
+ path.cubicTo(325.71086,57.501867, 410.12308,19.428758, 427.45202,29.094560);
+ path.cubicTo(444.78096,38.760366, 443.62570,54.289660, 443.62570,54.289660);
+ path.lineTo(443.62570,100.11509);
+ path.lineTo(355.22951,136.82424);
+ path.closeSubpath();
+
+ return path;
+}
+
+
+QPainterPath Paths::deer()
+{
+ QPainterPath path;
+
+ path.moveTo(39.88,31.658);
+ path.cubicTo(35.632,31.658, 31.398,31.004, 27.871,32.82);
+ path.cubicTo(25.015,34.29, 19.608,34.158, 16.297,34.158);
+ path.cubicTo(14.722,34.158, 17.755,37.718, 17.709,38.922);
+ path.cubicTo(17.578,42.396, 24.612,43.15, 26.755,44.058);
+ path.cubicTo(30.062,45.46, 28.682,47.701, 28.963,50.574);
+ path.cubicTo(29.715,58.243, 26.887,63.745, 24.182,70.589);
+ path.cubicTo(23.365,72.657, 21.772,75.56, 21.972,77.866);
+ path.cubicTo(22.333,82.029, 15.803,77.207, 13.894,76.535);
+ path.cubicTo(10.977,75.508, 5.507,74.071, 2.424,75.331);
+ path.cubicTo(-1.532,76.947, 0.076,80.491, 2.169,82.806);
+ path.cubicTo(6.17,87.234, 2.703,90.713, 3.895,95.363);
+ path.cubicTo(4.321,97.026, 11.682,104.683, 12.858,103.668);
+ path.cubicTo(16.706,100.347, 11.464,98.692, 10.105,96.164);
+ path.cubicTo(9.487,95.015, 8.616,83.742, 8.866,83.759);
+ path.cubicTo(10.018,83.837, 12.591,85.867, 13.671,86.392);
+ path.cubicTo(16.889,87.954, 20.066,89.63, 22.963,91.741);
+ path.cubicTo(29.156,94.47, 35.543,96.965, 42.102,98.676);
+ path.cubicTo(51.085,101.02, 59.407,102.003, 68.009,106.005);
+ path.cubicTo(72.92,108.289, 72.05,113.282, 75.744,117.004);
+ path.cubicTo(79.422,120.709, 84.733,123.053, 88.978,126.053);
+ path.cubicTo(92.402,128.473, 95.422,132.308, 97.334,135.998);
+ path.cubicTo(99.551,140.279, 99.071,146.004, 99.838,150.674);
+ path.cubicTo(100.369,153.91, 104.378,156.321, 106.302,158.859);
+ path.cubicTo(110.471,164.355, 109.86,155.112, 108.163,154.412);
+ path.cubicTo(104.97,153.094, 103.991,146.625, 103.812,143.439);
+ path.cubicTo(103.525,138.336, 105.568,134.331, 101.918,130.346);
+ path.cubicTo(95.104,122.907, 89.488,114.182, 94.711,103.742);
+ path.cubicTo(96.889,99.388, 91.191,95.497, 96.94,94.368);
+ path.cubicTo(99.551,93.856, 102.49,94.367, 104.326,92.034);
+ path.cubicTo(106.639,89.095, 105.063,85.343, 102.943,82.798);
+ path.cubicTo(102.686,82.417, 102.359,82.121, 101.962,81.909);
+ path.cubicTo(102.331,81.909, 101.923,86.98, 100.981,87.628);
+ path.cubicTo(98.868,89.082, 95.569,91.586, 92.88,91.672);
+ path.cubicTo(90.569,91.745, 86.738,89.184, 85.212,87.658);
+ path.cubicTo(84.092,86.538, 80.176,86.157, 78.598,85.83);
+ path.cubicTo(74.737,85.031, 71.741,84.326, 68.012,82.806);
+ path.cubicTo(63.318,80.893, 58.687,78.672, 54.555,75.71);
+ path.cubicTo(44.573,68.555, 42.755,56.146, 44.022,44.495);
+ path.cubicTo(44.295,41.987, 43.169,38.057, 44.617,35.915);
+ path.cubicTo(44.961,35.406, 46.52,35.553, 47.119,35.024);
+ path.cubicTo(47.882,34.35, 49.574,31.822, 49.878,30.792);
+ path.cubicTo(51.126,26.569, 44.36,32.002, 45.336,31.938);
+ path.cubicTo(43.861,32.036, 47.011,22.934, 47.191,22.574);
+ path.cubicTo(47.555,21.846, 52.489,13.123, 49.511,13.222);
+ path.cubicTo(47.643,13.284, 48.563,18.667, 46.354,18.227);
+ path.cubicTo(43.964,17.751, 40.522,11.396, 41.566,9.011);
+ path.cubicTo(43.4,4.819, 39.743,3.905, 39.214,7.564);
+ path.cubicTo(39.112,8.269, 40.893,13.438, 38.159,12.665);
+ path.cubicTo(35.335,11.866, 35.748,-0.125, 34.38,-8.0352391e-15);
+ path.cubicTo(31.991,0.219, 34.074,10.836, 33.361,12.176);
+ path.cubicTo(33.144,12.584, 29.68,8.66, 29.459,7.718);
+ path.cubicTo(28.48,3.558, 28.031,5.106, 26.87,7.752);
+ path.cubicTo(25.333,11.254, 37.159,17.423, 39.292,18.663);
+ path.cubicTo(40.993,19.651, 42.39,20.504, 42.973,22.48);
+ path.cubicTo(43.482,24.205, 44.098,26.568, 42.926,28.191);
+ path.cubicTo(42.092,29.346, 39.88,29.982, 39.88,31.658);
+ return path;
+}
+
+
+QPainterPath Paths::fire()
+{
+ QPainterPath path;
+
+ path.moveTo(362.83759,116.70426);
+ path.cubicTo(342.56574,131.59686, 300.71403,161.23127, 311.38454,218.12635);
+ path.cubicTo(322.05506,275.02144, 358.53432,301.66527, 328.90674,328.73285);
+ path.cubicTo(299.27916,355.80044, 251.48877,339.59410, 255.46042,288.61972);
+ path.cubicTo(258.22374,253.15368, 278.34141,205.10942, 278.34141,205.10942);
+ path.cubicTo(278.34141,205.10942, 234.02455,233.13427, 219.68939,254.01270);
+ path.cubicTo(205.35424,274.89113, 189.71452,330.07842, 208.58356,373.33974);
+ path.cubicTo(227.45261,416.60109, 316.46286,456.33444, 351.12048,514.32780);
+ path.cubicTo(374.10258,552.78425, 355.05815,613.59741, 310.80422,636.59310);
+ path.cubicTo(256.63287,664.74219, 299.16588,580.49238, 285.22551,523.86186);
+ path.cubicTo(273.46790,476.09839, 265.70022,445.12001, 188.03132,432.51681);
+ path.cubicTo(233.72591,465.34901, 242.16068,495.04075, 241.45928,524.11772);
+ path.cubicTo(240.78648,552.00862, 214.39595,634.57293, 177.39967,596.79021);
+ path.cubicTo(140.72642,559.33737, 214.27071,512.68654, 170.92945,471.62081);
+ path.cubicTo(174.73284,501.40284, 145.30515,514.98828, 131.55318,544.54392);
+ path.cubicTo(118.22673,573.18509, 123.55251,610.30651, 139.07596,645.41379);
+ path.cubicTo(181.14122,740.38745, 266.95518,726.23964, 208.75321,797.88229);
+ path.cubicTo(164.01134,852.95649, 162.90150,907.45084, 205.60384,970.81121);
+ path.cubicTo(240.06795,1021.9479, 371.11663,1060.7652, 432.20697,960.93460);
+ path.cubicTo(501.87852,820.00694, 357.14883,780.33174, 386.29974,732.84721);
+ path.cubicTo(405.70205,701.24238, 472.56601,668.86516, 501.09199,644.21233);
+ path.cubicTo(564.18184,587.55421, 561.84437,497.32621, 522.74229,471.25817);
+ path.cubicTo(530.19030,501.05022, 514.99952,542.79339, 483.67099,551.29691);
+ path.cubicTo(423.41173,567.65308, 458.18351,411.79373, 564.02075,393.61925);
+ path.cubicTo(530.91135,366.44998, 501.31413,367.33484, 454.91711,379.11707);
+ path.cubicTo(397.61736,393.57908, 407.64322,315.40944, 494.34643,262.67861);
+ path.cubicTo(549.19500,229.32101, 499.11573,147.63302, 491.66772,136.46100);
+ path.cubicTo(485.38713,213.93294, 435.43515,233.35601, 409.98053,235.72292);
+ path.cubicTo(375.27049,238.95043, 377.84554,214.33812, 396.75003,178.92950);
+ path.cubicTo(416.21172,142.47722, 448.15395,89.429942, 376.51366,44.060977);
+ path.cubicTo(388.13560,71.270572, 395.93673,94.012962, 362.83759,116.70426);
+ path.closeSubpath();
+ return path;
+}
+
+
+QPainterPath Paths::lips()
+{
+ QPainterPath path;
+
+ path.moveTo(177.02257,176.65905);
+ path.cubicTo(154.11895,176.65905, 136.56711,174.32266, 110.41800,155.61729);
+ path.cubicTo(83.894106,136.64382, 70.456540,123.78263, 44.264608,101.00195);
+ path.cubicTo(36.985036,94.670475, 11.607987,76.421189, 0.62503194,72.562763);
+ path.cubicTo(22.778258,60.937514, 46.738237,46.430325, 55.325084,40.325054);
+ path.cubicTo(79.128700,23.400628, 99.203004,0.53294656, 116.15033,0.61582047);
+ path.cubicTo(129.59137,0.68308215, 144.54744,18.524567, 177.02257,18.524567);
+ path.cubicTo(210.04060,18.524567, 224.45379,0.68308215, 237.89483,0.61582047);
+ path.cubicTo(254.84216,0.53294656, 274.91646,23.400628, 298.72008,40.325054);
+ path.cubicTo(307.30692,46.430325, 331.26690,60.937514, 353.42013,72.562763);
+ path.cubicTo(342.43717,76.421189, 317.06013,94.670475, 309.78055,101.00195);
+ path.cubicTo(283.58862,123.78263, 270.15105,136.64382, 243.62716,155.61729);
+ path.cubicTo(217.47805,174.32266, 199.38332,176.65905, 177.02257,176.65905);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::bezier1()
+{
+ QPainterPath path;
+ path.moveTo(50, 50);
+ path.cubicTo(100, 100,
+ 520, 90,
+ 400,400);
+ return path;
+}
+
+QPainterPath Paths::bezier2()
+{
+ QPainterPath path;
+ path.moveTo(200,200);
+ path.cubicTo(200,125, 500,100, 500,500);
+
+ return path;
+}
+
+QPainterPath Paths::random1()
+{
+ QPainterPath path;
+
+ path.moveTo(65.714286,91.428571);
+ path.lineTo(217.14286, 102.85714);
+ path.cubicTo(219.04762, 106.66666,
+ 220.95238, 110.47619,
+ 222.85714,114.28571);
+ path.cubicTo(231.2679, 131.10723,
+ 214.72525, 138.24185,
+ 211.42857,151.42857);
+ path.cubicTo(207.25902, 168.10676,
+ 213.24674, 175.8441,
+ 217.14286,191.42857);
+ path.cubicTo(221.088, 207.20915,
+ 201.21538,205.71429,
+ 188.57143,205.71429);
+ path.cubicTo(170.18303, 205.71429,
+ 161.42918, 197.50045,
+ 145.71429,185.71429);
+ path.cubicTo(113.93441, 161.87938,
+ 132.73699, 182.37652,
+ 137.14286, 200);
+ path.cubicTo(140.37884, 212.94392,
+ 128.50252, 217.16009,
+ 117.14286, 220);
+ path.cubicTo(98.323209, 224.70491,
+ 91.206108, 205.41767,
+ 82.857143, 194.28571);
+ path.cubicTo(77.307286, 186.8859,
+ 84.541768, 158.97578,
+ 85.714286, 154.28571);
+ path.cubicTo(87.843677, 145.76815,
+ 67.066253, 132.78054,
+ 60 , 125.71429);
+ path.cubicTo(54.074503, 119.78879,
+ 64.646395, 95.700137,
+ 65.714286, 91.428571);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::random2()
+{
+ QPainterPath path;
+
+ path.moveTo(314.28571,160);
+ path.cubicTo(434.28571,125.71429,
+ 505.71429,200,
+ 505.71429,200);
+ path.lineTo(454.28571, 305.71429);
+ path.lineTo(337.14286, 302.85714);
+ path.cubicTo(337.14286, 302.85714,
+ 308.57143, 340,
+ 337.14286, 302.85714);
+ path.cubicTo(365.71429, 265.71429,
+ 200, 420,
+ 300, 291.42857);
+ path.cubicTo(400, 162.85714,
+ 254.28571, 240,
+ 254.28571, 240);
+ path.cubicTo(254.28571,240,
+ 240,71.428571,
+ 288.57143,134.28571);
+ path.cubicTo(337.14286,197.14286,
+ 314.28571,162.85714,
+ 314.28571,160);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::bezier3()
+{
+ QPainterPath path;
+ path.moveTo(295, 217);
+ path.cubicTo(364, 57,
+ 377, 34,
+ 456, 222);
+ return path;
+}
+
+QPainterPath Paths::bezier4()
+{
+ QPainterPath path;
+ path.moveTo(200, 125);
+ path.cubicTo(200, 125,
+ 623, 126,
+ 623, 126);
+ return path;
+}
+
+QPainterPath Paths::heart2()
+{
+ QPainterPath path;
+ path.moveTo(263.41570, 235.14588);
+ path.cubicTo(197.17570,235.14588,
+ 143.41575,288.90587,
+ 143.41575,355.14588);
+ path.cubicTo(143.41575, 489.90139,
+ 279.34890, 525.23318,
+ 371.97820, 658.45392);
+ return path;
+}
+
+QPainterPath Paths::rect2()
+{
+ QPainterPath path;
+
+ path.addRect(80, 80, 100, 100);
+
+ return path;
+}
+
+
+QPainterPath Paths::rect3()
+{
+ QPainterPath path;
+
+ path.addRect(100, 40, 100, 100);
+
+ return path;
+}
+
+
+QPainterPath Paths::rect4()
+{
+ QPainterPath path;
+
+ path.addRect(100, 0, 200, 200);
+
+ path.addRect(120, 20, 80, 80);
+
+ return path;
+}
+
+QPainterPath Paths::simpleCurve()
+{
+ QPainterPath path;
+ path.moveTo(74, 160);
+ path.cubicTo( 74, 160,
+ 274, 406,
+ 425, 166);
+ path.cubicTo(577, -73,
+ 77, 160,
+ 74, 160);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::simpleCurve2()
+{
+ QPainterPath path;
+ path.moveTo(54, 140);
+ path.cubicTo( 54, 140,
+ 254, 386,
+ 405, 146);
+ path.cubicTo(557, -93,
+ 57, 140,
+ 54, 140);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::frame1()
+{
+ QPainterPath path;
+ path.moveTo(190.71429, 40.933613);
+ path.lineTo(683.57141, 40.933613);
+ path.cubicTo(697.42141, 40.933613,
+ 708.57141, 52.083613,
+ 708.57141, 65.933613);
+ path.lineTo(708.57141, 375.93361);
+ path.cubicTo(708.57141, 389.78361,
+ 697.42141, 400.93361,
+ 683.57141, 400.93361);
+ path.lineTo(190.71429, 400.93361);
+ path.cubicTo(176.86429, 400.93361,
+ 165.71429, 389.78361,
+ 165.71429,375.93361);
+ path.lineTo(165.71429, 65.933613);
+ path.cubicTo(165.71429,52.083613,
+ 176.86429,40.933613,
+ 190.71429,40.933613);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::frame2()
+{
+ QPainterPath path;
+ path.moveTo(55.114286, 103.79076);
+ path.lineTo(187.74288, 103.79076);
+ path.cubicTo(192.95048, 103.79076,
+ 197.14288, 107.88102,
+ 197.14288, 112.96176);
+ path.lineTo(197.14288, 131.76261);
+ path.cubicTo(197.14288, 136.84335,
+ 192.95048, 140.93361,
+ 187.74288, 140.93361);
+ path.lineTo(55.114286, 140.93361);
+ path.cubicTo(49.906687, 140.93361,
+ 45.714287, 136.84335,
+ 45.714287, 131.76261);
+ path.lineTo(45.714287, 112.96176);
+ path.cubicTo(45.714287, 107.88102,
+ 49.906687, 103.79076,
+ 55.114286, 103.79076);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::frame3()
+{
+ QPainterPath path;
+ path.moveTo(200,80.933609);
+ path.lineTo(682.85715,80.933609);
+ path.lineTo(682.85715,446.6479);
+ path.lineTo(200,446.6479);
+ path.lineTo(200,80.933609);
+ path.closeSubpath();
+ return path;
+}
+
+QPainterPath Paths::frame4()
+{
+ QPainterPath path;
+
+ path.moveTo(88.571434,206.64789);
+ path.lineTo(231.42858,206.64789);
+ path.lineTo(231.42858,246.64789);
+ path.lineTo(88.571434,246.64789);
+ path.lineTo(88.571434,206.64789);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::simpleCurve3()
+{
+ QPainterPath path;
+
+ path.moveTo(0, 0);
+ path.cubicTo(400,0,
+ 0,400,
+ 0,0);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::rect5()
+{
+ QPainterPath path;
+
+ path.addRect(0, 0, 200, 200);
+
+ return path;
+}
+
+QPainterPath Paths::triangle1()
+{
+ QPainterPath path;
+
+ path.moveTo(0, 0);
+ path.lineTo(60, 0);
+ path.lineTo(60, 60);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::triangle2()
+{
+ QPainterPath path;
+
+ path.moveTo(0, 120);
+ path.lineTo(60, 120);
+ path.lineTo(60, 60);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::node()
+{
+ QRectF m_rect;
+ m_rect.setWidth(150);
+ m_rect.setHeight(100);
+
+ QPainterPath shape;
+ shape.addRoundRect(m_rect, 25);
+
+ const int conWidth = 10;
+ const int xOffset = 7;
+
+ QRectF rect(xOffset,
+ conWidth + 20,
+ conWidth, conWidth);
+ shape.addEllipse(rect);
+ //shape.addRect(rect);
+
+ rect = QRectF(m_rect.right() - conWidth - xOffset,
+ conWidth + 20,
+ conWidth, conWidth);
+ shape.addEllipse(rect);
+ //shape.addRect(rect);
+ return shape;
+}
+
+QPainterPath Paths::interRect()
+{
+ QPainterPath path;
+ path.addRect(132, 42, 1, 1);
+ return path;
+}
+
+QPainterPath Paths::bezierFlower()
+{
+ QPainterPath path;
+ path.moveTo(0, 0);
+ path.cubicTo(0, 50, -25, 75, -50, 100);
+ path.closeSubpath();
+ path.moveTo(0, 0);
+ path.cubicTo(0, 50, 25, 75, 50, 100);
+ path.closeSubpath();
+
+ path.moveTo(0, 0);
+ path.cubicTo(0, -50, -25, -75, -50, -100);
+ path.closeSubpath();
+ path.moveTo(0, 0);
+ path.cubicTo(0, -50, 25, -75, 50, -100);
+ path.closeSubpath();
+
+ path.moveTo(0, 0);
+ path.cubicTo(-50, 0, -75, -25, -100, -50);
+ path.closeSubpath();
+ path.moveTo(0, 0);
+ path.cubicTo(-50, 0, -75, 25, -100, 50);
+ path.closeSubpath();
+
+ path.moveTo(0, 0);
+ path.cubicTo(50, 0, 75, -25, 100, -50);
+ path.closeSubpath();
+ path.moveTo(0, 0);
+ path.cubicTo(50, 0, 75, 25, 100, 50);
+ path.closeSubpath();
+
+ return path;
+}
+
+QPainterPath Paths::clover()
+{
+ QPainterPath path;
+ path.moveTo(50, 50);
+ path.lineTo(100, 25);
+ path.lineTo(100, 75);
+ path.lineTo(0, 25);
+ path.lineTo(0, 75);
+ path.lineTo(50, 50);
+ path.lineTo(75, 0);
+ path.lineTo(25, 0);
+ path.lineTo(75, 100);
+ path.lineTo(25, 100);
+ path.lineTo(50, 50);
+ return path;
+}
+
+QPainterPath Paths::ellipses()
+{
+ QPainterPath path;
+ path.addEllipse(0, 0, 100, 100);
+ path.addEllipse(0, 20, 100, 60);
+ path.addEllipse(0, 40, 100, 20);
+ return path;
+}
+
+QPainterPath Paths::windingFill()
+{
+ QPainterPath path;
+ path.addRect(0, 0, 100, 100);
+ path.addRect(50, 25, 100, 50);
+ path.setFillRule(Qt::WindingFill);
+ return path;
+}
+
+QPainterPath Paths::oddEvenFill()
+{
+ QPainterPath path;
+ path.addRect(0, 0, 100, 100);
+ path.moveTo(50, 25);
+ path.lineTo(50, 75);
+ path.lineTo(150, 75);
+ path.lineTo(150, 25);
+ path.lineTo(50, 25);
+ path.setFillRule(Qt::OddEvenFill);
+ return path;
+}
+
+QPainterPath Paths::squareWithHole()
+{
+ QPainterPath path;
+ path.addRect(0, 0, 100, 100);
+ path.addRect(30, 30, 40, 40);
+ return path;
+}
+
+QPainterPath Paths::circleWithHole()
+{
+ QPainterPath path;
+ path.addEllipse(0, 0, 100, 100);
+ path.addEllipse(30, 30, 40, 40);
+ return path;
+}
+
+QPainterPath Paths::bezierQuadrant()
+{
+ QPainterPath path;
+ int d = 1;
+ for (int i = 25; i <= 85; i += 10) {
+ path.moveTo(50, 100);
+ path.cubicTo(50, i, 50 + i* d / 2, 0, 50 + 50 * d, 0);
+ path.lineTo(50 + 50 * d, 100);
+ path.closeSubpath();
+ }
+
+ QMatrix m(2, 0,
+ 0, 2,
+ 0, 0);
+
+ return path;
+}
diff --git a/tests/auto/gui/painting/qpathclipper/paths.h b/tests/auto/gui/painting/qpathclipper/paths.h
new file mode 100644
index 0000000000..89ef785857
--- /dev/null
+++ b/tests/auto/gui/painting/qpathclipper/paths.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PATHS_H
+#define PATHS_H
+
+#include <QPainterPath>
+
+namespace Paths
+{
+ QPainterPath rect();
+ QPainterPath heart();
+ QPainterPath body();
+ QPainterPath mailbox();
+ QPainterPath deer();
+ QPainterPath fire();
+ QPainterPath lips();
+
+ QPainterPath bezier1();
+ QPainterPath bezier2();
+ QPainterPath bezier3();
+ QPainterPath bezier4();
+
+ QPainterPath random1();
+ QPainterPath random2();
+
+ QPainterPath heart2();
+ QPainterPath rect2();
+ QPainterPath rect3();
+ QPainterPath rect4();
+ QPainterPath rect5();
+ QPainterPath rect6();
+
+ QPainterPath simpleCurve();
+ QPainterPath simpleCurve2();
+ QPainterPath simpleCurve3();
+
+ QPainterPath frame1();
+ QPainterPath frame2();
+ QPainterPath frame3();
+ QPainterPath frame4();
+
+ QPainterPath triangle1();
+ QPainterPath triangle2();
+
+ QPainterPath node();
+ QPainterPath interRect();
+
+ QPainterPath bezierFlower();
+ QPainterPath clover();
+ QPainterPath ellipses();
+ QPainterPath windingFill();
+ QPainterPath oddEvenFill();
+ QPainterPath squareWithHole();
+ QPainterPath circleWithHole();
+ QPainterPath bezierQuadrant();
+}
+#endif
diff --git a/tests/auto/gui/painting/qpathclipper/qpathclipper.pro b/tests/auto/gui/painting/qpathclipper/qpathclipper.pro
new file mode 100644
index 0000000000..2becd7dd03
--- /dev/null
+++ b/tests/auto/gui/painting/qpathclipper/qpathclipper.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+INCLUDEPATH += .
+HEADERS += paths.h
+SOURCES += tst_qpathclipper.cpp paths.cpp
+QT += gui-private
+
+requires(contains(QT_CONFIG,private_tests))
+
+unix:!mac:!symbian:LIBS+=-lm
+
+
diff --git a/tests/auto/gui/painting/qpathclipper/tst_qpathclipper.cpp b/tests/auto/gui/painting/qpathclipper/tst_qpathclipper.cpp
new file mode 100644
index 0000000000..57a56b2d1a
--- /dev/null
+++ b/tests/auto/gui/painting/qpathclipper/tst_qpathclipper.cpp
@@ -0,0 +1,1334 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "private/qpathclipper_p.h"
+#include "paths.h"
+#include "pathcompare.h"
+
+#include <QtTest/QtTest>
+
+#include <qpainterpath.h>
+#include <qpolygon.h>
+#include <qdebug.h>
+#include <qpainter.h>
+
+#include <math.h>
+
+class tst_QPathClipper : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPathClipper();
+ virtual ~tst_QPathClipper();
+
+private:
+ void clipTest(int subjectIndex, int clipIndex, QPathClipper::Operation op);
+
+ QList<QPainterPath> paths;
+
+public slots:
+ void initTestCase();
+
+private slots:
+ void testWingedEdge();
+
+ void testComparePaths();
+
+ void clip_data();
+ void clip();
+
+ void clip2();
+ void clip3();
+
+ void testIntersections();
+ void testIntersections2();
+ void testIntersections3();
+ void testIntersections4();
+ void testIntersections5();
+ void testIntersections6();
+ void testIntersections7();
+ void testIntersections8();
+ void testIntersections9();
+
+ void zeroDerivativeCurves();
+
+ void task204301_data();
+ void task204301();
+
+ void task209056();
+ void task251909();
+
+ void qtbug3778();
+};
+
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPathClipper::Operation)
+
+tst_QPathClipper::tst_QPathClipper()
+{
+}
+
+tst_QPathClipper::~tst_QPathClipper()
+{
+}
+
+void tst_QPathClipper::initTestCase()
+{
+ paths << Paths::rect();
+ paths << Paths::heart();
+ paths << Paths::body();
+ paths << Paths::mailbox();
+ paths << Paths::deer();
+ paths << Paths::fire();
+
+ paths << Paths::random1();
+ paths << Paths::random2();
+
+ paths << Paths::heart2();
+ paths << Paths::rect2();
+ paths << Paths::rect3();
+ paths << Paths::rect4();
+ paths << Paths::rect5();
+ paths << Paths::rect6();
+
+ paths << Paths::frame1();
+ paths << Paths::frame2();
+ paths << Paths::frame3();
+ paths << Paths::frame4();
+
+ paths << Paths::triangle1();
+ paths << Paths::triangle2();
+
+ paths << Paths::node();
+ paths << Paths::interRect();
+
+ paths << Paths::simpleCurve();
+ paths << Paths::simpleCurve2();
+ paths << Paths::simpleCurve3();
+
+ paths << Paths::bezier1();
+ paths << Paths::bezier2();
+ paths << Paths::bezier3();
+ paths << Paths::bezier4();
+
+ paths << Paths::bezierFlower();
+ paths << Paths::lips();
+ paths << Paths::clover();
+ paths << Paths::ellipses();
+ paths << Paths::windingFill();
+ paths << Paths::oddEvenFill();
+ paths << Paths::squareWithHole();
+ paths << Paths::circleWithHole();
+ paths << Paths::bezierQuadrant();
+
+ // make sure all the bounding rects are centered at the origin
+ for (int i = 0; i < paths.size(); ++i) {
+ QRectF bounds = paths[i].boundingRect();
+
+ QMatrix m(1, 0,
+ 0, 1,
+ -bounds.center().x(), -bounds.center().y());
+
+ paths[i] = m.map(paths[i]);
+ }
+}
+
+static QPainterPath samplePath1()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(200, 246.64789));
+ path.lineTo(QPointF(200, 206.64789));
+ path.lineTo(QPointF(231.42858, 206.64789));
+ path.lineTo(QPointF(231.42858, 246.64789));
+ path.lineTo(QPointF(200, 246.64789));
+ return path;
+}
+
+static QPainterPath samplePath2()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(200, 146.64789));
+ path.lineTo(QPointF(200, 106.64789));
+ path.lineTo(QPointF(231.42858, 106.64789));
+ path.lineTo(QPointF(231.42858, 146.64789));
+ path.lineTo(QPointF(200, 146.64789));
+ return path;
+}
+
+static QPainterPath samplePath3()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(231.42858, 80.933609));
+ path.lineTo(QPointF(200, 80.933609));
+ path.lineTo(QPointF(200, 96.64788999999999));
+ path.lineTo(QPointF(231.42858, 96.64788999999999));
+ path.lineTo(QPointF(231.42858, 80.933609));
+ return path;
+}
+
+static QPainterPath samplePath4()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(288.571434, 80.933609));
+ path.lineTo(QPointF(431.42858, 80.933609));
+ path.lineTo(QPointF(431.42858, 96.64788999999999));
+ path.lineTo(QPointF(288.571434, 96.64788999999999));
+ path.lineTo(QPointF(288.571434, 80.933609));
+ return path;
+}
+
+static QPainterPath samplePath5()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(588.571434, 80.933609));
+ path.lineTo(QPointF(682.85715, 80.933609));
+ path.lineTo(QPointF(682.85715, 96.64788999999999));
+ path.lineTo(QPointF(588.571434, 96.64788999999999));
+ path.lineTo(QPointF(588.571434, 80.933609));
+ return path;
+}
+
+static QPainterPath samplePath6()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(588.571434, 80.933609));
+ path.lineTo(QPointF(200, 80.933609));
+ path.lineTo(QPointF(200, 446.6479));
+ path.lineTo(QPointF(682.85715, 446.6479));
+ path.lineTo(QPointF(682.85715, 96.64788999999999));
+ path.lineTo(QPointF(731.42858, 96.64788999999999));
+ path.lineTo(QPointF(731.42858, 56.64788999999999));
+ path.lineTo(QPointF(588.571434, 56.64788999999999));
+ path.lineTo(QPointF(588.571434, 80.933609));
+ return path;
+}
+
+static QPainterPath samplePath7()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(682.85715, 206.64789));
+ path.lineTo(QPointF(682.85715, 246.64789));
+ path.lineTo(QPointF(588.571434, 246.64789));
+ path.lineTo(QPointF(588.571434, 206.64789));
+ path.lineTo(QPointF(682.85715, 206.64789));
+ return path;
+}
+
+static QPainterPath samplePath8()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(682.85715, 406.64789));
+ path.lineTo(QPointF(682.85715, 446.64789));
+ path.lineTo(QPointF(588.571434, 446.64789));
+ path.lineTo(QPointF(588.571434, 406.64789));
+ path.lineTo(QPointF(682.85715, 406.64789));
+ return path;
+}
+
+static QPainterPath samplePath9()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(682.85715, 426.64789));
+ path.lineTo(QPointF(682.85715, 446.6479));
+ path.lineTo(QPointF(568.571434, 446.6479));
+ path.lineTo(QPointF(568.571434, 426.64789));
+ path.lineTo(QPointF(682.85715, 426.64789));
+ return path;
+}
+
+static QPainterPath samplePath10()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(511.42858, 446.6479));
+ path.lineTo(QPointF(368.571434, 446.6479));
+ path.lineTo(QPointF(368.571434, 426.64789));
+ path.lineTo(QPointF(511.42858, 426.64789));
+ path.lineTo(QPointF(511.42858, 446.6479));
+ return path;
+}
+
+static QPainterPath samplePath13()
+{
+ QPainterPath path;
+ path.moveTo(QPointF(160, 200));
+ path.lineTo(QPointF(100, 200));
+ path.lineTo(QPointF(100, 130));
+ path.lineTo(QPointF(160, 130));
+ path.lineTo(QPointF(160, 200));
+ return path;
+}
+
+static QPainterPath samplePath14()
+{
+ QPainterPath path;
+
+ path.moveTo(160, 80);
+ path.lineTo(160, 180);
+ path.lineTo(100, 180);
+ path.lineTo(100, 80);
+ path.lineTo(160, 80);
+ path.moveTo(160, 80);
+ path.lineTo(160, 100);
+ path.lineTo(120, 100);
+ path.lineTo(120, 80);
+
+ return path;
+}
+
+void tst_QPathClipper::clip_data()
+{
+ //create the testtable instance and define the elements
+ QTest::addColumn<QPainterPath>("subject");
+ QTest::addColumn<QPainterPath>("clip");
+ QTest::addColumn<QPathClipper::Operation>("op");
+ QTest::addColumn<QPainterPath>("result");
+
+ //next we fill it with data
+ QTest::newRow( "simple1" ) << Paths::frame3()
+ << Paths::frame4()
+ << QPathClipper::BoolAnd
+ << samplePath1();
+
+ QTest::newRow( "simple2" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(0, -100)
+ << QPathClipper::BoolAnd
+ << samplePath2();
+
+ QTest::newRow( "simple3" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(0, -150)
+ << QPathClipper::BoolAnd
+ << samplePath3();
+
+ QTest::newRow( "simple4" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(200, -150)
+ << QPathClipper::BoolAnd
+ << samplePath4();
+
+ QTest::newRow( "simple5" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(500, -150)
+ << QPathClipper::BoolAnd
+ << samplePath5();
+
+ QTest::newRow( "simple6" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(500, -150)
+ << QPathClipper::BoolOr
+ << samplePath6();
+
+ QTest::newRow( "simple7" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(500, 0)
+ << QPathClipper::BoolAnd
+ << samplePath7();
+
+ QTest::newRow( "simple8" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(500, 200)
+ << QPathClipper::BoolAnd
+ << samplePath8();
+
+ QTest::newRow( "simple9" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(480, 220)
+ << QPathClipper::BoolAnd
+ << samplePath9();
+
+ QTest::newRow( "simple10" ) << Paths::frame3()
+ << Paths::frame4() * QTransform().translate(280, 220)
+ << QPathClipper::BoolAnd
+ << samplePath10();
+
+ QTest::newRow( "simple_move_to1" ) << Paths::rect4()
+ << Paths::rect2() * QTransform().translate(-20, 50)
+ << QPathClipper::BoolAnd
+ << samplePath13();
+
+ QTest::newRow( "simple_move_to2" ) << Paths::rect4()
+ << Paths::rect2() * QTransform().translate(-20, 0)
+ << QPathClipper::BoolAnd
+ << samplePath14();
+}
+
+// sanity check to make sure comparePaths declared above works
+void tst_QPathClipper::testComparePaths()
+{
+ QPainterPath a;
+ QPainterPath b;
+
+ a.addRect(0, 0, 10, 10);
+ b.addRect(0, 0, 10.00001, 10.00001);
+
+ QVERIFY(!QPathCompare::comparePaths(a, b));
+
+ b = QPainterPath();
+ b.addRect(0, 0, 10.00000000001, 10.00000000001);
+
+ QVERIFY(QPathCompare::comparePaths(a, b));
+
+ b = QPainterPath();
+ b.moveTo(10, 0);
+ b.lineTo(0, 0);
+ b.lineTo(0, 10);
+ b.lineTo(10, 10);
+
+ QVERIFY(QPathCompare::comparePaths(a, b));
+ b.lineTo(10, 0);
+ QVERIFY(QPathCompare::comparePaths(a, b));
+
+ b = QPainterPath();
+ b.moveTo(10, 0);
+ b.lineTo(0, 10);
+ b.lineTo(0, 0);
+ b.lineTo(10, 10);
+
+ QVERIFY(!QPathCompare::comparePaths(a, b));
+}
+
+void tst_QPathClipper::clip()
+{
+ if (sizeof(double) != sizeof(qreal)) {
+ QSKIP("This test only works for qreal=double, otherwise ends in rounding errors", SkipAll);
+ }
+ QFETCH( QPainterPath, subject );
+ QFETCH( QPainterPath, clip );
+ QFETCH( QPathClipper::Operation, op );
+ QFETCH( QPainterPath, result);
+ QPathClipper clipper(subject, clip);
+ QPainterPath x = clipper.clip(op);
+
+ QVERIFY(QPathCompare::comparePaths(x, result));
+}
+
+static inline QPointF randomPointInRect(const QRectF &rect)
+{
+ qreal rx = qrand() / (RAND_MAX + 1.);
+ qreal ry = qrand() / (RAND_MAX + 1.);
+
+ return QPointF(rect.left() + rx * rect.width(),
+ rect.top() + ry * rect.height());
+}
+
+void tst_QPathClipper::clipTest(int subjectIndex, int clipIndex, QPathClipper::Operation op)
+{
+ const QPainterPath &subject = paths[subjectIndex];
+ const QPainterPath &clip = paths[clipIndex];
+ const int count = 40;
+
+ QRectF bounds = subject.boundingRect().united(clip.boundingRect());
+
+ const qreal adjustX = bounds.width() * 0.01;
+ const qreal adjustY = bounds.height() * 0.01;
+
+ // make sure we test some points that are outside both paths as well
+ bounds = bounds.adjusted(-adjustX, -adjustY, adjustX, adjustY);
+
+ const int dim = 256;
+ const qreal scale = qMin(dim / bounds.width(), dim / bounds.height());
+
+ QPathClipper clipper(subject, clip);
+ QPainterPath result = clipper.clip(op);
+
+ // using the image here is a bit of a hacky way to make sure we don't test points that
+ // are too close to the path edges to avoid test fails that are due to numerical errors
+ QImage img(dim, dim, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+ QPainter p(&img);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.scale(scale, scale);
+ p.translate(-bounds.topLeft());
+ p.setPen(Qt::black);
+ p.drawPath(subject);
+ p.setPen(Qt::red);
+ p.drawPath(clip);
+ p.end();
+
+ for (int i = 0; i < count; ++i) {
+ QPointF point;
+ QRgb pixel;
+ do {
+ point = randomPointInRect(bounds);
+ const QPointF imagePoint = (point - bounds.topLeft()) * scale;
+
+ pixel = img.pixel(int(imagePoint.x()), int(imagePoint.y()));
+ } while (qAlpha(pixel) > 0);
+
+ const bool inSubject = subject.contains(point);
+ const bool inClip = clip.contains(point);
+
+ const bool inResult = result.contains(point);
+
+ bool expected = false;
+ switch (op) {
+ case QPathClipper::BoolAnd:
+ expected = inSubject && inClip;
+ break;
+ case QPathClipper::BoolOr:
+ expected = inSubject || inClip;
+ break;
+ case QPathClipper::BoolSub:
+ expected = inSubject && !inClip;
+ break;
+ default:
+ break;
+ }
+
+ if (expected != inResult) {
+ char str[256];
+ const char *opStr =
+ op == QPathClipper::BoolAnd ? "and" :
+ op == QPathClipper::BoolOr ? "or" : "sub";
+ sprintf(str, "Expected: %d, actual: %d, subject: %d, clip: %d, op: %s\n",
+ int(expected), int(inResult), subjectIndex, clipIndex, opStr);
+
+ // debugging
+#if 0
+ QRect rect = bounds.toAlignedRect();
+
+ QPainter p(&img);
+ p.scale(scale, scale);
+ p.translate(-bounds.topLeft());
+
+ p.setPen(Qt::NoPen);
+ p.setBrush(QColor(0x700ff00));
+ p.drawPath(result);
+
+ p.setPen(Qt::blue);
+ p.drawPoint(point);
+ p.end();
+
+ char str2[256];
+ sprintf(str2, "fail-%d-%d-%s.png", subjectIndex, clipIndex, opStr);
+ img.save(str2);
+#endif
+ QFAIL(str);
+ }
+ }
+}
+
+void tst_QPathClipper::clip2()
+{
+ if (sizeof(double) != sizeof(qreal))
+ QSKIP("This test only works for qreal=double, otherwise ends in rounding errors", SkipAll);
+
+ int operation = 0;
+
+ for (int i = 0; i < paths.size(); ++i) {
+ for (int j = 0; j <= i; ++j) {
+ QPathClipper::Operation op = QPathClipper::Operation((operation++) % 3);
+ clipTest(i, j, op);
+ }
+ }
+}
+
+void tst_QPathClipper::clip3()
+{
+ int operation = 0;
+
+ // this subset should work correctly for qreal = float
+ for (int i = 0; i < 20; ++i) {
+ for (int j = 0; j <= i; ++j) {
+ QPathClipper::Operation op = QPathClipper::Operation((operation++) % 3);
+ clipTest(i, j, op);
+ }
+ }
+}
+
+void tst_QPathClipper::testIntersections()
+{
+ QPainterPath path1;
+ QPainterPath path2;
+
+ path1.addRect(0, 0, 100, 100);
+ path2.addRect(20, 20, 20, 20);
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+ QVERIFY(path1.contains(path2));
+ QVERIFY(!path2.contains(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addEllipse(0, 0, 100, 100);
+ path2.addEllipse(200, 200, 100, 100);
+ QVERIFY(!path1.intersects(path2));
+ QVERIFY(!path2.intersects(path1));
+ QVERIFY(!path1.contains(path2));
+ QVERIFY(!path2.contains(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addEllipse(0, 0, 100, 100);
+ path2.addEllipse(50, 50, 100, 100);
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+ QVERIFY(!path1.contains(path2));
+ QVERIFY(!path2.contains(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(100, 100, 100, 100);
+ path2.addRect(50, 100, 100, 20);
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+ QVERIFY(!path1.contains(path2));
+ QVERIFY(!path2.contains(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(100, 100, 100, 100);
+ path2.addRect(110, 201, 100, 20);
+ QVERIFY(!path1.intersects(path2));
+ QVERIFY(!path2.intersects(path1));
+ QVERIFY(!path1.contains(path2));
+ QVERIFY(!path2.contains(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(0, 0, 100, 100);
+ path2.addRect(20, 20, 20, 20);
+ path2.addRect(25, 25, 5, 5);
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+ QVERIFY(path1.contains(path2));
+ QVERIFY(!path2.contains(path1));
+}
+
+void tst_QPathClipper::testIntersections2()
+{
+ QPainterPath path1;
+ QPainterPath path2;
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+
+ path1.moveTo(-8,-8);
+ path1.lineTo(107,-8);
+ path1.lineTo(107,107);
+ path1.lineTo(-8,107);
+
+ path2.moveTo(0,0);
+ path2.lineTo(100,0);
+ path2.lineTo(100,100);
+ path2.lineTo(0,100);
+ path2.lineTo(0,0);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+ QVERIFY(path1.contains(path2));
+ QVERIFY(!path2.contains(path1));
+
+ path1.closeSubpath();
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+ QVERIFY(path1.contains(path2));
+ QVERIFY(!path2.contains(path1));
+}
+
+void tst_QPathClipper::testIntersections3()
+{
+ QPainterPath path1 = Paths::node();
+ QPainterPath path2 = Paths::interRect();
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+}
+
+void tst_QPathClipper::testIntersections4()
+{
+ QPainterPath path1;
+ QPainterPath path2;
+
+ path1.moveTo(-5, 0);
+ path1.lineTo(5, 0);
+
+ path2.moveTo(0, -5);
+ path2.lineTo(0, 5);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+}
+
+void tst_QPathClipper::testIntersections5()
+{
+ QPainterPath path1;
+ QPainterPath path2;
+
+ path1.addRect(0, 0, 4, 4);
+ path1.addRect(2, 1, 1, 1);
+ path2.addRect(0.5, 2, 1, 1);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+}
+
+void tst_QPathClipper::testIntersections6()
+{
+ QPainterPath path1;
+ QPainterPath path2;
+
+ path1.moveTo(QPointF(-115.567, -98.3254));
+ path1.lineTo(QPointF(-45.9007, -98.3254));
+ path1.lineTo(QPointF(-45.9007, -28.6588));
+ path1.lineTo(QPointF(-115.567, -28.6588));
+
+ path2.moveTo(QPointF(-110, -110));
+ path2.lineTo(QPointF(110, -110));
+ path2.lineTo(QPointF(110, 110));
+ path2.lineTo(QPointF(-110, 110));
+ path2.lineTo(QPointF(-110, -110));
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+}
+
+
+void tst_QPathClipper::testIntersections7()
+{
+ QPainterPath path1;
+ QPainterPath path2;
+
+ path1.addRect(0, 0, 10, 10);
+ path2.addRect(5, 0, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(0, 0, 10, 10);
+ path2.addRect(0, 5, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(0, 0, 10, 10);
+ path2.addRect(0, 0, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ ///
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(1, 1, 10, 10);
+ path2.addRect(5, 1, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(1, 1, 10, 10);
+ path2.addRect(1, 5, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(1, 1, 10, 10);
+ path2.addRect(1, 1, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(1, 1, 10, 10);
+ path2.addRect(5, 5, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(1, 1, 10, 10);
+ path2.addRect(9, 9, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(1, 1, 10, 10);
+ path2.addRect(10, 10, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(1, 1, 9, 9);
+ path2.addRect(11, 11, 10, 10);
+
+ QVERIFY(!path1.intersects(path2));
+ QVERIFY(!path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(1, 1, 10, 10);
+ path2.addRect(12, 12, 10, 10);
+
+ QVERIFY(!path1.intersects(path2));
+ QVERIFY(!path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(11, 11, 10, 10);
+ path2.addRect(12, 12, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();
+ path2 = QPainterPath();
+ path1.addRect(11, 11, 10, 10);
+ path2.addRect(10, 10, 10, 10);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+}
+
+
+void tst_QPathClipper::testIntersections8()
+{
+ QPainterPath path1 = Paths::node() * QTransform().translate(100, 50);
+ QPainterPath path2 = Paths::node() * QTransform().translate(150, 50);;
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = Paths::node();
+ path2 = Paths::node();
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = Paths::node();
+ path2 = Paths::node() * QTransform().translate(0, 30);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = Paths::node();
+ path2 = Paths::node() * QTransform().translate(30, 0);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = Paths::node();
+ path2 = Paths::node() * QTransform().translate(30, 30);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = Paths::node();
+ path2 = Paths::node() * QTransform().translate(1, 1);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+}
+
+
+void tst_QPathClipper::testIntersections9()
+{
+ QPainterPath path1;
+ QPainterPath path2;
+
+ path1.addRect(QRectF(-1,143, 146, 106));
+ path2.addRect(QRectF(-9,145, 150, 100));
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();;
+ path2 = QPainterPath();
+
+ path1.addRect(QRectF(-1,191, 136, 106));
+ path2.addRect(QRectF(-19,194, 150, 100));
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+
+ path1 = QPainterPath();;
+ path2 = QPainterPath();
+
+ path1.moveTo(-1 , 143);
+ path1.lineTo(148 , 143);
+ path1.lineTo(148 , 250);
+ path1.lineTo(-1 , 250);
+
+ path2.moveTo(-5 , 146);
+ path2.lineTo(145 , 146);
+ path2.lineTo(145 , 246);
+ path2.lineTo(-5 , 246);
+ path2.lineTo(-5 , 146);
+
+ QVERIFY(path1.intersects(path2));
+ QVERIFY(path2.intersects(path1));
+}
+
+QPainterPath pathFromRect(qreal x, qreal y, qreal w, qreal h)
+{
+ QPainterPath path;
+ path.addRect(QRectF(x, y, w, h));
+ return path;
+}
+
+QPainterPath pathFromLine(qreal x1, qreal y1, qreal x2, qreal y2)
+{
+ QPainterPath path;
+ path.moveTo(x1, y1);
+ path.lineTo(x2, y2);
+ return path;
+}
+
+static int loopLength(const QWingedEdge &list, QWingedEdge::TraversalStatus status)
+{
+ int start = status.edge;
+
+ int length = 0;
+ do {
+ ++length;
+ status = list.next(status);
+ } while (status.edge != start);
+
+ return length;
+}
+
+void tst_QPathClipper::testWingedEdge()
+{
+ {
+ QWingedEdge list;
+ int e1 = list.addEdge(QPointF(0, 0), QPointF(10, 0));
+ int e2 = list.addEdge(QPointF(0, 0), QPointF(0, 10));
+ int e3 = list.addEdge(QPointF(0, 0), QPointF(-10, 0));
+ int e4 = list.addEdge(QPointF(0, 0), QPointF(0, -10));
+
+ QCOMPARE(list.edgeCount(), 4);
+ QCOMPARE(list.vertexCount(), 5);
+
+ QWingedEdge::TraversalStatus status = { e1, QPathEdge::RightTraversal, QPathEdge::Forward };
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e1);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e4);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e4);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e3);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e3);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e2);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e2);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e1);
+ }
+ {
+ QWingedEdge list;
+ int e1 = list.addEdge(QPointF(5, 0), QPointF(5, 10));
+ int e2 = list.addEdge(QPointF(5, 0), QPointF(10, 5));
+ int e3 = list.addEdge(QPointF(10, 5), QPointF(5, 10));
+ int e4 = list.addEdge(QPointF(5, 0), QPointF(0, 5));
+ int e5 = list.addEdge(QPointF(0, 5), QPointF(5, 10));
+
+ QCOMPARE(list.edgeCount(), 5);
+ QCOMPARE(list.vertexCount(), 4);
+
+ QWingedEdge::TraversalStatus status = { e1, QPathEdge::RightTraversal, QPathEdge::Forward };
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e5);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e4);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e1);
+
+ QCOMPARE(loopLength(list, status), 3);
+
+ status.flip();
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(loopLength(list, status), 3);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e2);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e3);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e1);
+
+ status = list.next(status);
+ status.flip();
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e2);
+ QCOMPARE(loopLength(list, status), 4);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e4);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Forward);
+ QCOMPARE(status.traversal, QPathEdge::RightTraversal);
+ QCOMPARE(status.edge, e5);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e3);
+
+ status = list.next(status);
+ QCOMPARE(status.direction, QPathEdge::Backward);
+ QCOMPARE(status.traversal, QPathEdge::LeftTraversal);
+ QCOMPARE(status.edge, e2);
+ }
+ {
+ QPainterPath path = pathFromRect(0, 0, 20, 20);
+ QWingedEdge list(path, QPainterPath());
+
+ QCOMPARE(list.edgeCount(), 4);
+ QCOMPARE(list.vertexCount(), 4);
+
+ QWingedEdge::TraversalStatus status = { 0, QPathEdge::RightTraversal, QPathEdge::Forward };
+
+ QPathEdge *edge = list.edge(status.edge);
+ QCOMPARE(QPointF(*list.vertex(edge->first)), QPointF(0, 0));
+ QCOMPARE(QPointF(*list.vertex(edge->second)), QPointF(20, 0));
+
+ status = list.next(status);
+ QCOMPARE(status.edge, 1);
+
+ status = list.next(status);
+ QCOMPARE(status.edge, 2);
+
+ status = list.next(status);
+ QCOMPARE(status.edge, 3);
+
+ status = list.next(status);
+ QCOMPARE(status.edge, 0);
+
+ status.flipDirection();
+ status = list.next(status);
+ QCOMPARE(status.edge, 3);
+
+ status = list.next(status);
+ QCOMPARE(status.edge, 2);
+
+ status = list.next(status);
+ QCOMPARE(status.edge, 1);
+
+ status = list.next(status);
+ QCOMPARE(status.edge, 0);
+
+ QWingedEdge list2(path, pathFromRect(10, 5, 20, 10));
+
+ QCOMPARE(list2.edgeCount(), 12);
+ QCOMPARE(list2.vertexCount(), 10);
+
+ status.flipDirection();
+ QCOMPARE(loopLength(list2, status), 8);
+
+ status = list2.next(status);
+ edge = list2.edge(status.edge);
+ QCOMPARE(QPointF(*list2.vertex(edge->first)), QPointF(20, 0));
+ QCOMPARE(QPointF(*list2.vertex(edge->second)), QPointF(20, 5));
+
+ status = list2.next(status);
+ status.flipTraversal();
+
+ edge = list2.edge(status.edge);
+ QCOMPARE(QPointF(*list2.vertex(edge->first)), QPointF(10, 5));
+ QCOMPARE(QPointF(*list2.vertex(edge->second)), QPointF(20, 5));
+
+ QCOMPARE(loopLength(list2, status), 4);
+
+ status.flipDirection();
+ status = list2.next(status);
+ status.flipTraversal();
+
+ edge = list2.edge(status.edge);
+ QCOMPARE(QPointF(*list2.vertex(edge->first)), QPointF(20, 5));
+ QCOMPARE(QPointF(*list2.vertex(edge->second)), QPointF(20, 15));
+
+ QCOMPARE(loopLength(list2, status), 4);
+ status = list2.next(status);
+ status = list2.next(status);
+
+ edge = list2.edge(status.edge);
+ QCOMPARE(QPointF(*list2.vertex(edge->first)), QPointF(30, 5));
+ QCOMPARE(QPointF(*list2.vertex(edge->second)), QPointF(30, 15));
+ }
+}
+
+void tst_QPathClipper::zeroDerivativeCurves()
+{
+ // zero derivative at end
+ {
+ QPainterPath a;
+ a.cubicTo(100, 0, 100, 100, 100, 100);
+ a.lineTo(100, 200);
+ a.lineTo(0, 200);
+
+ QPainterPath b;
+ b.moveTo(50, 100);
+ b.lineTo(150, 100);
+ b.lineTo(150, 150);
+ b.lineTo(50, 150);
+
+ QPainterPath c = a.united(b);
+ QVERIFY(c.contains(QPointF(25, 125)));
+ QVERIFY(c.contains(QPointF(75, 125)));
+ QVERIFY(c.contains(QPointF(125, 125)));
+ }
+
+ // zero derivative at start
+ {
+ QPainterPath a;
+ a.cubicTo(100, 0, 100, 100, 100, 100);
+ a.lineTo(100, 200);
+ a.lineTo(0, 200);
+
+ QPainterPath b;
+ b.moveTo(50, 100);
+ b.lineTo(150, 100);
+ b.lineTo(150, 150);
+ b.lineTo(50, 150);
+
+ QPainterPath c = a.united(b);
+ QVERIFY(c.contains(QPointF(25, 125)));
+ QVERIFY(c.contains(QPointF(75, 125)));
+ QVERIFY(c.contains(QPointF(125, 125)));
+ }
+}
+
+static bool strictContains(const QPainterPath &a, const QPainterPath &b)
+{
+ return b.subtracted(a) == QPainterPath();
+}
+
+Q_DECLARE_METATYPE(QPolygonF)
+
+void tst_QPathClipper::task204301_data()
+{
+ QTest::addColumn<QPolygonF>("points");
+
+ {
+ QPointF a(51.09013255685567855835, 31.30814891308546066284);
+ QPointF b(98.39898971840739250183, 11.02079074829816818237);
+ QPointF c(91.23911846894770860672, 45.86981737054884433746);
+ QPointF d(66.58616356085985898972, 63.10526528395712375641);
+ QPointF e(82.08219456479714892794, 94.90238165489137145414);
+ QPointF f(16.09013040543221251255, 105.66263409332729850121);
+ QPointF g(10.62811442650854587555, 65.09154842235147953033);
+ QPointF h(5.16609844751656055450, 24.52046275138854980469);
+ QPolygonF v;
+ v << a << b << c << d << e << f << g << h;
+ QTest::newRow("failed_on_linux") << v;
+ }
+
+ {
+ QPointF a(50.014648437500000, 24.392089843750000);
+ QPointF b(92.836303710937500, 5.548706054687500);
+ QPointF c(92.145690917968750, 54.390258789062500);
+ QPointF d(65.402221679687500, 74.345092773437500);
+ QPointF e(80.789794921787347, 124.298095703129690);
+ QPointF f(34.961242675812954, 87.621459960852135);
+ QPointF g(18.305969238281250, 57.426757812500000);
+ QPointF h(1.650695800781250, 27.232055664062500);
+ QPolygonF v;
+ v << a << b << c << d << e << f << g << h;
+ QTest::newRow("failed_on_windows") << v;
+ }
+}
+
+void tst_QPathClipper::task204301()
+{
+ QFETCH(QPolygonF, points);
+
+ QPointF a = points[0];
+ QPointF b = points[1];
+ QPointF c = points[2];
+ QPointF d = points[3];
+ QPointF e = points[4];
+ QPointF f = points[5];
+ QPointF g = points[6];
+ QPointF h = points[7];
+
+ QPainterPath subA;
+ subA.addPolygon(QPolygonF() << a << b << c << d);
+ subA.closeSubpath();
+
+ QPainterPath subB;
+ subB.addPolygon(QPolygonF() << f << e << d << g);
+ subB.closeSubpath();
+
+ QPainterPath subC;
+ subC.addPolygon(QPolygonF() << h << a << d << g);
+ subC.closeSubpath();
+
+ QPainterPath path;
+ path.addPath(subA);
+ path.addPath(subB);
+ path.addPath(subC);
+
+ QPainterPath simplified = path.simplified();
+
+ QVERIFY(strictContains(simplified, subA));
+ QVERIFY(strictContains(simplified, subB));
+ QVERIFY(strictContains(simplified, subC));
+}
+
+void tst_QPathClipper::task209056()
+{
+ QPainterPath p1;
+ p1.moveTo( QPointF(188.506, 287.793) );
+ p1.lineTo( QPointF(288.506, 287.793) );
+ p1.lineTo( QPointF(288.506, 387.793) );
+ p1.lineTo( QPointF(188.506, 387.793) );
+ p1.lineTo( QPointF(188.506, 287.793) );
+
+ QPainterPath p2;
+ p2.moveTo( QPointF(419.447, 164.383) );
+ p2.cubicTo( QPointF(419.447, 69.5486), QPointF(419.447, 259.218),QPointF(419.447, 164.383) );
+
+ p2.cubicTo( QPointF(48.9378, 259.218), QPointF(131.879, 336.097),QPointF(234.192, 336.097) );
+ p2.cubicTo( QPointF(336.506, 336.097), QPointF(419.447, 259.218),QPointF(419.447, 164.383) );
+
+ QPainterPath p3 = p1.intersected(p2);
+
+ QVERIFY(p3 != QPainterPath());
+}
+
+void tst_QPathClipper::task251909()
+{
+ QPainterPath p1;
+ p1.moveTo(0, -10);
+ p1.lineTo(10, -10);
+ p1.lineTo(10, 0);
+ p1.lineTo(0, 0);
+
+ QPainterPath p2;
+ p2.moveTo(0, 8e-14);
+ p2.lineTo(10, -8e-14);
+ p2.lineTo(10, 10);
+ p2.lineTo(0, 10);
+
+ QPainterPath result = p1.united(p2);
+
+ QVERIFY(result.elementCount() <= 5);
+}
+
+void tst_QPathClipper::qtbug3778()
+{
+ if (sizeof(double) != sizeof(qreal)) {
+ QSKIP("This test only works for qreal=double, otherwise ends in rounding errors", SkipAll);
+ }
+ QPainterPath path1;
+ path1.moveTo(200, 3.22409e-5);
+ // e-5 and higher leads to a bug
+ // Using 3.22409e-4 starts to work correctly
+ path1.lineTo(0, 0);
+ path1.lineTo(1.07025e-13, 1450);
+ path1.lineTo(750, 950);
+ path1.lineTo(950, 750);
+ path1.lineTo(200, 3.22409e-13);
+
+ QPainterPath path2;
+ path2.moveTo(0, 0);
+ path2.lineTo(200, 800);
+ path2.lineTo(600, 1500);
+ path2.lineTo(1500, 1400);
+ path2.lineTo(1900, 1200);
+ path2.lineTo(2000, 1000);
+ path2.lineTo(1400, 0);
+ path2.lineTo(0, 0);
+
+ QPainterPath p12 = path1.intersected(path2);
+
+ QVERIFY(p12.contains(QPointF(100, 100)));
+}
+
+QTEST_APPLESS_MAIN(tst_QPathClipper)
+
+
+#include "tst_qpathclipper.moc"
diff --git a/tests/auto/gui/painting/qpen/.gitignore b/tests/auto/gui/painting/qpen/.gitignore
new file mode 100644
index 0000000000..a9187367dc
--- /dev/null
+++ b/tests/auto/gui/painting/qpen/.gitignore
@@ -0,0 +1 @@
+tst_qpen
diff --git a/tests/auto/gui/painting/qpen/qpen.pro b/tests/auto/gui/painting/qpen/qpen.pro
new file mode 100644
index 0000000000..53bd5e2b6e
--- /dev/null
+++ b/tests/auto/gui/painting/qpen/qpen.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qpen.cpp
+
+
+
diff --git a/tests/auto/gui/painting/qpen/tst_qpen.cpp b/tests/auto/gui/painting/qpen/tst_qpen.cpp
new file mode 100644
index 0000000000..64d725bc50
--- /dev/null
+++ b/tests/auto/gui/painting/qpen/tst_qpen.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include "qpen.h"
+#include "qbrush.h"
+
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPen : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPen();
+
+private slots:
+ void getSetCheck();
+ void swap();
+ void operator_eq_eq();
+ void operator_eq_eq_data();
+
+ void stream();
+ void stream_data();
+
+ void constructor();
+ void constructor_data();
+};
+
+// Testing get/set functions
+void tst_QPen::getSetCheck()
+{
+ QPen obj1;
+ // qreal QPen::miterLimit()
+ // void QPen::setMiterLimit(qreal)
+ obj1.setMiterLimit(0.0);
+ QCOMPARE(0.0, obj1.miterLimit());
+ obj1.setMiterLimit(qreal(1.1));
+ QCOMPARE(qreal(1.1), obj1.miterLimit());
+
+ // qreal QPen::widthF()
+ // void QPen::setWidthF(qreal)
+ obj1.setWidthF(0.0);
+ QCOMPARE(0.0, obj1.widthF());
+ obj1.setWidthF(qreal(1.1));
+ QCOMPARE(qreal(1.1), obj1.widthF());
+
+ // int QPen::width()
+ // void QPen::setWidth(int)
+ for (int i = 0; i < 100; ++i) {
+ obj1.setWidth(i);
+ QCOMPARE(i, obj1.width());
+ }
+}
+
+void tst_QPen::swap()
+{
+ QPen p1(Qt::black), p2(Qt::white);
+ p1.swap(p2);
+ QCOMPARE(p1.color(), QColor(Qt::white));
+ QCOMPARE(p2.color(), QColor(Qt::black));
+}
+
+Q_DECLARE_METATYPE(QPen)
+Q_DECLARE_METATYPE(QBrush)
+
+tst_QPen::tst_QPen()
+
+{
+}
+
+void tst_QPen::operator_eq_eq_data()
+{
+ QTest::addColumn<QPen>("pen1");
+ QTest::addColumn<QPen>("pen2");
+ QTest::addColumn<bool>("isEqual");
+
+ QTest::newRow("differentColor") << QPen(Qt::red)
+ << QPen(Qt::blue)
+ << bool(FALSE);
+ QTest::newRow("differentWidth") << QPen(Qt::red, 2)
+ << QPen(Qt::red, 3)
+ << bool(FALSE);
+ QTest::newRow("differentPenStyle") << QPen(Qt::red, 2, Qt::DashLine)
+ << QPen(Qt::red, 2, Qt::DotLine)
+ << bool(FALSE);
+ QTest::newRow("differentCapStyle") << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::BevelJoin)
+ << QPen(Qt::red, 2, Qt::DashLine, Qt::SquareCap, Qt::BevelJoin)
+ << bool(FALSE);
+ QTest::newRow("differentJoinStyle") << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::BevelJoin)
+ << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::MiterJoin)
+ << bool(FALSE);
+ QTest::newRow("same") << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::BevelJoin)
+ << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::BevelJoin)
+ << bool(TRUE);
+
+}
+
+void tst_QPen::operator_eq_eq()
+{
+ QFETCH(QPen, pen1);
+ QFETCH(QPen, pen2);
+ QFETCH(bool, isEqual);
+ QCOMPARE(pen1 == pen2, isEqual);
+}
+
+
+void tst_QPen::constructor_data()
+{
+ QTest::addColumn<QPen>("pen");
+ QTest::addColumn<QBrush>("brush");
+ QTest::addColumn<double>("width");
+ QTest::addColumn<int>("style");
+ QTest::addColumn<int>("capStyle");
+ QTest::addColumn<int>("joinStyle");
+
+ QTest::newRow("solid_black") << QPen() << QBrush(Qt::black) << 0. << (int)Qt::SolidLine
+ << (int) Qt::SquareCap << (int)Qt::BevelJoin;
+ QTest::newRow("solid_red") << QPen(Qt::red) << QBrush(Qt::red) << 0. << (int)Qt::SolidLine
+ << (int)Qt::SquareCap << (int)Qt::BevelJoin;
+ QTest::newRow("full") << QPen(QBrush(QLinearGradient(0, 0, 100, 100)), 10,
+ Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin)
+ << QBrush(QLinearGradient(0, 0, 100, 100)) << 10. << (int)Qt::SolidLine
+ << (int)Qt::RoundCap << (int)Qt::MiterJoin;
+
+}
+
+
+void tst_QPen::constructor()
+{
+ QFETCH(QPen, pen);
+ QFETCH(QBrush, brush);
+ QFETCH(double, width);
+ QFETCH(int, style);
+ QFETCH(int, capStyle);
+ QFETCH(int, joinStyle);
+
+ QCOMPARE(pen.style(), Qt::PenStyle(style));
+ QCOMPARE(pen.capStyle(), Qt::PenCapStyle(capStyle));
+ QCOMPARE(pen.joinStyle(), Qt::PenJoinStyle(joinStyle));
+ QCOMPARE(pen.widthF(), width);
+ QCOMPARE(pen.brush(), brush);
+}
+
+
+void tst_QPen::stream_data()
+{
+ QTest::addColumn<QPen>("pen");
+
+ QTest::newRow("solid_black") << QPen();
+ QTest::newRow("solid_red") << QPen(Qt::red);
+ QTest::newRow("full") << QPen(QBrush(QLinearGradient(0, 0, 100, 100)), 10, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin);
+}
+
+
+void tst_QPen::stream()
+{
+ QFETCH(QPen, pen);
+
+ QByteArray bytes;
+
+ {
+ QDataStream stream(&bytes, QIODevice::WriteOnly);
+ stream << pen;
+ }
+
+ QPen cmp;
+ {
+ QDataStream stream(&bytes, QIODevice::ReadOnly);
+ stream >> cmp;
+ }
+
+ QCOMPARE(pen.widthF(), cmp.widthF());
+ QCOMPARE(pen.style(), cmp.style());
+ QCOMPARE(pen.capStyle(), cmp.capStyle());
+ QCOMPARE(pen.joinStyle(), cmp.joinStyle());
+ QCOMPARE(pen.brush(), cmp.brush());
+
+ QCOMPARE(pen, cmp);
+}
+
+QTEST_APPLESS_MAIN(tst_QPen)
+#include "tst_qpen.moc"
diff --git a/tests/auto/gui/painting/qpolygon/.gitignore b/tests/auto/gui/painting/qpolygon/.gitignore
new file mode 100644
index 0000000000..7c9d48c848
--- /dev/null
+++ b/tests/auto/gui/painting/qpolygon/.gitignore
@@ -0,0 +1 @@
+tst_qpointarray
diff --git a/tests/auto/gui/painting/qpolygon/qpolygon.pro b/tests/auto/gui/painting/qpolygon/qpolygon.pro
new file mode 100644
index 0000000000..186b704d17
--- /dev/null
+++ b/tests/auto/gui/painting/qpolygon/qpolygon.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qpolygon.cpp
+
+unix:!mac:!symbian:LIBS+=-lm
+
+
diff --git a/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp b/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp
new file mode 100644
index 0000000000..f47073a048
--- /dev/null
+++ b/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qpolygon.h>
+#include <qpainterpath.h>
+#include <math.h>
+
+#include <qpainter.h>
+#include <qdialog.h>
+
+
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/painting/qpolygon.h gui/painting/qpolygon.cpp
+
+class tst_QPolygon : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPolygon();
+
+private slots:
+ void makeEllipse();
+ void swap();
+};
+
+tst_QPolygon::tst_QPolygon()
+{
+}
+
+void tst_QPolygon::makeEllipse()
+{
+ // create an ellipse with R1 = R2 = R, i.e. a circle
+ QPolygon pa;
+ const int R = 50; // radius
+ QPainterPath path;
+ path.addEllipse(0, 0, 2*R, 2*R);
+ pa = path.toSubpathPolygons().at(0).toPolygon();
+
+ int i;
+ // make sure that all points are R+-1 away from the center
+ bool err = FALSE;
+ for (i = 1; i < pa.size(); i++) {
+ QPoint p = pa.at( i );
+ double r = sqrt( pow( double(p.x() - R), 2.0 ) + pow( double(p.y() - R), 2.0 ) );
+ // ### too strict ? at least from visual inspection it looks
+ // quite odd around the main axes. 2.0 passes easily.
+ err |= ( qAbs( r - double(R) ) > 2.0 );
+ }
+ QVERIFY( !err );
+}
+
+void tst_QPolygon::swap()
+{
+ QPolygon p1(QVector<QPoint>() << QPoint(0,0) << QPoint(10,10) << QPoint(-10,10));
+ QPolygon p2(QVector<QPoint>() << QPoint(0,0) << QPoint( 0,10) << QPoint( 10,10) << QPoint(10,0));
+ p1.swap(p2);
+ QCOMPARE(p1.count(),4);
+ QCOMPARE(p2.count(),3);
+}
+
+QTEST_APPLESS_MAIN(tst_QPolygon)
+#include "tst_qpolygon.moc"
diff --git a/tests/auto/gui/painting/qprinter/.gitignore b/tests/auto/gui/painting/qprinter/.gitignore
new file mode 100644
index 0000000000..85de0e9675
--- /dev/null
+++ b/tests/auto/gui/painting/qprinter/.gitignore
@@ -0,0 +1,4 @@
+tqpluginloader/st_qprinter
+silly
+test.pdf
+
diff --git a/tests/auto/gui/painting/qprinter/qprinter.pro b/tests/auto/gui/painting/qprinter/qprinter.pro
new file mode 100644
index 0000000000..cbe4ad7986
--- /dev/null
+++ b/tests/auto/gui/painting/qprinter/qprinter.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += printsupport widgets
+SOURCES += tst_qprinter.cpp
+
+mac*:CONFIG+=insignificant_test
diff --git a/tests/auto/gui/painting/qprinter/tst_qprinter.cpp b/tests/auto/gui/painting/qprinter/tst_qprinter.cpp
new file mode 100644
index 0000000000..a6b6895981
--- /dev/null
+++ b/tests/auto/gui/painting/qprinter/tst_qprinter.cpp
@@ -0,0 +1,1044 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <qprinter.h>
+#include <qpagesetupdialog.h>
+#include <qpainter.h>
+#include <qprintdialog.h>
+#include <qprinterinfo.h>
+#include <qvariant.h>
+#include <qpainter.h>
+#include <qprintengine.h>
+
+#include <math.h>
+
+#ifdef Q_WS_WIN
+#include <windows.h>
+#endif
+
+Q_DECLARE_METATYPE(QRect)
+
+QT_FORWARD_DECLARE_CLASS(QPrinter)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#ifndef QT_NO_PRINTER
+
+class tst_QPrinter : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPrinter();
+ virtual ~tst_QPrinter();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+// Add your testfunctions and testdata create functions here
+ void testPageSize();
+ void testPageRectAndPaperRect();
+ void testPageRectAndPaperRect_data();
+ void testSetOptions();
+ void testMargins_data();
+ void testMargins();
+ void testNonExistentPrinter();
+ void testPageSetupDialog();
+ void testMulitpleSets_data();
+ void testMulitpleSets();
+ void testPageMargins_data();
+ void testPageMargins();
+ void changingOutputFormat();
+ void outputFormatFromSuffix();
+ void setGetPaperSize();
+ void valuePreservation();
+ void errorReporting();
+ void testCustomPageSizes();
+ void printDialogCompleter();
+
+ void testCopyCount();
+ void testCurrentPage();
+
+ void taskQTBUG4497_reusePrinterOnDifferentFiles();
+ void testPdfTitle();
+
+private:
+};
+
+// Testing get/set functions
+void tst_QPrinter::getSetCheck()
+{
+ QPrinter obj1;
+ // OutputFormat QPrinter::outputFormat()
+ // void QPrinter::setOutputFormat(OutputFormat)
+ obj1.setOutputFormat(QPrinter::OutputFormat(QPrinter::PdfFormat));
+ QCOMPARE(QPrinter::OutputFormat(QPrinter::PdfFormat), obj1.outputFormat());
+
+ // bool QPrinter::collateCopies()
+ // void QPrinter::setCollateCopies(bool)
+ obj1.setCollateCopies(false);
+ QCOMPARE(false, obj1.collateCopies());
+ obj1.setCollateCopies(true);
+ QCOMPARE(true, obj1.collateCopies());
+
+ obj1.setColorMode(QPrinter::GrayScale);
+ QCOMPARE(obj1.colorMode(), QPrinter::GrayScale);
+ obj1.setColorMode(QPrinter::Color);
+ QCOMPARE(obj1.colorMode(), QPrinter::Color);
+
+ obj1.setCreator(QString::fromLatin1("RandomQtUser"));
+ QCOMPARE(obj1.creator(), QString::fromLatin1("RandomQtUser"));
+
+ obj1.setDocName(QString::fromLatin1("RandomQtDocument"));
+ QCOMPARE(obj1.docName(), QString::fromLatin1("RandomQtDocument"));
+
+ obj1.setDoubleSidedPrinting(true);
+ QCOMPARE(obj1.doubleSidedPrinting(), true);
+ obj1.setDoubleSidedPrinting(false);
+ QCOMPARE(obj1.doubleSidedPrinting(), false);
+
+ obj1.setFromTo(1, 4);
+ QCOMPARE(obj1.fromPage(), 1);
+ QCOMPARE(obj1.toPage(), 4);
+
+ obj1.setFullPage(true);
+ QCOMPARE(obj1.fullPage(), true);
+ obj1.setFullPage(false);
+ QCOMPARE(obj1.fullPage(), false);
+
+ obj1.setOrientation(QPrinter::Landscape);
+ QCOMPARE(obj1.orientation(), QPrinter::Landscape);
+ obj1.setOrientation(QPrinter::Portrait);
+ QCOMPARE(obj1.orientation(), QPrinter::Portrait);
+
+ obj1.setOutputFileName(QString::fromLatin1("RandomQtName"));
+ QCOMPARE(obj1.outputFileName(), QString::fromLatin1("RandomQtName"));
+
+ obj1.setPageOrder(QPrinter::FirstPageFirst);
+ QCOMPARE(obj1.pageOrder(), QPrinter::FirstPageFirst);
+ obj1.setPageOrder(QPrinter::LastPageFirst);
+ QCOMPARE(obj1.pageOrder(), QPrinter::LastPageFirst);
+
+ obj1.setPaperSource(QPrinter::Cassette);
+ QCOMPARE(obj1.paperSource(), QPrinter::Cassette);
+ obj1.setPaperSource(QPrinter::Middle);
+ QCOMPARE(obj1.paperSource(), QPrinter::Middle);
+
+#ifdef Q_OS_UNIX
+ obj1.setPrintProgram(QString::fromLatin1("/bin/true"));
+ QCOMPARE(obj1.printProgram(), QString::fromLatin1("/bin/true"));
+
+ obj1.setPrinterSelectionOption(QString::fromLatin1("--option"));
+ QCOMPARE(obj1.printerSelectionOption(), QString::fromLatin1("--option"));
+#endif
+
+ obj1.setPrinterName(QString::fromLatin1("myPrinter"));
+ QCOMPARE(obj1.printerName(), QString::fromLatin1("myPrinter"));
+
+ // bool QPrinter::fontEmbeddingEnabled()
+ // void QPrinter::setFontEmbeddingEnabled(bool)
+ obj1.setFontEmbeddingEnabled(false);
+ QCOMPARE(false, obj1.fontEmbeddingEnabled());
+ obj1.setFontEmbeddingEnabled(true);
+ QCOMPARE(true, obj1.fontEmbeddingEnabled());
+
+ // PageSize QPrinter::pageSize()
+ // void QPrinter::setPageSize(PageSize)
+ obj1.setPageSize(QPrinter::PageSize(QPrinter::A4));
+ QCOMPARE(QPrinter::PageSize(QPrinter::A4), obj1.pageSize());
+ obj1.setPageSize(QPrinter::PageSize(QPrinter::Letter));
+ QCOMPARE(QPrinter::PageSize(QPrinter::Letter), obj1.pageSize());
+ obj1.setPageSize(QPrinter::PageSize(QPrinter::Legal));
+ QCOMPARE(QPrinter::PageSize(QPrinter::Legal), obj1.pageSize());
+
+ // PrintRange QPrinter::printRange()
+ // void QPrinter::setPrintRange(PrintRange)
+ obj1.setPrintRange(QPrinter::PrintRange(QPrinter::AllPages));
+ QCOMPARE(QPrinter::PrintRange(QPrinter::AllPages), obj1.printRange());
+ obj1.setPrintRange(QPrinter::PrintRange(QPrinter::Selection));
+ QCOMPARE(QPrinter::PrintRange(QPrinter::Selection), obj1.printRange());
+ obj1.setPrintRange(QPrinter::PrintRange(QPrinter::PageRange));
+ QCOMPARE(QPrinter::PrintRange(QPrinter::PageRange), obj1.printRange());
+}
+
+tst_QPrinter::tst_QPrinter()
+{
+}
+
+tst_QPrinter::~tst_QPrinter()
+{
+}
+
+// initTestCase will be executed once before the first testfunction is executed.
+void tst_QPrinter::initTestCase()
+{
+// TODO: Add testcase generic initialization code here.
+// suggestion:
+// testWidget = new QPrinter(0,"testWidget");
+// testWidget->setFixedSize(200, 200);
+// qApp->setMainWidget(testWidget);
+// testWidget->show();
+}
+
+// cleanupTestCase will be executed once after the last testfunction is executed.
+void tst_QPrinter::cleanupTestCase()
+{
+// TODO: Add testcase generic cleanup code here.
+// suggestion:
+// testWidget->hide();
+// qApp->setMainWidget(0);
+// delete testWidget;
+}
+
+// init() will be executed immediately before each testfunction is run.
+void tst_QPrinter::init()
+{
+// TODO: Add testfunction specific initialization code here.
+}
+
+// cleanup() will be executed immediately after each testfunction is run.
+void tst_QPrinter::cleanup()
+{
+// TODO: Add testfunction specific cleanup code here.
+}
+
+#define MYCOMPARE(a, b) QCOMPARE(QVariant((int)a), QVariant((int)b))
+
+void tst_QPrinter::testPageSetupDialog()
+{
+ // Make sure this doesn't crash at least
+ {
+ QPrinter printer;
+ QPageSetupDialog dialog(&printer);
+ }
+}
+
+void tst_QPrinter::testPageSize()
+{
+#if defined (Q_WS_WIN)
+ QPrinter prn;
+
+ prn.setPageSize(QPrinter::Letter);
+ MYCOMPARE(prn.pageSize(), QPrinter::Letter);
+ MYCOMPARE(prn.winPageSize(), DMPAPER_LETTER);
+
+ prn.setPageSize(QPrinter::A4);
+ MYCOMPARE(prn.pageSize(), QPrinter::A4);
+ MYCOMPARE(prn.winPageSize(), DMPAPER_A4);
+
+ prn.setWinPageSize(DMPAPER_LETTER);
+ MYCOMPARE(prn.winPageSize(), DMPAPER_LETTER);
+ MYCOMPARE(prn.pageSize(), QPrinter::Letter);
+
+ prn.setWinPageSize(DMPAPER_A4);
+ MYCOMPARE(prn.winPageSize(), DMPAPER_A4);
+ MYCOMPARE(prn.pageSize(), QPrinter::A4);
+#else
+ QSKIP("QPrinter::winPageSize() does not exist for nonwindows platforms", SkipAll);
+#endif
+}
+
+void tst_QPrinter::testPageRectAndPaperRect_data()
+{
+ QTest::addColumn<int>("orientation");
+ QTest::addColumn<bool>("withPainter");
+ QTest::addColumn<int>("resolution");
+ QTest::addColumn<bool>("doPaperRect");
+
+ // paperrect
+ QTest::newRow("paperRect0") << int(QPrinter::Portrait) << true << 300 << true;
+ QTest::newRow("paperRect1") << int(QPrinter::Portrait) << false << 300 << true;
+ QTest::newRow("paperRect2") << int(QPrinter::Landscape) << true << 300 << true;
+ QTest::newRow("paperRect3") << int(QPrinter::Landscape) << false << 300 << true;
+ QTest::newRow("paperRect4") << int(QPrinter::Portrait) << true << 600 << true;
+ QTest::newRow("paperRect5") << int(QPrinter::Portrait) << false << 600 << true;
+ QTest::newRow("paperRect6") << int(QPrinter::Landscape) << true << 600 << true;
+ QTest::newRow("paperRect7") << int(QPrinter::Landscape) << false << 600 << true;
+ QTest::newRow("paperRect8") << int(QPrinter::Portrait) << true << 1200 << true;
+ QTest::newRow("paperRect9") << int(QPrinter::Portrait) << false << 1200 << true;
+ QTest::newRow("paperRect10") << int(QPrinter::Landscape) << true << 1200 << true;
+ QTest::newRow("paperRect11") << int(QPrinter::Landscape) << false << 1200 << true;
+
+ // page rect
+ QTest::newRow("pageRect0") << int(QPrinter::Portrait) << true << 300 << false;
+ QTest::newRow("pageRect1") << int(QPrinter::Portrait) << false << 300 << false;
+ QTest::newRow("pageRect2") << int(QPrinter::Landscape) << true << 300 << false;
+ QTest::newRow("pageRect3") << int(QPrinter::Landscape) << false << 300 << false;
+ QTest::newRow("pageRect4") << int(QPrinter::Portrait) << true << 600 << false;
+ QTest::newRow("pageRect5") << int(QPrinter::Portrait) << false << 600 << false;
+ QTest::newRow("pageRect6") << int(QPrinter::Landscape) << true << 600 << false;
+ QTest::newRow("pageRect7") << int(QPrinter::Landscape) << false << 600 << false;
+ QTest::newRow("pageRect8") << int(QPrinter::Portrait) << true << 1200 << false;
+ QTest::newRow("pageRect9") << int(QPrinter::Portrait) << false << 1200 << false;
+ QTest::newRow("pageRect10") << int(QPrinter::Landscape) << true << 1200 << false;
+ QTest::newRow("pageRect11") << int(QPrinter::Landscape) << false << 1200 << false;
+}
+
+void tst_QPrinter::testPageRectAndPaperRect()
+{
+ QFETCH(bool, withPainter);
+ QFETCH(int, orientation);
+ QFETCH(int, resolution);
+ QFETCH(bool, doPaperRect);
+
+ QPainter *painter = 0;
+ QPrinter printer(QPrinter::HighResolution);
+ printer.setOrientation(QPrinter::Orientation(orientation));
+ printer.setOutputFileName("silly");
+
+ QRect pageRect = doPaperRect ? printer.paperRect() : printer.pageRect();
+ float inchesX = float(pageRect.width()) / float(printer.resolution());
+ float inchesY = float(pageRect.height()) / float(printer.resolution());
+ printer.setResolution(resolution);
+ if (withPainter)
+ painter = new QPainter(&printer);
+
+ QRect otherRect = doPaperRect ? printer.paperRect() : printer.pageRect();
+ float otherInchesX = float(otherRect.width()) / float(printer.resolution());
+ float otherInchesY = float(otherRect.height()) / float(printer.resolution());
+ if (painter != 0)
+ delete painter;
+
+ QVERIFY(qAbs(otherInchesX - inchesX) < 0.01);
+ QVERIFY(qAbs(otherInchesY - inchesY) < 0.01);
+
+ QVERIFY(printer.orientation() == QPrinter::Portrait || pageRect.width() > pageRect.height());
+ QVERIFY(printer.orientation() != QPrinter::Portrait || pageRect.width() < pageRect.height());
+}
+
+void tst_QPrinter::testSetOptions()
+{
+ QPrinter prn;
+ QPrintDialog dlg(&prn);
+
+ // Verify default values
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintToFile), TRUE);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintSelection), FALSE);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintPageRange), TRUE);
+
+ dlg.setEnabledOptions(QAbstractPrintDialog::PrintPageRange);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintToFile), FALSE);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintSelection), FALSE);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintPageRange), TRUE);
+
+ dlg.setEnabledOptions((QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintSelection
+ | QAbstractPrintDialog::PrintPageRange)));
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintToFile), FALSE);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintSelection), TRUE);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintPageRange), TRUE);
+
+ dlg.setEnabledOptions(QAbstractPrintDialog::PrintSelection);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintToFile), FALSE);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintSelection), TRUE);
+ MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintPageRange), FALSE);
+}
+
+void tst_QPrinter::testMargins_data()
+{
+ QTest::addColumn<int>("orientation");
+ QTest::addColumn<bool>("fullpage");
+ QTest::addColumn<int>("pagesize");
+ QTest::addColumn<int>("width");
+ QTest::addColumn<int>("height");
+ QTest::addColumn<bool>("withPainter");
+
+ QTest::newRow("data0") << int(QPrinter::Portrait) << true << int(QPrinter::A4) << 210 << 297 << false;
+ QTest::newRow("data1") << int(QPrinter::Landscape) << true << int(QPrinter::A4) << 297 << 210 << false;
+ QTest::newRow("data2") << int(QPrinter::Landscape) << false << int(QPrinter::A4) << 297 << 210 << false;
+ QTest::newRow("data3") << int(QPrinter::Portrait) << false << int(QPrinter::A4) << 210 << 297 << false;
+ QTest::newRow("data4") << int(QPrinter::Portrait) << true << int(QPrinter::A4) << 210 << 297 << true;
+ QTest::newRow("data5") << int(QPrinter::Landscape) << true << int(QPrinter::A4) << 297 << 210 << true;
+ QTest::newRow("data6") << int(QPrinter::Landscape) << false << int(QPrinter::A4) << 297 << 210 << true;
+ QTest::newRow("data7") << int(QPrinter::Portrait) << false << int(QPrinter::A4) << 210 << 297 << true;
+}
+
+void tst_QPrinter::testMargins()
+{
+ QFETCH(bool, withPainter);
+ QFETCH(int, orientation);
+ QFETCH(int, pagesize);
+ QFETCH(int, width);
+ QFETCH(int, height);
+ QFETCH(bool, fullpage);
+ Q_UNUSED(width);
+ Q_UNUSED(height);
+ QPrinter printer;
+ QPainter *painter = 0;
+ printer.setOutputFileName("silly");
+ printer.setOrientation((QPrinter::Orientation)orientation);
+ printer.setFullPage(fullpage);
+ printer.setPageSize((QPrinter::PageSize)pagesize);
+ if (withPainter)
+ painter = new QPainter(&printer);
+
+ if (painter)
+ delete painter;
+}
+
+void tst_QPrinter::testNonExistentPrinter()
+{
+#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_MAC)
+ QSKIP("QPrinter::testNonExistentPrinter() is not relevant for this platform", SkipAll);
+#else
+ QPrinter printer;
+ QPainter painter;
+
+ // Make sure it doesn't crash on setting or getting properties
+ printer.setPrinterName("some non existing printer");
+ printer.setPageSize(QPrinter::A4);
+ printer.setOrientation(QPrinter::Portrait);
+ printer.setFullPage(true);
+ printer.pageSize();
+ printer.orientation();
+ printer.fullPage();
+ printer.setCopyCount(1);
+ printer.printerName();
+
+ // nor metrics
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmWidth), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmHeight), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmWidthMM), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmHeightMM), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmNumColors), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmDepth), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmDpiX), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmDpiY), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmPhysicalDpiX), 0);
+ QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmPhysicalDpiY), 0);
+
+ QVERIFY(!painter.begin(&printer));
+#endif
+}
+
+
+void tst_QPrinter::testMulitpleSets_data()
+{
+ QTest::addColumn<int>("resolution");
+ QTest::addColumn<int>("pageSize");
+ QTest::addColumn<int>("widthMMAfter");
+ QTest::addColumn<int>("heightMMAfter");
+
+
+ QTest::newRow("lowRes") << int(QPrinter::ScreenResolution) << int(QPrinter::A4) << 210 << 297;
+ QTest::newRow("lowResLetter") << int(QPrinter::ScreenResolution) << int(QPrinter::Letter) << 216 << 279;
+ QTest::newRow("lowResA5") << int(QPrinter::ScreenResolution) << int(QPrinter::A5) << 148 << 210;
+ QTest::newRow("midRes") << int(QPrinter::PrinterResolution) << int(QPrinter::A4) << 210 << 297;
+ QTest::newRow("midResLetter") << int(QPrinter::PrinterResolution) << int(QPrinter::Letter) << 216 << 279;
+ QTest::newRow("midResA5") << int(QPrinter::PrinterResolution) << int(QPrinter::A5) << 148 << 210;
+ QTest::newRow("highRes") << int(QPrinter::HighResolution) << int(QPrinter::A4) << 210 << 297;
+ QTest::newRow("highResLetter") << int(QPrinter::HighResolution) << int(QPrinter::Letter) << 216 << 279;
+ QTest::newRow("highResA5") << int(QPrinter::HighResolution) << int(QPrinter::A5) << 148 << 210;
+}
+
+static void computePageValue(const QPrinter &printer, int &retWidth, int &retHeight)
+{
+ const double Inch2MM = 25.4;
+
+ double width = double(printer.paperRect().width()) / printer.logicalDpiX() * Inch2MM;
+ double height = double(printer.paperRect().height()) / printer.logicalDpiY() * Inch2MM;
+ retWidth = qRound(width);
+ retHeight = qRound(height);
+}
+
+void tst_QPrinter::testMulitpleSets()
+{
+ // A very simple test, but Mac needs to have its format "validated" if the format is changed
+ // This takes care of that.
+ QFETCH(int, resolution);
+ QFETCH(int, pageSize);
+ QFETCH(int, widthMMAfter);
+ QFETCH(int, heightMMAfter);
+
+
+ QPrinter::PrinterMode mode = QPrinter::PrinterMode(resolution);
+ QPrinter::PageSize printerPageSize = QPrinter::PageSize(pageSize);
+ QPrinter printer(mode);
+ printer.setFullPage(true);
+
+ int paperWidth, paperHeight;
+ //const int Tolerance = 2;
+
+ computePageValue(printer, paperWidth, paperHeight);
+ printer.setPageSize(printerPageSize);
+
+ if (printer.pageSize() != printerPageSize) {
+ QSKIP("Current page size is not supported on this printer", SkipSingle);
+ return;
+ }
+
+ QCOMPARE(printer.widthMM(), widthMMAfter);
+ QCOMPARE(printer.heightMM(), heightMMAfter);
+
+ computePageValue(printer, paperWidth, paperHeight);
+
+ QVERIFY(qAbs(paperWidth - widthMMAfter) <= 2);
+ QVERIFY(qAbs(paperHeight - heightMMAfter) <= 2);
+
+ // Set it again and see if it still works.
+ printer.setPageSize(printerPageSize);
+ QCOMPARE(printer.widthMM(), widthMMAfter);
+ QCOMPARE(printer.heightMM(), heightMMAfter);
+
+ printer.setOrientation(QPrinter::Landscape);
+ computePageValue(printer, paperWidth, paperHeight);
+ QVERIFY(qAbs(paperWidth - heightMMAfter) <= 2);
+ QVERIFY(qAbs(paperHeight - widthMMAfter) <= 2);
+}
+
+void tst_QPrinter::changingOutputFormat()
+{
+#if QT_VERSION < 0x050000
+ QPrinter p;
+ p.setOutputFormat(QPrinter::PostScriptFormat);
+ p.setPageSize(QPrinter::A8);
+ p.setOutputFormat(QPrinter::PdfFormat);
+ QCOMPARE(p.pageSize(), QPrinter::A8);
+#endif
+}
+
+void tst_QPrinter::outputFormatFromSuffix()
+{
+ if (QPrinterInfo::availablePrinters().size() == 0)
+ QSKIP("No printers available.", SkipAll);
+ QPrinter p;
+ QVERIFY(p.outputFormat() == QPrinter::NativeFormat);
+ p.setOutputFileName("test.pdf");
+ QVERIFY(p.outputFormat() == QPrinter::PdfFormat);
+ p.setOutputFileName(QString());
+ QVERIFY(p.outputFormat() == QPrinter::NativeFormat);
+}
+
+void tst_QPrinter::setGetPaperSize()
+{
+ QPrinter p;
+ p.setOutputFormat(QPrinter::PdfFormat);
+ QSizeF size(500, 10);
+ p.setPaperSize(size, QPrinter::Millimeter);
+ QCOMPARE(p.paperSize(QPrinter::Millimeter), size);
+ QSizeF ptSize = p.paperSize(QPrinter::Point);
+ //qDebug() << ptSize;
+ QVERIFY(qAbs(ptSize.width() - size.width() * (72/25.4)) < 1E-4);
+ QVERIFY(qAbs(ptSize.height() - size.height() * (72/25.4)) < 1E-4);
+}
+
+void tst_QPrinter::testPageMargins_data()
+{
+ QTest::addColumn<qreal>("left");
+ QTest::addColumn<qreal>("top");
+ QTest::addColumn<qreal>("right");
+ QTest::addColumn<qreal>("bottom");
+ QTest::addColumn<int>("unit");
+
+ QTest::newRow("data0") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Millimeter);
+ QTest::newRow("data1") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Point);
+ QTest::newRow("data2") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Inch);
+ QTest::newRow("data3") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Pica);
+ QTest::newRow("data4") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Didot);
+ QTest::newRow("data5") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Cicero);
+}
+
+void tst_QPrinter::testPageMargins()
+{
+ QPrinter obj1;
+
+ qreal toMillimeters[6];
+ toMillimeters[QPrinter::Millimeter] = 1;
+ toMillimeters[QPrinter::Point] = 0.352777778;
+ toMillimeters[QPrinter::Inch] = 25.4;
+ toMillimeters[QPrinter::Pica] = 4.23333333;
+ toMillimeters[QPrinter::Didot] = 0.376;
+ toMillimeters[QPrinter::Cicero] = 4.51166667;
+
+ QFETCH(qreal, left);
+ QFETCH(qreal, top);
+ QFETCH(qreal, right);
+ QFETCH(qreal, bottom);
+ QFETCH(int, unit);
+
+ qreal nLeft, nTop, nRight, nBottom;
+
+ obj1.setPageMargins(left, top, right, bottom, static_cast<QPrinter::Unit>(unit));
+
+ qreal tolerance = 0.05;
+
+ obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Millimeter);
+ QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Millimeter]) < tolerance);
+ QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Millimeter]) < tolerance);
+ QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Millimeter]) < tolerance);
+ QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Millimeter]) < tolerance);
+
+ obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Point);
+ QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Point]) < tolerance);
+ QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Point]) < tolerance);
+ QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Point]) < tolerance);
+ QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Point]) < tolerance);
+
+ obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Inch);
+ QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Inch]) < tolerance);
+ QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Inch]) < tolerance);
+ QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Inch]) < tolerance);
+ QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Inch]) < tolerance);
+
+ obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Pica);
+ QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Pica]) < tolerance);
+ QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Pica]) < tolerance);
+ QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Pica]) < tolerance);
+ QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Pica]) < tolerance);
+
+ obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Didot);
+ QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Didot]) < tolerance);
+ QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Didot]) < tolerance);
+ QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Didot]) < tolerance);
+ QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Didot]) < tolerance);
+
+ obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Cicero);
+ QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Cicero]) < tolerance);
+ QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Cicero]) < tolerance);
+ QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Cicero]) < tolerance);
+ QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Cicero]) < tolerance);
+}
+
+void tst_QPrinter::valuePreservation()
+{
+ QPrinter::OutputFormat oldFormat = QPrinter::PdfFormat;
+ QPrinter::OutputFormat newFormat = QPrinter::NativeFormat; // TODO: Correct?
+
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ bool status = printer.collateCopies();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.collateCopies(), status);
+
+ printer.setCollateCopies(!status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.collateCopies(), !status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.collateCopies(), !status);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QPrinter::ColorMode status = printer.colorMode();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.colorMode(), status);
+
+ printer.setColorMode(QPrinter::ColorMode(!status));
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.colorMode(), QPrinter::ColorMode(!status));
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.colorMode(), QPrinter::ColorMode(!status));
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QString status = printer.creator();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.creator(), status);
+
+ status = QString::fromLatin1("Mr. Test");
+ printer.setCreator(status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.creator(), status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.creator(), status);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QString status = printer.docName();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.docName(), status);
+
+ status = QString::fromLatin1("Test document");
+ printer.setDocName(status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.docName(), status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.docName(), status);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ bool status = printer.doubleSidedPrinting();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.doubleSidedPrinting(), status);
+
+ printer.setDoubleSidedPrinting(!status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.doubleSidedPrinting(), !status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.doubleSidedPrinting(), !status);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ bool status = printer.fontEmbeddingEnabled();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.fontEmbeddingEnabled(), status);
+
+ printer.setFontEmbeddingEnabled(!status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.fontEmbeddingEnabled(), !status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.fontEmbeddingEnabled(), !status);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ bool status = printer.fullPage();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.fullPage(), status);
+
+ printer.setFullPage(!status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.fullPage(), !status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.fullPage(), !status);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QPrinter::Orientation status = printer.orientation();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.orientation(), status);
+
+ printer.setOrientation(QPrinter::Orientation(!status));
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.orientation(), QPrinter::Orientation(!status));
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.orientation(), QPrinter::Orientation(!status));
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QString status = printer.outputFileName();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.outputFileName(), status);
+
+ status = QString::fromLatin1("Test file");
+ printer.setOutputFileName(status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.outputFileName(), status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.outputFileName(), status);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QPrinter::PageOrder status = printer.pageOrder();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.pageOrder(), status);
+
+ printer.setPageOrder(QPrinter::PageOrder(!status));
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.pageOrder(), QPrinter::PageOrder(!status));
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.pageOrder(), QPrinter::PageOrder(!status));
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QPrinter::PageSize status = printer.pageSize();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.pageSize(), status);
+
+ printer.setPageSize(QPrinter::B5);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.pageSize(), QPrinter::B5);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.pageSize(), QPrinter::B5);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QPrinter::PaperSource status = printer.paperSource();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.paperSource(), status);
+
+ printer.setPaperSource(QPrinter::Manual);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.paperSource(), QPrinter::Manual);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.paperSource(), QPrinter::Manual);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QString status = printer.printProgram();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.printProgram(), status);
+
+ status = QString::fromLatin1("/usr/local/bin/lpr");
+ printer.setPrintProgram(status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.printProgram(), status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.printProgram(), status);
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QPrinter::PrintRange status = printer.printRange();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.printRange(), status);
+
+ printer.setPrintRange(QPrinter::PrintRange(!status));
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.printRange(), QPrinter::PrintRange(!status));
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.printRange(), QPrinter::PrintRange(!status));
+ }
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QString status = printer.printerName();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.printerName(), status);
+
+ status = QString::fromLatin1("SuperDuperPrinter");
+ printer.setPrinterName(status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.printerName(), status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.printerName(), status);
+ }
+#ifndef Q_OS_WIN
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ QString status = printer.printerSelectionOption();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.printerSelectionOption(), status);
+
+ status = QString::fromLatin1("Optional option");
+ printer.setPrinterSelectionOption(status);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.printerSelectionOption(), status);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.printerSelectionOption(), status);
+ }
+#endif
+ {
+ QPrinter printer;
+ printer.setOutputFormat(oldFormat);
+ int status = printer.resolution();
+ printer.setOutputFormat(newFormat);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.resolution(), status);
+
+ printer.setResolution(status-150);
+ printer.setOutputFormat(newFormat);
+ QCOMPARE(printer.resolution(), status-150);
+ printer.setOutputFormat(oldFormat);
+ QCOMPARE(printer.resolution(), status-150);
+ }
+}
+
+void tst_QPrinter::errorReporting()
+{
+ QPrinter p;
+ p.setOutputFormat(QPrinter::PdfFormat);
+ QCOMPARE(p.isValid(), true);
+ QPainter painter;
+#ifndef Q_WS_WIN
+ // not sure how to choose a never-writable file on windows. But its QFile behavior anyway, so lets rely on it failing elsewhere
+ p.setOutputFileName("/foobar/nonwritable.pdf");
+ QCOMPARE(painter.begin(&p), false); // it should check the output file is writable
+#endif
+ p.setOutputFileName("test.pdf");
+ QCOMPARE(painter.begin(&p), true); // it should check the output
+ QCOMPARE(p.isValid(), true);
+ painter.end();
+}
+
+void tst_QPrinter::testCustomPageSizes()
+{
+ QPrinter p;
+
+ QSizeF customSize(8.5, 11.0);
+ p.setPaperSize(customSize, QPrinter::Inch);
+
+ QSizeF paperSize = p.paperSize(QPrinter::Inch);
+ QCOMPARE(paperSize, customSize);
+
+ QPrinter p2(QPrinter::HighResolution);
+ p2.setPaperSize(customSize, QPrinter::Inch);
+ paperSize = p.paperSize(QPrinter::Inch);
+ QCOMPARE(paperSize, customSize);
+}
+
+void tst_QPrinter::printDialogCompleter()
+{
+#if defined(QT_NO_COMPLETER) || defined(QT_NO_FILEDIALOG)
+ QSKIP("QT_NO_COMPLETER || QT_NO_FILEDIALOG: Auto-complete turned off in QPrinterDialog.", QTest::SkipAll);
+#else
+ QPrintDialog dialog;
+ dialog.printer()->setOutputFileName("file.pdf");
+ dialog.setEnabledOptions(QAbstractPrintDialog::PrintToFile);
+ dialog.show();
+
+ QTest::qWait(100);
+
+ QTest::keyClick(&dialog, Qt::Key_Tab);
+ QTest::keyClick(&dialog, 'P');
+ // The test passes if it doesn't crash.
+#endif
+}
+
+void tst_QPrinter::testCopyCount()
+{
+ QPrinter p;
+ p.setCopyCount(15);
+ QCOMPARE(p.copyCount(), 15);
+}
+
+static void printPage(QPainter *painter)
+{
+ painter->setPen(QPen(Qt::black, 4));
+ painter->drawRect(50, 60, 70, 80);
+}
+
+void tst_QPrinter::taskQTBUG4497_reusePrinterOnDifferentFiles()
+{
+ QPrinter printer;
+ {
+
+ printer.setOutputFileName("out1.ps");
+ QPainter painter(&printer);
+ printPage(&painter);
+
+ }
+ {
+
+ printer.setOutputFileName("out2.ps");
+ QPainter painter(&printer);
+ printPage(&painter);
+
+ }
+ QFile file1("out1.ps");
+ QVERIFY(file1.open(QIODevice::ReadOnly));
+
+ QFile file2("out2.ps");
+ QVERIFY(file2.open(QIODevice::ReadOnly));
+
+ QCOMPARE(file1.readAll(), file2.readAll());
+}
+
+void tst_QPrinter::testCurrentPage()
+{
+ QPrinter printer;
+ printer.setFromTo(1, 10);
+
+ // Test set print range
+ printer.setPrintRange(QPrinter::CurrentPage);
+ QCOMPARE(printer.printRange(), QPrinter::CurrentPage);
+ QCOMPARE(printer.fromPage(), 1);
+ QCOMPARE(printer.toPage(), 10);
+
+ QPrintDialog dialog(&printer);
+
+ // Test default Current Page option to off
+ QCOMPARE(dialog.isOptionEnabled(QPrintDialog::PrintCurrentPage), false);
+
+ // Test enable Current Page option
+ dialog.setOption(QPrintDialog::PrintCurrentPage);
+ QCOMPARE(dialog.isOptionEnabled(QPrintDialog::PrintCurrentPage), true);
+
+}
+
+void tst_QPrinter::testPdfTitle()
+{
+ // Check the document name is represented correctly in produced pdf
+ {
+ QPainter painter;
+ QPrinter printer;
+ // This string is just the UTF-8 encoding of the string: \()f &oslash; hiragana o
+ const char title[]={0x5c, 0x28, 0x29, 0x66, 0xc3, 0xb8, 0xe3, 0x81, 0x8a, 0x00};
+ printer.setOutputFileName("file.pdf");
+ printer.setDocName(QString::fromUtf8(title));
+ painter.begin(&printer);
+ painter.end();
+ }
+ QFile file("file.pdf");
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ // The we expect the title to appear in the PDF as:
+ // ASCII('\title (') UTF16(\\\(\)f &oslash; hiragana o) ASCII(')').
+ // which has the following binary representation
+ const char expected[] = {
+ 0x2f, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x20, 0x28, 0xfe,
+ 0xff, 0x00, 0x5c, 0x5c, 0x00, 0x5c, 0x28, 0x00, 0x5c,
+ 0x29, 0x00, 0x66, 0x00, 0xf8, 0x30, 0x4a, 0x29};
+ QVERIFY(file.readAll().contains(QByteArray(expected, 26)));
+}
+
+QTEST_MAIN(tst_QPrinter)
+#include "tst_qprinter.moc"
+
+#else //QT_NO_PRINTER
+
+QTEST_NOOP_MAIN
+
+#endif //QT_NO_PRINTER
diff --git a/tests/auto/gui/painting/qprinterinfo/.gitignore b/tests/auto/gui/painting/qprinterinfo/.gitignore
new file mode 100644
index 0000000000..fcef7c1997
--- /dev/null
+++ b/tests/auto/gui/painting/qprinterinfo/.gitignore
@@ -0,0 +1 @@
+tst_qprinterinfo
diff --git a/tests/auto/gui/painting/qprinterinfo/qprinterinfo.pro b/tests/auto/gui/painting/qprinterinfo/qprinterinfo.pro
new file mode 100644
index 0000000000..1bf799d6ce
--- /dev/null
+++ b/tests/auto/gui/painting/qprinterinfo/qprinterinfo.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+SOURCES += tst_qprinterinfo.cpp
+
+QT += printsupport network
+
+DEFINES += QT_USE_USING_NAMESPACE
+
diff --git a/tests/auto/gui/painting/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/gui/painting/qprinterinfo/tst_qprinterinfo.cpp
new file mode 100644
index 0000000000..7e5da4a6f8
--- /dev/null
+++ b/tests/auto/gui/painting/qprinterinfo/tst_qprinterinfo.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGlobal>
+#include <QtAlgorithms>
+#include <QtNetwork/QHostInfo>
+
+#ifndef QT_NO_PRINTER
+#include <qprinterinfo.h>
+
+#ifdef Q_OS_UNIX
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+#endif
+
+Q_DECLARE_METATYPE(QRect)
+
+
+#if defined(Q_OS_WIN32)
+# define ACCEPTABLE_WINDOWS
+#endif
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPrinterInfo : public QObject
+{
+ Q_OBJECT
+
+public:
+ //tst_QPrinterInfo();
+ //virtual ~tst_QPrinterInfo();
+
+
+public slots:
+ //void initTestCase();
+ //void cleanupTestCase();
+ //void init();
+ //void cleanup();
+private slots:
+ void testForDefaultPrinter();
+ void testForPrinters();
+ void testForPaperSizes();
+ void testConstructors();
+ void testAssignment();
+
+private:
+ void macFixNameFormat(QString *printerName);
+ QString getDefaultPrinterFromSystem();
+ QStringList getPrintersFromSystem();
+
+ QString getOutputFromCommand(const QStringList& command);
+};
+
+void tst_QPrinterInfo::macFixNameFormat(QString *printerName)
+{
+// Modify the format of the printer name to match Qt, lpstat returns
+// foo___domain_no, Qt returns foo @ domain.no
+#ifdef Q_WS_MAC
+ printerName->replace(QLatin1String("___"), QLatin1String(" @ "));
+ printerName->replace(QLatin1String("_"), QLatin1String("."));
+#else
+ Q_UNUSED(printerName);
+#endif
+}
+
+QString tst_QPrinterInfo::getDefaultPrinterFromSystem()
+{
+ QStringList command;
+ command << "lpstat" << "-d";
+ QString output = getOutputFromCommand(command);
+
+ QRegExp noDefaultReg("[^:]*no .*default");
+ int pos = noDefaultReg.indexIn(output);
+ if (pos >= 0) {
+ return QString();
+ }
+
+ QRegExp defaultReg("default.*: *([a-zA-Z0-9_]+)");
+ defaultReg.indexIn(output);
+ QString printer = defaultReg.cap(1);
+ macFixNameFormat(&printer);
+ return printer;
+}
+
+QStringList tst_QPrinterInfo::getPrintersFromSystem()
+{
+ QStringList ans;
+
+ QStringList command;
+ command << "lpstat" << "-p";
+ QString output = getOutputFromCommand(command);
+ QStringList list = output.split(QChar::fromLatin1('\n'));
+
+ QRegExp reg("^[Pp]rinter ([.a-zA-Z0-9-_@]+)");
+ for (int c = 0; c < list.size(); ++c) {
+ if (reg.indexIn(list[c]) >= 0) {
+ QString printer = reg.cap(1);
+ macFixNameFormat(&printer);
+ ans << printer;
+ }
+ }
+
+ return ans;
+}
+
+// This function does roughly the same as the `command substitution` in
+// the shell.
+QString tst_QPrinterInfo::getOutputFromCommand(const QStringList& command)
+{
+// The command execution does nothing on non-unix systems.
+#ifdef Q_OS_UNIX
+ int pid;
+ int status = 0;
+ int pipePtr[2];
+
+ // Create a pipe that is shared between parent and child process.
+ if (pipe(pipePtr) < 0) {
+ return QString();
+ }
+ pid = fork();
+ if (pid < 0) {
+ close(pipePtr[0]);
+ close(pipePtr[1]);
+ return QString();
+ } else if (pid == 0) {
+ // In child.
+ // Close the reading end.
+ close(pipePtr[0]);
+ // Redirect stdout to the pipe.
+ if (dup2(pipePtr[1], 1) < 0) {
+ exit(1);
+ }
+
+ char** argv = new char*[command.size()+1];
+ for (int c = 0; c < command.size(); ++c) {
+ argv[c] = new char[command[c].size()+1];
+ strcpy(argv[c], command[c].toLatin1().data());
+ }
+ argv[command.size()] = NULL;
+ execvp(argv[0], argv);
+ // Shouldn't get here, but it's possible if command is not found.
+ close(pipePtr[1]);
+ close(1);
+ for (int c = 0; c < command.size(); ++c) {
+ delete [] argv[c];
+ }
+ delete [] argv;
+ exit(1);
+ } else {
+ // In parent.
+ // Close the writing end.
+ close(pipePtr[1]);
+
+ QFile pipeRead;
+ if (!pipeRead.open(pipePtr[0], QIODevice::ReadOnly)) {
+ close(pipePtr[0]);
+ return QString();
+ }
+ QByteArray array;
+ array = pipeRead.readAll();
+ pipeRead.close();
+ close(pipePtr[0]);
+ wait(&status);
+ return QString(array);
+ }
+#else
+ return QString();
+#endif // Q_OS_UNIX
+}
+
+void tst_QPrinterInfo::testForDefaultPrinter()
+{
+#if defined(Q_OS_UNIX) || defined(ACCEPTABLE_WINDOWS)
+# ifdef ACCEPTABLE_WINDOWS
+ if (QHostInfo::localHostName() == "fantomet" || QHostInfo::localHostName() == "bobo") {
+ QWARN("Test is hardcoded to \"fantomet\" and \"bobo\" on Windows and may fail");
+ } else {
+ QSKIP("Test is hardcoded to \"fantomet\" and \"bobo\" on Windows", SkipAll);
+ }
+ QString defSysPrinter;
+ if (QHostInfo::localHostName() == "fantomet") {
+ defSysPrinter = "Yacc (Lexmark Optra T610 PS3)";
+ } else if (QHostInfo::localHostName() == "bobo") {
+ defSysPrinter = "press";
+ }
+# else
+ QString defSysPrinter = getDefaultPrinterFromSystem();
+# endif
+ if (defSysPrinter == "") return;
+
+ QList<QPrinterInfo> list = QPrinterInfo::availablePrinters();
+ bool found = false;
+ for (int c = 0; c < list.size(); ++c) {
+ if (list[c].isDefault()) {
+ QVERIFY(list.at(c).printerName() == defSysPrinter);
+ QVERIFY(!list.at(c).isNull());
+ found = true;
+ } else {
+ QVERIFY(list.at(c).printerName() != defSysPrinter);
+ QVERIFY(!list.at(c).isNull());
+ }
+ }
+
+ if (!found && defSysPrinter != "") QFAIL("No default printer reported by Qt, although there is one");
+#else
+ QSKIP("Test doesn't work on non-Unix", SkipAll);
+#endif // defined(Q_OS_UNIX) || defined(ACCEPTABLE_WINDOWS)
+}
+
+void tst_QPrinterInfo::testForPrinters()
+{
+#if defined(Q_OS_UNIX) || defined(ACCEPTABLE_WINDOWS)
+# ifdef ACCEPTABLE_WINDOWS
+ if (QHostInfo::localHostName() == "fantomet" || QHostInfo::localHostName() == "bobo") {
+ QWARN("Test is hardcoded to \"fantomet\" and \"bobo\" on Windows and may fail");
+ } else {
+ QSKIP("Test is hardcoded to \"fantomet\" and \"bobo\" on Windows", SkipAll);
+ }
+ QStringList sysPrinters;
+ if (QHostInfo::localHostName() == "fantomet") {
+ sysPrinters
+ << "Press"
+ << "Canon PS-IPU Color Laser Copier v52.3"
+ << "EPSON EPL-N4000 PS3"
+ << "Kroksleiven"
+ << "Lexmark Optra Color 1200 PS"
+ << "Yacc (Lexmark Optra T610 PCL)"
+ << "Yacc (Lexmark Optra T610 PS3)"
+ ;
+ } else if (QHostInfo::localHostName() == "bobo") {
+ sysPrinters
+ << "press"
+ << "finnmarka"
+ << "nordmarka"
+ ;
+ }
+# else
+ QStringList sysPrinters = getPrintersFromSystem();
+# endif
+ QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters();
+
+ QCOMPARE(printers.size(), sysPrinters.size());
+
+ QHash<QString, bool> qtPrinters;
+
+ for (int j = 0; j < printers.size(); ++j) {
+ qtPrinters.insert(printers.at(j).printerName(), !printers.at(j).isNull());
+ }
+
+ for (int i = 0; i < sysPrinters.size(); ++i) {
+ if (!qtPrinters.value(sysPrinters.at(i))) {
+ qDebug() << "Available printers: " << qtPrinters;
+ QFAIL(qPrintable(QString("Printer '%1' reported by system, but not reported by Qt").arg(sysPrinters.at(i))));
+ }
+ }
+#else
+ QSKIP("Test doesn't work on non-Unix", SkipAll);
+#endif // defined(Q_OS_UNIX) || defined(ACCEPTABLE_WINDOWS)
+}
+
+void tst_QPrinterInfo::testForPaperSizes()
+{
+QSKIP("PaperSize feature doesn't work on Windows, fails on Mac, and is unstable on Linux", SkipAll);
+ // This test is based on common printers found at the Oslo
+ // office. It is likely to be skipped or fail for other locations.
+ QStringList hardPrinters;
+ hardPrinters << "Finnmarka" << "Huldra";
+
+ QList<QList<QPrinter::PaperSize> > hardSizes;
+ hardSizes
+ << QList<QPrinter::PaperSize>()
+ << QList<QPrinter::PaperSize>()
+ ;
+ hardSizes[0] // Finnmarka
+ << QPrinter::Letter
+ << QPrinter::A4
+ << QPrinter::A3
+ << QPrinter::A5
+ << QPrinter::B4
+ << QPrinter::B5
+ << QPrinter::Custom // COM10
+ << QPrinter::Custom // C5
+ << QPrinter::Custom // DL
+ << QPrinter::Custom // Monarch
+ << QPrinter::Executive
+ << QPrinter::Custom // Foolscap
+ << QPrinter::Custom // ISO B5
+ << QPrinter::Ledger
+ << QPrinter::Legal
+ << QPrinter::Custom // Japanese Post Card
+ << QPrinter::Custom // Invoice
+ ;
+ hardSizes[1] // Huldra
+ << QPrinter::Custom // Not listed at http://localhost:631/, name "Custom"
+ << QPrinter::Letter
+ << QPrinter::A4
+ << QPrinter::A5
+ << QPrinter::A6
+ << QPrinter::B5
+ << QPrinter::Custom // #5 1/2 Envelope
+ << QPrinter::Custom // 6x9 Envelope
+ << QPrinter::Custom // #10 Envelope
+ << QPrinter::Custom // A7 Envelope
+ << QPrinter::Custom // C5 Envelope
+ << QPrinter::Custom // DL Envelope
+ << QPrinter::Custom // Monarch Envelope
+ << QPrinter::Custom // #6 3/4 Envelope
+ << QPrinter::Executive
+ << QPrinter::Custom // US Folio
+ << QPrinter::Custom // Index Card
+ << QPrinter::Custom // ISO B5
+ << QPrinter::Legal
+ << QPrinter::Custom // Statement
+ ;
+
+ QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters();
+ for (int i = 0; i < printers.size(); ++i) {
+ for (int j = 0; j < hardPrinters.size(); ++j) {
+ if (printers[i].printerName() == hardPrinters[j]) {
+ QList<QPrinter::PaperSize> sizes = printers[i].supportedPaperSizes();
+ qSort(sizes);
+ qSort(hardSizes[j]);
+ QCOMPARE(sizes, hardSizes[j]);
+ }
+ }
+ }
+}
+
+void tst_QPrinterInfo::testConstructors()
+{
+ QList<QPrinterInfo> prns(QPrinterInfo::availablePrinters());
+
+ for (int c = 0; c < prns.size(); ++c) {
+ QList<QPrinter::PaperSize> list1, list2;
+ list1 = prns[c].supportedPaperSizes();
+ QPrinter pr(prns[c]);
+ list2 = QPrinterInfo(pr).supportedPaperSizes();
+ QCOMPARE(list2, list1);
+ }
+}
+
+void tst_QPrinterInfo::testAssignment()
+{
+ QList<QPrinterInfo> prns(QPrinterInfo::availablePrinters());
+
+ for (int c = 0; c < prns.size(); ++c) {
+ QPrinterInfo pi = QPrinterInfo::defaultPrinter();
+ pi = prns[c];
+ QCOMPARE(pi.printerName(), prns[c].printerName());
+ QCOMPARE(pi.supportedPaperSizes(), prns[c].supportedPaperSizes());
+ }
+}
+
+QTEST_MAIN(tst_QPrinterInfo)
+#include "tst_qprinterinfo.moc"
+#else
+QTEST_NOOP_MAIN
+#endif
diff --git a/tests/auto/gui/painting/qregion/.gitignore b/tests/auto/gui/painting/qregion/.gitignore
new file mode 100644
index 0000000000..8be21c3736
--- /dev/null
+++ b/tests/auto/gui/painting/qregion/.gitignore
@@ -0,0 +1 @@
+tst_qregion
diff --git a/tests/auto/gui/painting/qregion/qregion.pro b/tests/auto/gui/painting/qregion/qregion.pro
new file mode 100644
index 0000000000..8dbb4844a0
--- /dev/null
+++ b/tests/auto/gui/painting/qregion/qregion.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT += gui-private
+
+SOURCES += tst_qregion.cpp
+
+
+
diff --git a/tests/auto/gui/painting/qregion/tst_qregion.cpp b/tests/auto/gui/painting/qregion/tst_qregion.cpp
new file mode 100644
index 0000000000..58d2034e41
--- /dev/null
+++ b/tests/auto/gui/painting/qregion/tst_qregion.cpp
@@ -0,0 +1,1012 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qregion.h>
+
+#include <qbitmap.h>
+#include <qpainter.h>
+#include <qpolygon.h>
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#endif
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QRegion : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QRegion();
+
+private slots:
+ void boundingRect();
+ void rects();
+ void swap();
+ void setRects();
+ void ellipseRegion();
+ void polygonRegion();
+ void bitmapRegion();
+ void intersected_data();
+ void intersected();
+ void emptyPolygonRegion_data();
+ void emptyPolygonRegion();
+
+ void intersects_region_data();
+ void intersects_region();
+ void intersects_rect_data();
+ void intersects_rect();
+ void contains_point();
+
+ void operator_plus_data();
+ void operator_plus();
+ void operator_minus_data();
+ void operator_minus();
+ void operator_intersect_data();
+ void operator_intersect();
+ void operator_xor_data();
+ void operator_xor();
+
+ void rectCount_data();
+ void rectCount();
+
+ void isEmpty_data();
+ void isEmpty();
+#if defined(Q_WS_X11) && defined(QT_BUILD_INTERNAL)
+ void clipRectangles();
+#endif
+
+ void regionFromPath();
+
+ void regionToPath_data();
+ void regionToPath();
+};
+
+Q_DECLARE_METATYPE(QPolygon)
+Q_DECLARE_METATYPE(QVector<QRect>)
+Q_DECLARE_METATYPE(QRegion)
+
+tst_QRegion::tst_QRegion()
+{
+}
+
+void tst_QRegion::boundingRect()
+{
+ {
+ QRect rect;
+ QRegion region( rect );
+ QCOMPARE( region.boundingRect(), rect );
+ }
+ {
+ QRect rect( 10, -20, 30, 40 );
+ QRegion region( rect );
+ QCOMPARE( region.boundingRect(), rect );
+ }
+ {
+ QRect rect(15,25,10,10);
+ QRegion region( rect );
+ QCOMPARE( region.boundingRect(), rect );
+ }
+
+}
+
+void tst_QRegion::rects()
+{
+ {
+ QRect rect;
+ QRegion region( rect );
+ QVERIFY( region.isEmpty() );
+ QVERIFY( region.rects().isEmpty() );
+ }
+ {
+ QRect rect( 10, -20, 30, 40 );
+ QRegion region( rect );
+ QCOMPARE( region.rects().count(), 1 );
+ QCOMPARE( region.rects()[0], rect );
+ }
+ {
+ QRect r( QPoint(10, 10), QPoint(40, 40) );
+ QRegion region( r );
+ QVERIFY( region.contains( QPoint(10,10) ) );
+ QVERIFY( region.contains( QPoint(20,40) ) );
+ QVERIFY( region.contains( QPoint(40,20) ) );
+ QVERIFY( !region.contains( QPoint(20,41) ) );
+ QVERIFY( !region.contains( QPoint(41,20) ) );
+ }
+ {
+ QRect r( 10, 10, 30, 30 );
+ QRegion region( r );
+ QVERIFY( region.contains( QPoint(10,10) ) );
+ QVERIFY( region.contains( QPoint(20,39) ) );
+ QVERIFY( region.contains( QPoint(39,20) ) );
+ QVERIFY( !region.contains( QPoint(20,40) ) );
+ QVERIFY( !region.contains( QPoint(40,20) ) );
+ }
+}
+
+void tst_QRegion::swap()
+{
+ QRegion r1(QRect( 0, 0,10,10));
+ QRegion r2(QRect(10,10,10,10));
+ r1.swap(r2);
+ QCOMPARE(r1.rects().front(), QRect(10,10,10,10));
+ QCOMPARE(r2.rects().front(), QRect( 0, 0,10,10));
+}
+
+void tst_QRegion::setRects()
+{
+ {
+ QRegion region;
+ region.setRects( 0, 0 );
+ QVERIFY( region.rects().isEmpty() );
+ }
+ {
+ QRegion region;
+ QRect rect;
+ region.setRects( &rect, 0 );
+ QVERIFY(region.isEmpty());
+ QVERIFY(region == QRegion());
+ QVERIFY(!region.boundingRect().isValid());
+ QVERIFY(region.rects().isEmpty());
+ }
+ {
+ QRegion region;
+ QRect rect;
+ region.setRects( &rect, 1 );
+ QVERIFY( !region.boundingRect().isValid() );
+ QVERIFY( region.rects().isEmpty() );
+ }
+ {
+ QRegion region;
+ QRect rect( 10, -20, 30, 40 );
+ region.setRects( &rect, 1 );
+ QCOMPARE( region.rects().count(), 1 );
+ QCOMPARE( region.rects()[0], rect );
+ }
+}
+
+void tst_QRegion::ellipseRegion()
+{
+ QRegion region(0, 0, 100, 100, QRegion::Ellipse);
+
+ // These should not be inside the circe
+ QVERIFY(!region.contains(QPoint(13, 13)));
+ QVERIFY(!region.contains(QPoint(13, 86)));
+ QVERIFY(!region.contains(QPoint(86, 13)));
+ QVERIFY(!region.contains(QPoint(86, 86)));
+
+ // These should be inside
+ QVERIFY(region.contains(QPoint(16, 16)));
+ QVERIFY(region.contains(QPoint(16, 83)));
+ QVERIFY(region.contains(QPoint(83, 16)));
+ QVERIFY(region.contains(QPoint(83, 83)));
+
+ // ..a..
+ // .. ..
+ // . .
+ // . .
+ // b c
+ // . .
+ // . .
+ // .. ..
+ // ..d..
+ QVERIFY(region.contains(QPoint(50, 0))); // Mid-top (a)
+ QVERIFY(region.contains(QPoint(0, 50))); // Mid-left (b)
+ QVERIFY(region.contains(QPoint(99, 50))); // Mid-right (c)
+ QVERIFY(region.contains(QPoint(50, 99))); // Mid-bottom (d)
+
+ QRect bounds = region.boundingRect();
+ QCOMPARE(bounds.x(), 0);
+ QCOMPARE(bounds.y(), 0);
+ QCOMPARE(bounds.width(), 100);
+ QCOMPARE(bounds.height(), 100);
+}
+
+void tst_QRegion::polygonRegion()
+{
+ QPolygon pa;
+ {
+ QRegion region ( pa );
+ QVERIFY( region.isEmpty() );
+ }
+ {
+ pa.setPoints( 8, 10, 10, // a____________b
+ 40, 10, // | |
+ 40, 20, // |___ ___|
+ 30, 20, // | |
+ 30, 40, // | |
+ 20, 40, // | |
+ 20, 20, // |____c
+ 10, 20 );
+
+ QRegion region ( pa );
+ QVERIFY( !region.isEmpty() );
+
+ // These should not be inside the circle
+ QVERIFY( !region.contains( QPoint( 9, 9 ) ) );
+ QVERIFY( !region.contains( QPoint( 30, 41 ) ) );
+ QVERIFY( !region.contains( QPoint( 41, 10 ) ) );
+ QVERIFY( !region.contains( QPoint( 31, 21 ) ) );
+
+ // These should be inside
+ QVERIFY( region.contains( QPoint( 10, 10 ) ) ); // Upper-left (a)
+
+ }
+}
+
+void tst_QRegion::emptyPolygonRegion_data()
+{
+ QTest::addColumn<QPolygon>("pa");
+ QTest::addColumn<bool>("isEmpty");
+ QTest::addColumn<int>("numRects");
+ QTest::addColumn<QVector<QRect> >("rects");
+
+ QPolygon pa;
+
+
+ QTest::newRow("no points") << pa << true << 0 << QVector<QRect>();
+ pa = QPolygon() << QPoint(10,10);
+ QTest::newRow("one point") << pa << true << 0 << QVector<QRect>();
+ pa = QPolygon() << QPoint(10,10) << QPoint(10,20);
+ QTest::newRow("two points, horizontal") << pa << true << 0 << QVector<QRect>();
+
+ pa = QPolygon() << QPoint(10,10) << QPoint(20,10);
+ QTest::newRow("two points, vertical") << pa << true << 0 << QVector<QRect>();
+
+ pa = QPolygon() << QPoint(10,10) << QPoint(20,20);
+ QTest::newRow("two points, diagonal") << pa << true << 0 << QVector<QRect>();
+
+ pa = QPolygon() << QPoint(10,10) << QPoint(15,15) << QPoint(10,15) << QPoint(10, 10) ;
+ QVector<QRect> v;
+ v << QRect(10,11,1, 1) << QRect(10,12,2,1) << QRect(10,13,3,1) << QRect(10,14,4,1);
+ QTest::newRow("triangle") << pa << false << 4 << v;
+
+ v.clear();
+ v << QRect(10,10,10,10);
+
+ QTest::newRow("rectangle") << QPolygon(QRect(10,10,10,10)) << false << 1 << v;
+
+}
+
+void tst_QRegion::emptyPolygonRegion()
+{
+ QFETCH(QPolygon, pa);
+
+ QRegion r(pa);
+ QTEST(r.isEmpty(), "isEmpty");
+ QTEST(r.rects().count(), "numRects");
+ QTEST(r.rects(), "rects");
+}
+
+
+static const char *circle_xpm[] = {
+ "20 20 2 1",
+ " c #FFFFFF",
+ ". c #000000",
+ " ...... ",
+ " .......... ",
+ " .............. ",
+ " ................ ",
+ " ................ ",
+ " .................. ",
+ " .................. ",
+ "....................",
+ "....................",
+ "....................",
+ "....................",
+ "....................",
+ "....................",
+ " .................. ",
+ " .................. ",
+ " ................ ",
+ " ................ ",
+ " .............. ",
+ " .......... ",
+ " ...... "
+};
+
+void tst_QRegion::bitmapRegion()
+{
+ QBitmap circle;
+ {
+ QRegion region( circle );
+ QVERIFY( region.isEmpty() );
+ }
+ {
+ circle = QPixmap( circle_xpm );
+ QRegion region( circle );
+
+ //// These should not be inside the circe
+ QVERIFY( !region.contains( QPoint( 2, 2 ) ) );
+ QVERIFY( !region.contains( QPoint( 2, 17 ) ) );
+ QVERIFY( !region.contains( QPoint( 17, 2 ) ) );
+ QVERIFY( !region.contains( QPoint( 17, 17 ) ) );
+
+ //// These should be inside
+ QVERIFY( region.contains( QPoint( 3, 3 ) ) );
+ QVERIFY( region.contains( QPoint( 3, 16 ) ) );
+ QVERIFY( region.contains( QPoint( 16, 3 ) ) );
+ QVERIFY( region.contains( QPoint( 16, 16 ) ) );
+
+ QVERIFY( region.contains( QPoint( 0, 10 ) ) ); // Mid-left
+ QVERIFY( region.contains( QPoint( 10, 0 ) ) ); // Mid-top
+ QVERIFY( region.contains( QPoint( 19, 10 ) ) ); // Mid-right
+ QVERIFY( region.contains( QPoint( 10, 19 ) ) ); // Mid-bottom
+ }
+}
+
+void tst_QRegion::intersected_data()
+{
+ QTest::addColumn<QRegion>("r1");
+ QTest::addColumn<QRegion>("r2");
+ QTest::addColumn<bool>("intersects");
+ // QTest::addColumn<QRegion>("intersected");
+
+ QPolygon ps1(8);
+ QPolygon ps2(8);
+ ps1.putPoints(0,8, 20,20, 50,20, 50,100, 70,100, 70,20, 120,20, 120,200, 20, 200);
+ ps2.putPoints(0,8, 100,150, 140,150, 140,160, 160,160, 160,150, 200,150, 200,180, 100,180);
+ QTest::newRow("task30716") << QRegion(ps1) << QRegion(ps2) << true;
+}
+
+void tst_QRegion::intersected()
+{
+ QFETCH(QRegion, r1);
+ QFETCH(QRegion, r2);
+ QFETCH(bool, intersects);
+
+ QRegion interReg = r1.intersected(r2);
+ QVERIFY(interReg.isEmpty() != intersects);
+ // Need a way to test the intersected QRegion is right
+}
+
+void tst_QRegion::intersects_region_data()
+{
+ QTest::addColumn<QRegion>("r1");
+ QTest::addColumn<QRegion>("r2");
+ QTest::addColumn<bool>("intersects");
+
+ QTest::newRow("rect overlap rect") << QRegion(100, 100, 200, 200)
+ << QRegion(200, 200, 200, 200)
+ << true;
+
+ QTest::newRow("rect not overlap rect") << QRegion(100, 100, 200, 200)
+ << QRegion(400, 400, 200, 200)
+ << false;
+
+ QTest::newRow("ellipse overlap ellipse") << QRegion(100, 100, 200, 200, QRegion::Ellipse)
+ << QRegion(200, 200, 200, 200, QRegion::Ellipse)
+ << true;
+
+ QTest::newRow("ellipse not overlap ellipse") << QRegion(100, 100, 200, 200, QRegion::Ellipse)
+ << QRegion(400, 400, 200, 200, QRegion::Ellipse)
+ << false;
+}
+
+void tst_QRegion::intersects_region()
+{
+ QFETCH(QRegion, r1);
+ QFETCH(QRegion, r2);
+ QFETCH(bool, intersects);
+ QCOMPARE(r1.intersects(r2), intersects);
+}
+
+
+void tst_QRegion::intersects_rect_data()
+{
+ QTest::addColumn<QRegion>("region");
+ QTest::addColumn<QRect>("rect");
+ QTest::addColumn<bool>("intersects");
+
+ QTest::newRow("rect overlap rect") << QRegion(100, 100, 200, 200)
+ << QRect(200, 200, 200, 200)
+ << true;
+
+ QTest::newRow("rect not overlap rect") << QRegion(100, 100, 200, 200)
+ << QRect(400, 400, 200, 200)
+ << false;
+
+ QTest::newRow("ellipse overlap rect") << QRegion(100, 100, 200, 200, QRegion::Ellipse)
+ << QRect(200, 200, 200, 200)
+ << true;
+
+ QTest::newRow("ellipse not overlap rect") << QRegion(100, 100, 200, 200, QRegion::Ellipse)
+ << QRect(400, 400, 200, 200)
+ << false;
+}
+
+void tst_QRegion::intersects_rect()
+{
+ QFETCH(QRegion, region);
+ QFETCH(QRect, rect);
+ QFETCH(bool, intersects);
+ QCOMPARE(region.intersects(rect), intersects);
+}
+
+void tst_QRegion::contains_point()
+{
+ QCOMPARE(QRegion().contains(QPoint(1,1)),false);
+ QCOMPARE(QRegion(0,0,2,2).contains(QPoint(1,1)),true);
+}
+
+void tst_QRegion::operator_plus_data()
+{
+ QTest::addColumn<QRegion>("r1");
+ QTest::addColumn<QRegion>("r2");
+ QTest::addColumn<QRegion>("expected");
+
+ QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion();
+ QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10))
+ << QRegion(QRect(10, 10, 10, 10));
+ QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion()
+ << QRegion(QRect(10, 10, 10, 10));
+
+ QRegion expected;
+ QVector<QRect> rects;
+ rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10);
+ expected.setRects(rects.constData(), rects.size());
+ QTest::newRow("non overlapping") << QRegion(10, 10, 10, 10)
+ << QRegion(22, 10, 10, 10)
+ << expected;
+
+ rects.clear();
+ rects << QRect(50, 0, 50, 2);
+ expected.setRects(rects.constData(), rects.size());
+ QTest::newRow("adjacent y-rects") << QRegion(50, 0, 50, 1)
+ << QRegion(50, 1, 50, 1)
+ << expected;
+
+ rects.clear();
+ rects << QRect(50, 0, 2, 1);
+ expected.setRects(rects.constData(), rects.size());
+ QTest::newRow("adjacent x-rects") << QRegion(50, 0, 1, 1)
+ << QRegion(51, 0, 1, 1)
+ << expected;
+
+ rects.clear();
+ rects << QRect(10, 10, 10, 10) << QRect(10, 20, 5, 10);
+ QRegion r1;
+ r1.setRects(rects.constData(), rects.size());
+ QTest::newRow("double merge") << r1 << QRegion(15, 20, 5, 10)
+ << QRegion(10, 10, 10, 20);
+ rects.clear();
+ rects << QRect(15, 10, 5, 10) << QRect(10, 20, 10, 10);
+ r1.setRects(rects.constData(), rects.size());
+ QTest::newRow("double merge 2") << r1 << QRegion(10, 10, 5, 10)
+ << QRegion(10, 10, 10, 20);
+ QTest::newRow("overlapping x") << QRegion(10, 10, 10, 10)
+ << QRegion(15, 10, 10, 10)
+ << QRegion(10, 10, 15, 10);
+ QTest::newRow("overlapping y") << QRegion(10, 10, 10, 10)
+ << QRegion(10, 15, 10, 10)
+ << QRegion(10, 10, 10, 15);
+ rects.clear();
+ rects << QRect(10, 10, 10, 10) << QRect(10, 20, 5, 10);
+ r1.setRects(rects.constData(), rects.size());
+ rects.clear();
+ rects << QRect(15, 20, 5, 10) << QRect(10, 30, 10, 10);
+ QRegion r2;
+ r2.setRects(rects.constData(), rects.size());
+ QTest::newRow("triple merge") << r1 << r2
+ << QRegion(10, 10, 10, 30);
+
+ rects.clear();
+ rects << QRect(10, 10, 4, 10) << QRect(15, 10, 10, 10);
+ r1.setRects(rects.constData(), rects.size());
+ rects.clear();
+ rects << QRect(15, 20, 10, 10);
+ r2.setRects(rects.constData(), rects.size());
+ rects.clear();
+ rects << QRect(10, 10, 4, 10) << QRect(15, 10, 10, 10)
+ << QRect(15, 20, 10, 10);
+ expected.setRects(rects.constData(), rects.size());
+ QTest::newRow("don't merge y") << r1 << r2 << expected;
+
+ QTest::newRow("equal 1") << QRegion(10, 10, 10, 10)
+ << QRegion(10, 10, 10, 10)
+ << QRegion(10, 10, 10, 10);
+ QTest::newRow("equal 2") << expected << expected << expected;
+}
+
+void tst_QRegion::operator_plus()
+{
+ QFETCH(QRegion, r1);
+ QFETCH(QRegion, r2);
+ QFETCH(QRegion, expected);
+
+ if (r1 + r2 != expected) {
+ qDebug() << "r1 + r2" << (r1 + r2);
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(r1 + r2, expected);
+ if (r2.rectCount() == 1) {
+ if (r1 + r2.boundingRect() != expected) {
+ qDebug() << "r1 + QRect(r2)" << (r1 + r2.boundingRect());
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(r1 + r2.boundingRect(), expected);
+ }
+
+ if (r2 + r1 != expected) {
+ qDebug() << "r2 + r1" << (r2 + r1);
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(r2 + r1, expected);
+ if (r1.rectCount() == 1) {
+ if (r1 + r2.boundingRect() != expected) {
+ qDebug() << "r2 + QRect(r1)" << (r2 + r1.boundingRect());
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(r2 + r1.boundingRect(), expected);
+ }
+
+ QRegion result1 = r1;
+ result1 += r2;
+ if (result1 != expected) {
+ qDebug() << "r1 += r2" << result1;
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(result1, expected);
+ if (r2.rectCount() == 1) {
+ result1 = r1;
+ result1 += r2.boundingRect();
+ if (result1 != expected) {
+ qDebug() << "r1 += QRect(r2)" << result1;
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(result1, expected);
+ }
+
+ QRegion result2 = r2;
+ result2 += r1;
+ if (result2 != expected) {
+ qDebug() << "r2 += r1" << result2;
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(result2, expected);
+ if (r1.rectCount() == 1) {
+ result2 = r2;
+ result2 += r1.boundingRect();
+ if (result2 != expected) {
+ qDebug() << "r2 += QRect(r1)" << result2;
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(result2, expected);
+ }
+}
+
+void tst_QRegion::operator_minus_data()
+{
+ QTest::addColumn<QRegion>("dest");
+ QTest::addColumn<QRegion>("subtract");
+ QTest::addColumn<QRegion>("expected");
+
+ QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion();
+ QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10))
+ << QRegion();
+ QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion()
+ << QRegion(QRect(10, 10, 10, 10));
+
+ QRegion dest;
+ QVector<QRect> rects;
+ rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10);
+ dest.setRects(rects.constData(), rects.size());
+ QTest::newRow("simple 1") << dest
+ << QRegion(22, 10, 10, 10)
+ << QRegion(10, 10, 10, 10);
+ QTest::newRow("simple 2") << dest
+ << QRegion(10, 10, 10, 10)
+ << QRegion(22, 10, 10, 10);
+
+ rects.clear();
+ rects << QRect(0, 0, 10, 10) << QRect(15, 0, 10, 10);
+ dest.setRects(rects.constData(), rects.size());
+
+ QRegion minus;
+ rects.clear();
+ rects << QRect(0, 0, 12, 12) << QRect(15, 0, 12, 12);
+ minus.setRects(rects.constData(), rects.size());
+ QTest::newRow("empty 3") << dest << minus << QRegion();
+}
+
+void tst_QRegion::operator_minus()
+{
+ QFETCH(QRegion, dest);
+ QFETCH(QRegion, subtract);
+ QFETCH(QRegion, expected);
+
+ if (dest - subtract != expected) {
+ qDebug() << "dest - subtract" << (dest - subtract);
+ qDebug() << "expected" << expected;
+ };
+ QCOMPARE(dest - subtract, expected);
+
+ dest -= subtract;
+
+ if (dest != expected) {
+ qDebug() << "dest" << dest;
+ qDebug() << "expected" << expected;
+ };
+ QCOMPARE(dest, expected);
+}
+
+void tst_QRegion::operator_intersect_data()
+{
+ QTest::addColumn<QRegion>("r1");
+ QTest::addColumn<QRegion>("r2");
+ QTest::addColumn<QRegion>("expected");
+
+ QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion();
+ QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10))
+ << QRegion();
+ QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion()
+ << QRegion();
+
+ QRegion dest;
+ QVector<QRect> rects;
+ rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10);
+ dest.setRects(rects.constData(), rects.size());
+ QTest::newRow("simple 1") << dest
+ << QRegion(22, 10, 10, 10)
+ << QRegion(22, 10, 10, 10);
+ QTest::newRow("simple 2") << dest
+ << QRegion(10, 10, 10, 10)
+ << QRegion(10, 10, 10, 10);
+
+ rects.clear();
+ rects << QRect(10, 10, 10, 10) << QRect(10, 20, 15, 10);
+ dest.setRects(rects.constData(), rects.size());
+ QTest::newRow("merge 1") << dest
+ << QRegion(10, 10, 10, 20)
+ << QRegion(10, 10, 10, 20);
+
+ rects.clear();
+ rects << QRect(11, 11, 218, 117) << QRect(11, 128, 218, 27)
+ << QRect(264, 128, 122, 27) << QRect(11, 155, 218, 43)
+ << QRect(11, 198, 218, 27) << QRect(264, 198, 122, 27)
+ << QRect(11, 225, 218, 221);
+ dest.setRects(rects.constData(), rects.size());
+ QTest::newRow("merge 2") << dest << QRegion(11, 11, 218, 458)
+ << QRegion(11, 11, 218, 435);
+
+ rects.clear();
+ rects << QRect(0, 0, 10, 10) << QRect(20, 0, 10, 10);
+ dest.setRects(rects.constData(), rects.size());
+ QTest::newRow("empty 3") << dest << QRegion(11, 0, 5, 5) << QRegion();
+
+ QTest::newRow("extents check") << dest << QRegion(0, 0, 15, 15)
+ << QRegion(0, 0, 10, 10);
+
+ rects.clear();
+ rects << QRect(10, 10, 10, 10) << QRect(10, 20, 10, 10)
+ << QRect(30, 20, 10, 10) << QRect(10, 30, 10, 10);
+ dest.setRects(rects.constData(), rects.size());
+ rects.clear();
+ rects << QRect(10, 10, 10, 10) << QRect(10, 20, 10, 10)
+ << QRect(30, 20, 10, 10);
+ QRegion expected;
+ expected.setRects(rects.constData(), rects.size());
+ QTest::newRow("dont merge") << dest << QRegion(0, 0, 100, 30)
+ << expected;
+}
+
+void tst_QRegion::operator_intersect()
+{
+ QFETCH(QRegion, r1);
+ QFETCH(QRegion, r2);
+ QFETCH(QRegion, expected);
+
+ if ((r1 & r2) != expected) {
+ qDebug() << "r1 & r2" << (r1 & r2);
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(r1 & r2, expected);
+
+ if ((r2 & r1) != expected) {
+ qDebug() << "r2 & r1" << (r2 & r1);
+ qDebug() << "expected" << expected;
+ }
+ QCOMPARE(r2 & r1, expected);
+
+ r1 &= r2;
+ QCOMPARE(r1, expected);
+}
+
+void tst_QRegion::operator_xor_data()
+{
+ QTest::addColumn<QRegion>("dest");
+ QTest::addColumn<QRegion>("arg");
+ QTest::addColumn<QRegion>("expected");
+
+ QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion();
+ QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10))
+ << QRegion(QRect(10, 10, 10, 10));
+ QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion()
+ << QRegion(QRect(10, 10, 10, 10));
+
+ QRegion dest;
+ QVector<QRect> rects;
+ rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10);
+ dest.setRects(rects.constData(), rects.size());
+ QTest::newRow("simple 1") << dest
+ << QRegion(22, 10, 10, 10)
+ << QRegion(10, 10, 10, 10);
+ QTest::newRow("simple 2") << dest
+ << QRegion(10, 10, 10, 10)
+ << QRegion(22, 10, 10, 10);
+ QTest::newRow("simple 3") << dest << dest << QRegion();
+ QTest::newRow("simple 4") << QRegion(10, 10, 10, 10)
+ << QRegion(10, 10, 5, 10)
+ << QRegion(15, 10, 5, 10);
+ QTest::newRow("simple 5") << QRegion(10, 10, 10, 10)
+ << QRegion(10, 10, 10, 5)
+ << QRegion(10, 15, 10, 5);
+
+ const QRegion rgnA(0, 0, 100, 100);
+ const QRegion rgnB(0, 0, 10, 10);
+
+ QTest::newRow("simple 6") << rgnA
+ << rgnA - rgnB
+ << rgnB;
+
+ QTest::newRow("simple 7") << rgnB
+ << rgnA
+ << rgnA - rgnB;
+}
+
+void tst_QRegion::operator_xor()
+{
+ QFETCH(QRegion, dest);
+ QFETCH(QRegion, arg);
+ QFETCH(QRegion, expected);
+
+ QCOMPARE(dest ^ arg, expected);
+ QCOMPARE(dest.xored(arg), expected);
+
+ dest ^= arg;
+ QCOMPARE(dest, expected);
+}
+
+void tst_QRegion::rectCount_data()
+{
+ QTest::addColumn<QRegion>("region");
+ QTest::addColumn<int>("expected");
+
+ QTest::newRow("empty") << QRegion() << 0;
+ QTest::newRow("rect") << QRegion(10, 10, 10, 10) << 1;
+
+ QRegion dest;
+ QVector<QRect> rects;
+ rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10);
+ dest.setRects(rects.constData(), rects.size());
+
+ QTest::newRow("2 rects") << dest << rects.size();
+}
+
+void tst_QRegion::rectCount()
+{
+ QFETCH(QRegion, region);
+ QFETCH(int, expected);
+
+ QCOMPARE(region.rectCount(), expected);
+}
+
+void tst_QRegion::isEmpty_data()
+{
+ QTest::addColumn<QRegion>("region");
+
+ QTest::newRow("QRegion") << QRegion();
+
+ QVector<QRect> rects;
+ rects << QRect(0, 0, 10, 10) << QRect(15, 0, 10, 10);
+ QRegion r1;
+ r1.setRects(rects.constData(), rects.size());
+
+ QRegion r2;
+ rects.clear();
+ rects << QRect(0, 0, 12, 12) << QRect(15, 0, 12, 12);
+ r2.setRects(rects.constData(), rects.size());
+ QTest::newRow("minus") << (r1 - r2);
+}
+
+void tst_QRegion::isEmpty()
+{
+ QFETCH(QRegion, region);
+
+ QVERIFY(region.isEmpty());
+ QCOMPARE(region, QRegion());
+ QCOMPARE(region.rectCount(), 0);
+ QCOMPARE(region.boundingRect(), QRect());
+ QVERIFY(region.rects().isEmpty());
+}
+
+#if defined(Q_WS_X11) && defined(QT_BUILD_INTERNAL)
+void tst_QRegion::clipRectangles()
+{
+ QRegion region(30, 30, 30, 30);
+ int num = 0;
+ qt_getClipRects(region, num);
+ QCOMPARE(num, 1);
+
+ region += QRegion(10, 10, 10, 10);
+ XRectangle *rects2 = static_cast<XRectangle *>(qt_getClipRects(region, num));
+ QCOMPARE(num, 2);
+
+ // Here's the important part (Y-sorted):
+ QCOMPARE(int(rects2[0].y), 10);
+ QCOMPARE(int(rects2[1].y), 30);
+}
+#endif
+
+void tst_QRegion::regionFromPath()
+{
+ {
+ QPainterPath path;
+ path.addRect(0, 0, 10, 10);
+ path.addRect(0, 100, 100, 1000);
+
+ QRegion rgn(path.toFillPolygon().toPolygon());
+ QCOMPARE(rgn.rects().size(), 2);
+ QCOMPARE(rgn.rects().at(0), QRect(0, 0, 10, 10));
+ QCOMPARE(rgn.rects().at(1), QRect(0, 100, 100, 1000));
+
+ QCOMPARE(rgn.boundingRect(), QRect(0, 0, 100, 1100));
+ }
+
+ {
+ QPainterPath path;
+ path.addRect(0, 0, 100, 100);
+ path.addRect(10, 10, 80, 80);
+
+ QRegion rgn(path.toFillPolygon().toPolygon());
+ QCOMPARE(rgn.rects().size(), 4);
+
+ QCOMPARE(rgn.rects().at(0), QRect(0, 0, 100, 10));
+ QCOMPARE(rgn.rects().at(1), QRect(0, 10, 10, 80));
+ QCOMPARE(rgn.rects().at(2), QRect(90, 10, 10, 80));
+ QCOMPARE(rgn.rects().at(3), QRect(0, 90, 100, 10));
+
+ QCOMPARE(rgn.boundingRect(), QRect(0, 0, 100, 100));
+ }
+}
+
+Q_DECLARE_METATYPE(QPainterPath)
+
+void tst_QRegion::regionToPath_data()
+{
+ QTest::addColumn<QPainterPath>("path");
+ {
+ QPainterPath path;
+ path.addRect(QRect(0, 0, 10, 10));
+
+ QTest::newRow("Rectangle") << path;
+ }
+
+ {
+ QPainterPath path;
+ path.addRect(QRect(0, 0, 10, 10));
+ path.addRect(QRect(20, 0, 10, 10));
+
+ QTest::newRow("Two rects") << path;
+ }
+
+ {
+ QPainterPath path;
+ path.addEllipse(QRect(0, 0, 10, 10));
+
+ QTest::newRow("Ellipse") << path;
+ }
+
+ {
+ QPainterPath path;
+ path.addRect(QRect(0, 0, 3, 8));
+ path.addRect(QRect(6, 0, 3, 8));
+ path.addRect(QRect(3, 3, 3, 2));
+ path.addRect(QRect(12, 3, 3, 2));
+
+ QTest::newRow("H-dot") << path;
+ }
+
+ {
+ QPainterPath path;
+ for (int y = 0; y <= 10; ++y) {
+ for (int x = 0; x <= 10; ++x) {
+ if (!(y & 1) || ((x ^ y) & 1))
+ path.addRect(QRect(x, y, 1, 1));
+ }
+ }
+
+ QTest::newRow("Grid") << path;
+ }
+}
+
+#ifdef QT_BUILD_INTERNAL
+QT_BEGIN_NAMESPACE
+extern QPainterPath qt_regionToPath(const QRegion &region);
+QT_END_NAMESPACE
+#endif
+
+void tst_QRegion::regionToPath()
+{
+#ifdef QT_BUILD_INTERNAL
+
+ QFETCH(QPainterPath, path);
+
+ for (int i = 0; i < 360; i += 10) {
+
+ QTransform transform;
+ transform.scale(5, 5);
+ transform.rotate(i);
+
+ QPainterPath mapped = transform.map(path);
+ QRegion region(mapped.toFillPolygon().toPolygon());
+
+ QPainterPath a;
+ a.addRegion(region);
+
+ QPainterPath b = qt_regionToPath(region);
+
+ QRect r = a.boundingRect().toAlignedRect();
+ QImage ia(r.size(), QImage::Format_RGB32);
+ ia.fill(0xffffffff);
+ QImage ib = ia;
+
+ QPainter p(&ia);
+ p.translate(-r.x(), -r.y());
+ p.fillPath(a, Qt::red);
+ p.end();
+ p.begin(&ib);
+ p.translate(-r.x(), -r.y());
+ p.fillPath(b, Qt::red);
+ p.end();
+
+ QCOMPARE(ia, ib);
+ QCOMPARE(a.boundingRect(), b.boundingRect());
+ }
+#endif
+}
+
+QTEST_MAIN(tst_QRegion)
+#include "tst_qregion.moc"
diff --git a/tests/auto/gui/painting/qtransform/.gitignore b/tests/auto/gui/painting/qtransform/.gitignore
new file mode 100644
index 0000000000..f1da0161e7
--- /dev/null
+++ b/tests/auto/gui/painting/qtransform/.gitignore
@@ -0,0 +1 @@
+tst_qtransform
diff --git a/tests/auto/gui/painting/qtransform/qtransform.pro b/tests/auto/gui/painting/qtransform/qtransform.pro
new file mode 100644
index 0000000000..92bef8ce38
--- /dev/null
+++ b/tests/auto/gui/painting/qtransform/qtransform.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+HEADERS +=
+SOURCES += tst_qtransform.cpp
+
+unix:!mac:!symbian:LIBS+=-lm
+
+
diff --git a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp
new file mode 100644
index 0000000000..f8319c9e13
--- /dev/null
+++ b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp
@@ -0,0 +1,807 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "qtransform.h"
+#include <math.h>
+#include <qpolygon.h>
+#include <qdebug.h>
+
+Q_DECLARE_METATYPE(QRect)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTransform : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTransform();
+ virtual ~tst_QTransform();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void mapRect_data();
+ void operator_star_qrect_data();
+ void mapToPolygon_data();
+ void mapRect();
+ void operator_star_qrect();
+ void assignments();
+ void mapToPolygon();
+ void translate();
+ void scale();
+ void matrix();
+ void testOffset();
+ void types();
+ void scalarOps();
+ void transform();
+ void mapEmptyPath();
+ void boundingRect();
+ void controlPointRect();
+ void inverted_data();
+ void inverted();
+ void projectivePathMapping();
+ void mapInt();
+ void mapPathWithPoint();
+
+private:
+ void mapping_data();
+};
+
+Q_DECLARE_METATYPE(QTransform)
+Q_DECLARE_METATYPE(QPolygon)
+
+tst_QTransform::tst_QTransform()
+{
+}
+
+tst_QTransform::~tst_QTransform()
+{
+}
+
+void tst_QTransform::init()
+{
+ // No initialisation is required
+}
+
+void tst_QTransform::cleanup()
+{
+ // No cleanup is required.
+}
+
+#if defined(Q_OS_WIN) && !defined(M_PI)
+#define M_PI 3.14159265897932384626433832795f
+#endif
+
+void tst_QTransform::mapRect_data()
+{
+ mapping_data();
+
+ // rotations that are not multiples of 90 degrees. mapRect returns the bounding rect here.
+ qreal deg = -45;
+ QTest::newRow( "rot 45 a" )
+ << QTransform().rotate(deg)
+ << QRect( 0, 0, 10, 10 )
+ << QPolygon( QRect( 0, -7, 14, 14 ) );
+ QTest::newRow( "rot 45 b" )
+ << QTransform().rotate(deg)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 21, -14, 50, 49 ) );
+ QTest::newRow( "rot 45 c" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 0, 0, 10, 10 )
+ << QPolygon( QRect( 0, -71, 141, 142 ) );
+ QTest::newRow( "rot 45 d" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 212, -141, 495, 495 ) );
+
+ deg = 45;
+ QTest::newRow( "rot -45 a" )
+ << QTransform().rotate(deg)
+ << QRect( 0, 0, 10, 10 )
+ << QPolygon( QRect( -7, 0, 14, 14 ) );
+ QTest::newRow( "rot -45 b" )
+ << QTransform().rotate(deg)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -35, 21, 49, 50 ) );
+ QTest::newRow( "rot -45 c" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 0, 0, 10, 10 )
+ << QPolygon( QRect( -71, 0, 142, 141 ) );
+ QTest::newRow( "rot -45 d" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -354, 212, 495, 495 ) );
+}
+
+void tst_QTransform::operator_star_qrect_data()
+{
+ mapping_data();
+}
+
+void tst_QTransform::mapToPolygon_data()
+{
+ mapping_data();
+}
+
+void tst_QTransform::mapping_data()
+{
+ //create the testtable instance and define the elements
+ QTest::addColumn<QTransform>("matrix");
+ QTest::addColumn<QRect>("src");
+ QTest::addColumn<QPolygon>("res");
+
+ //next we fill it with data
+
+ // identity
+ QTest::newRow( "identity" )
+ << QTransform()
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 10, 20, 30, 40 ) );
+ // scaling
+ QTest::newRow( "scale 0" )
+ << QTransform().scale(2, 2)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 20, 40, 60, 80 ) );
+ QTest::newRow( "scale 1" )
+ << QTransform().scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 100, 200, 300, 400 ) );
+ // mirroring
+ QTest::newRow( "mirror 0" )
+ << QTransform().scale(-1, 1)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -40, 20, 30, 40 ) );
+ QTest::newRow( "mirror 1" )
+ << QTransform().scale(1, -1)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 10, -60, 30, 40 ) );
+ QTest::newRow( "mirror 2" )
+ << QTransform().scale(-1, -1)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -40, -60, 30, 40 ) );
+ QTest::newRow( "mirror 3" )
+ << QTransform().scale(-2, -2)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -80, -120, 60, 80 ) );
+ QTest::newRow( "mirror 4" )
+ << QTransform().scale(-10, -10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -400, -600, 300, 400 ) );
+ QTest::newRow( "mirror 5" )
+ << QTransform().scale(-1, 1)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -30, 0, 30, 40 ) );
+ QTest::newRow( "mirror 6" )
+ << QTransform().scale(1, -1)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( 0, -40, 30, 40 ) );
+ QTest::newRow( "mirror 7" )
+ << QTransform().scale(-1, -1)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -30, -40, 30, 40 ) );
+ QTest::newRow( "mirror 8" )
+ << QTransform().scale(-2, -2)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -60, -80, 60, 80 ) );
+ QTest::newRow( "mirror 9" )
+ << QTransform().scale(-10, -10) << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -300, -400, 300, 400 ) );
+
+ // rotations
+ float deg = 0.;
+ QTest::newRow( "rot 0 a" )
+ << QTransform().rotate(deg)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon ( QRect( 0, 0, 30, 40 ) );
+ deg = 0.00001f;
+ QTest::newRow( "rot 0 b" )
+ << QTransform().rotate(deg)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon ( QRect( 0, 0, 30, 40 ) );
+ deg = 0.;
+ QTest::newRow( "rot 0 c" )
+ << QTransform().rotate(deg)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon ( QRect( 10, 20, 30, 40 ) );
+ deg = 0.00001f;
+ QTest::newRow( "rot 0 d" )
+ << QTransform().rotate(deg)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon ( QRect( 10, 20, 30, 40 ) );
+
+ // rotations
+ deg = -90.f;
+ QTest::newRow( "rotscale 90 a" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( 0, -300, 400, 300 ) );
+ deg = -90.00001f;
+ QTest::newRow( "rotscale 90 b" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( 0, -300, 400, 300 ) );
+ deg = -90.f;
+ QTest::newRow( "rotscale 90 c" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 200, -400, 400, 300 ) );
+ deg = -90.00001f;
+ QTest::newRow( "rotscale 90 d" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 200, -400, 400, 300 ) );
+
+ deg = 180.f;
+ QTest::newRow( "rotscale 180 a" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -300, -400, 300, 400 ) );
+ deg = 180.000001f;
+ QTest::newRow( "rotscale 180 b" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -300, -400, 300, 400 ) );
+ deg = 180.f;
+ QTest::newRow( "rotscale 180 c" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -400, -600, 300, 400 ) );
+ deg = 180.000001f;
+ QTest::newRow( "rotscale 180 d" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -400, -600, 300, 400 ) );
+
+ deg = -270.f;
+ QTest::newRow( "rotscale 270 a" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -400, 0, 400, 300 ) );
+ deg = -270.0000001f;
+ QTest::newRow( "rotscale 270 b" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -400, 0, 400, 300 ) );
+ deg = -270.f;
+ QTest::newRow( "rotscale 270 c" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -600, 100, 400, 300 ) );
+ deg = -270.000001f;
+ QTest::newRow( "rotscale 270 d" )
+ << QTransform().rotate(deg).scale(10, 10)
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -600, 100, 400, 300 ) );
+}
+
+void tst_QTransform::mapRect()
+{
+ QFETCH( QTransform, matrix );
+ QFETCH( QRect, src );
+ QFETCH( QPolygon, res );
+ QRect mapped = matrix.mapRect(src);
+ QCOMPARE( mapped, res.boundingRect().adjusted(0, 0, -1, -1) );
+
+ QRectF r = matrix.mapRect(QRectF(src));
+ QRect ir(r.topLeft().toPoint(), r.bottomRight().toPoint() - QPoint(1, 1));
+ QCOMPARE( mapped, ir );
+}
+
+void tst_QTransform::operator_star_qrect()
+{
+#if 0
+ QFETCH( QTransform, matrix );
+ QFETCH( QRect, src );
+ QFETCH( QPolygon, res );
+
+ QCOMPARE( (matrix * src), QRegion(res) );
+#endif
+}
+
+void tst_QTransform::assignments()
+{
+ QTransform m;
+ m.scale(2, 3);
+ m.rotate(45);
+ m.shear(4, 5);
+
+ QTransform c1(m);
+
+ QCOMPARE(m.m11(), c1.m11());
+ QCOMPARE(m.m12(), c1.m12());
+ QCOMPARE(m.m21(), c1.m21());
+ QCOMPARE(m.m22(), c1.m22());
+ QCOMPARE(m.dx(), c1.dx());
+ QCOMPARE(m.dy(), c1.dy());
+
+ QTransform c2 = m;
+ QCOMPARE(m.m11(), c2.m11());
+ QCOMPARE(m.m12(), c2.m12());
+ QCOMPARE(m.m21(), c2.m21());
+ QCOMPARE(m.m22(), c2.m22());
+ QCOMPARE(m.dx(), c2.dx());
+ QCOMPARE(m.dy(), c2.dy());
+}
+
+
+void tst_QTransform::mapToPolygon()
+{
+ QFETCH( QTransform, matrix );
+ QFETCH( QRect, src );
+ QFETCH( QPolygon, res );
+
+ QPolygon poly = matrix.mapToPolygon(src);
+
+ // don't care about starting point
+ bool equal = false;
+ for (int i = 0; i < poly.size(); ++i) {
+ QPolygon rot;
+ for (int j = i; j < poly.size(); ++j)
+ rot << poly[j];
+ for (int j = 0; j < i; ++j)
+ rot << poly[j];
+ if (rot == res)
+ equal = true;
+ }
+
+ QVERIFY(equal);
+}
+
+
+void tst_QTransform::translate()
+{
+ QTransform m( 1, 2, 3, 4, 5, 6 );
+ QTransform res2( m );
+ QTransform res( 1, 2, 3, 4, 75, 106 );
+ m.translate( 10, 20 );
+ QVERIFY( m == res );
+ m.translate( -10, -20 );
+ QVERIFY( m == res2 );
+ QVERIFY( QTransform::fromTranslate( 0, 0 ).type() == QTransform::TxNone );
+ QVERIFY( QTransform::fromTranslate( 10, 0 ).type() == QTransform::TxTranslate );
+ QVERIFY( QTransform::fromTranslate( -1, 5 ) == QTransform().translate( -1, 5 ));
+ QVERIFY( QTransform::fromTranslate( 0, 0 ) == QTransform());
+}
+
+void tst_QTransform::scale()
+{
+ QTransform m( 1, 2, 3, 4, 5, 6 );
+ QTransform res2( m );
+ QTransform res( 10, 20, 60, 80, 5, 6 );
+ m.scale( 10, 20 );
+ QVERIFY( m == res );
+ m.scale( 1./10., 1./20. );
+ QVERIFY( m == res2 );
+ QVERIFY( QTransform::fromScale( 1, 1 ).type() == QTransform::TxNone );
+ QVERIFY( QTransform::fromScale( 2, 4 ).type() == QTransform::TxScale );
+ QVERIFY( QTransform::fromScale( 2, 4 ) == QTransform().scale( 2, 4 ));
+ QVERIFY( QTransform::fromScale( 1, 1 ) == QTransform());
+}
+
+void tst_QTransform::matrix()
+{
+ QMatrix mat1;
+ mat1.scale(0.3, 0.7);
+ mat1.translate(53.3, 94.4);
+ mat1.rotate(45);
+
+ QMatrix mat2;
+ mat2.rotate(33);
+ mat2.scale(0.6, 0.6);
+ mat2.translate(13.333, 7.777);
+
+ QTransform tran1(mat1);
+ QTransform tran2(mat2);
+ QTransform dummy;
+ dummy.setMatrix(mat1.m11(), mat1.m12(), 0,
+ mat1.m21(), mat1.m22(), 0,
+ mat1.dx(), mat1.dy(), 1);
+
+ QVERIFY(tran1 == dummy);
+ QVERIFY(tran1.inverted() == dummy.inverted());
+ QVERIFY(tran1.inverted() == QTransform(mat1.inverted()));
+ QVERIFY(tran2.inverted() == QTransform(mat2.inverted()));
+
+ QMatrix mat3 = mat1 * mat2;
+ QTransform tran3 = tran1 * tran2;
+ QVERIFY(QTransform(mat3) == tran3);
+
+ /* QMatrix::operator==() doesn't use qFuzzyCompare(), which
+ * on win32-g++ results in a failure. So we work around it by
+ * calling QTranform::operator==(), which performs a fuzzy compare. */
+ QCOMPARE(QTransform(mat3), QTransform(tran3.toAffine()));
+
+ QTransform tranInv = tran1.inverted();
+ QMatrix matInv = mat1.inverted();
+
+ QRect rect(43, 70, 200, 200);
+ QPoint pt(43, 66);
+ QVERIFY(tranInv.map(pt) == matInv.map(pt));
+ QVERIFY(tranInv.map(pt) == matInv.map(pt));
+
+ QPainterPath path;
+ path.moveTo(55, 60);
+ path.lineTo(110, 110);
+ path.quadTo(220, 50, 10, 20);
+ path.closeSubpath();
+ QVERIFY(tranInv.map(path) == matInv.map(path));
+}
+
+void tst_QTransform::testOffset()
+{
+ QTransform trans;
+ const QMatrix &aff = trans.toAffine();
+ QCOMPARE((void*)(&aff), (void*)(&trans));
+}
+
+void tst_QTransform::types()
+{
+ QTransform m1;
+ QCOMPARE(m1.type(), QTransform::TxNone);
+
+ m1.translate(1.0f, 0.0f);
+ QCOMPARE(m1.type(), QTransform::TxTranslate);
+ QCOMPARE(m1.inverted().type(), QTransform::TxTranslate);
+
+ m1.scale(1.0f, 2.0f);
+ QCOMPARE(m1.type(), QTransform::TxScale);
+ QCOMPARE(m1.inverted().type(), QTransform::TxScale);
+
+ m1.rotate(45.0f);
+ QCOMPARE(m1.type(), QTransform::TxRotate);
+ QCOMPARE(m1.inverted().type(), QTransform::TxRotate);
+
+ m1.shear(0.5f, 0.25f);
+ QCOMPARE(m1.type(), QTransform::TxShear);
+ QCOMPARE(m1.inverted().type(), QTransform::TxShear);
+
+ m1.rotate(45.0f, Qt::XAxis);
+ QCOMPARE(m1.type(), QTransform::TxProject);
+ m1.shear(0.5f, 0.25f);
+ QCOMPARE(m1.type(), QTransform::TxProject);
+ m1.rotate(45.0f);
+ QCOMPARE(m1.type(), QTransform::TxProject);
+ m1.scale(1.0f, 2.0f);
+ QCOMPARE(m1.type(), QTransform::TxProject);
+ m1.translate(1.0f, 0.0f);
+ QCOMPARE(m1.type(), QTransform::TxProject);
+
+ QTransform m2(1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ -1.0f, -1.0f, 1.0f);
+
+ QCOMPARE(m2.type(), QTransform::TxTranslate);
+ QCOMPARE((m1 * m2).type(), QTransform::TxProject);
+
+ m1 *= QTransform();
+ QCOMPARE(m1.type(), QTransform::TxProject);
+
+ m1 *= QTransform(1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 1.0f);
+ QCOMPARE(m1.type(), QTransform::TxProject);
+
+ m2.reset();
+ QCOMPARE(m2.type(), QTransform::TxNone);
+
+ m2.setMatrix(1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f);
+ QCOMPARE(m2.type(), QTransform::TxNone);
+
+ m2 *= QTransform();
+ QCOMPARE(m2.type(), QTransform::TxNone);
+
+ m2.setMatrix(2.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f);
+ QCOMPARE(m2.type(), QTransform::TxScale);
+ m2 *= QTransform();
+ QCOMPARE(m2.type(), QTransform::TxScale);
+
+ m2.setMatrix(0.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f);
+ QCOMPARE(m2.type(), QTransform::TxRotate);
+ m2 *= QTransform();
+ QCOMPARE(m2.type(), QTransform::TxRotate);
+
+ m2.setMatrix(1.0f, 0.0f, 0.5f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f);
+ QCOMPARE(m2.type(), QTransform::TxProject);
+ m2 *= QTransform();
+ QCOMPARE(m2.type(), QTransform::TxProject);
+
+ m2.setMatrix(1.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f);
+ QCOMPARE(m2.type(), QTransform::TxShear);
+
+ m2 *= m2.inverted();
+ QCOMPARE(m2.type(), QTransform::TxNone);
+
+ m2.translate(5.0f, 5.0f);
+ m2.rotate(45.0f);
+ m2.rotate(-45.0f);
+ QCOMPARE(m2.type(), QTransform::TxTranslate);
+
+ m2.scale(2.0f, 3.0f);
+ m2.shear(1.0f, 0.0f);
+ m2.shear(-1.0f, 0.0f);
+ QCOMPARE(m2.type(), QTransform::TxScale);
+
+ m2 *= QTransform(1.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f);
+ QCOMPARE(m2.type(), QTransform::TxShear);
+
+ m2 *= QTransform(1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 1.0f);
+ QCOMPARE(m2.type(), QTransform::TxShear);
+
+ QTransform m3(1.8f, 0.0f, 0.0f,
+ 0.0f, 1.8f, 0.0f,
+ 0.0f, 0.0f, 1.0f);
+
+ QCOMPARE(m3.type(), QTransform::TxScale);
+ m3.translate(5.0f, 5.0f);
+ QCOMPARE(m3.type(), QTransform::TxScale);
+ QCOMPARE(m3.inverted().type(), QTransform::TxScale);
+
+ m3.setMatrix(1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f);
+ QCOMPARE(m3.type(), QTransform::TxProject);
+
+ m3.setMatrix(0.0f, 2.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f);
+ QCOMPARE(m3.type(), QTransform::TxProject);
+
+ QTransform m4;
+ m4.scale(5, 5);
+ m4.translate(4, 2);
+ m4.rotate(45);
+
+ QCOMPARE(m4.type(), QTransform::TxRotate);
+
+ QTransform m5;
+ m5.scale(5, 5);
+ m5 = m5.adjoint() / m5.determinant();
+ QCOMPARE(m5.type(), QTransform::TxScale);
+}
+
+
+void tst_QTransform::scalarOps()
+{
+ QTransform t;
+ QCOMPARE(t.m11(), 1.);
+ QCOMPARE(t.m33(), 1.);
+ QCOMPARE(t.m21(), 0.);
+
+ t = QTransform() + 3;
+ QCOMPARE(t.m11(), 4.);
+ QCOMPARE(t.m33(), 4.);
+ QCOMPARE(t.m21(), 3.);
+
+ t = t - 3;
+ QCOMPARE(t.m11(), 1.);
+ QCOMPARE(t.m33(), 1.);
+ QCOMPARE(t.m21(), 0.);
+ QCOMPARE(t.isIdentity(), true);
+
+ t += 3;
+ t = t * 2;
+ QCOMPARE(t.m11(), 8.);
+ QCOMPARE(t.m33(), 8.);
+ QCOMPARE(t.m21(), 6.);
+}
+
+void tst_QTransform::transform()
+{
+ QTransform t;
+ t.rotate(30, Qt::YAxis);
+ t.translate(15, 10);
+ t.scale(2, 2);
+ t.rotate(30);
+ t.shear(0.5, 0.5);
+
+ QTransform a, b, c, d, e;
+ a.rotate(30, Qt::YAxis);
+ b.translate(15, 10);
+ c.scale(2, 2);
+ d.rotate(30);
+ e.shear(0.5, 0.5);
+
+ QVERIFY(qFuzzyCompare(t, e * d * c * b * a));
+}
+
+void tst_QTransform::mapEmptyPath()
+{
+ QPainterPath path;
+ path.moveTo(10, 10);
+ path.lineTo(10, 10);
+ QCOMPARE(QTransform().map(path), path);
+}
+
+void tst_QTransform::boundingRect()
+{
+ QPainterPath path;
+ path.moveTo(10, 10);
+ path.lineTo(10, 10);
+ QCOMPARE(path.boundingRect(), QRectF(10, 10, 0, 0));
+}
+
+void tst_QTransform::controlPointRect()
+{
+ QPainterPath path;
+ path.moveTo(10, 10);
+ path.lineTo(10, 10);
+ QCOMPARE(path.controlPointRect(), QRectF(10, 10, 0, 0));
+}
+
+void tst_QTransform::inverted_data()
+{
+ QTest::addColumn<QTransform>("matrix");
+
+ QTest::newRow("identity")
+ << QTransform();
+
+ QTest::newRow("TxTranslate")
+ << QTransform().translate(200, 10);
+
+ QTest::newRow("TxScale")
+ << QTransform().scale(5, 2);
+
+ QTest::newRow("TxTranslate TxScale")
+ << QTransform().translate(100, -10).scale(40, 2);
+
+ QTest::newRow("TxScale TxTranslate")
+ << QTransform().scale(40, 2).translate(100, -10);
+
+ QTest::newRow("TxRotate")
+ << QTransform().rotate(40, Qt::ZAxis);
+
+ QTest::newRow("TxRotate TxScale")
+ << QTransform().rotate(60, Qt::ZAxis).scale(2, 0.25);
+
+ QTest::newRow("TxScale TxRotate")
+ << QTransform().scale(2, 0.25).rotate(30, Qt::ZAxis);
+
+ QTest::newRow("TxRotate TxScale TxTranslate")
+ << QTransform().rotate(60, Qt::ZAxis).scale(2, 0.25).translate(200, -3000);
+
+ QTest::newRow("TxRotate TxTranslate TxScale")
+ << QTransform().rotate(60, Qt::ZAxis).translate(200, -3000).scale(19, 77);
+
+ QTest::newRow("TxShear")
+ << QTransform().shear(10, 10);
+
+ QTest::newRow("TxShear TxRotate")
+ << QTransform().shear(10, 10).rotate(45, Qt::ZAxis);
+
+ QTest::newRow("TxShear TxRotate TxScale")
+ << QTransform().shear(10, 10).rotate(45, Qt::ZAxis).scale(19, 81);
+
+ QTest::newRow("TxTranslate TxShear TxRotate TxScale")
+ << QTransform().translate(150, -1).shear(10, 10).rotate(45, Qt::ZAxis).scale(19, 81);
+
+ const qreal s = 500000;
+
+ QTransform big;
+ big.scale(s, s);
+
+ QTest::newRow("big") << big;
+
+ QTransform smallTransform;
+ smallTransform.scale(1/s, 1/s);
+
+ QTest::newRow("small") << smallTransform;
+}
+
+void tst_QTransform::inverted()
+{
+ if (sizeof(qreal) != sizeof(double))
+ QSKIP("precision error if qreal is not double", SkipAll);
+
+ QFETCH(QTransform, matrix);
+
+ const QTransform inverted = matrix.inverted();
+
+ QVERIFY(matrix.isIdentity() == inverted.isIdentity());
+ QVERIFY(matrix.type() == inverted.type());
+
+ QVERIFY((matrix * inverted).isIdentity());
+ QVERIFY((inverted * matrix).isIdentity());
+}
+
+void tst_QTransform::projectivePathMapping()
+{
+ QPainterPath path;
+ path.addRect(-50, -50, 100, 100);
+
+ const QRectF view(0, 0, 1024, 1024);
+
+ QVERIFY(view.intersects(path.boundingRect()));
+
+ for (int i = 0; i < 85; i += 5) {
+ QTransform transform;
+ transform.translate(512, 512);
+ transform.rotate(i, Qt::YAxis);
+
+ const QPainterPath mapped = transform.map(path);
+
+ QVERIFY(view.intersects(mapped.boundingRect()));
+ QVERIFY(transform.inverted().mapRect(view).intersects(path.boundingRect()));
+ }
+}
+
+void tst_QTransform::mapInt()
+{
+ int x = 0;
+ int y = 0;
+
+ QTransform::fromTranslate(10, 10).map(x, y, &x, &y);
+
+ QCOMPARE(x, 10);
+ QCOMPARE(y, 10);
+}
+
+void tst_QTransform::mapPathWithPoint()
+{
+ QPainterPath p(QPointF(10, 10));
+ p = QTransform::fromTranslate(10, 10).map(p);
+ QCOMPARE(p.currentPosition(), QPointF(20, 20));
+}
+
+QTEST_APPLESS_MAIN(tst_QTransform)
+
+
+#include "tst_qtransform.moc"
diff --git a/tests/auto/gui/painting/qwmatrix/.gitignore b/tests/auto/gui/painting/qwmatrix/.gitignore
new file mode 100644
index 0000000000..c983191769
--- /dev/null
+++ b/tests/auto/gui/painting/qwmatrix/.gitignore
@@ -0,0 +1 @@
+tst_qwmatrix
diff --git a/tests/auto/gui/painting/qwmatrix/qwmatrix.pro b/tests/auto/gui/painting/qwmatrix/qwmatrix.pro
new file mode 100644
index 0000000000..bab298bc93
--- /dev/null
+++ b/tests/auto/gui/painting/qwmatrix/qwmatrix.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+SOURCES += tst_qwmatrix.cpp
+
+unix:!mac:!symbian:LIBS+=-lm
+
+
diff --git a/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp
new file mode 100644
index 0000000000..0e7372d9d8
--- /dev/null
+++ b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp
@@ -0,0 +1,436 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qmatrix.h>
+#include <math.h>
+#include <qpolygon.h>
+
+Q_DECLARE_METATYPE(QRect)
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/painting/qmatrix.h gui/painting/qmatrix.cpp
+
+class tst_QWMatrix : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWMatrix();
+ virtual ~tst_QWMatrix();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void mapRect_data();
+ void operator_star_qrect_data();
+ void mapToPolygon_data();
+ void mapRect();
+ void operator_star_qrect();
+ void operator_star_qwmatrix();
+ void assignments();
+ void mapToPolygon();
+ void translate();
+ void scale();
+ void mapPolygon();
+
+private:
+ void mapping_data();
+};
+
+Q_DECLARE_METATYPE(QMatrix)
+Q_DECLARE_METATYPE(QPolygon)
+
+tst_QWMatrix::tst_QWMatrix()
+{
+}
+
+tst_QWMatrix::~tst_QWMatrix()
+{
+}
+
+void tst_QWMatrix::init()
+{
+ // No initialisation is required
+}
+
+void tst_QWMatrix::cleanup()
+{
+ // No cleanup is required.
+}
+
+void tst_QWMatrix::mapRect_data()
+{
+ mapping_data();
+}
+
+void tst_QWMatrix::operator_star_qrect_data()
+{
+ mapping_data();
+}
+
+void tst_QWMatrix::mapToPolygon_data()
+{
+ mapping_data();
+}
+
+void tst_QWMatrix::mapping_data()
+{
+ //create the testtable instance and define the elements
+ QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QRect>("src");
+ QTest::addColumn<QPolygon>("res");
+
+ //next we fill it with data
+
+ // identity
+ QTest::newRow( "identity" ) << QMatrix( 1, 0, 0, 1, 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 10, 20, 30, 40 ) );
+ // scaling
+ QTest::newRow( "scale 0" ) << QMatrix( 2, 0, 0, 2, 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 20, 40, 60, 80 ) );
+ QTest::newRow( "scale 1" ) << QMatrix( 10, 0, 0, 10, 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 100, 200, 300, 400 ) );
+ // mirroring
+ QTest::newRow( "mirror 0" ) << QMatrix( -1, 0, 0, 1, 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -40, 20, 30, 40 ) );
+ QTest::newRow( "mirror 1" ) << QMatrix( 1, 0, 0, -1, 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 10, -60, 30, 40 ) );
+ QTest::newRow( "mirror 2" ) << QMatrix( -1, 0, 0, -1, 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -40, -60, 30, 40 ) );
+ QTest::newRow( "mirror 3" ) << QMatrix( -2, 0, 0, -2, 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -80, -120, 60, 80 ) );
+ QTest::newRow( "mirror 4" ) << QMatrix( -10, 0, 0, -10, 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -400, -600, 300, 400 ) );
+ QTest::newRow( "mirror 5" ) << QMatrix( -1, 0, 0, 1, 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -30, 0, 30, 40 ) );
+ QTest::newRow( "mirror 6" ) << QMatrix( 1, 0, 0, -1, 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( 0, -40, 30, 40 ) );
+ QTest::newRow( "mirror 7" ) << QMatrix( -1, 0, 0, -1, 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -30, -40, 30, 40 ) );
+ QTest::newRow( "mirror 8" ) << QMatrix( -2, 0, 0, -2, 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -60, -80, 60, 80 ) );
+ QTest::newRow( "mirror 9" ) << QMatrix( -10, 0, 0, -10, 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -300, -400, 300, 400 ) );
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+#define M_PI 3.14159265897932384626433832795f
+#endif
+
+ // rotations
+ float deg = 0.;
+ QTest::newRow( "rot 0 a" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ),
+ sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon ( QRect( 0, 0, 30, 40 ) );
+ deg = 0.00001f;
+ QTest::newRow( "rot 0 b" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ),
+ sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon ( QRect( 0, 0, 30, 40 ) );
+ deg = 0.;
+ QTest::newRow( "rot 0 c" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ),
+ sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon ( QRect( 10, 20, 30, 40 ) );
+ deg = 0.00001f;
+ QTest::newRow( "rot 0 d" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ),
+ sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon ( QRect( 10, 20, 30, 40 ) );
+
+#if 0
+ // rotations
+ deg = 90.;
+ QTest::newRow( "rotscale 90 a" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( 0, -299, 400, 300 ) );
+ deg = 90.00001;
+ QTest::newRow( "rotscale 90 b" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( 0, -299, 400, 300 ) );
+ deg = 90.;
+ QTest::newRow( "rotscale 90 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 200, -399, 400, 300 ) );
+ deg = 90.00001;
+ QTest::newRow( "rotscale 90 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 200, -399, 400, 300 ) );
+
+ deg = 180.;
+ QTest::newRow( "rotscale 180 a" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -299, -399, 300, 400 ) );
+ deg = 180.000001;
+ QTest::newRow( "rotscale 180 b" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -299, -399, 300, 400 ) );
+ deg = 180.;
+ QTest::newRow( "rotscale 180 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -399, -599, 300, 400 ) );
+ deg = 180.000001;
+ QTest::newRow( "rotscale 180 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -399, -599, 300, 400 ) );
+
+ deg = 270.;
+ QTest::newRow( "rotscale 270 a" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -399, 00, 400, 300 ) );
+ deg = 270.0000001;
+ QTest::newRow( "rotscale 270 b" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 30, 40 )
+ << QPolygon( QRect( -399, 00, 400, 300 ) );
+ deg = 270.;
+ QTest::newRow( "rotscale 270 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -599, 100, 400, 300 ) );
+ deg = 270.000001;
+ QTest::newRow( "rotscale 270 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -599, 100, 400, 300 ) );
+
+ // rotations that are not multiples of 90 degrees. mapRect returns the bounding rect here.
+ deg = 45;
+ QTest::newRow( "rot 45 a" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ),
+ sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 10, 10 )
+ << QPolygon( QRect( 0, -7, 14, 14 ) );
+ QTest::newRow( "rot 45 b" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ),
+ sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 21, -14, 49, 49 ) );
+ QTest::newRow( "rot 45 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 10, 10 )
+ << QPolygon( QRect( 0, -70, 141, 141 ) );
+ QTest::newRow( "rot 45 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( 212, -141, 495, 495 ) );
+
+ deg = -45;
+ QTest::newRow( "rot -45 a" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ),
+ sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 10, 10 )
+ << QPolygon( QRect( -7, 0, 14, 14 ) );
+ QTest::newRow( "rot -45 b" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ),
+ sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -35, 21, 49, 49 ) );
+ QTest::newRow( "rot -45 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 0, 0, 10, 10 )
+ << QPolygon( QRect( -70, 0, 141, 141 ) );
+ QTest::newRow( "rot -45 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ),
+ 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 )
+ << QRect( 10, 20, 30, 40 )
+ << QPolygon( QRect( -353, 212, 495, 495 ) );
+#endif
+}
+
+void tst_QWMatrix::mapRect()
+{
+ QFETCH( QMatrix, matrix );
+ QFETCH( QRect, src );
+// qDebug( "got src: %d/%d (%d/%d), matrix=[ %f %f %f %f %f %f ]",
+// src.x(), src.y(), src.width(), src.height(),
+// matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), matrix.dx(), matrix.dy() );
+ QTEST( QPolygon( matrix.mapRect(src) ), "res" );
+}
+
+void tst_QWMatrix::operator_star_qrect()
+{
+#if 0 // QT_VERSION >= 0x030100
+ QFETCH( QMatrix, matrix );
+ QFETCH( QRect, src );
+ QFETCH( QPolygon, res );
+
+ QCOMPARE( (matrix * src), QRegion(res) );
+#else
+ QSKIP( "Not tested with Qt versions < 3.1", SkipAll);
+#endif
+}
+
+
+void tst_QWMatrix::operator_star_qwmatrix()
+{
+#if 0
+ // Left out until the matrix multiply operator behaves properly..
+ QMatrix m1( 2, 3, 4, 5, 6, 7 );
+ QMatrix m2( 3, 4, 5, 6, 7, 8 );
+
+ QMatrix result1x2( 21, 26, 37, 46, 44, 75 );
+ QMatrix result2x1( 22, 29, 34, 45, 53, 80);
+
+ QMatrix product12 = m1*m2;
+ QMatrix product21 = m2*m1;
+
+ QVERIFY( product12==result1x2 );
+ QVERIFY( product21==result2x1 );
+#else
+ QSKIP( "Not tested with Qt versions since the operator is broken..",
+ SkipAll );
+#endif
+}
+
+
+void tst_QWMatrix::assignments()
+{
+ QMatrix m;
+ m.scale(2, 3);
+ m.rotate(45);
+ m.shear(4, 5);
+
+ QMatrix c1(m);
+
+ QCOMPARE(m.m11(), c1.m11());
+ QCOMPARE(m.m12(), c1.m12());
+ QCOMPARE(m.m21(), c1.m21());
+ QCOMPARE(m.m22(), c1.m22());
+ QCOMPARE(m.dx(), c1.dx());
+ QCOMPARE(m.dy(), c1.dy());
+
+ QMatrix c2 = m;
+ QCOMPARE(m.m11(), c2.m11());
+ QCOMPARE(m.m12(), c2.m12());
+ QCOMPARE(m.m21(), c2.m21());
+ QCOMPARE(m.m22(), c2.m22());
+ QCOMPARE(m.dx(), c2.dx());
+ QCOMPARE(m.dy(), c2.dy());
+}
+
+
+void tst_QWMatrix::mapToPolygon()
+{
+ QFETCH( QMatrix, matrix );
+ QFETCH( QRect, src );
+ QFETCH( QPolygon, res );
+
+ QCOMPARE( matrix.mapToPolygon( src ), res );
+}
+
+
+void tst_QWMatrix::translate()
+{
+ QMatrix m( 1, 2, 3, 4, 5, 6 );
+ QMatrix res2( m );
+ QMatrix res( 1, 2, 3, 4, 75, 106 );
+ m.translate( 10, 20 );
+ QVERIFY( m == res );
+ m.translate( -10, -20 );
+ QVERIFY( m == res2 );
+}
+
+void tst_QWMatrix::scale()
+{
+ QMatrix m( 1, 2, 3, 4, 5, 6 );
+ QMatrix res2( m );
+ QMatrix res( 10, 20, 60, 80, 5, 6 );
+ m.scale( 10, 20 );
+ QVERIFY( m == res );
+ m.scale( 1./10., 1./20. );
+ QVERIFY( m == res2 );
+}
+
+void tst_QWMatrix::mapPolygon()
+{
+ QPolygon poly;
+ poly << QPoint(0, 0) << QPoint(1, 1) << QPoint(100, 1) << QPoint(1, 100) << QPoint(-1, -1) << QPoint(-1000, 1000);
+
+ {
+ QMatrix m;
+ m.rotate(90);
+
+ // rotating 90 degrees four times should result in original poly
+ QPolygon mapped = m.map(m.map(m.map(m.map(poly))));
+ QCOMPARE(mapped, poly);
+
+ QMatrix m2;
+ m2.scale(10, 10);
+ QMatrix m3;
+ m3.scale(0.1, 0.1);
+
+ mapped = m3.map(m2.map(poly));
+ QCOMPARE(mapped, poly);
+ }
+
+ {
+ QMatrix m(1, 2, 3, 4, 5, 6);
+
+ QPolygon mapped = m.map(poly);
+ for (int i = 0; i < mapped.size(); ++i)
+ QCOMPARE(mapped.at(i), m.map(poly.at(i)));
+ }
+}
+
+QTEST_APPLESS_MAIN(tst_QWMatrix)
+#include "tst_qwmatrix.moc"
diff --git a/tests/auto/gui/text/qabstracttextdocumentlayout/.gitignore b/tests/auto/gui/text/qabstracttextdocumentlayout/.gitignore
new file mode 100644
index 0000000000..d747466790
--- /dev/null
+++ b/tests/auto/gui/text/qabstracttextdocumentlayout/.gitignore
@@ -0,0 +1 @@
+tst_qabstracttextdocumentlayout
diff --git a/tests/auto/gui/text/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro b/tests/auto/gui/text/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro
new file mode 100644
index 0000000000..22b013e37e
--- /dev/null
+++ b/tests/auto/gui/text/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qabstracttextdocumentlayout.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qabstracttextdocumentlayout.cpp
+
+
diff --git a/tests/auto/gui/text/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp b/tests/auto/gui/text/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp
new file mode 100644
index 0000000000..90f212e832
--- /dev/null
+++ b/tests/auto/gui/text/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qabstracttextdocumentlayout.h>
+#include <qimage.h>
+#include <qtextobject.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QAbstractTextDocumentLayout : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QAbstractTextDocumentLayout();
+ virtual ~tst_QAbstractTextDocumentLayout();
+
+private slots:
+ void getSetCheck();
+ void maximumBlockCount();
+};
+
+tst_QAbstractTextDocumentLayout::tst_QAbstractTextDocumentLayout()
+{
+}
+
+tst_QAbstractTextDocumentLayout::~tst_QAbstractTextDocumentLayout()
+{
+}
+
+class MyAbstractTextDocumentLayout : public QAbstractTextDocumentLayout
+{
+ Q_OBJECT
+public:
+ MyAbstractTextDocumentLayout(QTextDocument *doc)
+ : QAbstractTextDocumentLayout(doc)
+ , gotFullLayout(false)
+ , blockCount(0)
+ , changeEvents(0)
+ {
+ }
+
+ void draw(QPainter *, const PaintContext &) {}
+ int hitTest(const QPointF &, Qt::HitTestAccuracy) const { return 0; }
+ int pageCount() const { return 0; }
+ QSizeF documentSize() const { return QSizeF(); }
+ QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
+ QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
+ void documentChanged(int from, int /* oldLength */, int length) {
+ ++changeEvents;
+
+ QTextBlock last = document()->lastBlock();
+ int lastPos = last.position() + last.length() - 1;
+ if (from == 0 && length == lastPos)
+ gotFullLayout = true;
+ }
+
+ bool gotFullLayout;
+ int blockCount;
+ int changeEvents;
+
+public slots:
+ void blockCountChanged(int bc) { blockCount = bc; }
+};
+
+// Testing get/set functions
+void tst_QAbstractTextDocumentLayout::getSetCheck()
+{
+ QTextDocument doc;
+ MyAbstractTextDocumentLayout obj1(&doc);
+ // QPaintDevice * QAbstractTextDocumentLayout::paintDevice()
+ // void QAbstractTextDocumentLayout::setPaintDevice(QPaintDevice *)
+ QImage *var1 = new QImage(QSize(10,10), QImage::Format_ARGB32_Premultiplied);
+ obj1.setPaintDevice(var1);
+ QCOMPARE(static_cast<QPaintDevice *>(var1), obj1.paintDevice());
+ obj1.setPaintDevice((QPaintDevice *)0);
+ QCOMPARE(static_cast<QPaintDevice *>(0), obj1.paintDevice());
+ delete var1;
+}
+
+void tst_QAbstractTextDocumentLayout::maximumBlockCount()
+{
+ QTextDocument doc;
+ doc.setMaximumBlockCount(10);
+
+ MyAbstractTextDocumentLayout layout(&doc);
+ doc.setDocumentLayout(&layout);
+ QObject::connect(&doc, SIGNAL(blockCountChanged(int)), &layout, SLOT(blockCountChanged(int)));
+
+ QTextCursor cursor(&doc);
+ for (int i = 0; i < 10; ++i) {
+ cursor.insertBlock();
+ cursor.insertText("bla");
+ }
+
+ QCOMPARE(layout.blockCount, 10);
+
+ layout.gotFullLayout = false;
+ layout.changeEvents = 0;
+ cursor.insertBlock();
+ QCOMPARE(layout.changeEvents, 2);
+ cursor.insertText("foo");
+ QCOMPARE(layout.changeEvents, 3);
+ cursor.insertBlock();
+ QCOMPARE(layout.changeEvents, 5);
+ cursor.insertText("foo");
+ QCOMPARE(layout.changeEvents, 6);
+
+ QVERIFY(!layout.gotFullLayout);
+
+ QCOMPARE(layout.blockCount, 10);
+}
+
+QTEST_MAIN(tst_QAbstractTextDocumentLayout)
+#include "tst_qabstracttextdocumentlayout.moc"
diff --git a/tests/auto/gui/text/qcssparser/.gitignore b/tests/auto/gui/text/qcssparser/.gitignore
new file mode 100644
index 0000000000..6cc99800e0
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/.gitignore
@@ -0,0 +1 @@
+tst_qcssparser
diff --git a/tests/auto/gui/text/qcssparser/qcssparser.pro b/tests/auto/gui/text/qcssparser/qcssparser.pro
new file mode 100644
index 0000000000..16fa265231
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/qcssparser.pro
@@ -0,0 +1,17 @@
+load(qttest_p4)
+SOURCES += tst_qcssparser.cpp
+QT += xml gui-private
+
+requires(contains(QT_CONFIG,private_tests))
+!symbian: {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
+
+wince*|symbian: {
+ addFiles.files = testdata
+ addFiles.path = .
+ timesFont.files = C:/Windows/Fonts/times.ttf
+ timesFont.path = .
+ DEPLOYMENT += addFiles timesFont
+}
+
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/comments/input b/tests/auto/gui/text/qcssparser/testdata/scanner/comments/input
new file mode 100644
index 0000000000..af2b659a5b
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/comments/input
@@ -0,0 +1 @@
+/* let's see if comments actually work *//*foo*/ "it /*should be preserved \"in strings*/ though"
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/comments/output b/tests/auto/gui/text/qcssparser/testdata/scanner/comments/output
new file mode 100644
index 0000000000..80ede0ba22
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/comments/output
@@ -0,0 +1,4 @@
+S|/* let's see if comments actually work */
+S|/*foo*/
+S|
+STRING|"it /*should be preserved "in strings*/ though"
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/comments2/input b/tests/auto/gui/text/qcssparser/testdata/scanner/comments2/input
new file mode 100644
index 0000000000..3135acd78c
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/comments2/input
@@ -0,0 +1 @@
+/*foo*/{/*foo*/+/*foo*/>/*foo*/,/*foo*/}/*foo*/-
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/comments2/output b/tests/auto/gui/text/qcssparser/testdata/scanner/comments2/output
new file mode 100644
index 0000000000..d1f1259869
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/comments2/output
@@ -0,0 +1,12 @@
+S|/*foo*/
+LBRACE|{
+S|/*foo*/
+PLUS|+
+S|/*foo*/
+GREATER|>
+S|/*foo*/
+COMMA|,
+S|/*foo*/
+RBRACE|}
+S|/*foo*/
+MINUS|-
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/comments3/input b/tests/auto/gui/text/qcssparser/testdata/scanner/comments3/input
new file mode 100644
index 0000000000..8634543a8f
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/comments3/input
@@ -0,0 +1 @@
+url(/*comment*/"www.kde.org")
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/comments3/output b/tests/auto/gui/text/qcssparser/testdata/scanner/comments3/output
new file mode 100644
index 0000000000..af7bad752a
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/comments3/output
@@ -0,0 +1,4 @@
+FUNCTION|url(
+S|/*comment*/
+STRING|"www.kde.org"
+RPAREN|)
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/comments4/input b/tests/auto/gui/text/qcssparser/testdata/scanner/comments4/input
new file mode 100644
index 0000000000..62d039b00c
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/comments4/input
@@ -0,0 +1 @@
+!/*hmm*/important
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/comments4/output b/tests/auto/gui/text/qcssparser/testdata/scanner/comments4/output
new file mode 100644
index 0000000000..eb86e7bd15
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/comments4/output
@@ -0,0 +1,3 @@
+EXCLAMATION_SYM|!
+S|/*hmm*/
+IDENT|important
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/input b/tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/input
new file mode 100644
index 0000000000..deae3a8dab
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/input
@@ -0,0 +1 @@
+background: 'test_bug.png';
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/output b/tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/output
new file mode 100644
index 0000000000..ed52419594
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/output
@@ -0,0 +1,5 @@
+IDENT|background
+COLON|:
+S|
+STRING|'test_bug.png'
+SEMICOLON|;
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/simple/input b/tests/auto/gui/text/qcssparser/testdata/scanner/simple/input
new file mode 100644
index 0000000000..b37e587661
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/simple/input
@@ -0,0 +1 @@
+p { display:block; }
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/simple/output b/tests/auto/gui/text/qcssparser/testdata/scanner/simple/output
new file mode 100644
index 0000000000..71c60ec9bf
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/simple/output
@@ -0,0 +1,9 @@
+IDENT|p
+LBRACE| {
+S|
+IDENT|display
+COLON|:
+IDENT|block
+SEMICOLON|;
+S|
+RBRACE|}
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/unicode/input b/tests/auto/gui/text/qcssparser/testdata/scanner/unicode/input
new file mode 100644
index 0000000000..2c33f7be97
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/unicode/input
@@ -0,0 +1 @@
+\41"\7E"\00006Df
diff --git a/tests/auto/gui/text/qcssparser/testdata/scanner/unicode/output b/tests/auto/gui/text/qcssparser/testdata/scanner/unicode/output
new file mode 100644
index 0000000000..0829c37e28
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/testdata/scanner/unicode/output
@@ -0,0 +1,3 @@
+IDENT|A
+STRING|"~"
+IDENT|mf
diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
new file mode 100644
index 0000000000..1e82431a48
--- /dev/null
+++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
@@ -0,0 +1,1718 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QtXml/QtXml>
+#if defined(Q_OS_WINCE)
+#include <QtGui/QFontDatabase>
+#endif
+
+//TESTED_CLASS=QCss
+//TESTED_FILES=gui/text/qcssparser.cpp gui/text/qcssparser_p.h
+
+#include "private/qcssparser_p.h"
+
+class tst_QCssParser : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void scanner_data();
+ void scanner();
+ void term_data();
+ void term();
+ void expr_data();
+ void expr();
+ void import();
+ void media();
+ void page();
+ void ruleset();
+ void selector_data();
+ void selector();
+ void prio();
+ void escapes();
+ void malformedDeclarations_data();
+ void malformedDeclarations();
+ void invalidAtKeywords();
+ void marginValue();
+ void marginValue_data();
+ void colorValue_data();
+ void colorValue();
+ void styleSelector_data();
+ void styleSelector();
+ void specificity_data();
+ void specificity();
+ void specificitySort_data();
+ void specificitySort();
+ void rulesForNode_data();
+ void rulesForNode();
+ void shorthandBackgroundProperty_data();
+ void shorthandBackgroundProperty();
+ void pseudoElement_data();
+ void pseudoElement();
+ void gradient_data();
+ void gradient();
+ void extractFontFamily_data();
+ void extractFontFamily();
+ void extractBorder_data();
+ void extractBorder();
+ void noTextDecoration();
+ void quotedAndUnquotedIdentifiers();
+
+private:
+#if defined(Q_OS_WINCE)
+ int m_timesFontId;
+#endif
+};
+
+void tst_QCssParser::initTestCase()
+{
+#if defined(Q_OS_WINCE)
+ QFontDatabase fontDB;
+ m_timesFontId = -1;
+ if (!fontDB.families().contains("Times New Roman")) {
+ m_timesFontId = QFontDatabase::addApplicationFont("times.ttf");
+ QVERIFY(m_timesFontId != -1);
+ }
+#endif
+}
+
+void tst_QCssParser::cleanupTestCase()
+{
+#if defined(Q_OS_WINCE)
+ if (m_timesFontId != -1)
+ QFontDatabase::removeApplicationFont(m_timesFontId);
+#endif
+}
+
+void tst_QCssParser::scanner_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("output");
+
+#if !defined(Q_OS_IRIX) && !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
+ QDir d(SRCDIR);
+#else
+ QDir d(QDir::current());
+#endif
+ d.cd("testdata");
+ d.cd("scanner");
+ foreach (QFileInfo test, d.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) {
+ QString dir = test.absoluteFilePath() + QDir::separator();
+ QTest::newRow(qPrintable(test.baseName()))
+ << dir + "input"
+ << dir + "output"
+ ;
+ }
+}
+
+
+static const char *tokenName(QCss::TokenType t)
+{
+ switch (t) {
+ case QCss::NONE: return "NONE";
+ case QCss::S: return "S";
+ case QCss::CDO: return "CDO";
+ case QCss::CDC: return "CDC";
+ case QCss::INCLUDES: return "INCLUDES";
+ case QCss::DASHMATCH: return "DASHMATCH";
+ case QCss::LBRACE: return "LBRACE";
+ case QCss::PLUS: return "PLUS";
+ case QCss::GREATER: return "GREATER";
+ case QCss::COMMA: return "COMMA";
+ case QCss::STRING: return "STRING";
+ case QCss::INVALID: return "INVALID";
+ case QCss::IDENT: return "IDENT";
+ case QCss::HASH: return "HASH";
+ case QCss::ATKEYWORD_SYM: return "ATKEYWORD_SYM";
+ case QCss::EXCLAMATION_SYM: return "EXCLAMATION_SYM";
+ case QCss::LENGTH: return "LENGTH";
+ case QCss::PERCENTAGE: return "PERCENTAGE";
+ case QCss::NUMBER: return "NUMBER";
+ case QCss::FUNCTION: return "FUNCTION";
+ case QCss::COLON: return "COLON";
+ case QCss::SEMICOLON: return "SEMICOLON";
+ case QCss::RBRACE: return "RBRACE";
+ case QCss::SLASH: return "SLASH";
+ case QCss::MINUS: return "MINUS";
+ case QCss::DOT: return "DOT";
+ case QCss::STAR: return "STAR";
+ case QCss::LBRACKET: return "LBRACKET";
+ case QCss::RBRACKET: return "RBRACKET";
+ case QCss::EQUAL: return "EQUAL";
+ case QCss::LPAREN: return "LPAREN";
+ case QCss::RPAREN: return "RPAREN";
+ case QCss::OR: return "OR";
+ }
+ return "";
+}
+
+static void debug(const QVector<QCss::Symbol> &symbols, int index = -1)
+{
+ qDebug() << "all symbols:";
+ for (int i = 0; i < symbols.count(); ++i)
+ qDebug() << "(" << i << "); Token:" << tokenName(symbols.at(i).token) << "; Lexem:" << symbols.at(i).lexem();
+ if (index != -1)
+ qDebug() << "failure at index" << index;
+}
+
+//static void debug(const QCss::Parser &p) { debug(p.symbols); }
+
+void tst_QCssParser::scanner()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, output);
+
+ QFile inputFile(input);
+ QVERIFY(inputFile.open(QIODevice::ReadOnly|QIODevice::Text));
+ QVector<QCss::Symbol> symbols;
+ QCss::Scanner::scan(QCss::Scanner::preprocess(QString::fromUtf8(inputFile.readAll())), &symbols);
+
+ QVERIFY(symbols.count() > 1);
+ QVERIFY(symbols.last().token == QCss::S);
+ QVERIFY(symbols.last().lexem() == QLatin1String("\n"));
+ symbols.remove(symbols.count() - 1, 1);
+
+ QFile outputFile(output);
+ QVERIFY(outputFile.open(QIODevice::ReadOnly|QIODevice::Text));
+ QStringList lines;
+ while (!outputFile.atEnd()) {
+ QString line = QString::fromUtf8(outputFile.readLine());
+ if (line.endsWith(QLatin1Char('\n')))
+ line.chop(1);
+ lines.append(line);
+ }
+
+ if (lines.count() != symbols.count()) {
+ debug(symbols);
+ QCOMPARE(lines.count(), symbols.count());
+ }
+
+ for (int i = 0; i < lines.count(); ++i) {
+ QStringList l = lines.at(i).split(QChar::fromLatin1('|'));
+ QCOMPARE(l.count(), 2);
+ const QString expectedToken = l.at(0);
+ const QString expectedLexem = l.at(1);
+ QString actualToken = QString::fromLatin1(tokenName(symbols.at(i).token));
+ if (actualToken != expectedToken) {
+ debug(symbols, i);
+ QCOMPARE(actualToken, expectedToken);
+ }
+ if (symbols.at(i).lexem() != expectedLexem) {
+ debug(symbols, i);
+ QCOMPARE(symbols.at(i).lexem(), expectedLexem);
+ }
+ }
+}
+
+Q_DECLARE_METATYPE(QCss::Value)
+
+void tst_QCssParser::term_data()
+{
+ QTest::addColumn<bool>("parseSuccess");
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QCss::Value>("expectedValue");
+
+ QCss::Value val;
+
+ val.type = QCss::Value::Percentage;
+ val.variant = QVariant(double(200));
+ QTest::newRow("percentage") << true << "200%" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10px");
+ QTest::newRow("px") << true << "10px" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10cm");
+ QTest::newRow("cm") << true << "10cm" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10mm");
+ QTest::newRow("mm") << true << "10mm" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10pt");
+ QTest::newRow("pt") << true << "10pt" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10pc");
+ QTest::newRow("pc") << true << "10pc" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("42in");
+ QTest::newRow("inch") << true << "42in" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10deg");
+ QTest::newRow("deg") << true << "10deg" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10rad");
+ QTest::newRow("rad") << true << "10rad" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10grad");
+ QTest::newRow("grad") << true << "10grad" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10ms");
+ QTest::newRow("time") << true << "10ms" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10s");
+ QTest::newRow("times") << true << "10s" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10hz");
+ QTest::newRow("hz") << true << "10hz" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10khz");
+ QTest::newRow("khz") << true << "10khz" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10myunit");
+ QTest::newRow("dimension") << true << "10myunit" << val;
+
+ val.type = QCss::Value::Percentage;
+
+ val.type = QCss::Value::Percentage;
+ val.variant = QVariant(double(-200));
+ QTest::newRow("minuspercentage") << true << "-200%" << val;
+
+ val.type = QCss::Value::Length;
+ val.variant = QString("10em");
+ QTest::newRow("ems") << true << "10em" << val;
+
+ val.type = QCss::Value::String;
+ val.variant = QVariant(QString("foo"));
+ QTest::newRow("string") << true << "\"foo\"" << val;
+
+ val.type = QCss::Value::Function;
+ val.variant = QVariant(QStringList() << "myFunc" << "23, (nested text)");
+ QTest::newRow("function") << true << "myFunc(23, (nested text))" << val;
+
+ QTest::newRow("function_failure") << false << "myFunction((blah)" << val;
+ QTest::newRow("function_failure2") << false << "+myFunc(23, (nested text))" << val;
+
+ val.type = QCss::Value::Color;
+ val.variant = QVariant(QColor("#12ff34"));
+ QTest::newRow("hexcolor") << true << "#12ff34" << val;
+
+ val.type = QCss::Value::Color;
+ val.variant = QVariant(QColor("#ffbb00"));
+ QTest::newRow("hexcolor2") << true << "#fb0" << val;
+
+ QTest::ignoreMessage(QtWarningMsg, "QCssParser::parseHexColor: Unknown color name '#cafebabe'");
+ QTest::newRow("hexcolor_failure") << false << "#cafebabe" << val;
+
+ val.type = QCss::Value::Uri;
+ val.variant = QString("www.kde.org");
+ QTest::newRow("uri1") << true << "url(\"www.kde.org\")" << val;
+
+ QTest::newRow("uri2") << true << "url(www.kde.org)" << val;
+
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = int(QCss::Value_Italic);
+ QTest::newRow("italic") << true << "italic" << val;
+
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = int(QCss::Value_Italic);
+ QTest::newRow("ItaLIc") << true << "ItaLIc" << val;
+}
+
+void tst_QCssParser::term()
+{
+ QFETCH(bool, parseSuccess);
+ QFETCH(QString, css);
+ QFETCH(QCss::Value, expectedValue);
+
+ QCss::Parser parser(css);
+ QCss::Value val;
+ QVERIFY(parser.testTerm());
+ QCOMPARE(parser.parseTerm(&val), parseSuccess);
+ if (parseSuccess) {
+ QCOMPARE(int(val.type), int(expectedValue.type));
+ if (val.variant != expectedValue.variant) {
+ qDebug() << "val.variant:" << val.variant << "expectedValue.variant:" << expectedValue.variant;
+ QCOMPARE(val.variant, expectedValue.variant);
+ }
+ }
+}
+
+Q_DECLARE_METATYPE(QVector<QCss::Value>)
+
+void tst_QCssParser::expr_data()
+{
+ QTest::addColumn<bool>("parseSuccess");
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QVector<QCss::Value> >("expectedValues");
+
+ QVector<QCss::Value> values;
+ QCss::Value val;
+
+ QCss::Value comma;
+ comma.type = QCss::Value::TermOperatorComma;
+
+ val.type = QCss::Value::Identifier;
+ val.variant = QLatin1String("foo");
+ values << val;
+ values << comma;
+ val.variant = QLatin1String("bar");
+ values << val;
+ values << comma;
+ val.variant = QLatin1String("baz");
+ values << val;
+ QTest::newRow("list") << true << "foo, bar, baz" << values;
+ values.clear();
+}
+
+void tst_QCssParser::expr()
+{
+ QFETCH(bool, parseSuccess);
+ QFETCH(QString, css);
+ QFETCH(QVector<QCss::Value>, expectedValues);
+
+ QCss::Parser parser(css);
+ QVector<QCss::Value> values;
+ QVERIFY(parser.testExpr());
+ QCOMPARE(parser.parseExpr(&values), parseSuccess);
+ if (parseSuccess) {
+ QCOMPARE(values.count(), expectedValues.count());
+
+ for (int i = 0; i < values.count(); ++i) {
+ QCOMPARE(int(values.at(i).type), int(expectedValues.at(i).type));
+ QCOMPARE(values.at(i).variant, expectedValues.at(i).variant);
+ }
+ }
+}
+
+void tst_QCssParser::import()
+{
+ QCss::Parser parser("@import \"plainstring\";");
+ QVERIFY(parser.testImport());
+ QCss::ImportRule rule;
+ QVERIFY(parser.parseImport(&rule));
+ QCOMPARE(rule.href, QString("plainstring"));
+
+ parser = QCss::Parser("@import url(\"www.kde.org\") print/*comment*/,screen;");
+ QVERIFY(parser.testImport());
+ QVERIFY(parser.parseImport(&rule));
+ QCOMPARE(rule.href, QString("www.kde.org"));
+ QCOMPARE(rule.media.count(), 2);
+ QCOMPARE(rule.media.at(0), QString("print"));
+ QCOMPARE(rule.media.at(1), QString("screen"));
+}
+
+void tst_QCssParser::media()
+{
+ QCss::Parser parser("@media print/*comment*/,screen /*comment to ignore*/{ }");
+ QVERIFY(parser.testMedia());
+ QCss::MediaRule rule;
+ QVERIFY(parser.parseMedia(&rule));
+ QCOMPARE(rule.media.count(), 2);
+ QCOMPARE(rule.media.at(0), QString("print"));
+ QCOMPARE(rule.media.at(1), QString("screen"));
+ QVERIFY(rule.styleRules.isEmpty());
+}
+
+void tst_QCssParser::page()
+{
+ QCss::Parser parser("@page :first/*comment to ignore*/{ }");
+ QVERIFY(parser.testPage());
+ QCss::PageRule rule;
+ QVERIFY(parser.parsePage(&rule));
+ QCOMPARE(rule.selector, QString("first"));
+ QVERIFY(rule.declarations.isEmpty());
+}
+
+void tst_QCssParser::ruleset()
+{
+ {
+ QCss::Parser parser("p/*foo*/{ }");
+ QVERIFY(parser.testRuleset());
+ QCss::StyleRule rule;
+ QVERIFY(parser.parseRuleset(&rule));
+ QCOMPARE(rule.selectors.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.at(0).elementName, QString("p"));
+ QVERIFY(rule.declarations.isEmpty());
+ }
+
+ {
+ QCss::Parser parser("p/*comment*/,div{ }");
+ QVERIFY(parser.testRuleset());
+ QCss::StyleRule rule;
+ QVERIFY(parser.parseRuleset(&rule));
+ QCOMPARE(rule.selectors.count(), 2);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.at(0).elementName, QString("p"));
+ QCOMPARE(rule.selectors.at(1).basicSelectors.count(), 1);
+ QCOMPARE(rule.selectors.at(1).basicSelectors.at(0).elementName, QString("div"));
+ QVERIFY(rule.declarations.isEmpty());
+ }
+
+ {
+ QCss::Parser parser(":before, :after { }");
+ QVERIFY(parser.testRuleset());
+ QCss::StyleRule rule;
+ QVERIFY(parser.parseRuleset(&rule));
+ QCOMPARE(rule.selectors.count(), 2);
+
+ QCOMPARE(rule.selectors.at(0).basicSelectors.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.at(0).pseudos.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.at(0).pseudos.at(0).name, QString("before"));
+
+ QCOMPARE(rule.selectors.at(1).basicSelectors.count(), 1);
+ QCOMPARE(rule.selectors.at(1).basicSelectors.at(0).pseudos.count(), 1);
+ QCOMPARE(rule.selectors.at(1).basicSelectors.at(0).pseudos.at(0).name, QString("after"));
+
+ QVERIFY(rule.declarations.isEmpty());
+ }
+
+}
+
+Q_DECLARE_METATYPE(QCss::Selector)
+
+void tst_QCssParser::selector_data()
+{
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QCss::Selector>("expectedSelector");
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "p";
+ basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfPreceeds;
+ sel.basicSelectors << basic;
+
+ basic = QCss::BasicSelector();
+ basic.elementName = "div";
+ sel.basicSelectors << basic;
+
+ QTest::newRow("comment") << QString("p/* */+ div") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = QString();
+ sel.basicSelectors << basic;
+
+ QTest::newRow("any") << QString("*") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ sel.basicSelectors << basic;
+
+ QTest::newRow("element") << QString("e") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfAncestor;
+ sel.basicSelectors << basic;
+
+ basic.elementName = "f";
+ basic.relationToNext = QCss::BasicSelector::NoRelation;
+ sel.basicSelectors << basic;
+
+ QTest::newRow("descendant") << QString("e f") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfParent;
+ sel.basicSelectors << basic;
+
+ basic.elementName = "f";
+ basic.relationToNext = QCss::BasicSelector::NoRelation;
+ sel.basicSelectors << basic;
+
+ QTest::newRow("parent") << QString("e > f") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ QCss::Pseudo pseudo;
+ pseudo.name = "first-child";
+ basic.pseudos.append(pseudo);
+ sel.basicSelectors << basic;
+
+ QTest::newRow("first-child") << QString("e:first-child") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ QCss::Pseudo pseudo;
+ pseudo.name = "c";
+ pseudo.function = "lang";
+ basic.pseudos.append(pseudo);
+ sel.basicSelectors << basic;
+
+ QTest::newRow("lang") << QString("e:lang(c)") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfPreceeds;
+ sel.basicSelectors << basic;
+
+ basic.elementName = "f";
+ basic.relationToNext = QCss::BasicSelector::NoRelation;
+ sel.basicSelectors << basic;
+
+ QTest::newRow("precede") << QString("e + f") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ QCss::AttributeSelector attrSel;
+ attrSel.name = "foo";
+ basic.attributeSelectors << attrSel;
+ sel.basicSelectors << basic;
+
+ QTest::newRow("attr") << QString("e[foo]") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ QCss::AttributeSelector attrSel;
+ attrSel.name = "foo";
+ attrSel.value = "warning";
+ attrSel.valueMatchCriterium = QCss::AttributeSelector::MatchEqual;
+ basic.attributeSelectors << attrSel;
+ sel.basicSelectors << basic;
+
+ QTest::newRow("attr-equal") << QString("e[foo=\"warning\"]") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ QCss::AttributeSelector attrSel;
+ attrSel.name = "foo";
+ attrSel.value = "warning";
+ attrSel.valueMatchCriterium = QCss::AttributeSelector::MatchContains;
+ basic.attributeSelectors << attrSel;
+ sel.basicSelectors << basic;
+
+ QTest::newRow("attr-contains") << QString("e[foo~=\"warning\"]") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ QCss::AttributeSelector attrSel;
+ attrSel.name = "lang";
+ attrSel.value = "en";
+ attrSel.valueMatchCriterium = QCss::AttributeSelector::MatchBeginsWith;
+ basic.attributeSelectors << attrSel;
+ sel.basicSelectors << basic;
+
+ QTest::newRow("attr-contains") << QString("e[lang|=\"en\"]") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "div";
+
+ QCss::AttributeSelector attrSel;
+ attrSel.name = "class";
+ attrSel.valueMatchCriterium = QCss::AttributeSelector::MatchContains;
+ attrSel.value = "warning";
+ basic.attributeSelectors.append(attrSel);
+
+ attrSel.value = "foo";
+ basic.attributeSelectors.append(attrSel);
+
+ sel.basicSelectors << basic;
+
+ QTest::newRow("class") << QString("div.warning.foo") << sel;
+ }
+
+ {
+ QCss::Selector sel;
+ QCss::BasicSelector basic;
+
+ basic.elementName = "e";
+ basic.ids << "myid";
+ sel.basicSelectors << basic;
+
+ QTest::newRow("id") << QString("e#myid") << sel;
+ }
+}
+
+void tst_QCssParser::selector()
+{
+ QFETCH(QString, css);
+ QFETCH(QCss::Selector, expectedSelector);
+
+ QCss::Parser parser(css);
+ QVERIFY(parser.testSelector());
+ QCss::Selector selector;
+ QVERIFY(parser.parseSelector(&selector));
+
+ QCOMPARE(selector.basicSelectors.count(), expectedSelector.basicSelectors.count());
+ for (int i = 0; i < selector.basicSelectors.count(); ++i) {
+ const QCss::BasicSelector sel = selector.basicSelectors.at(i);
+ const QCss::BasicSelector expectedSel = expectedSelector.basicSelectors.at(i);
+ QCOMPARE(sel.elementName, expectedSel.elementName);
+ QCOMPARE(int(sel.relationToNext), int(expectedSel.relationToNext));
+
+ QCOMPARE(sel.pseudos.count(), expectedSel.pseudos.count());
+ for (int i = 0; i < sel.pseudos.count(); ++i) {
+ QCOMPARE(sel.pseudos.at(i).name, expectedSel.pseudos.at(i).name);
+ QCOMPARE(sel.pseudos.at(i).function, expectedSel.pseudos.at(i).function);
+ }
+
+ QCOMPARE(sel.attributeSelectors.count(), expectedSel.attributeSelectors.count());
+ for (int i = 0; i < sel.attributeSelectors.count(); ++i) {
+ QCOMPARE(sel.attributeSelectors.at(i).name, expectedSel.attributeSelectors.at(i).name);
+ QCOMPARE(sel.attributeSelectors.at(i).value, expectedSel.attributeSelectors.at(i).value);
+ QCOMPARE(int(sel.attributeSelectors.at(i).valueMatchCriterium), int(expectedSel.attributeSelectors.at(i).valueMatchCriterium));
+ }
+ }
+}
+
+void tst_QCssParser::prio()
+{
+ {
+ QCss::Parser parser("!important");
+ QVERIFY(parser.testPrio());
+ }
+ {
+ QCss::Parser parser("!impOrTAnt");
+ QVERIFY(parser.testPrio());
+ }
+ {
+ QCss::Parser parser("!\"important\"");
+ QVERIFY(!parser.testPrio());
+ QCOMPARE(parser.index, 0);
+ }
+ {
+ QCss::Parser parser("!importbleh");
+ QVERIFY(!parser.testPrio());
+ QCOMPARE(parser.index, 0);
+ }
+}
+
+void tst_QCssParser::escapes()
+{
+ QCss::Parser parser("\\hello");
+ parser.test(QCss::IDENT);
+ QCOMPARE(parser.lexem(), QString("hello"));
+}
+
+void tst_QCssParser::malformedDeclarations_data()
+{
+ QTest::addColumn<QString>("css");
+
+ QTest::newRow("1") << QString("p { color:green }");
+ QTest::newRow("2") << QString("p { color:green; color } /* malformed declaration missing ':', value */");
+ QTest::newRow("3") << QString("p { color:red; color; color:green } /* same with expected recovery */");
+ QTest::newRow("4") << QString("p { color:green; color: } /* malformed declaration missing value */");
+ QTest::newRow("5") << QString("p { color:red; color:; color:green } /* same with expected recovery */");
+ QTest::newRow("6") << QString("p { color:green; color{;color:maroon} } /* unexpected tokens { } */");
+ QTest::newRow("7") << QString("p { color:red; color{;color:maroon}; color:green } /* same with recovery */");
+}
+
+void tst_QCssParser::malformedDeclarations()
+{
+ QFETCH(QString, css);
+ QCss::Parser parser(css);
+ QVERIFY(parser.testRuleset());
+ QCss::StyleRule rule;
+ QVERIFY(parser.parseRuleset(&rule));
+
+ QCOMPARE(rule.selectors.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.at(0).elementName, QString("p"));
+
+ QVERIFY(rule.declarations.count() >= 1);
+ QCOMPARE(int(rule.declarations.last().d->propertyId), int(QCss::Color));
+ QCOMPARE(rule.declarations.last().d->values.count(), 1);
+ QCOMPARE(int(rule.declarations.last().d->values.at(0).type), int(QCss::Value::Identifier));
+ QCOMPARE(rule.declarations.last().d->values.at(0).variant.toString(), QString("green"));
+}
+
+void tst_QCssParser::invalidAtKeywords()
+{
+ QCss::Parser parser(""
+ "@three-dee {"
+ " @background-lighting {"
+ " azimuth: 30deg;"
+ " elevation: 190deg;"
+ " }"
+ " h1 { color: red }"
+ "}"
+ "h1 { color: blue }");
+
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCOMPARE(sheet.styleRules.count() + sheet.nameIndex.count(), 1);
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
+ sheet.styleRules.at(0) : *sheet.nameIndex.begin();
+
+ QCOMPARE(rule.selectors.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.count(), 1);
+ QCOMPARE(rule.selectors.at(0).basicSelectors.at(0).elementName, QString("h1"));
+
+ QCOMPARE(rule.declarations.count(), 1);
+ QCOMPARE(int(rule.declarations.at(0).d->propertyId), int(QCss::Color));
+ QCOMPARE(rule.declarations.at(0).d->values.count(), 1);
+ QCOMPARE(int(rule.declarations.at(0).d->values.at(0).type), int(QCss::Value::Identifier));
+ QCOMPARE(rule.declarations.at(0).d->values.at(0).variant.toString(), QString("blue"));
+}
+
+Q_DECLARE_METATYPE(QColor)
+
+void tst_QCssParser::colorValue_data()
+{
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QColor>("expectedColor");
+
+ QTest::newRow("identifier") << "color: black" << QColor("black");
+ QTest::newRow("string") << "color: \"green\"" << QColor("green");
+ QTest::newRow("hexcolor") << "color: #12af0e" << QColor(0x12, 0xaf, 0x0e);
+ QTest::newRow("functional1") << "color: rgb(21, 45, 73)" << QColor(21, 45, 73);
+ QTest::newRow("functional2") << "color: rgb(100%, 0%, 100%)" << QColor(0xff, 0, 0xff);
+ QTest::newRow("rgba") << "color: rgba(10, 20, 30, 40)" << QColor(10, 20, 30, 40);
+ QTest::newRow("rgb") << "color: rgb(10, 20, 30, 40)" << QColor(10, 20, 30, 40);
+ QTest::newRow("hsl") << "color: hsv(10, 20, 30)" << QColor::fromHsv(10, 20, 30, 255);
+ QTest::newRow("hsla") << "color: hsva(10, 20, 30, 40)" << QColor::fromHsv(10, 20, 30, 40);
+ QTest::newRow("invalid1") << "color: rgb(why, does, it, always, rain, on, me)" << QColor();
+ QTest::newRow("invalid2") << "color: rgba(i, meant, norway)" << QColor();
+ QTest::newRow("role") << "color: palette(base)" << qApp->palette().color(QPalette::Base);
+ QTest::newRow("role2") << "color: palette( window-text ) " << qApp->palette().color(QPalette::WindowText);
+ QTest::newRow("transparent") << "color: transparent" << QColor(Qt::transparent);
+}
+
+void tst_QCssParser::colorValue()
+{
+ QFETCH(QString, css);
+ QFETCH(QColor, expectedColor);
+
+ QCss::Parser parser(css);
+ QCss::Declaration decl;
+ QVERIFY(parser.parseNextDeclaration(&decl));
+ const QColor col = decl.colorValue();
+ QVERIFY(expectedColor.isValid() == col.isValid());
+ QCOMPARE(col, expectedColor);
+}
+
+class DomStyleSelector : public QCss::StyleSelector
+{
+public:
+ inline DomStyleSelector(const QDomDocument &doc, const QCss::StyleSheet &sheet)
+ : doc(doc)
+ {
+ styleSheets.append(sheet);
+ }
+
+ virtual QStringList nodeNames(NodePtr node) const { return QStringList(reinterpret_cast<QDomElement *>(node.ptr)->tagName()); }
+ virtual QString attribute(NodePtr node, const QString &name) const { return reinterpret_cast<QDomElement *>(node.ptr)->attribute(name); }
+ virtual bool hasAttribute(NodePtr node, const QString &name) const { return reinterpret_cast<QDomElement *>(node.ptr)->hasAttribute(name); }
+ virtual bool hasAttributes(NodePtr node) const { return reinterpret_cast<QDomElement *>(node.ptr)->hasAttributes(); }
+
+ virtual bool isNullNode(NodePtr node) const {
+ return reinterpret_cast<QDomElement *>(node.ptr)->isNull();
+ }
+ virtual NodePtr parentNode(NodePtr node) const {
+ NodePtr parent;
+ parent.ptr = new QDomElement(reinterpret_cast<QDomElement *>(node.ptr)->parentNode().toElement());
+ return parent;
+ }
+ virtual NodePtr duplicateNode(NodePtr node) const {
+ NodePtr n;
+ n.ptr = new QDomElement(*reinterpret_cast<QDomElement *>(node.ptr));
+ return n;
+ }
+ virtual NodePtr previousSiblingNode(NodePtr node) const {
+ NodePtr sibling;
+ sibling.ptr = new QDomElement(reinterpret_cast<QDomElement *>(node.ptr)->previousSiblingElement());
+ return sibling;
+ }
+ virtual void freeNode(NodePtr node) const {
+ delete reinterpret_cast<QDomElement *>(node.ptr);
+ }
+
+private:
+ QDomDocument doc;
+};
+
+Q_DECLARE_METATYPE(QDomDocument)
+
+void tst_QCssParser::marginValue_data()
+{
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QString>("expectedMargin");
+
+ QFont f;
+ int ex = QFontMetrics(f).xHeight();
+ int em = QFontMetrics(f).height();
+
+ QTest::newRow("one value") << "margin: 1px" << "1 1 1 1";
+ QTest::newRow("two values") << "margin: 1px 2px" << "1 2 1 2";
+ QTest::newRow("three value") << "margin: 1px 2px 3px" << "1 2 3 2";
+ QTest::newRow("four values") << "margin: 1px 2px 3px 4px" << "1 2 3 4";
+ QTest::newRow("default px") << "margin: 1 2 3 4" << "1 2 3 4";
+ QTest::newRow("no unit") << "margin: 1 2 3 4" << "1 2 3 4";
+ QTest::newRow("em") << "margin: 1ex 2ex 3ex 4ex" << QString("%1 %2 %3 %4").arg(ex).arg(2*ex).arg(3*ex).arg(4*ex);
+ QTest::newRow("ex") << "margin: 1 2em 3px 4ex" << QString("%1 %2 %3 %4").arg(1).arg(2*em).arg(3).arg(4*ex);
+
+ f.setPointSize(20);
+ f.setBold(true);
+ ex = QFontMetrics(f).xHeight();
+ em = QFontMetrics(f).height();
+ QTest::newRow("em2") << "font: bold 20pt; margin: 1ex 2ex 3ex 4ex" << QString("%1 %2 %3 %4").arg(ex).arg(2*ex).arg(3*ex).arg(4*ex);
+ QTest::newRow("ex2") << "margin: 1 2em 3px 4ex; font-size: 20pt; font-weight: bold;" << QString("%1 %2 %3 %4").arg(1).arg(2*em).arg(3).arg(4*ex);
+
+ QTest::newRow("crap") << "margin: crap" << "0 0 0 0";
+}
+
+void tst_QCssParser::marginValue()
+{
+ QFETCH(QString, css);
+ QFETCH(QString, expectedMargin);
+
+ QDomDocument doc;
+ QVERIFY(doc.setContent(QLatin1String("<!DOCTYPE test><test> <dummy/> </test>")));
+
+ css.prepend("dummy {");
+ css.append("}");
+
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ DomStyleSelector testSelector(doc, sheet);
+ QDomElement e = doc.documentElement().firstChildElement();
+ QCss::StyleSelector::NodePtr n;
+ n.ptr = &e;
+ QVector<QCss::StyleRule> rules = testSelector.styleRulesForNode(n);
+ QVector<QCss::Declaration> decls = rules.at(0).declarations;
+ QCss::ValueExtractor v(decls);
+
+ {
+ int m[4];
+ int p[4];
+ int spacing;
+ v.extractBox(m, p, &spacing);
+ QString str = QString("%1 %2 %3 %4").arg(m[0]).arg(m[1]).arg(m[2]).arg(m[3]);
+ QCOMPARE(str, expectedMargin);
+ }
+}
+
+void tst_QCssParser::styleSelector_data()
+{
+ QTest::addColumn<bool>("match");
+ QTest::addColumn<QString>("selector");
+ QTest::addColumn<QString>("xml");
+ QTest::addColumn<QString>("elementToCheck");
+
+ QTest::newRow("plain") << true << QString("p") << QString("<p />") << QString();
+ QTest::newRow("noplain") << false << QString("bar") << QString("<p />") << QString();
+
+ QTest::newRow("class") << true << QString(".foo") << QString("<p class=\"foo\" />") << QString();
+ QTest::newRow("noclass") << false << QString(".bar") << QString("<p class=\"foo\" />") << QString();
+
+ QTest::newRow("attrset") << true << QString("[justset]") << QString("<p justset=\"bar\" />") << QString();
+ QTest::newRow("notattrset") << false << QString("[justset]") << QString("<p otherattribute=\"blub\" />") << QString();
+
+ QTest::newRow("attrmatch") << true << QString("[foo=bar]") << QString("<p foo=\"bar\" />") << QString();
+ QTest::newRow("noattrmatch") << false << QString("[foo=bar]") << QString("<p foo=\"xyz\" />") << QString();
+
+ QTest::newRow("contains") << true << QString("[foo~=bar]") << QString("<p foo=\"baz bleh bar\" />") << QString();
+ QTest::newRow("notcontains") << false << QString("[foo~=bar]") << QString("<p foo=\"test\" />") << QString();
+
+ QTest::newRow("beingswith") << true << QString("[foo|=bar]") << QString("<p foo=\"bar-bleh\" />") << QString();
+ QTest::newRow("notbeingswith") << false << QString("[foo|=bar]") << QString("<p foo=\"bleh-bar\" />") << QString();
+
+ QTest::newRow("attr2") << true << QString("[bar=foo]") << QString("<p bleh=\"bar\" bar=\"foo\" />") << QString();
+
+ QTest::newRow("universal1") << true << QString("*") << QString("<p />") << QString();
+
+ QTest::newRow("universal3") << false << QString("*[foo=bar]") << QString("<p foo=\"bleh\" />") << QString();
+ QTest::newRow("universal4") << true << QString("*[foo=bar]") << QString("<p foo=\"bar\" />") << QString();
+
+ QTest::newRow("universal5") << false << QString("[foo=bar]") << QString("<p foo=\"bleh\" />") << QString();
+ QTest::newRow("universal6") << true << QString("[foo=bar]") << QString("<p foo=\"bar\" />") << QString();
+
+ QTest::newRow("universal7") << true << QString(".charfmt1") << QString("<p class=\"charfmt1\" />") << QString();
+
+ QTest::newRow("id") << true << QString("#blub") << QString("<p id=\"blub\" />") << QString();
+ QTest::newRow("noid") << false << QString("#blub") << QString("<p id=\"other\" />") << QString();
+
+ QTest::newRow("childselector") << true << QString("parent > child")
+ << QString("<parent><child /></parent>")
+ << QString("parent/child");
+
+ QTest::newRow("nochildselector2") << false << QString("parent > child")
+ << QString("<child><parent /></child>")
+ << QString("child/parent");
+
+ QTest::newRow("nochildselector3") << false << QString("parent > child")
+ << QString("<parent><intermediate><child /></intermediate></parent>")
+ << QString("parent/intermediate/child");
+
+ QTest::newRow("childselector2") << true << QString("parent[foo=bar] > child")
+ << QString("<parent foo=\"bar\"><child /></parent>")
+ << QString("parent/child");
+
+ QTest::newRow("nochildselector4") << false << QString("parent[foo=bar] > child")
+ << QString("<parent><child /></parent>")
+ << QString("parent/child");
+
+ QTest::newRow("nochildselector5") << false << QString("parent[foo=bar] > child")
+ << QString("<parent foo=\"bar\"><parent><child /></parent></parent>")
+ << QString("parent/parent/child");
+
+ QTest::newRow("childselectors") << true << QString("grandparent > parent > child")
+ << QString("<grandparent><parent><child /></parent></grandparent>")
+ << QString("grandparent/parent/child");
+
+ QTest::newRow("descendant") << true << QString("grandparent child")
+ << QString("<grandparent><parent><child /></parent></grandparent>")
+ << QString("grandparent/parent/child");
+
+ QTest::newRow("nodescendant") << false << QString("grandparent child")
+ << QString("<other><parent><child /></parent></other>")
+ << QString("other/parent/child");
+
+ QTest::newRow("descendant2") << true << QString("grandgrandparent grandparent child")
+ << QString("<grandgrandparent><inbetween><grandparent><parent><child /></parent></grandparent></inbetween></grandgrandparent>")
+ << QString("grandgrandparent/inbetween/grandparent/parent/child");
+
+ QTest::newRow("combined") << true << QString("grandparent parent > child")
+ << QString("<grandparent><inbetween><parent><child /></parent></inbetween></grandparent>")
+ << QString("grandparent/inbetween/parent/child");
+
+ QTest::newRow("combined2") << true << QString("grandparent > parent child")
+ << QString("<grandparent><parent><inbetween><child /></inbetween></parent></grandparent>")
+ << QString("grandparent/parent/inbetween/child");
+
+ QTest::newRow("combined3") << true << QString("grandparent > parent child")
+ << QString("<grandparent><parent><inbetween><child /></inbetween></parent></grandparent>")
+ << QString("grandparent/parent/inbetween/child");
+
+ QTest::newRow("nocombined") << false << QString("grandparent parent > child")
+ << QString("<inbetween><parent><child /></parent></inbetween>")
+ << QString("inbetween/parent/child");
+
+ QTest::newRow("nocombined2") << false << QString("grandparent parent > child")
+ << QString("<parent><child /></parent>")
+ << QString("parent/child");
+
+ QTest::newRow("previoussibling") << true << QString("p1 + p2")
+ << QString("<p1 /><p2 />")
+ << QString("p2");
+
+ QTest::newRow("noprevioussibling") << false << QString("p2 + p1")
+ << QString("<p1 /><p2 />")
+ << QString("p2");
+
+ QTest::newRow("ancestry_firstmismatch") << false << QString("parent child[foo=bar]")
+ << QString("<parent><child /></parent>")
+ << QString("parent/child");
+
+ QTest::newRow("unknown-pseudo") << false << QString("p:enabled:foobar") << QString("<p/>") << QString();
+}
+
+void tst_QCssParser::styleSelector()
+{
+ QFETCH(bool, match);
+ QFETCH(QString, selector);
+ QFETCH(QString, xml);
+ QFETCH(QString, elementToCheck);
+
+ QString css = QString("%1 { background-color: green }").arg(selector);
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QDomDocument doc;
+ xml.prepend("<!DOCTYPE test><test>");
+ xml.append("</test>");
+ QVERIFY(doc.setContent(xml));
+
+ DomStyleSelector testSelector(doc, sheet);
+
+ QDomElement e = doc.documentElement();
+ if (elementToCheck.isEmpty()) {
+ e = e.firstChildElement();
+ } else {
+ QStringList path = elementToCheck.split(QLatin1Char('/'));
+ do {
+ e = e.namedItem(path.takeFirst()).toElement();
+ } while (!path.isEmpty());
+ }
+ QVERIFY(!e.isNull());
+ QCss::StyleSelector::NodePtr n;
+ n.ptr = &e;
+ QVector<QCss::Declaration> decls = testSelector.declarationsForNode(n);
+
+ if (match) {
+ QCOMPARE(decls.count(), 1);
+ QCOMPARE(int(decls.at(0).d->propertyId), int(QCss::BackgroundColor));
+ QCOMPARE(decls.at(0).d->values.count(), 1);
+ QCOMPARE(int(decls.at(0).d->values.at(0).type), int(QCss::Value::Identifier));
+ QCOMPARE(decls.at(0).d->values.at(0).variant.toString(), QString("green"));
+ } else {
+ QVERIFY(decls.isEmpty());
+ }
+}
+
+void tst_QCssParser::specificity_data()
+{
+ QTest::addColumn<QString>("selector");
+ QTest::addColumn<int>("specificity");
+
+ QTest::newRow("universal") << QString("*") << 0;
+
+ QTest::newRow("elements+pseudos1") << QString("foo") << 1;
+ QTest::newRow("elements+pseudos2") << QString("foo *[blah]") << 1 + (1 * 0x10);
+
+ // should strictly speaking be '2', but we don't support pseudo-elements yet,
+ // only pseudo-classes
+ QTest::newRow("elements+pseudos3") << QString("li:first-line") << 1 + (1 * 0x10);
+
+ QTest::newRow("elements+pseudos4") << QString("ul li") << 2;
+ QTest::newRow("elements+pseudos5") << QString("ul ol+li") << 3;
+ QTest::newRow("elements+pseudos6") << QString("h1 + *[rel=up]") << 1 + (1 * 0x10);
+
+ QTest::newRow("elements+pseudos7") << QString("ul ol li.red") << 3 + (1 * 0x10);
+ QTest::newRow("elements+pseudos8") << QString("li.red.level") << 1 + (2 * 0x10);
+ QTest::newRow("id") << QString("#x34y") << 1 * 0x100;
+}
+
+void tst_QCssParser::specificity()
+{
+ QFETCH(QString, selector);
+
+ QString css = QString("%1 { }").arg(selector);
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCOMPARE(sheet.styleRules.count() + sheet.nameIndex.count() + sheet.idIndex.count() , 1);
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ? sheet.styleRules.at(0)
+ : (!sheet.nameIndex.isEmpty()) ? *sheet.nameIndex.begin()
+ : *sheet.idIndex.begin();
+ QCOMPARE(rule.selectors.count(), 1);
+ QTEST(rule.selectors.at(0).specificity(), "specificity");
+}
+
+void tst_QCssParser::specificitySort_data()
+{
+ QTest::addColumn<QString>("firstSelector");
+ QTest::addColumn<QString>("secondSelector");
+ QTest::addColumn<QString>("xml");
+
+ QTest::newRow("universal1") << QString("*") << QString("p") << QString("<p />");
+ QTest::newRow("attr") << QString("p") << QString("p[foo=bar]") << QString("<p foo=\"bar\" />");
+ QTest::newRow("id") << QString("p") << QString("#hey") << QString("<p id=\"hey\" />");
+ QTest::newRow("id2") << QString("[id=hey]") << QString("#hey") << QString("<p id=\"hey\" />");
+ QTest::newRow("class") << QString("p") << QString(".hey") << QString("<p class=\"hey\" />");
+}
+
+void tst_QCssParser::specificitySort()
+{
+ QFETCH(QString, firstSelector);
+ QFETCH(QString, secondSelector);
+ QFETCH(QString, xml);
+
+ firstSelector.append(" { color: green; }");
+ secondSelector.append(" { color: red; }");
+
+ QDomDocument doc;
+ xml.prepend("<!DOCTYPE test><test>");
+ xml.append("</test>");
+ QVERIFY(doc.setContent(xml));
+
+ for (int i = 0; i < 2; ++i) {
+ QString css;
+ if (i == 0)
+ css = firstSelector + secondSelector;
+ else
+ css = secondSelector + firstSelector;
+
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ DomStyleSelector testSelector(doc, sheet);
+
+ QDomElement e = doc.documentElement().firstChildElement();
+ QCss::StyleSelector::NodePtr n;
+ n.ptr = &e;
+ QVector<QCss::Declaration> decls = testSelector.declarationsForNode(n);
+
+ QCOMPARE(decls.count(), 2);
+
+ QCOMPARE(int(decls.at(0).d->propertyId), int(QCss::Color));
+ QCOMPARE(decls.at(0).d->values.count(), 1);
+ QCOMPARE(int(decls.at(0).d->values.at(0).type), int(QCss::Value::Identifier));
+ QCOMPARE(decls.at(0).d->values.at(0).variant.toString(), QString("green"));
+
+ QCOMPARE(int(decls.at(1).d->propertyId), int(QCss::Color));
+ QCOMPARE(decls.at(1).d->values.count(), 1);
+ QCOMPARE(int(decls.at(1).d->values.at(0).type), int(QCss::Value::Identifier));
+ QCOMPARE(decls.at(1).d->values.at(0).variant.toString(), QString("red"));
+ }
+}
+
+void tst_QCssParser::rulesForNode_data()
+{
+ QTest::addColumn<QString>("xml");
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<quint64>("pseudoClass");
+ QTest::addColumn<int>("declCount");
+ QTest::addColumn<QString>("value0");
+ QTest::addColumn<QString>("value1");
+
+ QTest::newRow("universal1") << QString("<p/>") << QString("* { color: red }")
+ << (quint64)QCss::PseudoClass_Unspecified << 1 << "red" << "";
+
+ QTest::newRow("basic") << QString("<p/>") << QString("p:enabled { color: red; bg:blue; }")
+ << (quint64)QCss::PseudoClass_Enabled << 2 << "red" << "blue";
+
+ QTest::newRow("single") << QString("<p/>")
+ << QString("p:enabled { color: red; } *:hover { color: white }")
+ << (quint64)QCss::PseudoClass_Hover << 1 << "white" << "";
+
+ QTest::newRow("multisel") << QString("<p/>")
+ << QString("p:enabled { color: red; } p:hover { color: gray } *:hover { color: white } ")
+ << (quint64)QCss::PseudoClass_Hover << 2 << "white" << "gray";
+
+ QTest::newRow("multisel2") << QString("<p/>")
+ << QString("p:enabled { color: red; } p:hover:focus { color: gray } *:hover { color: white } ")
+ << quint64(QCss::PseudoClass_Hover|QCss::PseudoClass_Focus) << 2 << "white" << "gray";
+
+ QTest::newRow("multisel3-diffspec") << QString("<p/>")
+ << QString("p:enabled { color: red; } p:hover:focus { color: gray } *:hover { color: white } ")
+ << quint64(QCss::PseudoClass_Hover) << 1 << "white" << "";
+
+ QTest::newRow("!-1") << QString("<p/>")
+ << QString("p:checked:!hover { color: red; } p:checked:hover { color: gray } p:checked { color: white }")
+ << quint64(QCss::PseudoClass_Hover|QCss::PseudoClass_Checked) << 2 << "white" << "gray";
+
+ QTest::newRow("!-2") << QString("<p/>")
+ << QString("p:checked:!hover:!pressed { color: red; } p:!checked:hover { color: gray } p:!focus { color: blue }")
+ << quint64(QCss::PseudoClass_Focus) << 0 << "" << "";
+
+ QTest::newRow("!-3") << QString("<p/>")
+ << QString("p:checked:!hover:!pressed { color: red; } p:!checked:hover { color: gray } p:!focus { color: blue; }")
+ << quint64(QCss::PseudoClass_Pressed) << 1 << "blue" << "";
+}
+
+void tst_QCssParser::rulesForNode()
+{
+ QFETCH(QString, xml);
+ QFETCH(QString, css);
+ QFETCH(quint64, pseudoClass);
+ QFETCH(int, declCount);
+ QFETCH(QString, value0);
+ QFETCH(QString, value1);
+
+ QDomDocument doc;
+ xml.prepend("<!DOCTYPE test><test>");
+ xml.append("</test>");
+ QVERIFY(doc.setContent(xml));
+
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ DomStyleSelector testSelector(doc, sheet);
+ QDomElement e = doc.documentElement().firstChildElement();
+ QCss::StyleSelector::NodePtr n;
+ n.ptr = &e;
+ QVector<QCss::StyleRule> rules = testSelector.styleRulesForNode(n);
+
+ QVector<QCss::Declaration> decls;
+ for (int i = 0; i < rules.count(); i++) {
+ const QCss::Selector &selector = rules.at(i).selectors.at(0);
+ quint64 negated = 0;
+ quint64 cssClass = selector.pseudoClass(&negated);
+ if ((cssClass == QCss::PseudoClass_Unspecified)
+ || ((((cssClass & pseudoClass) == cssClass)) && ((negated & pseudoClass) == 0)))
+ decls += rules.at(i).declarations;
+ }
+
+ QVERIFY(decls.count() == declCount);
+
+ if (declCount > 0)
+ QCOMPARE(decls.at(0).d->values.at(0).variant.toString(), value0);
+ if (declCount > 1)
+ QCOMPARE(decls.at(1).d->values.at(0).variant.toString(), value1);
+}
+
+void tst_QCssParser::shorthandBackgroundProperty_data()
+{
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QBrush>("expectedBrush");
+ QTest::addColumn<QString>("expectedImage");
+ QTest::addColumn<int>("expectedRepeatValue");
+ QTest::addColumn<int>("expectedAlignment");
+
+ QTest::newRow("simple color") << "background: red" << QBrush(QColor("red")) << QString() << int(QCss::Repeat_XY) << int(Qt::AlignLeft | Qt::AlignTop);
+ QTest::newRow("plain color") << "background-color: red" << QBrush(QColor("red")) << QString() << int(QCss::Repeat_XY) << int(Qt::AlignLeft | Qt::AlignTop);
+ QTest::newRow("palette color") << "background-color: palette(mid)" << qApp->palette().mid() << QString() << int(QCss::Repeat_XY) << int(Qt::AlignLeft | Qt::AlignTop);
+ QTest::newRow("multiple") << "background: url(chess.png) blue repeat-y" << QBrush(QColor("blue")) << QString("chess.png") << int(QCss::Repeat_Y) << int(Qt::AlignLeft | Qt::AlignTop);
+ QTest::newRow("plain alignment") << "background-position: center" << QBrush() << QString() << int(QCss::Repeat_XY) << int(Qt::AlignCenter);
+ QTest::newRow("plain alignment2") << "background-position: left top" << QBrush() << QString() << int(QCss::Repeat_XY) << int(Qt::AlignLeft | Qt::AlignTop);
+ QTest::newRow("plain alignment3") << "background-position: left" << QBrush() << QString() << int(QCss::Repeat_XY) << int(Qt::AlignLeft | Qt::AlignVCenter);
+ QTest::newRow("multi") << "background: left url(blah.png) repeat-x" << QBrush() << QString("blah.png") << int(QCss::Repeat_X) << int(Qt::AlignLeft | Qt::AlignVCenter);
+ QTest::newRow("multi2") << "background: url(blah.png) repeat-x top" << QBrush() << QString("blah.png") << int(QCss::Repeat_X) << int(Qt::AlignTop | Qt::AlignHCenter);
+ QTest::newRow("multi3") << "background: url(blah.png) top right" << QBrush() << QString("blah.png") << int(QCss::Repeat_XY) << int(Qt::AlignTop | Qt::AlignRight);
+}
+
+void tst_QCssParser::shorthandBackgroundProperty()
+{
+ QFETCH(QString, css);
+
+ QDomDocument doc;
+ QVERIFY(doc.setContent(QLatin1String("<!DOCTYPE test><test> <dummy/> </test>")));
+
+ css.prepend("dummy {");
+ css.append("}");
+
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ DomStyleSelector testSelector(doc, sheet);
+ QDomElement e = doc.documentElement().firstChildElement();
+ QCss::StyleSelector::NodePtr n;
+ n.ptr = &e;
+ QVector<QCss::StyleRule> rules = testSelector.styleRulesForNode(n);
+ QVector<QCss::Declaration> decls = rules.at(0).declarations;
+ QCss::ValueExtractor v(decls);
+
+ QBrush brush;
+ QString image;
+ QCss::Repeat repeat = QCss::Repeat_XY;
+ Qt::Alignment alignment = Qt::AlignTop | Qt::AlignLeft;
+ QCss::Origin origin = QCss::Origin_Padding;
+ QCss::Attachment attachment;
+ QCss::Origin ignoredOrigin;
+ v.extractBackground(&brush, &image, &repeat, &alignment, &origin, &attachment, &ignoredOrigin);
+
+ QFETCH(QBrush, expectedBrush);
+ QVERIFY(expectedBrush.color() == brush.color());
+
+ QTEST(image, "expectedImage");
+ QTEST(int(repeat), "expectedRepeatValue");
+ QTEST(int(alignment), "expectedAlignment");
+
+ //QTBUG-9674 : a second evaluation should give the same results
+ QVERIFY(v.extractBackground(&brush, &image, &repeat, &alignment, &origin, &attachment, &ignoredOrigin));
+ QVERIFY(expectedBrush.color() == brush.color());
+ QTEST(image, "expectedImage");
+ QTEST(int(repeat), "expectedRepeatValue");
+ QTEST(int(alignment), "expectedAlignment");
+}
+
+void tst_QCssParser::pseudoElement_data()
+{
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QString>("pseudoElement");
+ QTest::addColumn<int>("declCount");
+
+ // QComboBox::dropDown { border-image: blah; }
+ QTest::newRow("no pseudo-elements") << QString("dummy:hover { color: red }") << "" << 1;
+ QTest::newRow("no pseudo-elements") << QString("dummy:hover { color: red }") << "pe" << 0;
+
+ QTest::newRow("1 pseudo-element (1)") << QString("dummy::pe:hover { color: red }") << "pe" << 1;
+ QTest::newRow("1 pseudo-element (2)") << QString("dummy::pe:hover { color: red }") << "x" << 0;
+ QTest::newRow("1 pseudo-element (2)") << QString("whatever::pe:hover { color: red }") << "pe" << 0;
+
+ QTest::newRow("1 pseudo-element (3)")
+ << QString("dummy { color: white; } dummy::pe:hover { color: red }") << "x" << 0;
+ QTest::newRow("1 pseudo-element (4)")
+ << QString("dummy { color: white; } dummy::pe:hover { color: red } dummy { x:y }") << "" << 2;
+ QTest::newRow("1 pseudo-element (5)")
+ << QString("dummy { color: white; } dummy::pe:hover { color: red }") << "pe" << 1;
+ QTest::newRow("1 pseudo-element (6)")
+ << QString("dummy { color: white; } dummy::pe:hover { color: red } dummy::pe:checked { x: y} ") << "pe" << 2;
+
+ QTest::newRow("2 pseudo-elements (1)")
+ << QString("dummy { color: white; } dummy::pe1:hover { color: red } dummy::pe2:checked { x: y} ")
+ << "" << 1;
+ QTest::newRow("2 pseudo-elements (1)")
+ << QString("dummy { color: white; } dummy::pe1:hover { color: red } dummy::pe2:checked { x: y} ")
+ << "pe1" << 1;
+ QTest::newRow("2 pseudo-elements (2)")
+ << QString("dummy { color: white; } dummy::pe1:hover { color: red } dummy::pe2:checked { x: y} ")
+ << "pe2" << 1;
+}
+
+void tst_QCssParser::pseudoElement()
+{
+ QFETCH(QString, css);
+ QFETCH(QString, pseudoElement);
+ QFETCH(int, declCount);
+
+ QDomDocument doc;
+ QVERIFY(doc.setContent(QLatin1String("<!DOCTYPE test><test> <dummy/> </test>")));
+
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ DomStyleSelector testSelector(doc, sheet);
+ QDomElement e = doc.documentElement().firstChildElement();
+ QCss::StyleSelector::NodePtr n;
+ n.ptr = &e;
+ QVector<QCss::StyleRule> rules = testSelector.styleRulesForNode(n);
+ QVector<QCss::Declaration> decls;
+ for (int i = 0; i < rules.count(); i++) {
+ const QCss::Selector& selector = rules.at(i).selectors.at(0);
+ if (pseudoElement.compare(selector.pseudoElement(), Qt::CaseInsensitive) != 0)
+ continue;
+ decls += rules.at(i).declarations;
+
+ }
+ QVERIFY(decls.count() == declCount);
+}
+
+void tst_QCssParser::gradient_data()
+{
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QString>("type");
+ QTest::addColumn<QPointF>("start");
+ QTest::addColumn<QPointF>("finalStop");
+ QTest::addColumn<int>("spread");
+ QTest::addColumn<qreal>("stop0");
+ QTest::addColumn<QColor>("color0");
+ QTest::addColumn<qreal>("stop1");
+ QTest::addColumn<QColor>("color1");
+
+ QTest::newRow("color-string") <<
+ "selection-background-color: qlineargradient(x1:1, y1:2, x2:3, y2:4, "
+ "stop:0.2 red, stop:0.5 green)" << "linear" << QPointF(1, 2) << QPointF(3, 4)
+ << 0 << qreal(0.2) << QColor("red") << qreal(0.5) << QColor("green");
+
+ QTest::newRow("color-#") <<
+ "selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
+ "spread: reflect, stop:0.2 #123, stop:0.5 #456)" << "linear" << QPointF(0, 0) << QPointF(0, 1)
+ << 1 << qreal(0.2) << QColor("#123") << qreal(0.5) << QColor("#456");
+
+ QTest::newRow("color-rgb") <<
+ "selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
+ "spread: reflect, stop:0.2 rgb(1, 2, 3), stop:0.5 rgba(1, 2, 3, 4))" << "linear" << QPointF(0, 0) << QPointF(0, 1)
+ << 1 << qreal(0.2) << QColor(1, 2, 3) << qreal(0.5) << QColor(1, 2, 3, 4);
+
+ QTest::newRow("color-spaces") <<
+ "selection-background-color: qlineargradient(x1: 0, y1 :0,x2:0, y2 : 1 , "
+ "spread: reflect, stop:0.2 rgb(1, 2, 3), stop: 0.5 rgba(1, 2, 3, 4))" << "linear" << QPointF(0, 0) << QPointF(0, 1)
+ << 1 << qreal(0.2) << QColor(1, 2, 3) << qreal(0.5) << QColor(1, 2, 3, 4);
+
+ QTest::newRow("conical gradient") <<
+ "selection-background-color: qconicalgradient(cx: 4, cy : 2, angle: 23, "
+ "spread: repeat, stop:0.2 rgb(1, 2, 3), stop:0.5 rgba(1, 2, 3, 4))" << "conical" << QPointF(4, 2) << QPointF()
+ << 2 << qreal(0.2) << QColor(1, 2, 3) << qreal(0.5) << QColor(1, 2, 3, 4);
+
+ /* wont pass: stop values are expected to be sorted
+ QTest::newRow("unsorted-stop") <<
+ "selection-background: lineargradient(x1:0, y1:0, x2:0, y2:1, "
+ "stop:0.5 green, stop:0.2 red)" << QPointF(0, 0) << QPointF(0, 1)
+ 0 << 0.2 << QColor("red") << 0.5 << QColor("green");
+ */
+}
+
+void tst_QCssParser::gradient()
+{
+ QFETCH(QString, css);
+ QFETCH(QString, type);
+ QFETCH(QPointF, finalStop);
+ QFETCH(QPointF, start);
+ QFETCH(int, spread);
+ QFETCH(qreal, stop0); QFETCH(QColor, color0);
+ QFETCH(qreal, stop1); QFETCH(QColor, color1);
+
+ QDomDocument doc;
+ QVERIFY(doc.setContent(QLatin1String("<!DOCTYPE test><test> <dummy/> </test>")));
+
+ css.prepend("dummy {");
+ css.append("}");
+
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ DomStyleSelector testSelector(doc, sheet);
+ QDomElement e = doc.documentElement().firstChildElement();
+ QCss::StyleSelector::NodePtr n;
+ n.ptr = &e;
+ QVector<QCss::StyleRule> rules = testSelector.styleRulesForNode(n);
+ QVector<QCss::Declaration> decls = rules.at(0).declarations;
+ QCss::ValueExtractor ve(decls);
+ QBrush fg, sfg;
+ QBrush sbg, abg;
+ QVERIFY(ve.extractPalette(&fg, &sfg, &sbg, &abg));
+ if (type == "linear") {
+ QVERIFY(sbg.style() == Qt::LinearGradientPattern);
+ const QLinearGradient *lg = static_cast<const QLinearGradient *>(sbg.gradient());
+ QCOMPARE(lg->start(), start);
+ QCOMPARE(lg->finalStop(), finalStop);
+ } else if (type == "conical") {
+ QVERIFY(sbg.style() == Qt::ConicalGradientPattern);
+ const QConicalGradient *cg = static_cast<const QConicalGradient *>(sbg.gradient());
+ QCOMPARE(cg->center(), start);
+ }
+ const QGradient *g = sbg.gradient();
+ QCOMPARE(g->spread(), QGradient::Spread(spread));
+ QVERIFY(g->stops().at(0).first == stop0);
+ QVERIFY(g->stops().at(0).second == color0);
+ QVERIFY(g->stops().at(1).first == stop1);
+ QVERIFY(g->stops().at(1).second == color1);
+}
+
+void tst_QCssParser::extractFontFamily_data()
+{
+ if (QFontInfo(QFont("Times New Roman")).family() != "Times New Roman")
+ QSKIP("'Times New Roman' font not found ", SkipAll);
+
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<QString>("expectedFamily");
+
+ QTest::newRow("quoted-family-name") << "font-family: 'Times New Roman'" << QString("Times New Roman");
+ QTest::newRow("unquoted-family-name") << "font-family: Times New Roman" << QString("Times New Roman");
+ QTest::newRow("unquoted-family-name2") << "font-family: Times New Roman" << QString("Times New Roman");
+ QTest::newRow("multiple") << "font-family: Times New Roman , foobar, 'baz'" << QString("Times New Roman");
+ QTest::newRow("multiple2") << "font-family: invalid, Times New Roman " << QString("Times New Roman");
+ QTest::newRow("invalid") << "font-family: invalid" << QFontInfo(QFont("invalid font")).family();
+ QTest::newRow("shorthand") << "font: 12pt Times New Roman" << QString("Times New Roman");
+ QTest::newRow("shorthand multiple quote") << "font: 12pt invalid, \"Times New Roman\" " << QString("Times New Roman");
+ QTest::newRow("shorthand multiple") << "font: 12pt invalid, Times New Roman " << QString("Times New Roman");
+ QTest::newRow("invalid spaces") << "font-family: invalid spaces, Times New Roman " << QString("Times New Roman");
+ QTest::newRow("invalid spaces quotes") << "font-family: 'invalid spaces', 'Times New Roman' " << QString("Times New Roman");
+}
+
+
+void tst_QCssParser::extractFontFamily()
+{
+ QFETCH(QString, css);
+ css.prepend("dummy {");
+ css.append("}");
+
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCOMPARE(sheet.styleRules.count() + sheet.nameIndex.count(), 1);
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
+ sheet.styleRules.at(0) : *sheet.nameIndex.begin();
+
+ const QVector<QCss::Declaration> decls = rule.declarations;
+ QVERIFY(!decls.isEmpty());
+ QCss::ValueExtractor extractor(decls);
+
+ int adjustment = 0;
+ QFont fnt;
+ extractor.extractFont(&fnt, &adjustment);
+ QFontInfo info(fnt);
+
+#ifdef Q_WS_QPA
+ // Note, we have to QSKIP rather than QEXPECT_FAIL because font lookup is broken
+ // such that it may work or not work depending on the order in which fonts were
+ // loaded from disk
+ QSKIP("QTBUG-20986 may fail on qpa", SkipSingle);
+#endif
+
+ QTEST(info.family(), "expectedFamily");
+}
+
+void tst_QCssParser::extractBorder_data()
+{
+ QTest::addColumn<QString>("css");
+ QTest::addColumn<int>("expectedTopWidth");
+ QTest::addColumn<int>("expectedTopStyle");
+ QTest::addColumn<QColor>("expectedTopColor");
+
+ QTest::newRow("all values") << "border: 2px solid green" << 2 << (int)QCss::BorderStyle_Solid << QColor("green");
+ QTest::newRow("palette") << "border: 2px solid palette(highlight)" << 2 << (int)QCss::BorderStyle_Solid << qApp->palette().color(QPalette::Highlight);
+ QTest::newRow("just width") << "border: 2px" << 2 << (int)QCss::BorderStyle_None << QColor();
+ QTest::newRow("just style") << "border: solid" << 0 << (int)QCss::BorderStyle_Solid << QColor();
+ QTest::newRow("just color") << "border: green" << 0 << (int)QCss::BorderStyle_None << QColor("green");
+ QTest::newRow("width+style") << "border: 2px solid" << 2 << (int)QCss::BorderStyle_Solid << QColor();
+ QTest::newRow("style+color") << "border: solid green" << 0 << (int)QCss::BorderStyle_Solid << QColor("green");
+ QTest::newRow("width+color") << "border: 3px green" << 3 << (int)QCss::BorderStyle_None << QColor("green");
+ QTest::newRow("groove style") << "border: groove" << 0 << (int)QCss::BorderStyle_Groove << QColor();
+ QTest::newRow("ridge style") << "border: ridge" << 0 << (int)QCss::BorderStyle_Ridge << QColor();
+ QTest::newRow("double style") << "border: double" << 0 << (int)QCss::BorderStyle_Double << QColor();
+ QTest::newRow("inset style") << "border: inset" << 0 << (int)QCss::BorderStyle_Inset << QColor();
+ QTest::newRow("outset style") << "border: outset" << 0 << (int)QCss::BorderStyle_Outset << QColor();
+ QTest::newRow("dashed style") << "border: dashed" << 0 << (int)QCss::BorderStyle_Dashed << QColor();
+ QTest::newRow("dotted style") << "border: dotted" << 0 << (int)QCss::BorderStyle_Dotted << QColor();
+ QTest::newRow("dot-dash style") << "border: dot-dash" << 0 << (int)QCss::BorderStyle_DotDash << QColor();
+ QTest::newRow("dot-dot-dash style") << "border: dot-dot-dash" << 0 << (int)QCss::BorderStyle_DotDotDash << QColor();
+
+ QTest::newRow("top-width+color") << "border-top: 3px green" << 3 << (int)QCss::BorderStyle_None << QColor("green");
+}
+
+void tst_QCssParser::extractBorder()
+{
+ QFETCH(QString, css);
+ QFETCH(int, expectedTopWidth);
+ QFETCH(int, expectedTopStyle);
+ QFETCH(QColor, expectedTopColor);
+
+ css.prepend("dummy {");
+ css.append("}");
+
+ QCss::Parser parser(css);
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCOMPARE(sheet.styleRules.count() + sheet.nameIndex.count(), 1);
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
+ sheet.styleRules.at(0) : *sheet.nameIndex.begin();
+ const QVector<QCss::Declaration> decls = rule.declarations;
+ QVERIFY(!decls.isEmpty());
+ QCss::ValueExtractor extractor(decls);
+
+ int widths[4];
+ QBrush colors[4];
+ QCss::BorderStyle styles[4];
+ QSize radii[4];
+
+ extractor.extractBorder(widths, colors, styles, radii);
+ QVERIFY(widths[QCss::TopEdge] == expectedTopWidth);
+ QVERIFY(styles[QCss::TopEdge] == expectedTopStyle);
+ QVERIFY(colors[QCss::TopEdge] == expectedTopColor);
+
+ //QTBUG-9674 : a second evaluation should give the same results
+ QVERIFY(extractor.extractBorder(widths, colors, styles, radii));
+ QVERIFY(widths[QCss::TopEdge] == expectedTopWidth);
+ QVERIFY(styles[QCss::TopEdge] == expectedTopStyle);
+ QVERIFY(colors[QCss::TopEdge] == expectedTopColor);
+}
+
+void tst_QCssParser::noTextDecoration()
+{
+ QCss::Parser parser("dummy { text-decoration: none; }");
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCOMPARE(sheet.styleRules.count() + sheet.nameIndex.count(), 1);
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
+ sheet.styleRules.at(0) : *sheet.nameIndex.begin();
+ const QVector<QCss::Declaration> decls = rule.declarations;
+ QVERIFY(!decls.isEmpty());
+ QCss::ValueExtractor extractor(decls);
+
+ int adjustment = 0;
+ QFont f;
+ f.setUnderline(true);
+ f.setOverline(true);
+ f.setStrikeOut(true);
+ QVERIFY(extractor.extractFont(&f, &adjustment));
+
+ QVERIFY(!f.underline());
+ QVERIFY(!f.overline());
+ QVERIFY(!f.strikeOut());
+}
+
+void tst_QCssParser::quotedAndUnquotedIdentifiers()
+{
+ QCss::Parser parser("foo { font-style: \"italic\"; font-weight: bold }");
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCOMPARE(sheet.styleRules.count() + sheet.nameIndex.count(), 1);
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
+ sheet.styleRules.at(0) : *sheet.nameIndex.begin();
+ const QVector<QCss::Declaration> decls = rule.declarations;
+ QCOMPARE(decls.size(), 2);
+
+ QCOMPARE(decls.at(0).d->values.first().type, QCss::Value::String);
+ QCOMPARE(decls.at(0).d->property, QLatin1String("font-style"));
+ QCOMPARE(decls.at(0).d->values.first().toString(), QLatin1String("italic"));
+
+ QCOMPARE(decls.at(1).d->values.first().type, QCss::Value::KnownIdentifier);
+ QCOMPARE(decls.at(1).d->property, QLatin1String("font-weight"));
+ QCOMPARE(decls.at(1).d->values.first().toString(), QLatin1String("bold"));
+}
+
+QTEST_MAIN(tst_QCssParser)
+#include "tst_qcssparser.moc"
+
diff --git a/tests/auto/gui/text/qfont/.gitignore b/tests/auto/gui/text/qfont/.gitignore
new file mode 100644
index 0000000000..61aa3df16c
--- /dev/null
+++ b/tests/auto/gui/text/qfont/.gitignore
@@ -0,0 +1 @@
+tst_qfont
diff --git a/tests/auto/gui/text/qfont/qfont.pro b/tests/auto/gui/text/qfont/qfont.pro
new file mode 100644
index 0000000000..891cb0a093
--- /dev/null
+++ b/tests/auto/gui/text/qfont/qfont.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qfont.cpp
+
+
diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp
new file mode 100644
index 0000000000..a564e71e19
--- /dev/null
+++ b/tests/auto/gui/text/qfont/tst_qfont.cpp
@@ -0,0 +1,629 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qfont.h>
+#include <qfontdatabase.h>
+#include <qfontinfo.h>
+#include <qstringlist.h>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qlist.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QFont : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QFont();
+ virtual ~tst_QFont();
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void exactMatch();
+ void compare();
+ void resolve();
+ void resetFont();
+ void isCopyOf();
+ void setFontRaw();
+ void italicOblique();
+ void insertAndRemoveSubstitutions();
+ void serializeSpacing();
+ void lastResortFont();
+ void styleName();
+};
+
+// Testing get/set functions
+void tst_QFont::getSetCheck()
+{
+ QFont obj1;
+ // Style QFont::style()
+ // void QFont::setStyle(Style)
+ obj1.setStyle(QFont::Style(QFont::StyleNormal));
+ QCOMPARE(QFont::Style(QFont::StyleNormal), obj1.style());
+ obj1.setStyle(QFont::Style(QFont::StyleItalic));
+ QCOMPARE(QFont::Style(QFont::StyleItalic), obj1.style());
+ obj1.setStyle(QFont::Style(QFont::StyleOblique));
+ QCOMPARE(QFont::Style(QFont::StyleOblique), obj1.style());
+
+ // StyleStrategy QFont::styleStrategy()
+ // void QFont::setStyleStrategy(StyleStrategy)
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::PreferDefault));
+ QCOMPARE(QFont::StyleStrategy(QFont::PreferDefault), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::PreferBitmap));
+ QCOMPARE(QFont::StyleStrategy(QFont::PreferBitmap), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::PreferDevice));
+ QCOMPARE(QFont::StyleStrategy(QFont::PreferDevice), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::PreferOutline));
+ QCOMPARE(QFont::StyleStrategy(QFont::PreferOutline), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::ForceOutline));
+ QCOMPARE(QFont::StyleStrategy(QFont::ForceOutline), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::PreferMatch));
+ QCOMPARE(QFont::StyleStrategy(QFont::PreferMatch), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::PreferQuality));
+ QCOMPARE(QFont::StyleStrategy(QFont::PreferQuality), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::PreferAntialias));
+ QCOMPARE(QFont::StyleStrategy(QFont::PreferAntialias), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::NoAntialias));
+ QCOMPARE(QFont::StyleStrategy(QFont::NoAntialias), obj1.styleStrategy());
+ obj1.setStyleStrategy(QFont::StyleStrategy(QFont::OpenGLCompatible));
+ QCOMPARE(QFont::StyleStrategy(QFont::OpenGLCompatible), obj1.styleStrategy());
+}
+
+tst_QFont::tst_QFont()
+{
+}
+
+tst_QFont::~tst_QFont()
+{
+
+}
+
+void tst_QFont::init()
+{
+// TODO: Add initialization code here.
+// This will be executed immediately before each test is run.
+}
+
+void tst_QFont::cleanup()
+{
+// TODO: Add cleanup code here.
+// This will be executed immediately after each test is run.
+}
+
+void tst_QFont::exactMatch()
+{
+ QFont font;
+
+ // Check if a non-existing font hasn't an exact match
+ font = QFont( "BogusFont", 33 );
+ QVERIFY( !font.exactMatch() );
+
+#ifdef Q_WS_WIN
+ QSKIP("Exact matching on windows misses a lot because of the sample chars", SkipAll);
+ return;
+#endif
+
+#ifdef Q_WS_X11
+ QVERIFY(QFont("sans").exactMatch());
+ QVERIFY(QFont("sans-serif").exactMatch());
+ QVERIFY(QFont("serif").exactMatch());
+ QVERIFY(QFont("monospace").exactMatch());
+#endif
+
+ QSKIP("This test is bogus on Unix with support for font aliases in fontconfig", SkipAll);
+ return;
+
+ QFontDatabase fdb;
+
+ QList<QFontDatabase::WritingSystem> systems = fdb.writingSystems();
+ for (int system = 0; system < systems.count(); ++system) {
+ QStringList families = fdb.families(systems[system]);
+ if (families.isEmpty())
+ return;
+
+ QStringList::ConstIterator f_it, f_end = families.end();
+ for (f_it = families.begin(); f_it != f_end; ++f_it) {
+ const QString &family = *f_it;
+ if (family.contains('['))
+ continue;
+
+ QStringList styles = fdb.styles(family);
+ QVERIFY(!styles.isEmpty());
+ QStringList::ConstIterator s_it, s_end = styles.end();
+ for (s_it = styles.begin(); s_it != s_end; ++s_it) {
+ const QString &style = *s_it;
+
+ if (fdb.isSmoothlyScalable(family, style)) {
+ // smoothly scalable font... don't need to load every pointsize
+ font = fdb.font(family, style, 12);
+ QFontInfo fontinfo(font);
+
+ if (! fontinfo.exactMatch()) {
+ // Unfortunately, this can fail, since
+ // QFontDatabase does not fill in all font
+ // properties. Check to make sure that the
+ // test didn't fail for obvious reasons
+
+ if (fontinfo.family().isEmpty()
+ && fontinfo.pointSize() == 0) {
+ // this is a box rendering engine... this can happen from
+ // time to time, especially on X11 with iso10646-1 or
+ // unknown font encodings
+ continue;
+ }
+
+#ifdef Q_WS_WIN32
+ if (font.family().startsWith("MS ") || fontinfo.family().startsWith("MS ")) {
+ /* qDebug("Family matching skipped for MS-Alias font: %s, fontinfo: %s",
+ font.family().latin1(), fontinfo.family().latin1());
+ */
+ } else
+#endif
+ {
+ if (!(font.family() == fontinfo.family()
+ || fontinfo.family().contains(font.family())
+ || fontinfo.family().isEmpty())) {
+ qDebug("Test about to fail for font: %s, fontinfo: %s",
+ font.family().toLatin1().constData(),
+ fontinfo.family().toLatin1().constData());
+ }
+ QVERIFY(font.family() == fontinfo.family()
+ || fontinfo.family().contains(font.family())
+ || fontinfo.family().isEmpty());
+ }
+ if (font.pointSize() != -1) {
+ QVERIFY(font.pointSize() == fontinfo.pointSize());
+ } else {
+ QVERIFY(font.pixelSize() == fontinfo.pixelSize());
+ }
+ QVERIFY(font.italic() == fontinfo.italic());
+ if (font.weight() != fontinfo.weight()) {
+ qDebug("font is %s", font.toString().toLatin1().constData());
+ }
+ QVERIFY(font.weight() == fontinfo.weight());
+ } else {
+ font.setFixedPitch(!fontinfo.fixedPitch());
+ QFontInfo fontinfo1(font);
+ QVERIFY( !fontinfo1.exactMatch() );
+
+ font.setFixedPitch(fontinfo.fixedPitch());
+ QFontInfo fontinfo2(font);
+ QVERIFY( fontinfo2.exactMatch() );
+ }
+ }
+#if 0
+ // ############## can only work if we have float point sizes in QFD
+ else {
+ QList<int> sizes = fdb.pointSizes(family, style);
+ QVERIFY(!sizes.isEmpty());
+ QList<int>::ConstIterator z_it, z_end = sizes.end();
+ for (z_it = sizes.begin(); z_it != z_end; ++z_it) {
+ const int size = *z_it;
+
+ // Initialize the font, and check if it is an exact match
+ font = fdb.font(family, style, size);
+ QFontInfo fontinfo(font, (QFont::Script) script);
+
+ if (! fontinfo.exactMatch()) {
+ // Unfortunately, this can fail, since
+ // QFontDatabase does not fill in all font
+ // properties. Check to make sure that the
+ // test didn't fail for obvious reasons
+
+ if (fontinfo.family().isEmpty()
+ && fontinfo.pointSize() == 0) {
+ // this is a box rendering engine... this can happen from
+ // time to time, especially on X11 with iso10646-1 or
+ // unknown font encodings
+ continue;
+ }
+
+ // no need to skip MS-fonts here it seems
+ if (!(font.family() == fontinfo.family()
+ || fontinfo.family().contains(font.family())
+ || fontinfo.family().isEmpty())) {
+ qDebug("Test about to fail for font: %s, fontinfo: %s",
+ font.family().latin1(), fontinfo.family().latin1());
+ }
+ QVERIFY(font.family() == fontinfo.family()
+ || fontinfo.family().contains(font.family())
+ || fontinfo.family().isEmpty());
+ if (font.pointSize() != -1) {
+ QVERIFY(font.pointSize() == fontinfo.pointSize());
+ } else {
+ QVERIFY(font.pixelSize() == fontinfo.pixelSize());
+ }
+ QVERIFY(font.italic() == fontinfo.italic());
+ QVERIFY(font.weight() == fontinfo.weight());
+ } else {
+ font.setFixedPitch(!fontinfo.fixedPitch());
+ QFontInfo fontinfo1(font, (QFont::Script) script);
+ QVERIFY( !fontinfo1.exactMatch() );
+
+ font.setFixedPitch(fontinfo.fixedPitch());
+ QFontInfo fontinfo2(font, (QFont::Script) script);
+ QVERIFY( fontinfo2.exactMatch() );
+ }
+ }
+ }
+#endif
+ }
+ }
+ }
+}
+
+void tst_QFont::italicOblique()
+{
+ QFontDatabase fdb;
+
+ QStringList families = fdb.families();
+ if (families.isEmpty())
+ return;
+
+ QStringList::ConstIterator f_it, f_end = families.end();
+ for (f_it = families.begin(); f_it != f_end; ++f_it) {
+
+ QString family = *f_it;
+ QStringList styles = fdb.styles(family);
+ QVERIFY(!styles.isEmpty());
+ QStringList::ConstIterator s_it, s_end = styles.end();
+ for (s_it = styles.begin(); s_it != s_end; ++s_it) {
+ QString style = *s_it;
+
+ if (fdb.isSmoothlyScalable(family, style)) {
+ if (style.contains("Oblique")) {
+ style.replace("Oblique", "Italic");
+ } else if (style.contains("Italic")) {
+ style.replace("Italic", "Oblique");
+ } else {
+ continue;
+ }
+ QFont f = fdb.font(family, style, 12);
+ QVERIFY(f.italic());
+ }
+ }
+ }
+}
+
+void tst_QFont::compare()
+{
+ QFont font;
+ {
+ QFont font2 = font;
+ font2.setPointSize( 24 );
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ }
+ {
+ QFont font2 = font;
+ font2.setPixelSize( 24 );
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ }
+
+ font.setPointSize(12);
+ font.setItalic(false);
+ font.setWeight(QFont::Normal);
+ font.setUnderline(false);
+ font.setStrikeOut(false);
+ font.setOverline(false);
+ {
+ QFont font2 = font;
+ font2.setPointSize( 24 );
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ }
+ {
+ QFont font2 = font;
+ font2.setPixelSize( 24 );
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ }
+ {
+ QFont font2 = font;
+
+ font2.setItalic(true);
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ font2.setItalic(false);
+ QVERIFY( font == font2 );
+ QVERIFY(!(font < font2));
+
+ font2.setWeight(QFont::Bold);
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ font2.setWeight(QFont::Normal);
+ QVERIFY( font == font2 );
+ QVERIFY(!(font < font2));
+
+ font.setUnderline(true);
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ font.setUnderline(false);
+ QVERIFY( font == font2 );
+ QVERIFY(!(font < font2));
+
+ font.setStrikeOut(true);
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ font.setStrikeOut(false);
+ QVERIFY( font == font2 );
+ QVERIFY(!(font < font2));
+
+ font.setOverline(true);
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ font.setOverline(false);
+ QVERIFY( font == font2 );
+ QVERIFY(!(font < font2));
+
+ font.setCapitalization(QFont::SmallCaps);
+ QVERIFY( font != font2 );
+ QCOMPARE(font < font2,!(font2 < font));
+ font.setCapitalization(QFont::MixedCase);
+ QVERIFY( font == font2 );
+ QVERIFY(!(font < font2));
+ }
+
+#if defined(Q_WS_X11)
+ {
+ QFont font1, font2;
+ font1.setRawName("-Adobe-Helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1");
+ font2.setRawName("-Adobe-Helvetica-medium-r-normal--24-240-75-75-p-130-iso8859-1");
+ QVERIFY(font1 != font2);
+ }
+#endif
+}
+
+void tst_QFont::resolve()
+{
+ QFont font;
+ font.setPointSize(font.pointSize() * 2);
+ font.setItalic(false);
+ font.setWeight(QFont::Normal);
+ font.setUnderline(false);
+ font.setStrikeOut(false);
+ font.setOverline(false);
+ font.setStretch(QFont::Unstretched);
+
+ QFont font1;
+ font1.setWeight(QFont::Bold);
+ QFont font2 = font1.resolve(font);
+
+ QVERIFY(font2.weight() == font1.weight());
+
+ QVERIFY(font2.pointSize() == font.pointSize());
+ QVERIFY(font2.italic() == font.italic());
+ QVERIFY(font2.underline() == font.underline());
+ QVERIFY(font2.overline() == font.overline());
+ QVERIFY(font2.strikeOut() == font.strikeOut());
+ QVERIFY(font2.stretch() == font.stretch());
+
+ QFont font3;
+ font3.setStretch(QFont::UltraCondensed);
+ QFont font4 = font3.resolve(font1).resolve(font);
+
+ QVERIFY(font4.stretch() == font3.stretch());
+
+ QVERIFY(font4.weight() == font.weight());
+ QVERIFY(font4.pointSize() == font.pointSize());
+ QVERIFY(font4.italic() == font.italic());
+ QVERIFY(font4.underline() == font.underline());
+ QVERIFY(font4.overline() == font.overline());
+ QVERIFY(font4.strikeOut() == font.strikeOut());
+
+
+ QFont f1,f2,f3;
+ f2.setPointSize(45);
+ f3.setPointSize(55);
+
+ QFont f4 = f1.resolve(f2);
+ QCOMPARE(f4.pointSize(), 45);
+ f4 = f4.resolve(f3);
+ QCOMPARE(f4.pointSize(), 55);
+}
+
+void tst_QFont::resetFont()
+{
+ QWidget parent;
+ QFont parentFont = parent.font();
+ parentFont.setPointSize(parentFont.pointSize() + 2);
+ parent.setFont(parentFont);
+
+ QWidget *child = new QWidget(&parent);
+
+ QFont childFont = child->font();
+ childFont.setBold(!childFont.bold());
+ child->setFont(childFont);
+
+ QVERIFY(parentFont.resolve() != 0);
+ QVERIFY(childFont.resolve() != 0);
+ QVERIFY(childFont != parentFont);
+
+ child->setFont(QFont()); // reset font
+
+ QVERIFY(child->font().resolve() == 0);
+ QVERIFY(child->font().pointSize() == parent.font().pointSize());
+ QVERIFY(parent.font().resolve() != 0);
+}
+
+void tst_QFont::isCopyOf()
+{
+ QFont font;
+ QVERIFY(font.isCopyOf(QApplication::font()));
+
+ QFont font2("bogusfont", 23);
+ QVERIFY(! font2.isCopyOf(QApplication::font()));
+
+ QFont font3 = font;
+ QVERIFY(font3.isCopyOf(font));
+
+ font3.setPointSize(256);
+ QVERIFY(!font3.isCopyOf(font));
+ font3.setPointSize(font.pointSize());
+ QVERIFY(!font3.isCopyOf(font));
+}
+
+void tst_QFont::setFontRaw()
+{
+#ifndef Q_WS_X11
+ QSKIP("Only tested on X11", SkipAll);
+#else
+ QFont f;
+ f.setRawName("-*-fixed-bold-r-normal--0-0-*-*-*-0-iso8859-1");
+// qDebug("font family: %s", f.family().utf8());
+ QFontDatabase fdb;
+ QStringList families = fdb.families();
+ bool found = false;
+ for (int i = 0; i < families.size(); ++i) {
+ QString str = families.at(i);
+ if (str.contains('['))
+ str = str.left(str.indexOf('[')-1);
+ if (str.toLower() == "fixed")
+ found = true;
+ }
+ if (!found) {
+ QSKIP("Fixed font not available.", SkipSingle);
+ }
+ QCOMPARE(QFontInfo(f).family().left(5).toLower(), QString("fixed"));
+#endif
+}
+
+void tst_QFont::insertAndRemoveSubstitutions()
+{
+ QFont::removeSubstitution("BogusFontFamily");
+ // make sure it is empty before we start
+ QVERIFY(QFont::substitutes("BogusFontFamily").isEmpty());
+ QVERIFY(QFont::substitutes("bogusfontfamily").isEmpty());
+
+ // inserting Foo
+ QFont::insertSubstitution("BogusFontFamily", "Foo");
+ QCOMPARE(QFont::substitutes("BogusFontFamily").count(), 1);
+ QCOMPARE(QFont::substitutes("bogusfontfamily").count(), 1);
+
+ // inserting Bar and Baz
+ QStringList moreFonts;
+ moreFonts << "Bar" << "Baz";
+ QFont::insertSubstitutions("BogusFontFamily", moreFonts);
+ QCOMPARE(QFont::substitutes("BogusFontFamily").count(), 3);
+ QCOMPARE(QFont::substitutes("bogusfontfamily").count(), 3);
+
+ QFont::removeSubstitution("BogusFontFamily");
+ // make sure it is empty again
+ QVERIFY(QFont::substitutes("BogusFontFamily").isEmpty());
+ QVERIFY(QFont::substitutes("bogusfontfamily").isEmpty());
+}
+
+
+static QFont copyFont(const QFont &font1) // copy using a QDataStream
+{
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream ds(&buffer);
+ ds << font1;
+ buffer.close();
+
+ buffer.open(QIODevice::ReadOnly);
+ QFont font2;
+ ds >> font2;
+ return font2;
+}
+
+void tst_QFont::serializeSpacing()
+{
+ QFont font;
+ QCOMPARE(font.letterSpacing(), 0.);
+ QCOMPARE(font.wordSpacing(), 0.);
+
+ font.setLetterSpacing(QFont::AbsoluteSpacing, 105);
+ QCOMPARE(font.letterSpacing(), 105.);
+ QCOMPARE(font.letterSpacingType(), QFont::AbsoluteSpacing);
+ QCOMPARE(font.wordSpacing(), 0.);
+ QFont font2 = copyFont(font);
+ QCOMPARE(font2.letterSpacing(), 105.);
+ QCOMPARE(font2.letterSpacingType(), QFont::AbsoluteSpacing);
+ QCOMPARE(font2.wordSpacing(), 0.);
+
+ font.setWordSpacing(50.0);
+ QCOMPARE(font.letterSpacing(), 105.);
+ QCOMPARE(font.wordSpacing(), 50.);
+
+ QFont font3 = copyFont(font);
+ QCOMPARE(font3.letterSpacing(), 105.);
+ QCOMPARE(font3.letterSpacingType(), QFont::AbsoluteSpacing);
+ QCOMPARE(font3.wordSpacing(), 50.);
+}
+
+void tst_QFont::lastResortFont()
+{
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ QSKIP("QFont::lastResortFont() may abort with qFatal() on QWS/QPA", SkipAll);
+ // ...if absolutely no font is found. Just as ducumented for QFont::lastResortFont().
+ // This happens on our CI machines which run QWS autotests.
+#endif
+ QFont font;
+ QVERIFY(!font.lastResortFont().isEmpty());
+}
+
+void tst_QFont::styleName()
+{
+#if !defined(Q_WS_MAC)
+ QSKIP("Only tested on Mac", SkipAll);
+#else
+ QFont font("Helvetica Neue");
+ font.setStyleName("UltraLight");
+
+ QCOMPARE(QFontInfo(font).styleName(), QString("UltraLight"));
+#endif
+}
+
+QTEST_MAIN(tst_QFont)
+#include "tst_qfont.moc"
diff --git a/tests/auto/gui/text/qfontdatabase/.gitignore b/tests/auto/gui/text/qfontdatabase/.gitignore
new file mode 100644
index 0000000000..65edf9b279
--- /dev/null
+++ b/tests/auto/gui/text/qfontdatabase/.gitignore
@@ -0,0 +1 @@
+tst_qfontdatabase
diff --git a/tests/auto/gui/text/qfontdatabase/FreeMono.ttf b/tests/auto/gui/text/qfontdatabase/FreeMono.ttf
new file mode 100644
index 0000000000..d7ce52ddc7
--- /dev/null
+++ b/tests/auto/gui/text/qfontdatabase/FreeMono.ttf
Binary files differ
diff --git a/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro b/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro
new file mode 100644
index 0000000000..e7dfc3c73d
--- /dev/null
+++ b/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+SOURCES += tst_qfontdatabase.cpp
+!symbian:DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+wince*|symbian {
+ additionalFiles.files = FreeMono.ttf
+ additionalFiles.path = .
+ DEPLOYMENT += additionalFiles
+}
+
diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
new file mode 100644
index 0000000000..1df61d0a06
--- /dev/null
+++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qfontdatabase.h>
+
+#ifdef Q_OS_SYMBIAN
+#define SRCDIR "."
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QFontDatabase : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QFontDatabase();
+ virtual ~tst_QFontDatabase();
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void styles_data();
+ void styles();
+
+ void fixedPitch_data();
+ void fixedPitch();
+
+#ifdef Q_WS_MAC
+ void trickyFonts_data();
+ void trickyFonts();
+#endif
+
+ void widthTwoTimes_data();
+ void widthTwoTimes();
+
+ void addAppFont_data();
+ void addAppFont();
+};
+
+tst_QFontDatabase::tst_QFontDatabase()
+{
+#ifndef Q_OS_IRIX
+ QDir::setCurrent(SRCDIR);
+#endif
+}
+
+tst_QFontDatabase::~tst_QFontDatabase()
+{
+
+}
+
+void tst_QFontDatabase::init()
+{
+// TODO: Add initialization code here.
+// This will be executed immediately before each test is run.
+}
+
+void tst_QFontDatabase::cleanup()
+{
+// TODO: Add cleanup code here.
+// This will be executed immediately after each test is run.
+}
+
+void tst_QFontDatabase::styles_data()
+{
+ QTest::addColumn<QString>("font");
+
+ QTest::newRow( "data0" ) << QString( "Times New Roman" );
+}
+
+void tst_QFontDatabase::styles()
+{
+ QFETCH( QString, font );
+
+ QFontDatabase fdb;
+ QStringList styles = fdb.styles( font );
+ QStringList::Iterator it = styles.begin();
+ while ( it != styles.end() ) {
+ QString style = *it;
+ QString trimmed = style.trimmed();
+ ++it;
+
+ QCOMPARE( style, trimmed );
+ }
+}
+
+void tst_QFontDatabase::fixedPitch_data()
+{
+ QTest::addColumn<QString>("font");
+ QTest::addColumn<bool>("fixedPitch");
+
+ QTest::newRow( "Times New Roman" ) << QString( "Times New Roman" ) << false;
+ QTest::newRow( "Arial" ) << QString( "Arial" ) << false;
+ QTest::newRow( "Andale Mono" ) << QString( "Andale Mono" ) << true;
+ QTest::newRow( "Courier" ) << QString( "Courier" ) << true;
+ QTest::newRow( "Courier New" ) << QString( "Courier New" ) << true;
+#ifndef Q_WS_MAC
+ QTest::newRow( "Script" ) << QString( "Script" ) << false;
+ QTest::newRow( "Lucida Console" ) << QString( "Lucida Console" ) << true;
+#else
+ QTest::newRow( "Menlo" ) << QString( "Menlo" ) << true;
+ QTest::newRow( "Monaco" ) << QString( "Monaco" ) << true;
+#endif
+}
+
+void tst_QFontDatabase::fixedPitch()
+{
+#ifdef Q_WS_QWS
+ QSKIP("fixedPitch not implemented for Qtopia Core", SkipAll);
+#endif
+ QFETCH(QString, font);
+ QFETCH(bool, fixedPitch);
+
+ QFontDatabase fdb;
+ if (!fdb.families().contains(font))
+ QSKIP( "Font not installed", SkipSingle);
+
+#ifdef Q_WS_QPA
+ if (fixedPitch) {
+ // fixedPitch() never returns true on qpa
+ QEXPECT_FAIL("", "QTBUG-20754 fails on qpa", Abort);
+ }
+#endif
+
+ QCOMPARE(fdb.isFixedPitch(font), fixedPitch);
+
+ QFont qfont(font);
+ QFontInfo fi(qfont);
+ QCOMPARE(fi.fixedPitch(), fixedPitch);
+}
+
+#ifdef Q_WS_MAC
+void tst_QFontDatabase::trickyFonts_data()
+{
+ QTest::addColumn<QString>("font");
+
+ QTest::newRow( "Geeza Pro" ) << QString( "Geeza Pro" );
+}
+
+void tst_QFontDatabase::trickyFonts()
+{
+ QFETCH(QString, font);
+
+ QFontDatabase fdb;
+ if (!fdb.families().contains(font))
+ QSKIP( "Font not installed", SkipSingle);
+
+ QFont qfont(font);
+ QFontInfo fi(qfont);
+ QCOMPARE(fi.family(), font);
+}
+#endif
+
+void tst_QFontDatabase::widthTwoTimes_data()
+{
+ QTest::addColumn<QString>("font");
+ QTest::addColumn<int>("pixelSize");
+ QTest::addColumn<QString>("text");
+
+ QTest::newRow("Arial") << QString("Arial") << 1000 << QString("Some text");
+}
+
+void tst_QFontDatabase::widthTwoTimes()
+{
+ QFETCH(QString, font);
+ QFETCH(int, pixelSize);
+ QFETCH(QString, text);
+
+ QFont f;
+ f.setFamily(font);
+ f.setPixelSize(pixelSize);
+
+ QFontMetrics fm(f);
+ int w1 = fm.charWidth(text, 0);
+ int w2 = fm.charWidth(text, 0);
+
+ QCOMPARE(w1, w2);
+}
+
+void tst_QFontDatabase::addAppFont_data()
+{
+ QTest::addColumn<bool>("useMemoryFont");
+ QTest::newRow("font file") << false;
+ QTest::newRow("memory font") << true;
+}
+
+void tst_QFontDatabase::addAppFont()
+{
+ QFETCH(bool, useMemoryFont);
+ QSignalSpy fontDbChangedSpy(QApplication::instance(), SIGNAL(fontDatabaseChanged()));
+
+ QFontDatabase db;
+
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("memory font", "QTBUG-20754 fails on qpa", Abort);
+#endif
+
+ const QStringList oldFamilies = db.families();
+ QVERIFY(!oldFamilies.isEmpty());
+
+ fontDbChangedSpy.clear();
+
+ int id;
+ if (useMemoryFont) {
+ QFile fontfile("FreeMono.ttf");
+ fontfile.open(QIODevice::ReadOnly);
+ QByteArray fontdata = fontfile.readAll();
+ QVERIFY(!fontdata.isEmpty());
+ id = QFontDatabase::addApplicationFontFromData(fontdata);
+ } else {
+ id = QFontDatabase::addApplicationFont("FreeMono.ttf");
+ }
+#if defined(Q_OS_HPUX) && defined(QT_NO_FONTCONFIG)
+ // Documentation says that X11 systems that don't have fontconfig
+ // don't support application fonts.
+ QCOMPARE(id, -1);
+ return;
+#endif
+ QCOMPARE(fontDbChangedSpy.count(), 1);
+// addApplicationFont is supported on Mac, don't skip the test if it breaks.
+#ifndef Q_WS_MAC
+ if (id == -1) {
+ QSKIP("Skip the test since app fonts are not supported on this system", SkipSingle);
+ return;
+ }
+#endif
+
+ const QStringList addedFamilies = QFontDatabase::applicationFontFamilies(id);
+ QVERIFY(!addedFamilies.isEmpty());
+
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("font file", "QTBUG-20754 fails on qpa", Abort);
+#endif
+
+ const QStringList newFamilies = db.families();
+ QVERIFY(!newFamilies.isEmpty());
+ QVERIFY(newFamilies.count() >= oldFamilies.count());
+
+ for (int i = 0; i < addedFamilies.count(); ++i)
+ QVERIFY(newFamilies.contains(addedFamilies.at(i)));
+
+ QVERIFY(QFontDatabase::removeApplicationFont(id));
+ QCOMPARE(fontDbChangedSpy.count(), 2);
+
+ QVERIFY(db.families() == oldFamilies);
+}
+
+QTEST_MAIN(tst_QFontDatabase)
+#include "tst_qfontdatabase.moc"
diff --git a/tests/auto/gui/text/qfontmetrics/.gitignore b/tests/auto/gui/text/qfontmetrics/.gitignore
new file mode 100644
index 0000000000..0b428672a3
--- /dev/null
+++ b/tests/auto/gui/text/qfontmetrics/.gitignore
@@ -0,0 +1 @@
+tst_qfontmetrics
diff --git a/tests/auto/gui/text/qfontmetrics/qfontmetrics.pro b/tests/auto/gui/text/qfontmetrics/qfontmetrics.pro
new file mode 100644
index 0000000000..c0dc1abbe6
--- /dev/null
+++ b/tests/auto/gui/text/qfontmetrics/qfontmetrics.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+SOURCES += tst_qfontmetrics.cpp
+RESOURCES += testfont.qrc
+
diff --git a/tests/auto/gui/text/qfontmetrics/testfont.qrc b/tests/auto/gui/text/qfontmetrics/testfont.qrc
new file mode 100644
index 0000000000..bc0c0b0959
--- /dev/null
+++ b/tests/auto/gui/text/qfontmetrics/testfont.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/fonts">
+ <file>ucs4font.ttf</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp
new file mode 100644
index 0000000000..982cfc11d9
--- /dev/null
+++ b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qfontdatabase.h>
+#include <qstringlist.h>
+#include <qlist.h>
+
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QFontMetrics : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QFontMetrics();
+ virtual ~tst_QFontMetrics();
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void same();
+ void metrics();
+ void boundingRect();
+ void elidedText_data();
+ void elidedText();
+ void veryNarrowElidedText();
+ void averageCharWidth();
+ void bypassShaping();
+ void elidedMultiLength();
+ void elidedMultiLengthF();
+ void inFontUcs4();
+ void lineWidth();
+};
+
+tst_QFontMetrics::tst_QFontMetrics()
+
+{
+}
+
+tst_QFontMetrics::~tst_QFontMetrics()
+{
+
+}
+
+void tst_QFontMetrics::init()
+{
+}
+
+void tst_QFontMetrics::cleanup()
+{
+}
+
+void tst_QFontMetrics::same()
+{
+ QFont font;
+ font.setBold(true);
+ QFontMetrics fm(font);
+ const QString text = QLatin1String("Some stupid STRING");
+ QCOMPARE(fm.size(0, text), fm.size(0, text)) ;
+
+ {
+ QImage image;
+ QFontMetrics fm2(font, &image);
+ QString text2 = QLatin1String("Foo Foo");
+ QCOMPARE(fm2.size(0, text2), fm2.size(0, text2)); //used to crash
+ }
+
+ {
+ QImage image;
+ QFontMetricsF fm3(font, &image);
+ QString text2 = QLatin1String("Foo Foo");
+ QCOMPARE(fm3.size(0, text2), fm3.size(0, text2)); //used to crash
+ }
+}
+
+
+void tst_QFontMetrics::metrics()
+{
+ QFont font;
+ QFontDatabase fdb;
+
+ // Query the QFontDatabase for a specific font, store the
+ // result in family, style and size.
+ QStringList families = fdb.families();
+ if (families.isEmpty())
+ return;
+
+ QStringList::ConstIterator f_it, f_end = families.end();
+ for (f_it = families.begin(); f_it != f_end; ++f_it) {
+ const QString &family = *f_it;
+
+ QStringList styles = fdb.styles(family);
+ QStringList::ConstIterator s_it, s_end = styles.end();
+ for (s_it = styles.begin(); s_it != s_end; ++s_it) {
+ const QString &style = *s_it;
+
+ if (fdb.isSmoothlyScalable(family, style)) {
+ // smoothly scalable font... don't need to load every pointsize
+ font = fdb.font(family, style, 12);
+
+ QFontMetrics fontmetrics(font);
+ QCOMPARE(fontmetrics.ascent() + fontmetrics.descent() + 1,
+ fontmetrics.height());
+
+ QCOMPARE(fontmetrics.height() + fontmetrics.leading(),
+ fontmetrics.lineSpacing());
+ } else {
+ QList<int> sizes = fdb.pointSizes(family, style);
+ QVERIFY(!sizes.isEmpty());
+ QList<int>::ConstIterator z_it, z_end = sizes.end();
+ for (z_it = sizes.begin(); z_it != z_end; ++z_it) {
+ const int size = *z_it;
+
+ // Initialize the font, and check if it is an exact match
+ font = fdb.font(family, style, size);
+
+ QFontMetrics fontmetrics(font);
+ QCOMPARE(fontmetrics.ascent() + fontmetrics.descent() + 1,
+ fontmetrics.height());
+ QCOMPARE(fontmetrics.height() + fontmetrics.leading(),
+ fontmetrics.lineSpacing());
+ }
+ }
+ }
+ }
+}
+
+void tst_QFontMetrics::boundingRect()
+{
+ QFont f;
+ f.setPointSize(24);
+ QFontMetrics fm(f);
+ QRect r = fm.boundingRect(QChar('Y'));
+ QVERIFY(r.top() < 0);
+ r = fm.boundingRect(QString("Y"));
+ QVERIFY(r.top() < 0);
+}
+
+void tst_QFontMetrics::elidedText_data()
+{
+ QTest::addColumn<QFont>("font");
+ QTest::addColumn<QString>("text");
+
+ QTest::newRow("helvetica hello") << QFont("helvetica",10) << QString("hello") ;
+ QTest::newRow("helvetica hello &Bye") << QFont("helvetica",10) << QString("hello&Bye") ;
+}
+
+
+void tst_QFontMetrics::elidedText()
+{
+ QFETCH(QFont, font);
+ QFETCH(QString, text);
+ QFontMetrics fm(font);
+ int w = fm.width(text);
+ QString newtext = fm.elidedText(text,Qt::ElideRight,w+1, 0);
+ QCOMPARE(text,newtext); // should not elide
+ newtext = fm.elidedText(text,Qt::ElideRight,w-1, 0);
+ QVERIFY(text != newtext); // should elide
+}
+
+void tst_QFontMetrics::veryNarrowElidedText()
+{
+ QFont f;
+ QFontMetrics fm(f);
+ QString text("hello");
+ QCOMPARE(fm.elidedText(text, Qt::ElideRight, 0), QString());
+}
+
+void tst_QFontMetrics::averageCharWidth()
+{
+ QFont f;
+ QFontMetrics fm(f);
+ QVERIFY(fm.averageCharWidth() != 0);
+ QFontMetricsF fmf(f);
+ QVERIFY(fmf.averageCharWidth() != 0);
+}
+
+void tst_QFontMetrics::bypassShaping()
+{
+ QFont f;
+ f.setStyleStrategy(QFont::ForceIntegerMetrics);
+ QFontMetrics fm(f);
+ QString text = " A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z";
+ int textWidth = fm.width(text, -1, Qt::TextBypassShaping);
+ QVERIFY(textWidth != 0);
+ int charsWidth = 0;
+ for (int i = 0; i < text.size(); ++i)
+ charsWidth += fm.width(text[i]);
+ // This assertion is needed in QtWebKit's WebCore::Font::offsetForPositionForSimpleText
+ QCOMPARE(textWidth, charsWidth);
+}
+
+template<class FontMetrics> void elidedMultiLength_helper()
+{
+ QString text1 = "Long Text 1\x9cShorter\x9csmall";
+ QString text1_long = "Long Text 1";
+ QString text1_short = "Shorter";
+ QString text1_small = "small";
+ FontMetrics fm = FontMetrics(QFont());
+ int width_long = fm.size(0, text1_long).width();
+ QCOMPARE(fm.elidedText(text1,Qt::ElideRight, 8000), text1_long);
+ QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_long + 1), text1_long);
+ QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_long - 1), text1_short);
+ int width_short = fm.size(0, text1_short).width();
+ QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_short + 1), text1_short);
+ QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_short - 1), text1_small);
+
+ // Not even wide enough for "small" - should use ellipsis
+ QChar ellipsisChar(0x2026);
+ QString text1_el = QString::fromLatin1("s") + ellipsisChar;
+ int width_small = fm.width(text1_el);
+ QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_small + 1), text1_el);
+}
+
+void tst_QFontMetrics::elidedMultiLength()
+{
+ elidedMultiLength_helper<QFontMetrics>();
+}
+
+void tst_QFontMetrics::elidedMultiLengthF()
+{
+ elidedMultiLength_helper<QFontMetricsF>();
+}
+
+void tst_QFontMetrics::inFontUcs4()
+{
+ int id = QFontDatabase::addApplicationFont(":/fonts/ucs4font.ttf");
+ QVERIFY(id >= 0);
+
+ QFont font("QtTestUcs4");
+ {
+ QFontMetrics fm(font);
+
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20759 fails for qpa", Continue);
+#endif
+
+ QVERIFY(fm.inFontUcs4(0x1D7FF));
+ }
+
+ {
+ QFontMetricsF fm(font);
+
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20759 fails for qpa", Continue);
+#endif
+
+ QVERIFY(fm.inFontUcs4(0x1D7FF));
+ }
+
+ QFontDatabase::removeApplicationFont(id);
+}
+
+void tst_QFontMetrics::lineWidth()
+{
+ // QTBUG-13009, QTBUG-13011
+ QFont smallFont;
+ smallFont.setPointSize(8);
+ smallFont.setWeight(QFont::Light);
+ const QFontMetrics smallFontMetrics(smallFont);
+
+ QFont bigFont;
+ bigFont.setPointSize(40);
+ bigFont.setWeight(QFont::Black);
+ const QFontMetrics bigFontMetrics(bigFont);
+
+ QVERIFY(smallFontMetrics.lineWidth() >= 1);
+
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20759 fails for qpa", Continue);
+#endif
+
+ QVERIFY(smallFontMetrics.lineWidth() < bigFontMetrics.lineWidth());
+}
+
+QTEST_MAIN(tst_QFontMetrics)
+#include "tst_qfontmetrics.moc"
diff --git a/tests/auto/gui/text/qfontmetrics/ucs4font.ttf b/tests/auto/gui/text/qfontmetrics/ucs4font.ttf
new file mode 100644
index 0000000000..31b6997779
--- /dev/null
+++ b/tests/auto/gui/text/qfontmetrics/ucs4font.ttf
Binary files differ
diff --git a/tests/auto/gui/text/qglyphrun/qglyphrun.pro b/tests/auto/gui/text/qglyphrun/qglyphrun.pro
new file mode 100644
index 0000000000..480ad5b9a4
--- /dev/null
+++ b/tests/auto/gui/text/qglyphrun/qglyphrun.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+QT = core gui
+
+SOURCES += \
+ tst_qglyphrun.cpp
+
+wince*|symbian*: {
+ DEFINES += SRCDIR=\\\"\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
diff --git a/tests/auto/gui/text/qglyphrun/test.ttf b/tests/auto/gui/text/qglyphrun/test.ttf
new file mode 100644
index 0000000000..9043a576ef
--- /dev/null
+++ b/tests/auto/gui/text/qglyphrun/test.ttf
Binary files differ
diff --git a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
new file mode 100644
index 0000000000..e84915428f
--- /dev/null
+++ b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
@@ -0,0 +1,679 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <qglyphrun.h>
+#include <qpainter.h>
+#include <qtextlayout.h>
+#include <qfontdatabase.h>
+
+// #define DEBUG_SAVE_IMAGE
+
+class tst_QGlyphRun: public QObject
+{
+ Q_OBJECT
+
+#if !defined(QT_NO_RAWFONT)
+private slots:
+ void initTestCase();
+ void init();
+ void cleanupTestCase();
+
+ void constructionAndDestruction();
+ void copyConstructor();
+ void assignment();
+ void equalsOperator_data();
+ void equalsOperator();
+ void textLayoutGlyphIndexes();
+ void drawExistingGlyphs();
+ void drawNonExistentGlyphs();
+ void drawMultiScriptText1();
+ void drawMultiScriptText2();
+ void drawStruckOutText();
+ void drawOverlinedText();
+ void drawUnderlinedText();
+ void drawRightToLeft();
+ void detach();
+ void setRawData();
+ void setRawDataAndGetAsVector();
+
+private:
+ int m_testFontId;
+ QFont m_testFont;
+ bool m_testFont_ok;
+#endif // QT_NO_RAWFONT
+
+};
+
+#if !defined(QT_NO_RAWFONT)
+
+Q_DECLARE_METATYPE(QGlyphRun);
+
+void tst_QGlyphRun::initTestCase()
+{
+ m_testFont_ok = false;
+
+ m_testFontId = QFontDatabase::addApplicationFont(SRCDIR "test.ttf");
+ QVERIFY(m_testFontId >= 0);
+
+ m_testFont = QFont("QtsSpecialTestFont");
+
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20760 fails on qpa", Abort);
+#endif
+
+ QCOMPARE(QFontInfo(m_testFont).family(), QString::fromLatin1("QtsSpecialTestFont"));
+
+ m_testFont_ok = true;
+}
+
+void tst_QGlyphRun::init()
+{
+ if (!m_testFont_ok) {
+ QSKIP("Test font is not working correctly", SkipAll);
+ }
+}
+
+void tst_QGlyphRun::cleanupTestCase()
+{
+ QFontDatabase::removeApplicationFont(m_testFontId);
+}
+
+void tst_QGlyphRun::constructionAndDestruction()
+{
+ QGlyphRun glyphIndexes;
+}
+
+static QGlyphRun make_dummy_indexes()
+{
+ QGlyphRun glyphs;
+
+ QVector<quint32> glyphIndexes;
+ QVector<QPointF> positions;
+ QFont font;
+ font.setPointSize(18);
+
+ glyphIndexes.append(1);
+ glyphIndexes.append(2);
+ glyphIndexes.append(3);
+
+ positions.append(QPointF(1, 2));
+ positions.append(QPointF(3, 4));
+ positions.append(QPointF(5, 6));
+
+ glyphs.setRawFont(QRawFont::fromFont(font));
+ glyphs.setGlyphIndexes(glyphIndexes);
+ glyphs.setPositions(positions);
+
+ return glyphs;
+}
+
+void tst_QGlyphRun::copyConstructor()
+{
+ QGlyphRun glyphs;
+
+ {
+ QVector<quint32> glyphIndexes;
+ QVector<QPointF> positions;
+ QFont font;
+ font.setPointSize(18);
+
+ glyphIndexes.append(1);
+ glyphIndexes.append(2);
+ glyphIndexes.append(3);
+
+ positions.append(QPointF(1, 2));
+ positions.append(QPointF(3, 4));
+ positions.append(QPointF(5, 6));
+
+ glyphs.setRawFont(QRawFont::fromFont(font));
+ glyphs.setGlyphIndexes(glyphIndexes);
+ glyphs.setPositions(positions);
+ }
+
+ QGlyphRun otherGlyphs(glyphs);
+ QCOMPARE(otherGlyphs.rawFont(), glyphs.rawFont());
+ QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes());
+ QCOMPARE(glyphs.positions(), otherGlyphs.positions());
+}
+
+void tst_QGlyphRun::assignment()
+{
+ QGlyphRun glyphs(make_dummy_indexes());
+
+ QGlyphRun otherGlyphs = glyphs;
+ QCOMPARE(otherGlyphs.rawFont(), glyphs.rawFont());
+ QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes());
+ QCOMPARE(glyphs.positions(), otherGlyphs.positions());
+}
+
+void tst_QGlyphRun::equalsOperator_data()
+{
+ QTest::addColumn<QGlyphRun>("one");
+ QTest::addColumn<QGlyphRun>("two");
+ QTest::addColumn<bool>("equals");
+
+ QGlyphRun one(make_dummy_indexes());
+ QGlyphRun two(make_dummy_indexes());
+
+ QTest::newRow("Identical") << one << two << true;
+
+ {
+ QGlyphRun busted(two);
+
+ QVector<QPointF> positions = busted.positions();
+ positions[2] += QPointF(1, 1);
+ busted.setPositions(positions);
+
+
+ QTest::newRow("Different positions") << one << busted << false;
+ }
+
+ {
+ QGlyphRun busted(two);
+
+ QFont font;
+ font.setPixelSize(busted.rawFont().pixelSize() * 2);
+ busted.setRawFont(QRawFont::fromFont(font));
+
+ QTest::newRow("Different fonts") << one << busted << false;
+ }
+
+ {
+ QGlyphRun busted(two);
+
+ QVector<quint32> glyphIndexes = busted.glyphIndexes();
+ glyphIndexes[2] += 1;
+ busted.setGlyphIndexes(glyphIndexes);
+
+ QTest::newRow("Different glyph indexes") << one << busted << false;
+ }
+
+}
+
+void tst_QGlyphRun::equalsOperator()
+{
+ QFETCH(QGlyphRun, one);
+ QFETCH(QGlyphRun, two);
+ QFETCH(bool, equals);
+
+ QCOMPARE(one == two, equals);
+ QCOMPARE(one != two, !equals);
+}
+
+
+void tst_QGlyphRun::textLayoutGlyphIndexes()
+{
+ QString s;
+ s.append(QLatin1Char('A'));
+ s.append(QChar(0xe000));
+
+ QTextLayout layout(s);
+ layout.setFont(m_testFont);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> listOfGlyphs = layout.glyphRuns();
+
+ QCOMPARE(listOfGlyphs.size(), 1);
+
+ QGlyphRun glyphs = listOfGlyphs.at(0);
+
+ QCOMPARE(glyphs.glyphIndexes().size(), 2);
+ QCOMPARE(glyphs.glyphIndexes().at(0), quint32(2));
+ QCOMPARE(glyphs.glyphIndexes().at(1), quint32(1));
+}
+
+void tst_QGlyphRun::drawExistingGlyphs()
+{
+ QPixmap textLayoutDraw(1000, 1000);
+ QPixmap drawGlyphs(1000, 1000);
+
+ textLayoutDraw.fill(Qt::white);
+ drawGlyphs.fill(Qt::white);
+
+ QString s;
+ s.append(QLatin1Char('A'));
+ s.append(QChar(0xe000));
+
+ QTextLayout layout(s);
+ layout.setFont(m_testFont);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QPainter p(&textLayoutDraw);
+ layout.draw(&p, QPointF(50, 50));
+ }
+
+ QGlyphRun glyphs = layout.glyphRuns().size() > 0
+ ? layout.glyphRuns().at(0)
+ : QGlyphRun();
+
+ {
+ QPainter p(&drawGlyphs);
+ p.drawGlyphRun(QPointF(50, 50), glyphs);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ textLayoutDraw.save("drawExistingGlyphs_textLayoutDraw.png");
+ drawGlyphs.save("drawExistingGlyphs_drawGlyphIndexes.png");
+#endif
+
+ QCOMPARE(textLayoutDraw, drawGlyphs);
+}
+
+void tst_QGlyphRun::setRawData()
+{
+ QGlyphRun glyphRun;
+ glyphRun.setRawFont(QRawFont::fromFont(m_testFont));
+ glyphRun.setGlyphIndexes(QVector<quint32>() << 2 << 2 << 2);
+ glyphRun.setPositions(QVector<QPointF>() << QPointF(2, 3) << QPointF(20, 3) << QPointF(10, 20));
+
+ QPixmap baseline(100, 50);
+ baseline.fill(Qt::white);
+ {
+ QPainter p(&baseline);
+ p.drawGlyphRun(QPointF(3, 2), glyphRun);
+ }
+
+ QGlyphRun baselineCopied = glyphRun;
+
+ quint32 glyphIndexArray[3] = { 2, 2, 2 };
+ QPointF glyphPositionArray[3] = { QPointF(2, 3), QPointF(20, 3), QPointF(10, 20) };
+
+ glyphRun.setRawData(glyphIndexArray, glyphPositionArray, 3);
+
+ QPixmap rawDataGlyphs(100, 50);
+ rawDataGlyphs.fill(Qt::white);
+ {
+ QPainter p(&rawDataGlyphs);
+ p.drawGlyphRun(QPointF(3, 2), glyphRun);
+ }
+
+ quint32 otherGlyphIndexArray[1] = { 2 };
+ QPointF otherGlyphPositionArray[1] = { QPointF(2, 3) };
+
+ glyphRun.setRawData(otherGlyphIndexArray, otherGlyphPositionArray, 1);
+
+ QPixmap baselineCopiedPixmap(100, 50);
+ baselineCopiedPixmap.fill(Qt::white);
+ {
+ QPainter p(&baselineCopiedPixmap);
+ p.drawGlyphRun(QPointF(3, 2), baselineCopied);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ baseline.save("setRawData_baseline.png");
+ rawDataGlyphs.save("setRawData_rawDataGlyphs.png");
+ baselineCopiedPixmap.save("setRawData_baselineCopiedPixmap.png");
+#endif
+
+ QCOMPARE(rawDataGlyphs, baseline);
+ QCOMPARE(baselineCopiedPixmap, baseline);
+}
+
+void tst_QGlyphRun::setRawDataAndGetAsVector()
+{
+ QVector<quint32> glyphIndexArray;
+ glyphIndexArray << 3 << 2 << 1 << 4;
+
+ QVector<QPointF> glyphPositionArray;
+ glyphPositionArray << QPointF(1, 2) << QPointF(3, 4) << QPointF(5, 6) << QPointF(7, 8);
+
+ QGlyphRun glyphRun;
+ glyphRun.setRawData(glyphIndexArray.constData(), glyphPositionArray.constData(), 4);
+
+ QVector<quint32> glyphIndexes = glyphRun.glyphIndexes();
+ QVector<QPointF> glyphPositions = glyphRun.positions();
+
+ QCOMPARE(glyphIndexes.size(), 4);
+ QCOMPARE(glyphPositions.size(), 4);
+
+ QCOMPARE(glyphIndexes, glyphIndexArray);
+ QCOMPARE(glyphPositions, glyphPositionArray);
+
+ QGlyphRun otherGlyphRun;
+ otherGlyphRun.setGlyphIndexes(glyphIndexArray);
+ otherGlyphRun.setPositions(glyphPositionArray);
+
+ QCOMPARE(glyphRun, otherGlyphRun);
+}
+
+void tst_QGlyphRun::drawNonExistentGlyphs()
+{
+ QVector<quint32> glyphIndexes;
+ glyphIndexes.append(3);
+
+ QVector<QPointF> glyphPositions;
+ glyphPositions.append(QPointF(0, 0));
+
+ QGlyphRun glyphs;
+ glyphs.setGlyphIndexes(glyphIndexes);
+ glyphs.setPositions(glyphPositions);
+ glyphs.setRawFont(QRawFont::fromFont(m_testFont));
+
+ QPixmap image(1000, 1000);
+ image.fill(Qt::white);
+
+ QPixmap imageBefore = image;
+ {
+ QPainter p(&image);
+ p.drawGlyphRun(QPointF(50, 50), glyphs);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ image.save("drawNonExistentGlyphs.png");
+#endif
+
+ QCOMPARE(image, imageBefore); // Should be unchanged
+}
+
+void tst_QGlyphRun::drawMultiScriptText1()
+{
+ QString text;
+ text += QChar(0x03D0); // Greek, beta
+
+ QTextLayout textLayout(text);
+ textLayout.beginLayout();
+ textLayout.createLine();
+ textLayout.endLayout();
+
+ QPixmap textLayoutDraw(1000, 1000);
+ textLayoutDraw.fill(Qt::white);
+
+ QPixmap drawGlyphs(1000, 1000);
+ drawGlyphs.fill(Qt::white);
+
+ QList<QGlyphRun> glyphsList = textLayout.glyphRuns();
+ QCOMPARE(glyphsList.size(), 1);
+
+ {
+ QPainter p(&textLayoutDraw);
+ textLayout.draw(&p, QPointF(50, 50));
+ }
+
+ {
+ QPainter p(&drawGlyphs);
+ foreach (QGlyphRun glyphs, glyphsList)
+ p.drawGlyphRun(QPointF(50, 50), glyphs);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ textLayoutDraw.save("drawMultiScriptText1_textLayoutDraw.png");
+ drawGlyphs.save("drawMultiScriptText1_drawGlyphIndexes.png");
+#endif
+
+ QCOMPARE(drawGlyphs, textLayoutDraw);
+}
+
+
+void tst_QGlyphRun::drawMultiScriptText2()
+{
+ QString text;
+ text += QChar(0x0621); // Arabic, Hamza
+ text += QChar(0x03D0); // Greek, beta
+
+ QTextLayout textLayout(text);
+ textLayout.beginLayout();
+ textLayout.createLine();
+ textLayout.endLayout();
+
+ QPixmap textLayoutDraw(1000, 1000);
+ textLayoutDraw.fill(Qt::white);
+
+ QPixmap drawGlyphs(1000, 1000);
+ drawGlyphs.fill(Qt::white);
+
+ QList<QGlyphRun> glyphsList = textLayout.glyphRuns();
+ QCOMPARE(glyphsList.size(), 2);
+
+ {
+ QPainter p(&textLayoutDraw);
+ textLayout.draw(&p, QPointF(50, 50));
+ }
+
+ {
+ QPainter p(&drawGlyphs);
+ foreach (QGlyphRun glyphs, glyphsList)
+ p.drawGlyphRun(QPointF(50, 50), glyphs);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ textLayoutDraw.save("drawMultiScriptText2_textLayoutDraw.png");
+ drawGlyphs.save("drawMultiScriptText2_drawGlyphIndexes.png");
+#endif
+
+ QCOMPARE(drawGlyphs, textLayoutDraw);
+}
+
+void tst_QGlyphRun::detach()
+{
+ QGlyphRun glyphs;
+
+ glyphs.setGlyphIndexes(QVector<quint32>() << 1 << 2 << 3);
+
+ QGlyphRun otherGlyphs;
+ otherGlyphs = glyphs;
+
+ QCOMPARE(otherGlyphs.glyphIndexes(), glyphs.glyphIndexes());
+
+ otherGlyphs.setGlyphIndexes(QVector<quint32>() << 4 << 5 << 6);
+
+ QCOMPARE(otherGlyphs.glyphIndexes(), QVector<quint32>() << 4 << 5 << 6);
+ QCOMPARE(glyphs.glyphIndexes(), QVector<quint32>() << 1 << 2 << 3);
+}
+
+void tst_QGlyphRun::drawStruckOutText()
+{
+ QPixmap textLayoutDraw(1000, 1000);
+ QPixmap drawGlyphs(1000, 1000);
+
+ textLayoutDraw.fill(Qt::white);
+ drawGlyphs.fill(Qt::white);
+
+ QString s = QString::fromLatin1("Foobar");
+
+ QFont font;
+ font.setStrikeOut(true);
+
+ QTextLayout layout(s);
+ layout.setFont(font);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QPainter p(&textLayoutDraw);
+ layout.draw(&p, QPointF(50, 50));
+ }
+
+ QGlyphRun glyphs = layout.glyphRuns().size() > 0
+ ? layout.glyphRuns().at(0)
+ : QGlyphRun();
+
+ {
+ QPainter p(&drawGlyphs);
+ p.drawGlyphRun(QPointF(50, 50), glyphs);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ textLayoutDraw.save("drawStruckOutText_textLayoutDraw.png");
+ drawGlyphs.save("drawStruckOutText_drawGlyphIndexes.png");
+#endif
+
+ QCOMPARE(textLayoutDraw, drawGlyphs);
+}
+
+void tst_QGlyphRun::drawOverlinedText()
+{
+ QPixmap textLayoutDraw(1000, 1000);
+ QPixmap drawGlyphs(1000, 1000);
+
+ textLayoutDraw.fill(Qt::white);
+ drawGlyphs.fill(Qt::white);
+
+ QString s = QString::fromLatin1("Foobar");
+
+ QFont font;
+ font.setOverline(true);
+
+ QTextLayout layout(s);
+ layout.setFont(font);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QPainter p(&textLayoutDraw);
+ layout.draw(&p, QPointF(50, 50));
+ }
+
+ QGlyphRun glyphs = layout.glyphRuns().size() > 0
+ ? layout.glyphRuns().at(0)
+ : QGlyphRun();
+
+ {
+ QPainter p(&drawGlyphs);
+ p.drawGlyphRun(QPointF(50, 50), glyphs);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ textLayoutDraw.save("drawOverlineText_textLayoutDraw.png");
+ drawGlyphs.save("drawOverlineText_drawGlyphIndexes.png");
+#endif
+
+ QCOMPARE(textLayoutDraw, drawGlyphs);
+}
+
+void tst_QGlyphRun::drawUnderlinedText()
+{
+ QPixmap textLayoutDraw(1000, 1000);
+ QPixmap drawGlyphs(1000, 1000);
+
+ textLayoutDraw.fill(Qt::white);
+ drawGlyphs.fill(Qt::white);
+
+ QString s = QString::fromLatin1("Foobar");
+
+ QFont font;
+ font.setUnderline(true);
+
+ QTextLayout layout(s);
+ layout.setFont(font);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QPainter p(&textLayoutDraw);
+ layout.draw(&p, QPointF(50, 50));
+ }
+
+ QGlyphRun glyphs = layout.glyphRuns().size() > 0
+ ? layout.glyphRuns().at(0)
+ : QGlyphRun();
+
+ {
+ QPainter p(&drawGlyphs);
+ p.drawGlyphRun(QPointF(50, 50), glyphs);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ textLayoutDraw.save("drawUnderlineText_textLayoutDraw.png");
+ drawGlyphs.save("drawUnderlineText_drawGlyphIndexes.png");
+#endif
+
+ QCOMPARE(textLayoutDraw, drawGlyphs);
+}
+
+void tst_QGlyphRun::drawRightToLeft()
+{
+ QString s;
+ s.append(QChar(1575));
+ s.append(QChar(1578));
+
+ QPixmap textLayoutDraw(1000, 1000);
+ QPixmap drawGlyphs(1000, 1000);
+
+ textLayoutDraw.fill(Qt::white);
+ drawGlyphs.fill(Qt::white);
+
+ QFont font;
+ font.setUnderline(true);
+
+ QTextLayout layout(s);
+ layout.setFont(font);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QPainter p(&textLayoutDraw);
+ layout.draw(&p, QPointF(50, 50));
+ }
+
+ QGlyphRun glyphs = layout.glyphRuns().size() > 0
+ ? layout.glyphRuns().at(0)
+ : QGlyphRun();
+
+ {
+ QPainter p(&drawGlyphs);
+ p.drawGlyphRun(QPointF(50, 50), glyphs);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ textLayoutDraw.save("drawRightToLeft_textLayoutDraw.png");
+ drawGlyphs.save("drawRightToLeft_drawGlyphIndexes.png");
+#endif
+
+ QCOMPARE(textLayoutDraw, drawGlyphs);
+
+}
+
+#endif // QT_NO_RAWFONT
+
+QTEST_MAIN(tst_QGlyphRun)
+#include "tst_qglyphrun.moc"
+
diff --git a/tests/auto/gui/text/qrawfont/qrawfont.pro b/tests/auto/gui/text/qrawfont/qrawfont.pro
new file mode 100644
index 0000000000..1f73055b00
--- /dev/null
+++ b/tests/auto/gui/text/qrawfont/qrawfont.pro
@@ -0,0 +1,14 @@
+load(qttest_p4)
+
+QT = core core-private gui gui-private
+
+SOURCES += \
+ tst_qrawfont.cpp
+
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
+
+wince*|symbian*: {
+ DEFINES += SRCDIR=\\\"\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
diff --git a/tests/auto/gui/text/qrawfont/testfont.ttf b/tests/auto/gui/text/qrawfont/testfont.ttf
new file mode 100644
index 0000000000..d6042d2e58
--- /dev/null
+++ b/tests/auto/gui/text/qrawfont/testfont.ttf
Binary files differ
diff --git a/tests/auto/gui/text/qrawfont/testfont_bold_italic.ttf b/tests/auto/gui/text/qrawfont/testfont_bold_italic.ttf
new file mode 100644
index 0000000000..9f65ac8df7
--- /dev/null
+++ b/tests/auto/gui/text/qrawfont/testfont_bold_italic.ttf
Binary files differ
diff --git a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp
new file mode 100644
index 0000000000..1c18f2f1e8
--- /dev/null
+++ b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp
@@ -0,0 +1,897 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <qrawfont.h>
+#include <private/qrawfont_p.h>
+
+class tst_QRawFont: public QObject
+{
+ Q_OBJECT
+#if !defined(QT_NO_RAWFONT)
+private slots:
+ void init();
+
+ void invalidRawFont();
+
+ void explicitRawFontNotLoadedInDatabase_data();
+ void explicitRawFontNotLoadedInDatabase();
+
+ void explicitRawFontNotAvailableInSystem_data();
+ void explicitRawFontNotAvailableInSystem();
+
+ void correctFontData_data();
+ void correctFontData();
+
+ void glyphIndices();
+
+ void advances_data();
+ void advances();
+
+ void textLayout();
+
+ void fontTable_data();
+ void fontTable();
+
+ void supportedWritingSystems_data();
+ void supportedWritingSystems();
+
+ void supportsCharacter_data();
+ void supportsCharacter();
+
+ void supportsUcs4Character_data();
+ void supportsUcs4Character();
+
+ void fromFont_data();
+ void fromFont();
+
+ void copyConstructor_data();
+ void copyConstructor();
+
+ void detach_data();
+ void detach();
+
+ void unsupportedWritingSystem_data();
+ void unsupportedWritingSystem();
+
+ void rawFontSetPixelSize_data();
+ void rawFontSetPixelSize();
+
+#if defined(Q_WS_X11) || defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ void multipleRawFontsFromData();
+#endif
+
+#endif // QT_NO_RAWFONT
+};
+
+#if !defined(QT_NO_RAWFONT)
+Q_DECLARE_METATYPE(QFont::HintingPreference)
+Q_DECLARE_METATYPE(QFont::Style)
+Q_DECLARE_METATYPE(QFont::Weight)
+Q_DECLARE_METATYPE(QFontDatabase::WritingSystem)
+
+void tst_QRawFont::init()
+{
+#ifdef Q_WS_QPA
+ // Loading fonts from a QByteArray seems unimplemented for all qpa plugins at time of writing;
+ // almost all testfunctions fail on qpa due to this, except these few:
+ const QByteArray func = QTest::currentTestFunction();
+ if (func != "invalidRawFont"
+ && func != "explicitRawFontNotAvailableInSystem"
+ && func != "fromFont"
+ && func != "textLayout")
+ QEXPECT_FAIL("", "QTBUG-20976 fails on qpa", Abort);
+#endif
+}
+
+void tst_QRawFont::invalidRawFont()
+{
+ QRawFont font;
+ QVERIFY(!font.isValid());
+ QCOMPARE(font.pixelSize(), 0.0);
+ QVERIFY(font.familyName().isEmpty());
+ QCOMPARE(font.style(), QFont::StyleNormal);
+ QCOMPARE(font.weight(), -1);
+ QCOMPARE(font.ascent(), 0.0);
+ QCOMPARE(font.descent(), 0.0);
+ QVERIFY(font.glyphIndexesForString(QLatin1String("Test")).isEmpty());
+}
+
+void tst_QRawFont::explicitRawFontNotLoadedInDatabase_data()
+{
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+
+ QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
+ QTest::newRow("No hinting") << QFont::PreferNoHinting;
+ QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting;
+ QTest::newRow("Full hinting") << QFont::PreferFullHinting;
+}
+
+void tst_QRawFont::explicitRawFontNotLoadedInDatabase()
+{
+ QFETCH(QFont::HintingPreference, hintingPreference);
+
+ QRawFont font(QLatin1String(SRCDIR "testfont.ttf"), 10, hintingPreference);
+ QVERIFY(font.isValid());
+
+ QVERIFY(!QFontDatabase().families().contains(font.familyName()));
+}
+
+void tst_QRawFont::explicitRawFontNotAvailableInSystem_data()
+{
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+
+ QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
+ QTest::newRow("No hinting") << QFont::PreferNoHinting;
+ QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting;
+ QTest::newRow("Full hinting") << QFont::PreferFullHinting;
+}
+
+void tst_QRawFont::explicitRawFontNotAvailableInSystem()
+{
+ QFETCH(QFont::HintingPreference, hintingPreference);
+
+ QRawFont rawfont(QLatin1String(SRCDIR "testfont.ttf"), 10, hintingPreference);
+
+ {
+ QFont font(rawfont.familyName(), 10);
+
+ QVERIFY(!font.exactMatch());
+ QVERIFY(font.family() != QFontInfo(font).family());
+ }
+}
+
+void tst_QRawFont::correctFontData_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QString>("expectedFamilyName");
+ QTest::addColumn<QFont::Style>("style");
+ QTest::addColumn<QFont::Weight>("weight");
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+ QTest::addColumn<qreal>("unitsPerEm");
+ QTest::addColumn<qreal>("pixelSize");
+
+ int hintingPreferences[] = {
+ int(QFont::PreferDefaultHinting),
+ int(QFont::PreferNoHinting),
+ int(QFont::PreferVerticalHinting),
+ int(QFont::PreferFullHinting),
+ -1
+ };
+ int *hintingPreference = hintingPreferences;
+
+ while (*hintingPreference >= 0) {
+ QString fileName = QLatin1String(SRCDIR "testfont.ttf");
+ QString title = fileName
+ + QLatin1String(": hintingPreference=")
+ + QString::number(*hintingPreference);
+
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QString::fromLatin1("QtBidiTestFont")
+ << QFont::StyleNormal
+ << QFont::Normal
+ << QFont::HintingPreference(*hintingPreference)
+ << 1000.0
+ << 10.0;
+
+ fileName = QLatin1String(SRCDIR "testfont_bold_italic.ttf");
+ title = fileName
+ + QLatin1String(": hintingPreference=")
+ + QString::number(*hintingPreference);
+
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QString::fromLatin1("QtBidiTestFont")
+ << QFont::StyleItalic
+ << QFont::Bold
+ << QFont::HintingPreference(*hintingPreference)
+ << 1000.0
+ << 10.0;
+
+ ++hintingPreference;
+ }
+}
+
+void tst_QRawFont::correctFontData()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QString, expectedFamilyName);
+ QFETCH(QFont::Style, style);
+ QFETCH(QFont::Weight, weight);
+ QFETCH(QFont::HintingPreference, hintingPreference);
+ QFETCH(qreal, unitsPerEm);
+ QFETCH(qreal, pixelSize);
+
+ QRawFont font(fileName, 10, hintingPreference);
+ QVERIFY(font.isValid());
+
+ QCOMPARE(font.familyName(), expectedFamilyName);
+ QCOMPARE(font.style(), style);
+ QCOMPARE(font.weight(), int(weight));
+ QCOMPARE(font.hintingPreference(), hintingPreference);
+ QCOMPARE(font.unitsPerEm(), unitsPerEm);
+ QCOMPARE(font.pixelSize(), pixelSize);
+}
+
+void tst_QRawFont::glyphIndices()
+{
+ QRawFont font(QLatin1String(SRCDIR "testfont.ttf"), 10);
+ QVERIFY(font.isValid());
+
+ QVector<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("Foobar"));
+ QVector<quint32> expectedGlyphIndices;
+ expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86;
+
+ QCOMPARE(glyphIndices, expectedGlyphIndices);
+}
+
+void tst_QRawFont::advances_data()
+{
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+
+ QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
+ QTest::newRow("No hinting") << QFont::PreferNoHinting;
+ QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting;
+ QTest::newRow("Full hinting") << QFont::PreferFullHinting;
+}
+
+void tst_QRawFont::advances()
+{
+ QFETCH(QFont::HintingPreference, hintingPreference);
+
+ QRawFont font(QLatin1String(SRCDIR "testfont.ttf"), 10, hintingPreference);
+ QVERIFY(font.isValid());
+
+ QRawFontPrivate *font_d = QRawFontPrivate::get(font);
+ QVERIFY(font_d->fontEngine != 0);
+
+ QVector<quint32> glyphIndices;
+ glyphIndices << 44 << 83 << 83 << 70 << 69 << 86; // "Foobar"
+
+ bool supportsSubPixelPositions = font_d->fontEngine->supportsSubPixelPositions();
+ QVector<QPointF> advances = font.advancesForGlyphIndexes(glyphIndices);
+ for (int i=0; i<glyphIndices.size(); ++i) {
+ QVERIFY(qFuzzyCompare(qRound(advances.at(i).x()), 8.0));
+ if (supportsSubPixelPositions)
+ QVERIFY(advances.at(i).x() > 8.0);
+
+ QVERIFY(qFuzzyIsNull(advances.at(i).y()));
+ }
+}
+
+void tst_QRawFont::textLayout()
+{
+ QFontDatabase fontDatabase;
+ int id = fontDatabase.addApplicationFont(SRCDIR "testfont.ttf");
+ QVERIFY(id >= 0);
+
+ QString familyName = QString::fromLatin1("QtBidiTestFont");
+ QFont font(familyName);
+ font.setPixelSize(18.0);
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20976 fails on qpa", Abort);
+#endif
+ QCOMPARE(QFontInfo(font).family(), familyName);
+
+ QTextLayout layout(QLatin1String("Foobar"));
+ layout.setFont(font);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QGlyphRun glyphs = glyphRuns.at(0);
+
+ QRawFont rawFont = glyphs.rawFont();
+ QVERIFY(rawFont.isValid());
+ QCOMPARE(rawFont.familyName(), familyName);
+ QCOMPARE(rawFont.pixelSize(), 18.0);
+
+ QVector<quint32> expectedGlyphIndices;
+ expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86;
+
+ QCOMPARE(glyphs.glyphIndexes(), expectedGlyphIndices);
+
+ QVERIFY(fontDatabase.removeApplicationFont(id));
+}
+
+void tst_QRawFont::fontTable_data()
+{
+ QTest::addColumn<QByteArray>("tagName");
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+ QTest::addColumn<int>("offset");
+ QTest::addColumn<quint32>("expectedValue");
+
+ QTest::newRow("Head table, magic number, default hinting")
+ << QByteArray("head")
+ << QFont::PreferDefaultHinting
+ << 12
+ << (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? 0x5F0F3CF5
+ : 0xF53C0F5F);
+
+ QTest::newRow("Head table, magic number, no hinting")
+ << QByteArray("head")
+ << QFont::PreferNoHinting
+ << 12
+ << (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? 0x5F0F3CF5
+ : 0xF53C0F5F);
+
+ QTest::newRow("Head table, magic number, vertical hinting")
+ << QByteArray("head")
+ << QFont::PreferVerticalHinting
+ << 12
+ << (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? 0x5F0F3CF5
+ : 0xF53C0F5F);
+
+ QTest::newRow("Head table, magic number, full hinting")
+ << QByteArray("head")
+ << QFont::PreferFullHinting
+ << 12
+ << (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? 0x5F0F3CF5
+ : 0xF53C0F5F);
+}
+
+void tst_QRawFont::fontTable()
+{
+ QFETCH(QByteArray, tagName);
+ QFETCH(QFont::HintingPreference, hintingPreference);
+ QFETCH(int, offset);
+ QFETCH(quint32, expectedValue);
+
+ QRawFont font(QString::fromLatin1(SRCDIR "testfont.ttf"), 10, hintingPreference);
+ QVERIFY(font.isValid());
+
+ QByteArray table = font.fontTable(tagName);
+ QVERIFY(!table.isEmpty());
+
+ const quint32 *value = reinterpret_cast<const quint32 *>(table.constData() + offset);
+ QCOMPARE(*value, expectedValue);
+}
+
+typedef QList<QFontDatabase::WritingSystem> WritingSystemList;
+Q_DECLARE_METATYPE(WritingSystemList)
+
+void tst_QRawFont::supportedWritingSystems_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<WritingSystemList>("writingSystems");
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+
+ for (int hintingPreference=QFont::PreferDefaultHinting;
+ hintingPreference<=QFont::PreferFullHinting;
+ ++hintingPreference) {
+
+ QTest::newRow(qPrintable(QString::fromLatin1("testfont.ttf, hintingPreference=%1")
+ .arg(hintingPreference)))
+ << QString::fromLatin1(SRCDIR "testfont.ttf")
+ << (QList<QFontDatabase::WritingSystem>()
+ << QFontDatabase::Latin
+ << QFontDatabase::Hebrew
+ << QFontDatabase::Vietnamese) // Vietnamese uses same unicode bits as Latin
+ << QFont::HintingPreference(hintingPreference);
+
+ QTest::newRow(qPrintable(QString::fromLatin1("testfont_bold_italic.ttf, hintingPreference=%1")
+ .arg(hintingPreference)))
+ << QString::fromLatin1(SRCDIR "testfont_bold_italic.ttf")
+ << (QList<QFontDatabase::WritingSystem>()
+ << QFontDatabase::Latin
+ << QFontDatabase::Hebrew
+ << QFontDatabase::Devanagari
+ << QFontDatabase::Vietnamese) // Vietnamese uses same unicode bits as Latin
+ << QFont::HintingPreference(hintingPreference);
+ }
+}
+
+void tst_QRawFont::supportedWritingSystems()
+{
+ QFETCH(QString, fileName);
+ QFETCH(WritingSystemList, writingSystems);
+ QFETCH(QFont::HintingPreference, hintingPreference);
+
+ QRawFont font(fileName, 10, hintingPreference);
+ QVERIFY(font.isValid());
+
+ WritingSystemList actualWritingSystems = font.supportedWritingSystems();
+ QCOMPARE(actualWritingSystems.size(), writingSystems.size());
+
+ foreach (QFontDatabase::WritingSystem writingSystem, writingSystems)
+ QVERIFY(actualWritingSystems.contains(writingSystem));
+}
+
+void tst_QRawFont::supportsCharacter_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+ QTest::addColumn<QChar>("character");
+ QTest::addColumn<bool>("shouldBeSupported");
+
+ const char *fileNames[2] = {
+ SRCDIR "testfont.ttf",
+ SRCDIR "testfont_bold_italic.ttf"
+ };
+
+ for (int hintingPreference=QFont::PreferDefaultHinting;
+ hintingPreference<=QFont::PreferFullHinting;
+ ++hintingPreference) {
+
+ for (int i=0; i<2; ++i) {
+ QString fileName = QLatin1String(fileNames[i]);
+
+ // Latin text
+ for (char ch='!'; ch<='~'; ++ch) {
+ QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3")
+ .arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference);
+
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QFont::HintingPreference(hintingPreference)
+ << QChar::fromLatin1(ch)
+ << true;
+ }
+
+ // Hebrew text
+ for (quint16 ch=0x05D0; ch<=0x05EA; ++ch) {
+ QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3")
+ .arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference);
+
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QFont::HintingPreference(hintingPreference)
+ << QChar(ch)
+ << true;
+ }
+
+ QTest::newRow(qPrintable(QString::fromLatin1("Missing character, %1, hintingPreference=%2")
+ .arg(fileName).arg(hintingPreference)))
+ << fileName
+ << QFont::HintingPreference(hintingPreference)
+ << QChar(0xD8)
+ << false;
+ }
+ }
+}
+
+void tst_QRawFont::supportsCharacter()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QFont::HintingPreference, hintingPreference);
+ QFETCH(QChar, character);
+ QFETCH(bool, shouldBeSupported);
+
+ QRawFont font(fileName, 10, hintingPreference);
+ QVERIFY(font.isValid());
+
+ QCOMPARE(font.supportsCharacter(character), shouldBeSupported);
+}
+
+void tst_QRawFont::supportsUcs4Character_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+ QTest::addColumn<quint32>("ucs4");
+ QTest::addColumn<bool>("shouldBeSupported");
+
+ // Gothic text
+ for (int hintingPreference=QFont::PreferDefaultHinting;
+ hintingPreference<=QFont::PreferFullHinting;
+ ++hintingPreference) {
+ for (quint32 ch=0x10330; ch<=0x1034A; ++ch) {
+ {
+ QString fileName = QString::fromLatin1(SRCDIR "testfont.ttf");
+ QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3")
+ .arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference);
+
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QFont::HintingPreference(hintingPreference)
+ << ch
+ << true;
+ }
+
+ {
+ QString fileName = QString::fromLatin1(SRCDIR "testfont_bold_italic.ttf");
+ QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3")
+ .arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference);
+
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QFont::HintingPreference(hintingPreference)
+ << ch
+ << false;
+ }
+ }
+ }
+}
+
+void tst_QRawFont::supportsUcs4Character()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QFont::HintingPreference, hintingPreference);
+ QFETCH(quint32, ucs4);
+ QFETCH(bool, shouldBeSupported);
+
+ QRawFont font(fileName, 10, hintingPreference);
+ QVERIFY(font.isValid());
+
+ QCOMPARE(font.supportsCharacter(ucs4), shouldBeSupported);
+}
+
+void tst_QRawFont::fromFont_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+ QTest::addColumn<QString>("familyName");
+ QTest::addColumn<QFontDatabase::WritingSystem>("writingSystem");
+
+ for (int i=QFont::PreferDefaultHinting; i<=QFont::PreferFullHinting; ++i) {
+ QString titleBase = QString::fromLatin1("%2, hintingPreference=%1, writingSystem=%3")
+ .arg(i);
+ {
+ QString fileName = QString::fromLatin1(SRCDIR "testfont.ttf");
+ QFontDatabase::WritingSystem writingSystem = QFontDatabase::Any;
+
+ QString title = titleBase.arg(fileName).arg(writingSystem);
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QFont::HintingPreference(i)
+ << "QtBidiTestFont"
+ << writingSystem;
+ }
+
+ {
+ QString fileName = QString::fromLatin1(SRCDIR "testfont.ttf");
+ QFontDatabase::WritingSystem writingSystem = QFontDatabase::Hebrew;
+
+ QString title = titleBase.arg(fileName).arg(writingSystem);
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QFont::HintingPreference(i)
+ << "QtBidiTestFont"
+ << writingSystem;
+ }
+
+ {
+ QString fileName = QString::fromLatin1(SRCDIR "testfont.ttf");
+ QFontDatabase::WritingSystem writingSystem = QFontDatabase::Latin;
+
+ QString title = titleBase.arg(fileName).arg(writingSystem);
+ QTest::newRow(qPrintable(title))
+ << fileName
+ << QFont::HintingPreference(i)
+ << "QtBidiTestFont"
+ << writingSystem;
+ }
+ }
+}
+
+void tst_QRawFont::fromFont()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QFont::HintingPreference, hintingPreference);
+ QFETCH(QString, familyName);
+ QFETCH(QFontDatabase::WritingSystem, writingSystem);
+
+ QFontDatabase fontDatabase;
+ int id = fontDatabase.addApplicationFont(fileName);
+ QVERIFY(id >= 0);
+
+ QFont font(familyName);
+ font.setHintingPreference(hintingPreference);
+ font.setPixelSize(26.0);
+
+ QRawFont rawFont = QRawFont::fromFont(font, writingSystem);
+ QVERIFY(rawFont.isValid());
+
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20976 fails on qpa", Abort);
+#endif
+
+ QCOMPARE(rawFont.familyName(), familyName);
+ QCOMPARE(rawFont.pixelSize(), 26.0);
+
+ QVERIFY(fontDatabase.removeApplicationFont(id));
+}
+
+void tst_QRawFont::copyConstructor_data()
+{
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+
+ QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
+ QTest::newRow("No hinting preference") << QFont::PreferNoHinting;
+ QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting;
+ QTest::newRow("Full hinting preference") << QFont::PreferFullHinting;
+}
+
+void tst_QRawFont::copyConstructor()
+{
+ QFETCH(QFont::HintingPreference, hintingPreference);
+
+ {
+ QString rawFontFamilyName;
+ qreal rawFontPixelSize;
+ qreal rawFontAscent;
+ qreal rawFontDescent;
+ int rawFontTableSize;
+
+ QRawFont outerRawFont;
+ {
+ QRawFont rawFont(QString::fromLatin1(SRCDIR "testfont.ttf"), 11, hintingPreference);
+ QVERIFY(rawFont.isValid());
+
+ rawFontFamilyName = rawFont.familyName();
+ rawFontPixelSize = rawFont.pixelSize();
+ rawFontAscent = rawFont.ascent();
+ rawFontDescent = rawFont.descent();
+ rawFontTableSize = rawFont.fontTable("glyf").size();
+ QVERIFY(rawFontTableSize > 0);
+
+ {
+ QRawFont otherRawFont(rawFont);
+ QVERIFY(otherRawFont.isValid());
+ QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize);
+ QCOMPARE(otherRawFont.familyName(), rawFontFamilyName);
+ QCOMPARE(otherRawFont.hintingPreference(), hintingPreference);
+ QCOMPARE(otherRawFont.ascent(), rawFontAscent);
+ QCOMPARE(otherRawFont.descent(), rawFontDescent);
+ QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize);
+ }
+
+ {
+ QRawFont otherRawFont = rawFont;
+ QVERIFY(otherRawFont.isValid());
+ QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize);
+ QCOMPARE(otherRawFont.familyName(), rawFontFamilyName);
+ QCOMPARE(otherRawFont.hintingPreference(), hintingPreference);
+ QCOMPARE(otherRawFont.ascent(), rawFontAscent);
+ QCOMPARE(otherRawFont.descent(), rawFontDescent);
+ QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize);
+ }
+
+ outerRawFont = rawFont;
+ }
+
+ QVERIFY(outerRawFont.isValid());
+ QCOMPARE(outerRawFont.pixelSize(), rawFontPixelSize);
+ QCOMPARE(outerRawFont.familyName(), rawFontFamilyName);
+ QCOMPARE(outerRawFont.hintingPreference(), hintingPreference);
+ QCOMPARE(outerRawFont.ascent(), rawFontAscent);
+ QCOMPARE(outerRawFont.descent(), rawFontDescent);
+ QCOMPARE(outerRawFont.fontTable("glyf").size(), rawFontTableSize);
+ }
+}
+
+void tst_QRawFont::detach_data()
+{
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+
+ QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
+ QTest::newRow("No hinting preference") << QFont::PreferNoHinting;
+ QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting;
+ QTest::newRow("Full hinting preference") << QFont::PreferFullHinting;
+}
+
+void tst_QRawFont::detach()
+{
+ QFETCH(QFont::HintingPreference, hintingPreference);
+
+ {
+ QString rawFontFamilyName;
+ qreal rawFontPixelSize;
+ qreal rawFontAscent;
+ qreal rawFontDescent;
+ int rawFontTableSize;
+
+ QRawFont outerRawFont;
+ {
+ QRawFont rawFont(QString::fromLatin1(SRCDIR "testfont.ttf"), 11, hintingPreference);
+ QVERIFY(rawFont.isValid());
+
+ rawFontFamilyName = rawFont.familyName();
+ rawFontPixelSize = rawFont.pixelSize();
+ rawFontAscent = rawFont.ascent();
+ rawFontDescent = rawFont.descent();
+ rawFontTableSize = rawFont.fontTable("glyf").size();
+ QVERIFY(rawFontTableSize > 0);
+
+ {
+ QRawFont otherRawFont(rawFont);
+
+ otherRawFont.loadFromFile(QLatin1String(SRCDIR "testfont.ttf"),
+ rawFontPixelSize, hintingPreference);
+
+ QVERIFY(otherRawFont.isValid());
+ QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize);
+ QCOMPARE(otherRawFont.familyName(), rawFontFamilyName);
+ QCOMPARE(otherRawFont.hintingPreference(), hintingPreference);
+ QCOMPARE(otherRawFont.ascent(), rawFontAscent);
+ QCOMPARE(otherRawFont.descent(), rawFontDescent);
+ QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize);
+ }
+
+ {
+ QRawFont otherRawFont = rawFont;
+
+ otherRawFont.loadFromFile(QLatin1String(SRCDIR "testfont.ttf"),
+ rawFontPixelSize, hintingPreference);
+
+ QVERIFY(otherRawFont.isValid());
+ QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize);
+ QCOMPARE(otherRawFont.familyName(), rawFontFamilyName);
+ QCOMPARE(otherRawFont.hintingPreference(), hintingPreference);
+ QCOMPARE(otherRawFont.ascent(), rawFontAscent);
+ QCOMPARE(otherRawFont.descent(), rawFontDescent);
+ QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize);
+ }
+
+ outerRawFont = rawFont;
+
+ rawFont.loadFromFile(QLatin1String(SRCDIR "testfont.ttf"), rawFontPixelSize,
+ hintingPreference);
+ }
+
+ QVERIFY(outerRawFont.isValid());
+ QCOMPARE(outerRawFont.pixelSize(), rawFontPixelSize);
+ QCOMPARE(outerRawFont.familyName(), rawFontFamilyName);
+ QCOMPARE(outerRawFont.hintingPreference(), hintingPreference);
+ QCOMPARE(outerRawFont.ascent(), rawFontAscent);
+ QCOMPARE(outerRawFont.descent(), rawFontDescent);
+ QCOMPARE(outerRawFont.fontTable("glyf").size(), rawFontTableSize);
+ }
+}
+
+void tst_QRawFont::unsupportedWritingSystem_data()
+{
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+
+ QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
+ QTest::newRow("No hinting preference") << QFont::PreferNoHinting;
+ QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting;
+ QTest::newRow("Full hinting preference") << QFont::PreferFullHinting;
+}
+
+void tst_QRawFont::unsupportedWritingSystem()
+{
+ QFETCH(QFont::HintingPreference, hintingPreference);
+
+ QFontDatabase fontDatabase;
+ int id = fontDatabase.addApplicationFont(QLatin1String(SRCDIR "testfont.ttf"));
+
+ QFont font("QtBidiTestFont");
+ font.setHintingPreference(hintingPreference);
+ font.setPixelSize(12.0);
+
+ QRawFont rawFont = QRawFont::fromFont(font, QFontDatabase::Any);
+ QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont"));
+ QCOMPARE(rawFont.pixelSize(), 12.0);
+
+ rawFont = QRawFont::fromFont(font, QFontDatabase::Hebrew);
+ QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont"));
+ QCOMPARE(rawFont.pixelSize(), 12.0);
+
+ QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic);
+
+ QTextLayout layout;
+ layout.setFont(font);
+ layout.setText(arabicText);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QGlyphRun glyphs = glyphRuns.at(0);
+ QRawFont layoutFont = glyphs.rawFont();
+ QVERIFY(layoutFont.familyName() != QString::fromLatin1("QtBidiTestFont"));
+ QCOMPARE(layoutFont.pixelSize(), 12.0);
+
+ rawFont = QRawFont::fromFont(font, QFontDatabase::Arabic);
+ QCOMPARE(rawFont.familyName(), layoutFont.familyName());
+ QCOMPARE(rawFont.pixelSize(), 12.0);
+
+ fontDatabase.removeApplicationFont(id);
+}
+
+void tst_QRawFont::rawFontSetPixelSize_data()
+{
+ QTest::addColumn<QFont::HintingPreference>("hintingPreference");
+
+ QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
+ QTest::newRow("No hinting preference") << QFont::PreferNoHinting;
+ QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting;
+ QTest::newRow("Full hinting preference") << QFont::PreferFullHinting;
+}
+
+void tst_QRawFont::rawFontSetPixelSize()
+{
+ QFETCH(QFont::HintingPreference, hintingPreference);
+
+ QTextLayout layout("Foobar");
+
+ QFont font = layout.font();
+ font.setHintingPreference(hintingPreference);
+ font.setPixelSize(12);
+ layout.setFont(font);
+
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QGlyphRun glyphs = layout.glyphRuns().at(0);
+ QRawFont rawFont = glyphs.rawFont();
+ QCOMPARE(rawFont.pixelSize(), 12.0);
+
+ rawFont.setPixelSize(24);
+ QCOMPARE(rawFont.pixelSize(), 24.0);
+}
+
+#if defined(Q_WS_X11) || defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+void tst_QRawFont::multipleRawFontsFromData()
+{
+ QFile file(QString::fromLatin1(SRCDIR "testfont.ttf"));
+ QRawFont testFont;
+ if (file.open(QIODevice::ReadOnly)) {
+ testFont.loadFromData(file.readAll(), 11, QFont::PreferDefaultHinting);
+ file.close();
+ }
+ file.setFileName(QLatin1String(SRCDIR "testfont_bold_italic.ttf"));
+ QRawFont testFontBoldItalic;
+ if (file.open(QIODevice::ReadOnly))
+ testFontBoldItalic.loadFromData(file.readAll(), 11, QFont::PreferDefaultHinting);
+
+ QVERIFY(testFont.familyName() != (testFontBoldItalic.familyName())
+ || testFont.styleName() != (testFontBoldItalic.styleName()));
+}
+#endif
+
+#endif // QT_NO_RAWFONT
+
+QTEST_MAIN(tst_QRawFont)
+#include "tst_qrawfont.moc"
+
diff --git a/tests/auto/gui/text/qstatictext/qstatictext.pro b/tests/auto/gui/text/qstatictext/qstatictext.pro
new file mode 100644
index 0000000000..c8c36f81f7
--- /dev/null
+++ b/tests/auto/gui/text/qstatictext/qstatictext.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core core-private gui gui-private
+SOURCES += tst_qstatictext.cpp
+
diff --git a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
new file mode 100644
index 0000000000..79cbd692ea
--- /dev/null
+++ b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
@@ -0,0 +1,870 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtWidgets/QApplication>
+#include <QtGui/QPainter>
+#include <QtGui/QImage>
+
+#include <qstatictext.h>
+#include <qpaintengine.h>
+
+#include <private/qstatictext_p.h>
+#include <private/qapplication_p.h>
+
+// #define DEBUG_SAVE_IMAGE
+
+class tst_QStaticText: public QObject
+{
+ Q_OBJECT
+public:
+ tst_QStaticText() {}
+
+private slots:
+ void initTestCase();
+
+ void init();
+ void cleanup();
+
+ void constructionAndDestruction();
+ void drawToPoint_data();
+ void drawToPoint();
+ void drawToRect_data();
+ void drawToRect();
+ void setFont();
+ void setTextWidth();
+ void prepareToCorrectData();
+ void prepareToWrongData();
+
+ void copyConstructor();
+
+ void translatedPainter();
+ void rotatedPainter();
+ void scaledPainter();
+ void projectedPainter();
+#if 0
+ void rotatedScaledAndTranslatedPainter_data();
+ void rotatedScaledAndTranslatedPainter();
+#endif
+ void transformationChanged();
+
+ void plainTextVsRichText();
+
+ void setPenPlainText();
+ void setPenRichText();
+ void richTextOverridesPen();
+
+ void drawStruckOutText();
+ void drawOverlinedText();
+ void drawUnderlinedText();
+
+ void unprintableCharacter_qtbug12614();
+
+ void underlinedColor_qtbug20159();
+ void textDocumentColor();
+
+private:
+ bool supportsTransformations() const;
+
+ QImage const m_whiteSquare;
+};
+
+void tst_QStaticText::initTestCase()
+{
+ // a "blank" square; we compare against in our testfunctions to verify
+ // that we have actually painted something
+ QPixmap pm(1000, 1000);
+ pm.fill(Qt::white);
+ const_cast<QImage&>(m_whiteSquare) = pm.toImage();
+}
+
+void tst_QStaticText::init()
+{
+}
+
+void tst_QStaticText::cleanup()
+{
+}
+
+void tst_QStaticText::constructionAndDestruction()
+{
+ QStaticText text("My text");
+}
+
+void tst_QStaticText::copyConstructor()
+{
+ QStaticText text(QLatin1String("My text"));
+
+ QTextOption textOption(Qt::AlignRight);
+ text.setTextOption(textOption);
+
+ text.setPerformanceHint(QStaticText::AggressiveCaching);
+ text.setTextWidth(123.456);
+ text.setTextFormat(Qt::PlainText);
+
+ QStaticText copiedText(text);
+ copiedText.setText(QLatin1String("Other text"));
+
+ QCOMPARE(copiedText.textOption().alignment(), Qt::AlignRight);
+ QCOMPARE(copiedText.performanceHint(), QStaticText::AggressiveCaching);
+ QCOMPARE(copiedText.textWidth(), 123.456);
+ QCOMPARE(copiedText.textFormat(), Qt::PlainText);
+
+ QStaticText otherCopiedText(copiedText);
+ otherCopiedText.setTextWidth(789);
+
+ QCOMPARE(otherCopiedText.text(), QString::fromLatin1("Other text"));
+}
+
+Q_DECLARE_METATYPE(QStaticText::PerformanceHint)
+void tst_QStaticText::drawToPoint_data()
+{
+ QTest::addColumn<QStaticText::PerformanceHint>("performanceHint");
+
+ QTest::newRow("Moderate caching") << QStaticText::ModerateCaching;
+ QTest::newRow("Aggressive caching") << QStaticText::AggressiveCaching;
+}
+
+void tst_QStaticText::drawToPoint()
+{
+ QFETCH(QStaticText::PerformanceHint, performanceHint);
+
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.drawText(11, 12, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextFormat(Qt::PlainText);
+ text.setPerformanceHint(performanceHint);
+ p.drawStaticText(QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+void tst_QStaticText::drawToRect_data()
+{
+ QTest::addColumn<QStaticText::PerformanceHint>("performanceHint");
+
+ QTest::newRow("Moderate caching") << QStaticText::ModerateCaching;
+ QTest::newRow("Aggressive caching") << QStaticText::AggressiveCaching;
+}
+
+void tst_QStaticText::drawToRect()
+{
+ QFETCH(QStaticText::PerformanceHint, performanceHint);
+
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.drawText(QRectF(11, 12, 10, 500), "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextWidth(10),
+ p.setClipRect(QRectF(11, 12, 10, 500));
+ text.setPerformanceHint(performanceHint);
+ text.setTextFormat(Qt::PlainText);
+ p.drawStaticText(QPointF(11, 12), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("drawToRect_imageDrawText.png");
+ imageDrawStaticText.save("drawToRect_imageDrawStaticText.png");
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+void tst_QStaticText::prepareToCorrectData()
+{
+ QTransform transform;
+ transform.scale(2.0, 2.0);
+ transform.rotate(90, Qt::ZAxis);
+
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.setTransform(transform);
+ p.drawText(11, 12, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ p.setTransform(transform);
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.prepare(transform, p.font());
+ text.setTextFormat(Qt::PlainText);
+ p.drawStaticText(QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("prepareToCorrectData_imageDrawText.png");
+ imageDrawStaticText.save("prepareToCorrectData_imageDrawStaticText.png");
+#endif
+
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20977 fails on qpa", Abort);
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+
+ if (!supportsTransformations())
+ QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+void tst_QStaticText::prepareToWrongData()
+{
+ QTransform transform;
+ transform.scale(2.0, 2.0);
+ transform.rotate(90, Qt::ZAxis);
+
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.drawText(11, 12, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.prepare(transform, p.font());
+ text.setTextFormat(Qt::PlainText);
+ p.drawStaticText(QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+
+void tst_QStaticText::setFont()
+{
+ QFont font = QApplication::font();
+ font.setBold(true);
+ font.setPointSize(28);
+
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.drawText(QRectF(0, 0, 1000, 1000), 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+
+ p.setFont(font);
+ p.drawText(QRectF(11, 120, 1000, 1000), 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+
+ QStaticText text;
+ text.setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextFormat(Qt::PlainText);
+
+ p.drawStaticText(0, 0, text);
+
+ p.setFont(font);
+ p.drawStaticText(11, 120, text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("setFont_imageDrawText.png");
+ imageDrawStaticText.save("setFont_imageDrawStaticText.png");
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+void tst_QStaticText::setTextWidth()
+{
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.drawText(QRectF(11, 12, 10, 500), "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextWidth(10);
+ p.setClipRect(QRectF(11, 12, 10, 500));
+ p.drawStaticText(QPointF(11, 12), text);
+ }
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+void tst_QStaticText::translatedPainter()
+{
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.translate(100, 200);
+
+ p.drawText(11, 12, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ p.translate(100, 200);
+
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextFormat(Qt::PlainText);
+
+ p.drawStaticText(QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+bool tst_QStaticText::supportsTransformations() const
+{
+ QPixmap pm(10, 10);
+ QPainter p(&pm);
+ QPaintEngine *engine = p.paintEngine();
+
+ QPaintEngine::Type type = engine->type();
+
+ if (type == QPaintEngine::OpenGL
+#if !defined(Q_WS_WIN) && !defined(Q_WS_X11) && !defined(Q_WS_MAC)
+ || type == QPaintEngine::Raster
+#endif
+ )
+ return false;
+
+ return true;
+}
+
+void tst_QStaticText::rotatedPainter()
+{
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.rotate(30.0);
+ p.drawText(QRectF(0, 0, 1000, 100), 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextFormat(Qt::PlainText);
+
+ QPainter p(&imageDrawStaticText);
+ p.rotate(30.0);
+ p.drawStaticText(QPoint(0, 0), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("rotatedPainter_imageDrawText.png");
+ imageDrawStaticText.save("rotatedPainter_imageDrawStaticText.png");
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+
+ if (!supportsTransformations())
+ QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+void tst_QStaticText::scaledPainter()
+{
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.scale(2.0, 0.2);
+
+ p.drawText(11, 12, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ p.scale(2.0, 0.2);
+
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextFormat(Qt::PlainText);
+
+ p.drawStaticText(QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+
+ if (!supportsTransformations())
+ QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+void tst_QStaticText::projectedPainter()
+{
+ QTransform transform;
+ transform.rotate(90, Qt::XAxis);
+
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.setTransform(transform);
+
+ p.drawText(11, 12, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ p.setTransform(transform);
+
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextFormat(Qt::PlainText);
+
+ p.drawStaticText(QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+#if 0
+void tst_QStaticText::rotatedScaledAndTranslatedPainter_data()
+{
+ QTest::addColumn<qreal>("offset");
+
+ for (int i=0; i<100; ++i) {
+ qreal offset = 300 + i / 100.;
+ QTest::newRow(QByteArray::number(offset).constData()) << offset;
+ }
+}
+
+void tst_QStaticText::rotatedScaledAndTranslatedPainter()
+{
+ QFETCH(qreal, offset);
+
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.translate(offset, 0);
+ p.rotate(45.0);
+ p.scale(2.0, 2.0);
+ p.translate(100, 200);
+
+ p.drawText(11, 12, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ p.translate(offset, 0);
+ p.rotate(45.0);
+ p.scale(2.0, 2.0);
+ p.translate(100, 200);
+
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextFormat(Qt::PlainText);
+
+ p.drawStaticText(QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("rotatedScaledAndPainter_imageDrawText.png");
+ imageDrawStaticText.save("rotatedScaledAndPainter_imageDrawStaticText.png");
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+
+ if (!supportsTransformations())
+ QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+#endif
+
+void tst_QStaticText::transformationChanged()
+{
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.rotate(33.0);
+ p.scale(0.5, 0.7);
+
+ p.drawText(QRectF(0, 0, 1000, 1000), 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+
+ p.scale(2.0, 2.5);
+ p.drawText(QRectF(0, 0, 1000, 1000), 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticText(1000, 1000);
+ imageDrawStaticText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticText);
+ p.rotate(33.0);
+ p.scale(0.5, 0.7);
+
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextFormat(Qt::PlainText);
+
+ p.drawStaticText(QPointF(0, 0), text);
+
+ p.scale(2.0, 2.5);
+ p.drawStaticText(QPointF(0, 0), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("transformationChanged_imageDrawText.png");
+ imageDrawStaticText.save("transformationChanged_imageDrawStaticText.png");
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+
+ if (!supportsTransformations())
+ QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
+ QCOMPARE(imageDrawStaticText, imageDrawText);
+}
+
+void tst_QStaticText::plainTextVsRichText()
+{
+ QPixmap imagePlainText(1000, 1000);
+ imagePlainText.fill(Qt::white);
+ {
+ QPainter p(&imagePlainText);
+
+ QStaticText staticText;
+ staticText.setText("FOObar");
+ staticText.setTextFormat(Qt::PlainText);
+
+ p.drawStaticText(10, 10, staticText);
+ }
+
+ QPixmap imageRichText(1000, 1000);
+ imageRichText.fill(Qt::white);
+ {
+ QPainter p(&imageRichText);
+
+ QStaticText staticText;
+ staticText.setText("<html><body>FOObar</body></html>");
+ staticText.setTextFormat(Qt::RichText);
+
+ p.drawStaticText(10, 10, staticText);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imagePlainText.save("plainTextVsRichText_imagePlainText.png");
+ imageRichText.save("plainTextVsRichText_imageRichText.png");
+#endif
+
+ QVERIFY(imagePlainText.toImage() != m_whiteSquare);
+ QCOMPARE(imagePlainText, imageRichText);
+}
+
+void tst_QStaticText::setPenPlainText()
+{
+ QFont font = QApplication::font();
+ font.setStyleStrategy(QFont::NoAntialias);
+
+ QFontMetricsF fm(font);
+ QPixmap image(qCeil(fm.width("XXXXX")), qCeil(fm.height()));
+ image.fill(Qt::white);
+ {
+ QPainter p(&image);
+ p.setFont(font);
+ p.setPen(Qt::green);
+
+ QStaticText staticText("XXXXX");
+ staticText.setTextFormat(Qt::PlainText);
+ p.drawStaticText(0, 0, staticText);
+ }
+
+ QImage img = image.toImage();
+ for (int x=0; x<img.width(); ++x) {
+ for (int y=0; y<img.height(); ++y) {
+ QRgb pixel = img.pixel(x, y);
+ QVERIFY(pixel == QColor(Qt::white).rgba()
+ || pixel == QColor(Qt::green).rgba());
+ }
+ }
+}
+
+void tst_QStaticText::setPenRichText()
+{
+ QFont font = QApplication::font();
+ font.setStyleStrategy(QFont::NoAntialias);
+
+ QFontMetricsF fm(font);
+ QPixmap image(qCeil(fm.width("XXXXX")), qCeil(fm.height()));
+ image.fill(Qt::white);
+ {
+ QPainter p(&image);
+ p.setFont(font);
+ p.setPen(Qt::green);
+
+ QStaticText staticText;
+ staticText.setText("<html><body>XXXXX</body></html>");
+ staticText.setTextFormat(Qt::RichText);
+ p.drawStaticText(0, 0, staticText);
+ }
+
+ QImage img = image.toImage();
+ for (int x=0; x<img.width(); ++x) {
+ for (int y=0; y<img.height(); ++y) {
+ QRgb pixel = img.pixel(x, y);
+ QVERIFY(pixel == QColor(Qt::white).rgba()
+ || pixel == QColor(Qt::green).rgba());
+ }
+ }
+}
+
+void tst_QStaticText::richTextOverridesPen()
+{
+ QFont font = QApplication::font();
+ font.setStyleStrategy(QFont::NoAntialias);
+
+ QFontMetricsF fm(font);
+ QPixmap image(qCeil(fm.width("XXXXX")), qCeil(fm.height()));
+ image.fill(Qt::white);
+ {
+ QPainter p(&image);
+ p.setFont(font);
+ p.setPen(Qt::green);
+
+ QStaticText staticText;
+ staticText.setText("<html><body><font color=\"#ff0000\">XXXXX</font></body></html>");
+ staticText.setTextFormat(Qt::RichText);
+ p.drawStaticText(0, 0, staticText);
+ }
+
+ QImage img = image.toImage();
+ for (int x=0; x<img.width(); ++x) {
+ for (int y=0; y<img.height(); ++y) {
+ QRgb pixel = img.pixel(x, y);
+ QVERIFY(pixel == QColor(Qt::white).rgba()
+ || pixel == QColor(Qt::red).rgba());
+ }
+ }
+}
+
+void tst_QStaticText::drawStruckOutText()
+{
+ QPixmap imageDrawText(1000, 1000);
+ QPixmap imageDrawStaticText(1000, 1000);
+
+ imageDrawText.fill(Qt::white);
+ imageDrawStaticText.fill(Qt::white);
+
+ QString s = QString::fromLatin1("Foobar");
+
+ QFont font;
+ font.setStrikeOut(true);
+
+ {
+ QPainter p(&imageDrawText);
+ p.setFont(font);
+ p.drawText(QPointF(50, 50), s);
+ }
+
+ {
+ QPainter p(&imageDrawStaticText);
+ QStaticText text = QStaticText(s);
+ p.setFont(font);
+ p.drawStaticText(QPointF(50, 50 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("drawStruckOutText_imageDrawText.png");
+ imageDrawStaticText.save("drawStruckOutText_imageDrawStaticText.png");
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawText, imageDrawStaticText);
+}
+
+void tst_QStaticText::drawOverlinedText()
+{
+ QPixmap imageDrawText(1000, 1000);
+ QPixmap imageDrawStaticText(1000, 1000);
+
+ imageDrawText.fill(Qt::white);
+ imageDrawStaticText.fill(Qt::white);
+
+ QString s = QString::fromLatin1("Foobar");
+
+ QFont font;
+ font.setOverline(true);
+
+ {
+ QPainter p(&imageDrawText);
+ p.setFont(font);
+ p.drawText(QPointF(50, 50), s);
+ }
+
+ {
+ QPainter p(&imageDrawStaticText);
+ QStaticText text = QStaticText(s);
+ p.setFont(font);
+ p.drawStaticText(QPointF(50, 50 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("drawOverlinedText_imageDrawText.png");
+ imageDrawStaticText.save("drawOverlinedText_imageDrawStaticText.png");
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawText, imageDrawStaticText);
+}
+
+void tst_QStaticText::drawUnderlinedText()
+{
+ QPixmap imageDrawText(1000, 1000);
+ QPixmap imageDrawStaticText(1000, 1000);
+
+ imageDrawText.fill(Qt::white);
+ imageDrawStaticText.fill(Qt::white);
+
+ QString s = QString::fromLatin1("Foobar");
+
+ QFont font;
+ font.setUnderline(true);
+
+ {
+ QPainter p(&imageDrawText);
+ p.setFont(font);
+ p.drawText(QPointF(50, 50), s);
+ }
+
+ {
+ QPainter p(&imageDrawStaticText);
+ QStaticText text = QStaticText(s);
+ p.setFont(font);
+ p.drawStaticText(QPointF(50, 50 - QFontMetricsF(p.font()).ascent()), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("drawUnderlinedText_imageDrawText.png");
+ imageDrawStaticText.save("drawUnderlinedText_imageDrawStaticText.png");
+#endif
+
+ QCOMPARE(imageDrawText, imageDrawStaticText);
+}
+
+void tst_QStaticText::unprintableCharacter_qtbug12614()
+{
+ QString s(QChar(0x200B)); // U+200B, ZERO WIDTH SPACE
+
+ QStaticText staticText(s);
+
+ QVERIFY(staticText.size().isValid()); // Force layout. Should not crash.
+}
+
+void tst_QStaticText::underlinedColor_qtbug20159()
+{
+ QString multiScriptText;
+ multiScriptText += QChar(0x0410); // Cyrillic 'A'
+ multiScriptText += QLatin1Char('A');
+
+ QStaticText staticText(multiScriptText);
+
+ QFont font;
+ font.setUnderline(true);
+
+ staticText.prepare(QTransform(), font);
+
+ QStaticTextPrivate *d = QStaticTextPrivate::get(&staticText);
+ QCOMPARE(d->itemCount, 2);
+
+ // The pen should not be marked as dirty when drawing the underline
+ QVERIFY(!d->items[0].color.isValid());
+ QVERIFY(!d->items[1].color.isValid());
+}
+
+void tst_QStaticText::textDocumentColor()
+{
+ QStaticText staticText("A<font color=\"red\">B</font>");
+ staticText.setTextFormat(Qt::RichText);
+ staticText.prepare();
+
+ QStaticTextPrivate *d = QStaticTextPrivate::get(&staticText);
+ QCOMPARE(d->itemCount, 2);
+
+ // The pen should not be marked as dirty when drawing the underline
+ QVERIFY(!d->items[0].color.isValid());
+ QVERIFY(d->items[1].color.isValid());
+
+ QCOMPARE(d->items[1].color, QColor(Qt::red));
+}
+
+QTEST_MAIN(tst_QStaticText)
+#include "tst_qstatictext.moc"
diff --git a/tests/auto/gui/text/qsyntaxhighlighter/.gitignore b/tests/auto/gui/text/qsyntaxhighlighter/.gitignore
new file mode 100644
index 0000000000..3efe6efbe5
--- /dev/null
+++ b/tests/auto/gui/text/qsyntaxhighlighter/.gitignore
@@ -0,0 +1 @@
+tst_qsyntaxhighlighter
diff --git a/tests/auto/gui/text/qsyntaxhighlighter/qsyntaxhighlighter.pro b/tests/auto/gui/text/qsyntaxhighlighter/qsyntaxhighlighter.pro
new file mode 100644
index 0000000000..30fb3a5283
--- /dev/null
+++ b/tests/auto/gui/text/qsyntaxhighlighter/qsyntaxhighlighter.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+SOURCES += tst_qsyntaxhighlighter.cpp
+
+
diff --git a/tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp b/tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp
new file mode 100644
index 0000000000..24ade2dc91
--- /dev/null
+++ b/tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp
@@ -0,0 +1,549 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QTextDocument>
+#include <QTextLayout>
+#include <QDebug>
+#include <QAbstractTextDocumentLayout>
+#include <QSyntaxHighlighter>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+//
+class QTestDocumentLayout : public QAbstractTextDocumentLayout
+{
+ Q_OBJECT
+public:
+ inline QTestDocumentLayout(QTextDocument *doc)
+ : QAbstractTextDocumentLayout(doc), documentChangedCalled(false) {}
+
+ virtual void draw(QPainter *, const QAbstractTextDocumentLayout::PaintContext &) {}
+
+ virtual int hitTest(const QPointF &, Qt::HitTestAccuracy ) const { return 0; }
+
+ virtual void documentChanged(int, int, int) { documentChangedCalled = true; }
+
+ virtual int pageCount() const { return 1; }
+
+ virtual QSizeF documentSize() const { return QSize(); }
+
+ virtual QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
+ virtual QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
+
+ bool documentChangedCalled;
+};
+
+class tst_QSyntaxHighlighter : public QObject
+{
+ Q_OBJECT
+public:
+ inline tst_QSyntaxHighlighter() {}
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void basic();
+ void basicTwo();
+ void removeFormatsOnDelete();
+ void emptyBlocks();
+ void setCharFormat();
+ void highlightOnInit();
+ void stopHighlightingWhenStateDoesNotChange();
+ void unindent();
+ void highlightToEndOfDocument();
+ void highlightToEndOfDocument2();
+ void preservePreeditArea();
+ void task108530();
+ void avoidUnnecessaryRehighlight();
+ void noContentsChangedDuringHighlight();
+ void rehighlight();
+ void rehighlightBlock();
+
+private:
+ QTextDocument *doc;
+ QTestDocumentLayout *lout;
+ QTextCursor cursor;
+};
+
+void tst_QSyntaxHighlighter::init()
+{
+ doc = new QTextDocument;
+ lout = new QTestDocumentLayout(doc);
+ doc->setDocumentLayout(lout);
+ cursor = QTextCursor(doc);
+}
+
+void tst_QSyntaxHighlighter::cleanup()
+{
+ delete doc;
+ doc = 0;
+}
+
+class TestHighlighter : public QSyntaxHighlighter
+{
+public:
+ inline TestHighlighter(const QList<QTextLayout::FormatRange> &fmts, QTextDocument *parent)
+ : QSyntaxHighlighter(parent), formats(fmts), highlighted(false), callCount(0) {}
+ inline TestHighlighter(QTextDocument *parent)
+ : QSyntaxHighlighter(parent), highlighted(false), callCount(0) {}
+
+ virtual void highlightBlock(const QString &text)
+ {
+ for (int i = 0; i < formats.count(); ++i) {
+ const QTextLayout::FormatRange &range = formats.at(i);
+ setFormat(range.start, range.length, range.format);
+ }
+ highlighted = true;
+ highlightedText += text;
+ ++callCount;
+ }
+
+ QList<QTextLayout::FormatRange> formats;
+ bool highlighted;
+ int callCount;
+ QString highlightedText;
+};
+
+QT_BEGIN_NAMESPACE
+bool operator==(const QTextLayout::FormatRange &lhs, const QTextLayout::FormatRange &rhs)
+{
+ return lhs.start == rhs.start
+ && lhs.length == rhs.length
+ && lhs.format == rhs.format;
+}
+QT_END_NAMESPACE
+
+void tst_QSyntaxHighlighter::basic()
+{
+ QList<QTextLayout::FormatRange> formats;
+ QTextLayout::FormatRange range;
+ range.start = 0;
+ range.length = 2;
+ range.format.setForeground(Qt::blue);
+ formats.append(range);
+
+ range.start = 4;
+ range.length = 2;
+ range.format.setFontItalic(true);
+ formats.append(range);
+
+ range.start = 9;
+ range.length = 2;
+ range.format.setFontUnderline(true);
+ formats.append(range);
+
+ TestHighlighter *hl = new TestHighlighter(formats, doc);
+
+ lout->documentChangedCalled = false;
+ doc->setPlainText("Hello World");
+ QVERIFY(hl->highlighted);
+ QVERIFY(lout->documentChangedCalled);
+
+ QVERIFY(doc->begin().layout()->additionalFormats() == formats);
+}
+
+class CommentTestHighlighter : public QSyntaxHighlighter
+{
+public:
+ inline CommentTestHighlighter(QTextDocument *parent)
+ : QSyntaxHighlighter(parent), highlighted(false) {}
+
+ inline void reset()
+ {
+ highlighted = false;
+ }
+
+ virtual void highlightBlock(const QString &text)
+ {
+ QTextCharFormat commentFormat;
+ commentFormat.setForeground(Qt::darkGreen);
+ commentFormat.setFontWeight(QFont::StyleItalic);
+ commentFormat.setFontFixedPitch(true);
+ int textLength = text.length();
+
+ if (text.startsWith(QLatin1Char(';'))){
+ // The entire line is a comment
+ setFormat(0, textLength, commentFormat);
+ highlighted = true;
+ }
+ }
+ bool highlighted;
+};
+
+
+void tst_QSyntaxHighlighter::basicTwo()
+{
+ // Done for task 104409
+ CommentTestHighlighter *hl = new CommentTestHighlighter(doc);
+ doc->setPlainText("; a test");
+ QVERIFY(hl->highlighted);
+ QVERIFY(lout->documentChangedCalled);
+}
+
+void tst_QSyntaxHighlighter::removeFormatsOnDelete()
+{
+ QList<QTextLayout::FormatRange> formats;
+ QTextLayout::FormatRange range;
+ range.start = 0;
+ range.length = 9;
+ range.format.setForeground(Qt::blue);
+ formats.append(range);
+
+ TestHighlighter *hl = new TestHighlighter(formats, doc);
+
+ lout->documentChangedCalled = false;
+ doc->setPlainText("Hello World");
+ QVERIFY(hl->highlighted);
+ QVERIFY(lout->documentChangedCalled);
+
+ lout->documentChangedCalled = false;
+ QVERIFY(!doc->begin().layout()->additionalFormats().isEmpty());
+ delete hl;
+ QVERIFY(doc->begin().layout()->additionalFormats().isEmpty());
+ QVERIFY(lout->documentChangedCalled);
+}
+
+void tst_QSyntaxHighlighter::emptyBlocks()
+{
+ TestHighlighter *hl = new TestHighlighter(doc);
+
+ cursor.insertText("Foo");
+ cursor.insertBlock();
+ cursor.insertBlock();
+ hl->highlighted = false;
+ cursor.insertBlock();
+ QVERIFY(hl->highlighted);
+}
+
+void tst_QSyntaxHighlighter::setCharFormat()
+{
+ TestHighlighter *hl = new TestHighlighter(doc);
+
+ cursor.insertText("FooBar");
+ cursor.insertBlock();
+ cursor.insertText("Blah");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ QTextCharFormat fmt;
+ fmt.setFontItalic(true);
+ hl->highlighted = false;
+ hl->callCount = 0;
+ cursor.mergeCharFormat(fmt);
+ QVERIFY(hl->highlighted);
+ QCOMPARE(hl->callCount, 2);
+}
+
+void tst_QSyntaxHighlighter::highlightOnInit()
+{
+ cursor.insertText("Hello");
+ cursor.insertBlock();
+ cursor.insertText("World");
+
+ TestHighlighter *hl = new TestHighlighter(doc);
+ QTest::qWait(100);
+ QVERIFY(hl->highlighted);
+}
+
+class StateTestHighlighter : public QSyntaxHighlighter
+{
+public:
+ inline StateTestHighlighter(QTextDocument *parent)
+ : QSyntaxHighlighter(parent), state(0), highlighted(false) {}
+
+ inline void reset()
+ {
+ highlighted = false;
+ state = 0;
+ }
+
+ virtual void highlightBlock(const QString &text)
+ {
+ highlighted = true;
+ if (text == QLatin1String("changestate"))
+ setCurrentBlockState(state++);
+ }
+
+ int state;
+ bool highlighted;
+};
+
+void tst_QSyntaxHighlighter::stopHighlightingWhenStateDoesNotChange()
+{
+ cursor.insertText("state");
+ cursor.insertBlock();
+ cursor.insertText("changestate");
+ cursor.insertBlock();
+ cursor.insertText("keepstate");
+ cursor.insertBlock();
+ cursor.insertText("changestate");
+ cursor.insertBlock();
+ cursor.insertText("changestate");
+
+ StateTestHighlighter *hl = new StateTestHighlighter(doc);
+ QTest::qWait(100);
+ QVERIFY(hl->highlighted);
+
+ hl->reset();
+
+ // turn the text of the first block into 'changestate'
+ cursor.movePosition(QTextCursor::Start);
+ cursor.insertText("change");
+
+ // verify that we highlighted only to the 'keepstate' block,
+ // not beyond
+ QCOMPARE(hl->state, 2);
+}
+
+void tst_QSyntaxHighlighter::unindent()
+{
+ const QString spaces(" ");
+ const QString text("Foobar");
+ QString plainText;
+ for (int i = 0; i < 5; ++i) {
+ cursor.insertText(spaces + text);
+ cursor.insertBlock();
+
+ plainText += spaces;
+ plainText += text;
+ plainText += QLatin1Char('\n');
+ }
+ QCOMPARE(doc->toPlainText(), plainText);
+
+ TestHighlighter *hl = new TestHighlighter(doc);
+ hl->callCount = 0;
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.beginEditBlock();
+
+ plainText.clear();
+ for (int i = 0; i < 5; ++i) {
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 4);
+ cursor.removeSelectedText();
+ cursor.movePosition(QTextCursor::NextBlock);
+
+ plainText += text;
+ plainText += QLatin1Char('\n');
+ }
+
+ cursor.endEditBlock();
+ QCOMPARE(doc->toPlainText(), plainText);
+ QCOMPARE(hl->callCount, 5);
+}
+
+void tst_QSyntaxHighlighter::highlightToEndOfDocument()
+{
+ TestHighlighter *hl = new TestHighlighter(doc);
+ hl->callCount = 0;
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.beginEditBlock();
+
+ cursor.insertText("Hello");
+ cursor.insertBlock();
+ cursor.insertBlock();
+ cursor.insertText("World");
+ cursor.insertBlock();
+
+ cursor.endEditBlock();
+
+ QCOMPARE(hl->callCount, 4);
+}
+
+void tst_QSyntaxHighlighter::highlightToEndOfDocument2()
+{
+ TestHighlighter *hl = new TestHighlighter(doc);
+ hl->callCount = 0;
+
+ cursor.movePosition(QTextCursor::End);
+ cursor.beginEditBlock();
+ QTextBlockFormat fmt;
+ fmt.setAlignment(Qt::AlignLeft);
+ cursor.setBlockFormat(fmt);
+ cursor.insertText("Three\nLines\nHere");
+ cursor.endEditBlock();
+
+ QCOMPARE(hl->callCount, 3);
+}
+
+void tst_QSyntaxHighlighter::preservePreeditArea()
+{
+ QList<QTextLayout::FormatRange> formats;
+ QTextLayout::FormatRange range;
+ range.start = 0;
+ range.length = 8;
+ range.format.setForeground(Qt::blue);
+ formats << range;
+ range.start = 9;
+ range.length = 1;
+ range.format.setForeground(Qt::red);
+ formats << range;
+ TestHighlighter *hl = new TestHighlighter(formats, doc);
+
+ doc->setPlainText("Hello World");
+ cursor.movePosition(QTextCursor::Start);
+
+ QTextLayout *layout = cursor.block().layout();
+
+ layout->setPreeditArea(5, QString("foo"));
+ range.start = 5;
+ range.length = 3;
+ range.format.setFontUnderline(true);
+ formats.clear();
+ formats << range;
+
+ hl->callCount = 0;
+
+ cursor.beginEditBlock();
+ layout->setAdditionalFormats(formats);
+ cursor.endEditBlock();
+
+ QCOMPARE(hl->callCount, 1);
+
+ formats = layout->additionalFormats();
+ QCOMPARE(formats.count(), 3);
+
+ range = formats.at(0);
+
+ QCOMPARE(range.start, 5);
+ QCOMPARE(range.length, 3);
+ QVERIFY(range.format.fontUnderline());
+
+ range = formats.at(1);
+ QCOMPARE(range.start, 0);
+ QCOMPARE(range.length, 8 + 3);
+
+ range = formats.at(2);
+ QCOMPARE(range.start, 9 + 3);
+ QCOMPARE(range.length, 1);
+}
+
+void tst_QSyntaxHighlighter::task108530()
+{
+ TestHighlighter *hl = new TestHighlighter(doc);
+
+ cursor.insertText("test");
+ hl->callCount = 0;
+ hl->highlightedText.clear();
+ cursor.movePosition(QTextCursor::Start);
+ cursor.insertBlock();
+
+ QCOMPARE(hl->highlightedText, QString("test"));
+ QCOMPARE(hl->callCount, 2);
+}
+
+void tst_QSyntaxHighlighter::avoidUnnecessaryRehighlight()
+{
+ TestHighlighter *hl = new TestHighlighter(doc);
+ QVERIFY(!hl->highlighted);
+
+ doc->setPlainText("Hello World");
+ QVERIFY(hl->highlighted);
+
+ hl->highlighted = false;
+ QTest::qWait(100);
+ QVERIFY(!hl->highlighted);
+}
+
+void tst_QSyntaxHighlighter::noContentsChangedDuringHighlight()
+{
+ QList<QTextLayout::FormatRange> formats;
+ QTextLayout::FormatRange range;
+ range.start = 0;
+ range.length = 10;
+ range.format.setForeground(Qt::blue);
+ formats.append(range);
+
+ TestHighlighter *hl = new TestHighlighter(formats, doc);
+
+ lout->documentChangedCalled = false;
+ QTextCursor cursor(doc);
+
+ QSignalSpy contentsChangedSpy(doc, SIGNAL(contentsChanged()));
+ cursor.insertText("Hello World");
+
+ QCOMPARE(contentsChangedSpy.count(), 1);
+ QVERIFY(hl->highlighted);
+ QVERIFY(lout->documentChangedCalled);
+}
+
+void tst_QSyntaxHighlighter::rehighlight()
+{
+ TestHighlighter *hl = new TestHighlighter(doc);
+ hl->callCount = 0;
+ doc->setPlainText("Hello");
+ hl->callCount = 0;
+ hl->rehighlight();
+ QCOMPARE(hl->callCount, 1);
+}
+
+void tst_QSyntaxHighlighter::rehighlightBlock()
+{
+ TestHighlighter *hl = new TestHighlighter(doc);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.beginEditBlock();
+ cursor.insertText("Hello");
+ cursor.insertBlock();
+ cursor.insertText("World");
+ cursor.endEditBlock();
+
+ hl->callCount = 0;
+ hl->highlightedText.clear();
+ QTextBlock block = doc->begin();
+ hl->rehighlightBlock(block);
+
+ QCOMPARE(hl->highlightedText, QString("Hello"));
+ QCOMPARE(hl->callCount, 1);
+
+ hl->callCount = 0;
+ hl->highlightedText.clear();
+ hl->rehighlightBlock(block.next());
+
+ QCOMPARE(hl->highlightedText, QString("World"));
+ QCOMPARE(hl->callCount, 1);
+}
+
+QTEST_MAIN(tst_QSyntaxHighlighter)
+#include "tst_qsyntaxhighlighter.moc"
diff --git a/tests/auto/gui/text/qtextblock/.gitignore b/tests/auto/gui/text/qtextblock/.gitignore
new file mode 100644
index 0000000000..648a522140
--- /dev/null
+++ b/tests/auto/gui/text/qtextblock/.gitignore
@@ -0,0 +1 @@
+tst_qtextblock
diff --git a/tests/auto/gui/text/qtextblock/qtextblock.pro b/tests/auto/gui/text/qtextblock/qtextblock.pro
new file mode 100644
index 0000000000..d50ef5ca78
--- /dev/null
+++ b/tests/auto/gui/text/qtextblock/qtextblock.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qtextblock.cpp
+
+
+
diff --git a/tests/auto/gui/text/qtextblock/tst_qtextblock.cpp b/tests/auto/gui/text/qtextblock/tst_qtextblock.cpp
new file mode 100644
index 0000000000..b04a6f5559
--- /dev/null
+++ b/tests/auto/gui/text/qtextblock/tst_qtextblock.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#define protected public
+#include <qtextdocument.h>
+#undef protected
+#include <qdebug.h>
+#ifndef Q_WS_WIN
+#include <private/qtextdocument_p.h>
+#endif
+
+
+
+#include <qtextobject.h>
+#include <qtextcursor.h>
+
+
+//TESTED_FILES=
+
+QT_FORWARD_DECLARE_CLASS(QTextDocument)
+
+class tst_QTextBlock : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTextBlock();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void fragmentOverBlockBoundaries();
+ void excludeParagraphSeparatorFragment();
+ void backwardsBlockIterator();
+ void previousBlock_qtbug18026();
+ void removedBlock_qtbug18500();
+
+private:
+ QTextDocument *doc;
+ QTextCursor cursor;
+};
+
+tst_QTextBlock::tst_QTextBlock()
+{}
+
+void tst_QTextBlock::init()
+{
+ doc = new QTextDocument;
+ cursor = QTextCursor(doc);
+}
+
+void tst_QTextBlock::cleanup()
+{
+ cursor = QTextCursor();
+ delete doc;
+ doc = 0;
+}
+
+void tst_QTextBlock::fragmentOverBlockBoundaries()
+{
+ /* this creates two fragments in the piecetable:
+ * 1) 'hello<parag separator here>world'
+ * 2) '<parag separator>'
+ * (they are not united because the former was interested after the latter,
+ * hence their position in the pt buffer is the other way around)
+ */
+ cursor.insertText("Hello");
+ cursor.insertBlock();
+ cursor.insertText("World");
+
+ cursor.movePosition(QTextCursor::Start);
+
+ const QTextDocument *doc = cursor.block().document();
+ QVERIFY(doc);
+ // Block separators are always a fragment of their self. Thus:
+ // |Hello|\b|World|\b|
+#if !defined(Q_WS_WIN) && !defined(Q_WS_S60)
+ QVERIFY(doc->docHandle()->fragmentMap().numNodes() == 4);
+#endif
+ QCOMPARE(cursor.block().text(), QString("Hello"));
+ cursor.movePosition(QTextCursor::NextBlock);
+ QCOMPARE(cursor.block().text(), QString("World"));
+}
+
+void tst_QTextBlock::excludeParagraphSeparatorFragment()
+{
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ cursor.insertText("Hello", fmt);
+
+ QTextBlock block = doc->begin();
+ QVERIFY(block.isValid());
+
+ QTextBlock::Iterator it = block.begin();
+
+ QTextFragment fragment = it.fragment();
+ QVERIFY(fragment.isValid());
+ QCOMPARE(fragment.text(), QString("Hello"));
+
+ ++it;
+ QVERIFY(it.atEnd());
+ QVERIFY(it == block.end());
+}
+
+void tst_QTextBlock::backwardsBlockIterator()
+{
+ QTextCharFormat fmt;
+
+ fmt.setForeground(Qt::magenta);
+ cursor.insertText("A", fmt);
+
+ fmt.setForeground(Qt::red);
+ cursor.insertText("A", fmt);
+
+ fmt.setForeground(Qt::magenta);
+ cursor.insertText("A", fmt);
+
+ QTextBlock block = doc->begin();
+ QVERIFY(block.isValid());
+
+ QTextBlock::Iterator it = block.begin();
+ QCOMPARE(it.fragment().position(), 0);
+ ++it;
+ QCOMPARE(it.fragment().position(), 1);
+ ++it;
+
+ QCOMPARE(it.fragment().position(), 2);
+
+ --it;
+ QCOMPARE(it.fragment().position(), 1);
+ --it;
+ QCOMPARE(it.fragment().position(), 0);
+}
+
+void tst_QTextBlock::previousBlock_qtbug18026()
+{
+ QTextBlock last = doc->end().previous();
+ QVERIFY(last.isValid());
+}
+
+void tst_QTextBlock::removedBlock_qtbug18500()
+{
+ cursor.insertText("line 1\nline 2\nline 3 \nline 4\n");
+ cursor.setPosition(7);
+ QTextBlock block = cursor.block();
+ cursor.setPosition(21, QTextCursor::KeepAnchor);
+
+ cursor.removeSelectedText();
+ QVERIFY(!block.isValid());
+}
+
+QTEST_MAIN(tst_QTextBlock)
+#include "tst_qtextblock.moc"
diff --git a/tests/auto/gui/text/qtextcursor/.gitignore b/tests/auto/gui/text/qtextcursor/.gitignore
new file mode 100644
index 0000000000..b9b1f8e7d6
--- /dev/null
+++ b/tests/auto/gui/text/qtextcursor/.gitignore
@@ -0,0 +1 @@
+tst_qtextcursor
diff --git a/tests/auto/gui/text/qtextcursor/qtextcursor.pro b/tests/auto/gui/text/qtextcursor/qtextcursor.pro
new file mode 100644
index 0000000000..828b90ca16
--- /dev/null
+++ b/tests/auto/gui/text/qtextcursor/qtextcursor.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qtextcursor.cpp
+
+
+
diff --git a/tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp b/tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp
new file mode 100644
index 0000000000..2b0ba422e0
--- /dev/null
+++ b/tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp
@@ -0,0 +1,1862 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qtextdocument.h>
+#include <qtexttable.h>
+#include <qvariant.h>
+#include <qtextdocumentfragment.h>
+#include <qabstracttextdocumentlayout.h>
+#include <qtextlayout.h>
+#include <qtextcursor.h>
+#include <qdebug.h>
+
+//TESTED_FILES=gui/text/qtextcursor.cpp gui/text/qtextcursor_p.h
+
+QT_FORWARD_DECLARE_CLASS(QTextDocument)
+
+class tst_QTextCursor : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTextCursor();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void navigation1();
+ void navigation2_data();
+ void navigation2();
+ void navigation3();
+ void navigation4();
+ void navigation5();
+ void navigation6();
+ void navigation7();
+ void navigation8();
+ void navigation9();
+ void navigation10();
+ void movePositionEndOfLine();
+ void insertBlock();
+ void insertWithBlockSeparator1();
+ void insertWithBlockSeparator2();
+ void insertWithBlockSeparator3();
+ void insertWithBlockSeparator4();
+ void clearObjectType1();
+ void clearObjectType2();
+ void clearObjectType3();
+ void comparisonOperators1();
+ void comparisonOperators2();
+ void selection1();
+ void dontCopyTableAttributes();
+
+ void checkFrame1();
+ void checkFrame2();
+
+ void tableMovement();
+ void selectionsInTable();
+
+ void insertBlockToUseCharFormat();
+
+ void selectedText();
+
+ void insertBlockShouldRemoveSelection();
+ void insertBlockShouldRemoveSelection2();
+ void mergeCellShouldUpdateSelection();
+
+ void joinPreviousEditBlock();
+
+ void setBlockFormatInTable();
+
+ void blockCharFormat();
+ void blockCharFormat2();
+ void blockCharFormat3();
+ void blockCharFormatOnSelection();
+
+ void anchorInitialized1();
+ void anchorInitialized2();
+ void anchorInitialized3();
+
+ void selectWord();
+ void selectWordWithSeparators_data();
+ void selectWordWithSeparators();
+ void startOfWord();
+ void selectBlock();
+ void selectVisually();
+
+ void insertText();
+
+ void insertFragmentShouldUseCurrentCharFormat();
+
+ void endOfLine();
+
+ void editBlocksDuringRemove();
+ void selectAllDuringRemove();
+
+ void update_data();
+ void update();
+
+ void disallowSettingObjectIndicesOnCharFormats();
+
+ void blockAndColumnNumber();
+
+ void clearCells();
+
+ void task244408_wordUnderCursor_data();
+ void task244408_wordUnderCursor();
+
+ void adjustCursorsOnInsert();
+
+ void cursorPositionWithBlockUndoAndRedo();
+ void cursorPositionWithBlockUndoAndRedo2();
+ void cursorPositionWithBlockUndoAndRedo3();
+
+private:
+ int blockCount();
+
+ QTextDocument *doc;
+ QTextCursor cursor;
+};
+
+Q_DECLARE_METATYPE(QList<QVariant>)
+
+tst_QTextCursor::tst_QTextCursor()
+{}
+
+void tst_QTextCursor::init()
+{
+ doc = new QTextDocument;
+ cursor = QTextCursor(doc);
+}
+
+void tst_QTextCursor::cleanup()
+{
+ cursor = QTextCursor();
+ delete doc;
+ doc = 0;
+}
+
+void tst_QTextCursor::navigation1()
+{
+
+ cursor.insertText("Hello World");
+ QVERIFY(doc->toPlainText() == "Hello World");
+
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.position() == 11);
+ cursor.deletePreviousChar();
+ QVERIFY(cursor.position() == 10);
+ cursor.deletePreviousChar();
+ cursor.deletePreviousChar();
+ cursor.deletePreviousChar();
+ cursor.deletePreviousChar();
+ cursor.deletePreviousChar();
+ QVERIFY(doc->toPlainText() == "Hello");
+
+ QTextCursor otherCursor(doc);
+ otherCursor.movePosition(QTextCursor::Start);
+ otherCursor.movePosition(QTextCursor::Right);
+ cursor = otherCursor;
+ cursor.movePosition(QTextCursor::Right);
+ QVERIFY(cursor != otherCursor);
+ otherCursor.insertText("Hey");
+ QVERIFY(cursor.position() == 5);
+
+ doc->undo();
+ QVERIFY(cursor.position() == 2);
+ doc->redo();
+ QVERIFY(cursor.position() == 5);
+
+ doc->undo();
+
+ doc->undo();
+ QVERIFY(doc->toPlainText() == "Hello World");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 6);
+ QVERIFY(cursor.position() == 6);
+ otherCursor = cursor;
+ otherCursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 2);
+ otherCursor.deletePreviousChar();
+ otherCursor.deletePreviousChar();
+ otherCursor.deletePreviousChar();
+ QVERIFY(cursor.position() == 5);
+
+ cursor.movePosition(QTextCursor::End);
+ cursor.insertBlock();
+ {
+ int oldPos = cursor.position();
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.position() == oldPos);
+ }
+ QVERIFY(cursor.atBlockStart());
+ QVERIFY(cursor.position() == 9);
+
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ cursor.insertText("Test", fmt);
+ QVERIFY(fmt == cursor.charFormat());
+ QVERIFY(cursor.position() == 13);
+}
+
+void tst_QTextCursor::navigation2_data()
+{
+ QTest::addColumn<QStringList>("sl");
+ QTest::addColumn<QList<QVariant> >("movement");
+ QTest::addColumn<int>("finalPos");
+
+ QTest::newRow("startBlock1") << QStringList("Happy happy happy joy joy joy")
+ << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)) << 0;
+ QTest::newRow("endBlock1") << QStringList("Happy happy happy joy joy joy")
+ << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
+ << QVariant(QTextCursor::EndOfBlock)) << 29;
+ QTest::newRow("startBlock2") << QStringList("Happy happy happy joy joy joy")
+ << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
+ << QVariant(QTextCursor::EndOfBlock)
+ << QVariant(QTextCursor::StartOfBlock)) << 0;
+ QTest::newRow("endBlock2") << QStringList("Happy happy happy joy joy joy")
+ << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
+ << QVariant(QTextCursor::EndOfBlock)
+ << QVariant(QTextCursor::StartOfBlock)
+ << QVariant(QTextCursor::EndOfBlock)
+ ) << 29;
+ QTest::newRow("multiBlock1") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock))
+ << 18;
+ QTest::newRow("multiBlock2") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
+ << QVariant(QTextCursor::EndOfBlock))
+ << 29;
+ QTest::newRow("multiBlock3") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
+ << QVariant(QTextCursor::StartOfBlock))
+ << 18;
+ QTest::newRow("multiBlock4") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::Start)
+ << QVariant(QTextCursor::EndOfBlock))
+ << 17;
+ QTest::newRow("multiBlock5") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::Start)
+ << QVariant(QTextCursor::EndOfBlock)
+ << QVariant(QTextCursor::EndOfBlock))
+ << 17;
+ QTest::newRow("multiBlock6") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::End)
+ << QVariant(QTextCursor::StartOfBlock))
+ << 18;
+ QTest::newRow("multiBlock7") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock))
+ << 0;
+ QTest::newRow("multiBlock8") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
+ << QVariant(QTextCursor::EndOfBlock))
+ << 17;
+ QTest::newRow("multiBlock9") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
+ << QVariant(QTextCursor::NextBlock))
+ << 18;
+ QTest::newRow("multiBlock10") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
+ << QVariant(QTextCursor::NextBlock)
+ << QVariant(QTextCursor::NextBlock))
+ << 18;
+ QTest::newRow("multiBlock11") << (QStringList() << QString("Happy happy happy")
+ << QString("Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
+ << QVariant(QTextCursor::NextBlock)
+ << QVariant(QTextCursor::EndOfBlock))
+ << 29;
+ QTest::newRow("PreviousWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord))
+ << 26;
+ QTest::newRow("PreviousWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
+ << QVariant(QTextCursor::PreviousWord))
+ << 22;
+ QTest::newRow("EndWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
+ << QVariant(QTextCursor::PreviousWord)
+ << QVariant(QTextCursor::EndOfWord))
+ << 25;
+ QTest::newRow("NextWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
+ << QVariant(QTextCursor::PreviousWord)
+ << QVariant(QTextCursor::NextWord))
+ << 26;
+ QTest::newRow("NextWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::Start)
+ << QVariant(QTextCursor::NextWord)
+ << QVariant(QTextCursor::EndOfWord))
+ << 11;
+ QTest::newRow("StartWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
+ << QVariant(QTextCursor::PreviousWord)
+ << QVariant(QTextCursor::StartOfWord))
+ << 22;
+ QTest::newRow("StartWord3") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::Start)
+ << QVariant(QTextCursor::NextWord)
+ << QVariant(QTextCursor::EndOfWord)
+ << QVariant(QTextCursor::StartOfWord))
+ << 6;
+
+ QTest::newRow("PreviousCharacter") << (QStringList() << QString("Happy happy Joy Joy"))
+ << (QList<QVariant>() << QVariant(QTextCursor::PreviousCharacter)
+ << QVariant(QTextCursor::PreviousCharacter))
+ << 17;
+}
+
+void tst_QTextCursor::navigation2()
+{
+ QFETCH(QStringList, sl);
+ QFETCH(QList<QVariant>, movement);
+ int i;
+ for (i = 0; i < sl.size(); ++i) {
+ cursor.insertText(sl.at(i));
+ if (i < sl.size() - 1)
+ cursor.insertBlock();
+ }
+
+ for (i = 0; i < movement.size(); ++i)
+ cursor.movePosition(QTextCursor::MoveOperation(movement.at(i).toInt()));
+ QTEST(cursor.position(), "finalPos");
+}
+
+void tst_QTextCursor::navigation3()
+{
+ cursor.insertText("a");
+ cursor.deletePreviousChar();
+ QCOMPARE(cursor.position(), 0);
+ QVERIFY(doc->toPlainText().isEmpty());
+}
+
+void tst_QTextCursor::navigation4()
+{
+ cursor.insertText(" Test ");
+
+ cursor.setPosition(4);
+ cursor.movePosition(QTextCursor::EndOfWord);
+ QCOMPARE(cursor.position(), 6);
+}
+
+void tst_QTextCursor::navigation5()
+{
+ cursor.insertText("Test");
+ cursor.insertBlock();
+ cursor.insertText("Test");
+
+ cursor.setPosition(0);
+ cursor.movePosition(QTextCursor::EndOfBlock);
+ QCOMPARE(cursor.position(), 4);
+}
+
+void tst_QTextCursor::navigation6()
+{
+ // triger creation of document layout, so that QTextLines are there
+ doc->documentLayout();
+ doc->setTextWidth(1000);
+
+ cursor.insertText("Test ");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::EndOfLine);
+ QCOMPARE(cursor.position(), 8);
+}
+
+void tst_QTextCursor::navigation7()
+{
+ QVERIFY(doc->isEmpty());
+ for (int i = QTextCursor::Start; i <= QTextCursor::WordRight; ++i)
+ QVERIFY(!cursor.movePosition(QTextCursor::MoveOperation(i)));
+
+ doc->setPlainText("Hello World");
+ cursor.movePosition(QTextCursor::Start);
+ do {
+ } while (cursor.movePosition(QTextCursor::NextCharacter));
+ QVERIFY(true /*reached*/);
+}
+
+void tst_QTextCursor::navigation8()
+{
+ cursor.insertList(QTextListFormat::ListDecimal);
+ QCOMPARE(cursor.position(), 1);
+ cursor.insertText("foo");
+ QCOMPARE(cursor.position(), 4);
+
+ cursor.insertList(QTextListFormat::ListCircle);
+ QCOMPARE(cursor.position(), 5);
+ cursor.insertText("something");
+ QCOMPARE(cursor.position(), 14);
+
+ cursor.movePosition(QTextCursor::PreviousCharacter);
+ QCOMPARE(cursor.position(), 13);
+
+ cursor.setPosition(2);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.position(), 3);
+}
+
+void tst_QTextCursor::navigation9()
+{
+ cursor.insertText("Hello &-=+\t World");
+ cursor.movePosition(QTextCursor::PreviousWord);
+ QCOMPARE(cursor.position(), 15);
+ cursor.movePosition(QTextCursor::PreviousWord);
+ QCOMPARE(cursor.position(), 7);
+ cursor.movePosition(QTextCursor::PreviousWord);
+ QCOMPARE(cursor.position(), 0);
+ cursor.movePosition(QTextCursor::NextWord);
+ QCOMPARE(cursor.position(), 7);
+ cursor.movePosition(QTextCursor::NextWord);
+ QCOMPARE(cursor.position(), 15);
+}
+
+void tst_QTextCursor::navigation10()
+{
+ doc->setHtml("<html><p>just a simple paragraph.</p>"
+ "<table>"
+ "<tr><td>Cell number 1</td><td>another cell</td><td></td><td>previous</br>is</br>empty</td></tr>"
+ "<tr><td>row 2</td><td colspan=\"2\">foo bar</td><td>last cell</td></tr>"
+ "<tr><td colspan=\"3\">row 3</td><td>a</td></tr>"
+ "</table></html");
+ QCOMPARE(cursor.position(), 101); // end of document
+ cursor.setPosition(0);
+ QCOMPARE(cursor.position(), 0);
+ bool ok = cursor.movePosition(QTextCursor::EndOfLine);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 24);
+ ok = cursor.movePosition(QTextCursor::NextBlock);
+ QCOMPARE(cursor.position(), 25); // cell 1
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 39); // another..
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 52); // empty
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 53); // last on row 1
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 69); // row 2
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 75);
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 83);
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 93); // row 3
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 99);
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok == false);
+ QCOMPARE(cursor.position(), 99); // didn't move.
+ QVERIFY(cursor.currentTable());
+
+ // same thing in reverse...
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 93);
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 83);
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 75);
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 69);
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 53);
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 52);
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 39);
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 25);
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(!ok);
+ QCOMPARE(cursor.position(), 25); // can't leave the table
+
+ ok = cursor.movePosition(QTextCursor::NextRow);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 69);
+ ok = cursor.movePosition(QTextCursor::NextRow);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 93);
+ ok = cursor.movePosition(QTextCursor::NextRow);
+ QVERIFY(!ok);
+ QCOMPARE(cursor.position(), 93); // didn't move
+
+ ok = cursor.movePosition(QTextCursor::PreviousRow);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 83); // last col in row 2
+ ok = cursor.movePosition(QTextCursor::PreviousRow);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 53); // last col in row 1
+ ok = cursor.movePosition(QTextCursor::PreviousRow);
+ QVERIFY(!ok);
+ QCOMPARE(cursor.position(), 53);
+
+ // test usecase of jumping over a cell
+ doc->clear();
+ doc->setHtml("<html><table>tr><td rowspan=\"2\">a</td><td>b</td></tr><tr><td>c</td></tr></table></html>");
+ cursor.setPosition(1); // a
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 3); // b
+ ok = cursor.movePosition(QTextCursor::NextCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 5); // c
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 3); // b
+ ok = cursor.movePosition(QTextCursor::PreviousCell);
+ QVERIFY(ok);
+ QCOMPARE(cursor.position(), 1); // a
+}
+
+void tst_QTextCursor::insertBlock()
+{
+ QTextBlockFormat fmt;
+ fmt.setTopMargin(100);
+ cursor.insertBlock(fmt);
+ QVERIFY(cursor.position() == 1);
+ QVERIFY(cursor.blockFormat() == fmt);
+}
+
+void tst_QTextCursor::insertWithBlockSeparator1()
+{
+ QString text = "Hello" + QString(QChar::ParagraphSeparator) + "World";
+
+ cursor.insertText(text);
+
+ cursor.movePosition(QTextCursor::PreviousBlock);
+ QVERIFY(cursor.position() == 0);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.position() == 6);
+}
+
+void tst_QTextCursor::insertWithBlockSeparator2()
+{
+ cursor.insertText(QString(QChar::ParagraphSeparator));
+ QVERIFY(cursor.position() == 1);
+}
+
+void tst_QTextCursor::insertWithBlockSeparator3()
+{
+ cursor.insertText(QString(QChar::ParagraphSeparator) + "Hi" + QString(QChar::ParagraphSeparator));
+ QVERIFY(cursor.position() == 4);
+}
+
+void tst_QTextCursor::insertWithBlockSeparator4()
+{
+ cursor.insertText(QString(QChar::ParagraphSeparator) + QString(QChar::ParagraphSeparator));
+ QVERIFY(cursor.position() == 2);
+}
+
+void tst_QTextCursor::clearObjectType1()
+{
+ cursor.insertImage("test.png");
+ QVERIFY(cursor.charFormat().isValid());
+ QVERIFY(cursor.charFormat().isImageFormat());
+ cursor.insertText("Hey");
+ QVERIFY(cursor.charFormat().isValid());
+ QVERIFY(!cursor.charFormat().isImageFormat());
+}
+
+void tst_QTextCursor::clearObjectType2()
+{
+ cursor.insertImage("test.png");
+ QVERIFY(cursor.charFormat().isValid());
+ QVERIFY(cursor.charFormat().isImageFormat());
+ cursor.insertBlock();
+ QVERIFY(cursor.charFormat().isValid());
+ QVERIFY(!cursor.charFormat().isImageFormat());
+}
+
+void tst_QTextCursor::clearObjectType3()
+{
+ // like clearObjectType2 but tests different insertBlock overload
+ cursor.insertImage("test.png");
+ QVERIFY(cursor.charFormat().isValid());
+ QVERIFY(cursor.charFormat().isImageFormat());
+ QTextBlockFormat bfmt;
+ bfmt.setAlignment(Qt::AlignRight);
+ cursor.insertBlock(bfmt);
+ QVERIFY(cursor.charFormat().isValid());
+ QVERIFY(!cursor.charFormat().isImageFormat());
+}
+
+void tst_QTextCursor::comparisonOperators1()
+{
+ cursor.insertText("Hello World");
+
+ cursor.movePosition(QTextCursor::PreviousWord);
+
+ QTextCursor startCursor = cursor;
+ startCursor.movePosition(QTextCursor::Start);
+
+ QVERIFY(startCursor < cursor);
+
+ QTextCursor midCursor = startCursor;
+ midCursor.movePosition(QTextCursor::NextWord);
+
+ QVERIFY(midCursor <= cursor);
+ QVERIFY(midCursor == cursor);
+ QVERIFY(midCursor >= cursor);
+
+ QVERIFY(midCursor > startCursor);
+
+ QVERIFY(midCursor != startCursor);
+ QVERIFY(!(midCursor == startCursor));
+
+ QTextCursor nullCursor;
+
+ QVERIFY(!(startCursor < nullCursor));
+ QVERIFY(!(nullCursor < nullCursor));
+ QVERIFY(nullCursor < startCursor);
+
+ QVERIFY(nullCursor <= startCursor);
+ QVERIFY(!(startCursor <= nullCursor));
+
+ QVERIFY(!(nullCursor >= startCursor));
+ QVERIFY(startCursor >= nullCursor);
+
+ QVERIFY(!(nullCursor > startCursor));
+ QVERIFY(!(nullCursor > nullCursor));
+ QVERIFY(startCursor > nullCursor);
+}
+
+void tst_QTextCursor::comparisonOperators2()
+{
+ QTextDocument doc1;
+ QTextDocument doc2;
+
+ QTextCursor cursor1(&doc1);
+ QTextCursor cursor2(&doc2);
+
+ QVERIFY(cursor1 != cursor2);
+ QVERIFY(cursor1 == QTextCursor(&doc1));
+}
+
+void tst_QTextCursor::selection1()
+{
+ cursor.insertText("Hello World");
+
+ cursor.setPosition(0);
+ cursor.clearSelection();
+ cursor.setPosition(4, QTextCursor::KeepAnchor);
+
+ QCOMPARE(cursor.selectionStart(), 0);
+ QCOMPARE(cursor.selectionEnd(), 4);
+}
+
+void tst_QTextCursor::dontCopyTableAttributes()
+{
+ /* when pressing 'enter' inside a cell it shouldn't
+ * enlarge the table by adding another cell but just
+ * extend the cell */
+ QTextTable *table = cursor.insertTable(2, 2);
+ QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
+ cursor.insertBlock();
+ QCOMPARE(table->columns(), 2);
+}
+
+void tst_QTextCursor::checkFrame1()
+{
+ QVERIFY(cursor.position() == 0);
+ QPointer<QTextFrame> frame = cursor.insertFrame(QTextFrameFormat());
+ QVERIFY(frame != 0);
+
+ QTextFrame *root = frame->parentFrame();
+ QVERIFY(root != 0);
+
+ QVERIFY(frame->firstPosition() == 1);
+ QVERIFY(frame->lastPosition() == 1);
+ QVERIFY(frame->parentFrame() != 0);
+ QVERIFY(root->childFrames().size() == 1);
+
+ QVERIFY(cursor.position() == 1);
+ QVERIFY(cursor.selectionStart() == 1);
+ QVERIFY(cursor.selectionEnd() == 1);
+
+ doc->undo();
+
+ QVERIFY(!frame);
+ QVERIFY(root->childFrames().size() == 0);
+
+ QVERIFY(cursor.position() == 0);
+ QVERIFY(cursor.selectionStart() == 0);
+ QVERIFY(cursor.selectionEnd() == 0);
+
+ doc->redo();
+
+ frame = doc->frameAt(1);
+
+ QVERIFY(frame);
+ QVERIFY(frame->firstPosition() == 1);
+ QVERIFY(frame->lastPosition() == 1);
+ QVERIFY(frame->parentFrame() != 0);
+ QVERIFY(root->childFrames().size() == 1);
+
+ QVERIFY(cursor.position() == 1);
+ QVERIFY(cursor.selectionStart() == 1);
+ QVERIFY(cursor.selectionEnd() == 1);
+
+// cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
+// QVERIFY(cursor.position() == 2);
+// QVERIFY(cursor.selectionStart() == 0);
+// QVERIFY(cursor.selectionEnd() == 2);
+}
+
+void tst_QTextCursor::checkFrame2()
+{
+ QVERIFY(cursor.position() == 0);
+ cursor.insertText("A");
+ QVERIFY(cursor.position() == 1);
+ cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
+
+ QPointer<QTextFrame> frame = cursor.insertFrame(QTextFrameFormat());
+ QTextFrame *root = frame->parentFrame();
+
+ QVERIFY(frame->firstPosition() == 1);
+ QVERIFY(frame->lastPosition() == 2);
+ QVERIFY(frame->parentFrame() != 0);
+ QVERIFY(root->childFrames().size() == 1);
+
+ QVERIFY(cursor.position() == 1);
+ QVERIFY(cursor.selectionStart() == 1);
+ QVERIFY(cursor.selectionEnd() == 2);
+
+ doc->undo();
+
+ QVERIFY(!frame);
+ QVERIFY(root->childFrames().size() == 0);
+
+ QVERIFY(cursor.position() == 0);
+ QVERIFY(cursor.selectionStart() == 0);
+ QVERIFY(cursor.selectionEnd() == 1);
+
+ doc->redo();
+
+ frame = doc->frameAt(1);
+
+ QVERIFY(frame);
+ QVERIFY(frame->firstPosition() == 1);
+ QVERIFY(frame->lastPosition() == 2);
+ QVERIFY(frame->parentFrame() != 0);
+ QVERIFY(root->childFrames().size() == 1);
+
+ QVERIFY(cursor.position() == 1);
+ QVERIFY(cursor.selectionStart() == 1);
+ QVERIFY(cursor.selectionEnd() == 2);
+
+ cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor);
+ QVERIFY(cursor.position() == 0);
+ QVERIFY(cursor.selectionStart() == 0);
+ QVERIFY(cursor.selectionEnd() == 3);
+}
+
+void tst_QTextCursor::insertBlockToUseCharFormat()
+{
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ cursor.insertText("Hello", fmt);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
+
+ cursor.insertBlock();
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
+
+ fmt.setForeground(Qt::red);
+ cursor.insertText("Hello\nWorld", fmt);
+ cursor.insertText("Blah");
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
+
+ // ### we might want a testcase for createTable, too, as it calls insertBlock, too,
+ // and we might want to have the char format copied (the one that gets inserted
+ // as table separators, that are undeletable)
+}
+
+void tst_QTextCursor::tableMovement()
+{
+ QVERIFY(cursor.position() == 0);
+ cursor.insertText("AA");
+ QVERIFY(cursor.position() == 2);
+ cursor.movePosition(QTextCursor::Left);
+
+ cursor.insertTable(3, 3);
+ QCOMPARE(cursor.position(), 2);
+
+ cursor.movePosition(QTextCursor::Down);
+ QCOMPARE(cursor.position(), 5);
+
+ cursor.movePosition(QTextCursor::Right);
+ QCOMPARE(cursor.position(), 6);
+
+ cursor.movePosition(QTextCursor::Up);
+ QCOMPARE(cursor.position(), 3);
+
+ cursor.movePosition(QTextCursor::Right);
+ QCOMPARE(cursor.position(), 4);
+
+ cursor.movePosition(QTextCursor::Right);
+ QCOMPARE(cursor.position(), 5);
+
+ cursor.movePosition(QTextCursor::Up);
+ QCOMPARE(cursor.position(), 2);
+
+ cursor.movePosition(QTextCursor::Up);
+ QCOMPARE(cursor.position(), 0);
+
+}
+
+void tst_QTextCursor::selectionsInTable()
+{
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+
+ cursor = table->cellAt(0, 0).lastCursorPosition();
+ QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
+ QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor) == false);
+
+ cursor = table->cellAt(1, 0).lastCursorPosition();
+ QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
+ QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor) == false);
+
+ cursor = table->cellAt(0, 1).firstCursorPosition();
+ QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
+ QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor) == false);
+
+ cursor = table->cellAt(1, 1).firstCursorPosition();
+ QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
+ QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor) == false);
+}
+
+void tst_QTextCursor::selectedText()
+{
+ cursor.insertText("Hello World");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+
+ QCOMPARE(cursor.selectedText(), QString("Hello World"));
+}
+
+void tst_QTextCursor::insertBlockShouldRemoveSelection()
+{
+ cursor.insertText("Hello World");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selectedText(), QString("Hello"));
+
+ cursor.insertBlock();
+
+ QVERIFY(!cursor.hasSelection());
+ QVERIFY(doc->toPlainText().indexOf("Hello") == -1);
+}
+
+void tst_QTextCursor::insertBlockShouldRemoveSelection2()
+{
+ cursor.insertText("Hello World");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selectedText(), QString("Hello"));
+
+ QTextBlockFormat fmt = cursor.blockFormat();
+ cursor.insertBlock(fmt);
+
+ QVERIFY(!cursor.hasSelection());
+ QVERIFY(doc->toPlainText().indexOf("Hello") == -1);
+}
+
+void tst_QTextCursor::mergeCellShouldUpdateSelection()
+{
+ QTextTable *table = cursor.insertTable(4, 4);
+ cursor.setPosition(table->cellAt(0, 0).firstPosition());
+ cursor.setPosition(table->cellAt(3, 0).firstPosition(), QTextCursor::KeepAnchor); // aka bottom left
+ int firstRow, numRows, firstColumn, numColumns;
+ cursor.selectedTableCells(&firstRow, &numRows, &firstColumn, &numColumns);
+ QCOMPARE(firstRow, 0);
+ QCOMPARE(numRows, 4);
+ QCOMPARE(firstColumn, 0);
+ QCOMPARE(numColumns, 1);
+
+ table->removeColumns(firstColumn, numColumns);
+
+ QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
+ QCOMPARE(cursor.position(), table->cellAt(0, 0).firstPosition());
+ QCOMPARE(cursor.position(), cursor.anchor()); // empty. I don't really care where it ends up.
+
+ // prepare for another test with multiple cursors.
+ // note we have a 4 rows, 3 cols table now.
+ cursor.setPosition(table->cellAt(0, 0).firstPosition());
+ cursor.setPosition(table->cellAt(0, 2).firstPosition(), QTextCursor::KeepAnchor);
+
+ // now create a selection of a whole row.
+ QTextCursor c2 = table->cellAt(2, 0).firstCursorPosition();
+ c2.setPosition(table->cellAt(2, 2).firstPosition(), QTextCursor::KeepAnchor);
+
+ // just for good measure, another one for a block of cells.
+ QTextCursor c3 = table->cellAt(2, 1).firstCursorPosition();
+ c3.setPosition(table->cellAt(3, 2).firstPosition(), QTextCursor::KeepAnchor);
+
+ table->removeRows(2, 1);
+
+ QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
+ QCOMPARE(cursor.position(), table->cellAt(0, 2).firstPosition());
+
+ QCOMPARE(c2.position(), c2.anchor()); // empty. I don't really care where it ends up.
+
+ QCOMPARE(c3.anchor(), table->cellAt(2, 1).firstPosition());
+ QCOMPARE(c3.position(), table->cellAt(2, 2).firstPosition());
+
+
+ // prepare for another test where we remove a column
+ // note we have a 3 rows, 3 cols table now.
+ cursor.setPosition(table->cellAt(0, 0).firstPosition());
+ cursor.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
+
+ c2.setPosition(table->cellAt(0, 1).firstPosition());
+ c2.setPosition(table->cellAt(2, 2).firstPosition(), QTextCursor::KeepAnchor);
+
+ table->removeColumns(1, 1);
+
+ QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
+ QCOMPARE(cursor.position(), table->cellAt(2, 0).firstPosition());
+
+ QCOMPARE(c2.anchor(), table->cellAt(0, 1).firstPosition());
+ QCOMPARE(c2.position(), table->cellAt(2, 1).firstPosition());
+
+ // test for illegal cursor positions.
+ // note we have a 3 rows, 2 cols table now.
+ cursor.setPosition(table->cellAt(2, 0).firstPosition());
+ cursor.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
+
+ c2.setPosition(table->cellAt(0, 0).firstPosition());
+ c2.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
+
+ c3.setPosition(table->cellAt(2, 1).firstPosition());
+
+ table->removeRows(2, 1);
+
+ QCOMPARE(cursor.anchor(), table->cellAt(1, 1).lastPosition()+1);
+ QCOMPARE(cursor.position(), cursor.anchor());
+
+ QCOMPARE(c2.anchor(), table->cellAt(0, 0).firstPosition());
+ QCOMPARE(c2.position(), table->cellAt(1, 1).firstPosition());
+
+ QCOMPARE(c3.anchor(), table->cellAt(1, 1).firstPosition());
+ QCOMPARE(c3.position(), table->cellAt(1, 1).firstPosition());
+}
+
+void tst_QTextCursor::joinPreviousEditBlock()
+{
+ cursor.beginEditBlock();
+ cursor.insertText("Hello");
+ cursor.insertText("World");
+ cursor.endEditBlock();
+ QVERIFY(doc->toPlainText().startsWith("HelloWorld"));
+
+ cursor.joinPreviousEditBlock();
+ cursor.insertText("Hey");
+ cursor.endEditBlock();
+ QVERIFY(doc->toPlainText().startsWith("HelloWorldHey"));
+
+ doc->undo();
+ QVERIFY(!doc->toPlainText().contains("HelloWorldHey"));
+}
+
+void tst_QTextCursor::setBlockFormatInTable()
+{
+ // someone reported this on qt4-preview-feedback
+ QTextBlockFormat fmt;
+ fmt.setBackground(Qt::blue);
+ cursor.setBlockFormat(fmt);
+
+ QTextTable *table = cursor.insertTable(2, 2);
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ fmt.setBackground(Qt::red);
+ cursor.setBlockFormat(fmt);
+
+ cursor.movePosition(QTextCursor::Start);
+ QVERIFY(cursor.blockFormat().background().color() == Qt::blue);
+}
+
+void tst_QTextCursor::blockCharFormat2()
+{
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::green);
+ cursor.mergeBlockCharFormat(fmt);
+
+ fmt.setForeground(Qt::red);
+
+ cursor.insertText("Test", fmt);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.insertText("Red");
+ cursor.movePosition(QTextCursor::PreviousCharacter);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
+}
+
+void tst_QTextCursor::blockCharFormat3()
+{
+ QVERIFY(cursor.atBlockStart());
+ QVERIFY(cursor.atBlockEnd());
+ QVERIFY(cursor.atStart());
+
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::green);
+ cursor.setBlockCharFormat(fmt);
+ cursor.insertText("Test");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
+
+ cursor.movePosition(QTextCursor::Start);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
+
+ fmt.setForeground(Qt::red);
+ cursor.setBlockCharFormat(fmt);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
+
+ cursor.movePosition(QTextCursor::End);
+ cursor.movePosition(QTextCursor::Start);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
+
+ cursor.insertText("Test");
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
+
+ cursor.select(QTextCursor::Document);
+ cursor.removeSelectedText();
+ QVERIFY(cursor.atBlockStart());
+ QVERIFY(cursor.atBlockEnd());
+ QVERIFY(cursor.atStart());
+
+ cursor.insertText("Test");
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
+}
+
+void tst_QTextCursor::blockCharFormat()
+{
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ cursor.insertBlock(QTextBlockFormat(), fmt);
+ cursor.insertText("Hm");
+
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue);
+
+ fmt.setForeground(Qt::red);
+
+ cursor.setBlockCharFormat(fmt);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
+}
+
+void tst_QTextCursor::blockCharFormatOnSelection()
+{
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ cursor.insertBlock(QTextBlockFormat(), fmt);
+
+ fmt.setForeground(Qt::green);
+ cursor.insertText("Hm", fmt);
+
+ fmt.setForeground(Qt::red);
+ cursor.insertBlock(QTextBlockFormat(), fmt);
+ cursor.insertText("Ah");
+
+ fmt.setForeground(Qt::white);
+ cursor.insertBlock(QTextBlockFormat(), fmt);
+ cursor.insertText("bleh");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::white);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
+
+ fmt.setForeground(Qt::cyan);
+ cursor.setBlockCharFormat(fmt);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::cyan);
+
+ cursor.movePosition(QTextCursor::Right);
+ cursor.movePosition(QTextCursor::Right);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::cyan);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::white);
+}
+
+void tst_QTextCursor::anchorInitialized1()
+{
+ cursor.insertBlock();
+ cursor = QTextCursor(cursor.block());
+ QCOMPARE(cursor.position(), 1);
+ QCOMPARE(cursor.anchor(), 1);
+ QCOMPARE(cursor.selectionStart(), 1);
+ QCOMPARE(cursor.selectionEnd(), 1);
+}
+
+void tst_QTextCursor::anchorInitialized2()
+{
+ cursor.insertBlock();
+ cursor = QTextCursor(cursor.block().docHandle(), 1);
+ QCOMPARE(cursor.position(), 1);
+ QCOMPARE(cursor.anchor(), 1);
+ QCOMPARE(cursor.selectionStart(), 1);
+ QCOMPARE(cursor.selectionEnd(), 1);
+}
+
+void tst_QTextCursor::anchorInitialized3()
+{
+ QTextFrame *frame = cursor.insertFrame(QTextFrameFormat());
+ cursor = QTextCursor(frame);
+ QCOMPARE(cursor.position(), 1);
+ QCOMPARE(cursor.anchor(), 1);
+ QCOMPARE(cursor.selectionStart(), 1);
+ QCOMPARE(cursor.selectionEnd(), 1);
+}
+
+void tst_QTextCursor::selectWord()
+{
+ cursor.insertText("first second third");
+ cursor.insertBlock();
+ cursor.insertText("words in second paragraph");
+
+ cursor.setPosition(9);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selectionStart(), 6);
+ QCOMPARE(cursor.selectionEnd(), 12);
+
+ cursor.setPosition(5);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selectionStart(), 0);
+ QCOMPARE(cursor.selectionEnd(), 5);
+
+ cursor.setPosition(6);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selectionStart(), 6);
+ QCOMPARE(cursor.selectionEnd(), 12);
+
+ cursor.setPosition(14);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selectionStart(), 6);
+ QCOMPARE(cursor.selectionEnd(), 12);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selectionStart(), 0);
+ QCOMPARE(cursor.selectionEnd(), 5);
+
+ cursor.movePosition(QTextCursor::EndOfBlock);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selectionStart(), 17);
+ QCOMPARE(cursor.selectionEnd(), 22);
+}
+
+void tst_QTextCursor::selectWordWithSeparators_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("initialPosition");
+ QTest::addColumn<QString>("expectedSelectedText");
+
+ QTest::newRow("dereference") << QString::fromLatin1("foo->bar()") << 1 << QString::fromLatin1("foo");
+ QTest::newRow("funcsignature") << QString::fromLatin1("bar(int x);") << 1 << QString::fromLatin1("bar");
+ QTest::newRow("def") << QString::fromLatin1("foo *f;") << 1 << QString::fromLatin1("foo");
+}
+
+void tst_QTextCursor::selectWordWithSeparators()
+{
+ QFETCH(QString, text);
+ QFETCH(int, initialPosition);
+ QFETCH(QString, expectedSelectedText);
+
+ cursor.insertText(text);
+ cursor.setPosition(initialPosition);
+ cursor.select(QTextCursor::WordUnderCursor);
+
+ QCOMPARE(cursor.selectedText(), expectedSelectedText);
+}
+
+void tst_QTextCursor::startOfWord()
+{
+ cursor.insertText("first second");
+ cursor.setPosition(7);
+ cursor.movePosition(QTextCursor::StartOfWord);
+ QCOMPARE(cursor.position(), 0);
+}
+
+void tst_QTextCursor::selectBlock()
+{
+ cursor.insertText("foobar");
+ QTextBlockFormat blockFmt;
+ blockFmt.setAlignment(Qt::AlignHCenter);
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("blah");
+ cursor.insertBlock(QTextBlockFormat());
+
+ cursor.movePosition(QTextCursor::PreviousBlock);
+ QCOMPARE(cursor.block().text(), QString("blah"));
+
+ cursor.select(QTextCursor::BlockUnderCursor);
+ QVERIFY(cursor.hasSelection());
+
+ QTextDocumentFragment fragment(cursor);
+ doc->clear();
+ cursor.insertFragment(fragment);
+ QCOMPARE(blockCount(), 2);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.blockFormat().alignment() == Qt::AlignHCenter);
+ QCOMPARE(cursor.block().text(), QString("blah"));
+}
+
+void tst_QTextCursor::selectVisually()
+{
+ cursor.insertText("Foo\nlong line which is probably going to be cut in two when shown in a widget\nparagraph 3\n");
+
+ cursor.setPosition(6); // somewhere in the long paragraph.
+ cursor.select(QTextCursor::LineUnderCursor);
+ // since we are not yet laid-out, we expect the whole paragraph to be selected.
+ QCOMPARE(cursor.position(), 77);
+ QCOMPARE(cursor.anchor(), 4);
+}
+
+void tst_QTextCursor::insertText()
+{
+ QString txt = "Foo\nBar\r\nMeep";
+ txt += QChar::LineSeparator;
+ txt += "Baz";
+ txt += QChar::ParagraphSeparator;
+ txt += "yoyodyne";
+ cursor.insertText(txt);
+ QCOMPARE(blockCount(), 4);
+ cursor.movePosition(QTextCursor::Start);
+ QCOMPARE(cursor.block().text(), QString("Foo"));
+ cursor.movePosition(QTextCursor::NextBlock);
+ QCOMPARE(cursor.block().text(), QString("Bar"));
+ cursor.movePosition(QTextCursor::NextBlock);
+ QCOMPARE(cursor.block().text(), QString(QString("Meep") + QChar(QChar::LineSeparator) + QString("Baz")));
+ cursor.movePosition(QTextCursor::NextBlock);
+ QCOMPARE(cursor.block().text(), QString("yoyodyne"));
+}
+
+void tst_QTextCursor::insertFragmentShouldUseCurrentCharFormat()
+{
+ QTextDocumentFragment fragment = QTextDocumentFragment::fromPlainText("Hello World");
+ QTextCharFormat fmt;
+ fmt.setFontUnderline(true);
+
+ cursor.clearSelection();
+ cursor.setCharFormat(fmt);
+ cursor.insertFragment(fragment);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat() == fmt);
+}
+
+int tst_QTextCursor::blockCount()
+{
+ int cnt = 0;
+ for (QTextBlock blk = doc->begin(); blk.isValid(); blk = blk.next())
+ ++cnt;
+ return cnt;
+}
+
+void tst_QTextCursor::endOfLine()
+{
+ doc->setPageSize(QSizeF(100000, INT_MAX));
+
+ QString text("First Line \nSecond Line ");
+ text.replace(QLatin1Char('\n'), QChar(QChar::LineSeparator));
+ cursor.insertText(text);
+
+ // ensure layouted
+ doc->documentLayout()->documentSize();
+
+ cursor.movePosition(QTextCursor::Start);
+
+ QCOMPARE(cursor.block().layout()->lineCount(), 2);
+
+ cursor.movePosition(QTextCursor::EndOfLine);
+ QCOMPARE(cursor.position(), 14);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.position(), 15);
+ cursor.movePosition(QTextCursor::EndOfLine);
+ QCOMPARE(cursor.position(), 28);
+}
+
+class CursorListener : public QObject
+{
+ Q_OBJECT
+public:
+ CursorListener(QTextCursor *_cursor) : lastRecordedPosition(-1), lastRecordedAnchor(-1), recordingCount(0), cursor(_cursor) {}
+
+ int lastRecordedPosition;
+ int lastRecordedAnchor;
+ int recordingCount;
+
+public slots:
+ void recordCursorPosition()
+ {
+ lastRecordedPosition = cursor->position();
+ lastRecordedAnchor = cursor->anchor();
+ ++recordingCount;
+ }
+
+ void selectAllContents()
+ {
+ // Only test the first time
+ if (!recordingCount) {
+ recordingCount++;
+ cursor->select(QTextCursor::Document);
+ lastRecordedPosition = cursor->position();
+ lastRecordedAnchor = cursor->anchor();
+ }
+ }
+
+private:
+ QTextCursor *cursor;
+};
+
+void tst_QTextCursor::editBlocksDuringRemove()
+{
+ CursorListener listener(&cursor);
+
+ cursor.insertText("Hello World");
+ cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
+ QCOMPARE(cursor.selectedText(), QString("Hello World"));
+
+ connect(doc, SIGNAL(contentsChanged()), &listener, SLOT(recordCursorPosition()));
+ listener.recordingCount = 0;
+ cursor.deleteChar();
+
+ QCOMPARE(listener.recordingCount, 1);
+ QCOMPARE(listener.lastRecordedPosition, 0);
+ QCOMPARE(listener.lastRecordedAnchor, 0);
+
+ QVERIFY(doc->toPlainText().isEmpty());
+}
+
+void tst_QTextCursor::selectAllDuringRemove()
+{
+ CursorListener listener(&cursor);
+
+ cursor.insertText("Hello World");
+ cursor.movePosition(QTextCursor::End);
+
+ connect(doc, SIGNAL(contentsChanged()), &listener, SLOT(selectAllContents()));
+ listener.recordingCount = 0;
+ QTextCursor localCursor = cursor;
+ localCursor.deletePreviousChar();
+
+ QCOMPARE(listener.lastRecordedPosition, 10);
+ QCOMPARE(listener.lastRecordedAnchor, 0);
+}
+
+void tst_QTextCursor::update_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("position");
+ QTest::addColumn<int>("anchor");
+ QTest::addColumn<int>("modifyPosition");
+ QTest::addColumn<int>("modifyAnchor");
+ QTest::addColumn<QString>("insertText");
+ QTest::addColumn<int>("expectedPosition");
+ QTest::addColumn<int>("expectedAnchor");
+
+ QString text("Hello big world");
+ int charsToDelete = 3;
+ QTest::newRow("removeInsideSelection")
+ << text
+ << /*position*/ 0
+ << /*anchor*/ text.length()
+ // delete 'big'
+ << 6
+ << 6 + charsToDelete
+ << QString() // don't insert anything, just remove
+ << /*expectedPosition*/ 0
+ << /*expectedAnchor*/ text.length() - charsToDelete
+ ;
+
+ text = "Hello big world";
+ charsToDelete = 3;
+ QTest::newRow("removeInsideSelectionWithSwappedAnchorAndPosition")
+ << text
+ << /*position*/ text.length()
+ << /*anchor*/ 0
+ // delete 'big'
+ << 6
+ << 6 + charsToDelete
+ << QString() // don't insert anything, just remove
+ << /*expectedPosition*/ text.length() - charsToDelete
+ << /*expectedAnchor*/ 0
+ ;
+
+
+ text = "Hello big world";
+ charsToDelete = 3;
+ QString textToInsert("small");
+ QTest::newRow("replaceInsideSelection")
+ << text
+ << /*position*/ 0
+ << /*anchor*/ text.length()
+ // delete 'big' ...
+ << 6
+ << 6 + charsToDelete
+ << textToInsert // ... and replace 'big' with 'small'
+ << /*expectedPosition*/ 0
+ << /*expectedAnchor*/ text.length() - charsToDelete + textToInsert.length()
+ ;
+
+ text = "Hello big world";
+ charsToDelete = 3;
+ textToInsert = "small";
+ QTest::newRow("replaceInsideSelectionWithSwappedAnchorAndPosition")
+ << text
+ << /*position*/ text.length()
+ << /*anchor*/ 0
+ // delete 'big' ...
+ << 6
+ << 6 + charsToDelete
+ << textToInsert // ... and replace 'big' with 'small'
+ << /*expectedPosition*/ text.length() - charsToDelete + textToInsert.length()
+ << /*expectedAnchor*/ 0
+ ;
+
+
+ text = "Hello big world";
+ charsToDelete = 3;
+ QTest::newRow("removeBeforeSelection")
+ << text
+ << /*position*/ text.length() - 5
+ << /*anchor*/ text.length()
+ // delete 'big'
+ << 6
+ << 6 + charsToDelete
+ << QString() // don't insert anything, just remove
+ << /*expectedPosition*/ text.length() - 5 - charsToDelete
+ << /*expectedAnchor*/ text.length() - charsToDelete
+ ;
+
+ text = "Hello big world";
+ charsToDelete = 3;
+ QTest::newRow("removeAfterSelection")
+ << text
+ << /*position*/ 0
+ << /*anchor*/ 4
+ // delete 'big'
+ << 6
+ << 6 + charsToDelete
+ << QString() // don't insert anything, just remove
+ << /*expectedPosition*/ 0
+ << /*expectedAnchor*/ 4
+ ;
+
+}
+
+void tst_QTextCursor::update()
+{
+ QFETCH(QString, text);
+
+ doc->setPlainText(text);
+
+ QFETCH(int, position);
+ QFETCH(int, anchor);
+
+ cursor.setPosition(anchor);
+ cursor.setPosition(position, QTextCursor::KeepAnchor);
+
+ QCOMPARE(cursor.position(), position);
+ QCOMPARE(cursor.anchor(), anchor);
+
+ QFETCH(int, modifyPosition);
+ QFETCH(int, modifyAnchor);
+
+ QTextCursor modifyCursor = cursor;
+ modifyCursor.setPosition(modifyAnchor);
+ modifyCursor.setPosition(modifyPosition, QTextCursor::KeepAnchor);
+
+ QCOMPARE(modifyCursor.position(), modifyPosition);
+ QCOMPARE(modifyCursor.anchor(), modifyAnchor);
+
+ QFETCH(QString, insertText);
+ modifyCursor.insertText(insertText);
+
+ QFETCH(int, expectedPosition);
+ QFETCH(int, expectedAnchor);
+
+ QCOMPARE(cursor.position(), expectedPosition);
+ QCOMPARE(cursor.anchor(), expectedAnchor);
+}
+
+void tst_QTextCursor::disallowSettingObjectIndicesOnCharFormats()
+{
+ QTextCharFormat fmt;
+ fmt.setObjectIndex(42);
+ cursor.insertText("Hey", fmt);
+ QCOMPARE(cursor.charFormat().objectIndex(), -1);
+
+ cursor.select(QTextCursor::Document);
+ cursor.mergeCharFormat(fmt);
+ QCOMPARE(doc->begin().begin().fragment().charFormat().objectIndex(), -1);
+
+ cursor.select(QTextCursor::Document);
+ cursor.setCharFormat(fmt);
+ QCOMPARE(doc->begin().begin().fragment().charFormat().objectIndex(), -1);
+
+ cursor.setBlockCharFormat(fmt);
+ QCOMPARE(cursor.blockCharFormat().objectIndex(), -1);
+
+ cursor.movePosition(QTextCursor::End);
+ cursor.insertBlock(QTextBlockFormat(), fmt);
+ QCOMPARE(cursor.blockCharFormat().objectIndex(), -1);
+
+ doc->clear();
+
+ QTextTable *table = cursor.insertTable(1, 1);
+ cursor.select(QTextCursor::Document);
+ cursor.setCharFormat(fmt);
+
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ QVERIFY(!cursor.isNull());
+ QCOMPARE(cursor.blockCharFormat().objectIndex(), table->objectIndex());
+}
+
+void tst_QTextCursor::blockAndColumnNumber()
+{
+ QCOMPARE(QTextCursor().columnNumber(), 0);
+ QCOMPARE(QTextCursor().blockNumber(), 0);
+
+ QCOMPARE(cursor.columnNumber(), 0);
+ QCOMPARE(cursor.blockNumber(), 0);
+ cursor.insertText("Hello");
+ QCOMPARE(cursor.columnNumber(), 5);
+ QCOMPARE(cursor.blockNumber(), 0);
+
+ cursor.insertBlock();
+ QCOMPARE(cursor.columnNumber(), 0);
+ QCOMPARE(cursor.blockNumber(), 1);
+ cursor.insertText("Blah");
+ QCOMPARE(cursor.blockNumber(), 1);
+
+ // trigger a layout
+ doc->documentLayout();
+
+ cursor.insertBlock();
+ QCOMPARE(cursor.columnNumber(), 0);
+ QCOMPARE(cursor.blockNumber(), 2);
+ cursor.insertText("Test");
+ QCOMPARE(cursor.columnNumber(), 4);
+ QCOMPARE(cursor.blockNumber(), 2);
+ cursor.insertText(QString(QChar(QChar::LineSeparator)));
+ QCOMPARE(cursor.columnNumber(), 0);
+ QCOMPARE(cursor.blockNumber(), 2);
+ cursor.insertText("A");
+ QCOMPARE(cursor.columnNumber(), 1);
+ QCOMPARE(cursor.blockNumber(), 2);
+}
+
+void tst_QTextCursor::movePositionEndOfLine()
+{
+ cursor.insertText("blah\nblah\n");
+ // Select part of the second line ("la")
+ cursor.setPosition(6);
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 2);
+ QCOMPARE(cursor.selectedText(), QLatin1String("la"));
+
+ // trigger a layout
+ doc->documentLayout();
+
+ // Remove "la" and append "something" to the end in one undo operation
+ cursor.beginEditBlock();
+ cursor.removeSelectedText();
+ QTextCursor c2(doc);
+ c2.setPosition(7);
+ c2.insertText("foo"); // append to doc without touching the cursor.
+
+ QCOMPARE(cursor.position(), 6);
+ cursor.movePosition(QTextCursor::EndOfLine); // in an edit block visual movement is moved to the end of the paragraph
+ QCOMPARE(cursor.position(), 10);
+ cursor.endEditBlock();
+}
+
+void tst_QTextCursor::clearCells()
+{
+ QTextTable *table = cursor.insertTable(3, 5);
+ cursor.setPosition(table->cellAt(0,0).firstPosition()); // select cell 1 and cell 2
+ cursor.setPosition(table->cellAt(0,1).firstPosition(), QTextCursor::KeepAnchor);
+ cursor.deleteChar(); // should clear the cells, and not crash ;)
+}
+
+void tst_QTextCursor::task244408_wordUnderCursor_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("expected");
+ QTest::newRow("trailingSpace") << QString::fromLatin1("foo ") << QString::fromLatin1("");
+ QTest::newRow("noTrailingSpace") << QString::fromLatin1("foo") << QString::fromLatin1("foo");
+}
+
+void tst_QTextCursor::task244408_wordUnderCursor()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, expected);
+ cursor.insertText(input);
+ cursor.movePosition(QTextCursor::End);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QCOMPARE(cursor.selectedText(), expected);
+}
+
+void tst_QTextCursor::adjustCursorsOnInsert()
+{
+ cursor.insertText("Some text before ");
+ int posBefore = cursor.position();
+ cursor.insertText("selected text");
+ int posAfter = cursor.position();
+ cursor.insertText(" some text afterwards");
+
+ QTextCursor selection = cursor;
+ selection.setPosition(posBefore);
+ selection.setPosition(posAfter, QTextCursor::KeepAnchor);
+
+ cursor.setPosition(posBefore-1);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.anchor(), posBefore+1);
+ QCOMPARE(selection.position(), posAfter+1);
+ doc->undo();
+
+ cursor.setPosition(posBefore);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.anchor(), posBefore+1);
+ QCOMPARE(selection.position(), posAfter+1);
+ doc->undo();
+
+ cursor.setPosition(posBefore+1);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.anchor(), posBefore);
+ QCOMPARE(selection.position(), posAfter+1);
+ doc->undo();
+
+ cursor.setPosition(posAfter-1);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.anchor(), posBefore);
+ QCOMPARE(selection.position(), posAfter+1);
+ doc->undo();
+
+ selection.setKeepPositionOnInsert(true);
+ cursor.setPosition(posAfter);
+ cursor.insertText(QLatin1String("x"));
+ selection.setKeepPositionOnInsert(false);
+ QCOMPARE(selection.anchor(), posBefore);
+ QCOMPARE(selection.position(), posAfter);
+ doc->undo();
+
+ cursor.setPosition(posAfter+1);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.anchor(), posBefore);
+ QCOMPARE(selection.position(), posAfter);
+ doc->undo();
+
+ selection.setPosition(posAfter);
+ selection.setPosition(posBefore, QTextCursor::KeepAnchor);
+
+ cursor.setPosition(posBefore-1);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.position(), posBefore+1);
+ QCOMPARE(selection.anchor(), posAfter+1);
+ doc->undo();
+
+ cursor.setPosition(posBefore);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.position(), posBefore+1);
+ QCOMPARE(selection.anchor(), posAfter+1);
+ doc->undo();
+
+ cursor.setPosition(posBefore+1);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.position(), posBefore);
+ QCOMPARE(selection.anchor(), posAfter+1);
+ doc->undo();
+
+ cursor.setPosition(posAfter-1);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.position(), posBefore);
+ QCOMPARE(selection.anchor(), posAfter+1);
+ doc->undo();
+
+ cursor.setPosition(posAfter);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.position(), posBefore);
+ QCOMPARE(selection.anchor(), posAfter+1);
+ doc->undo();
+
+ cursor.setPosition(posAfter+1);
+ cursor.insertText(QLatin1String("x"));
+ QCOMPARE(selection.position(), posBefore);
+ QCOMPARE(selection.anchor(), posAfter);
+ doc->undo();
+
+}
+void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo()
+{
+ cursor.insertText("AAAABBBBCCCCDDDD");
+ cursor.setPosition(12);
+ int cursorPositionBefore = cursor.position();
+ cursor.beginEditBlock();
+ cursor.insertText("*");
+ cursor.setPosition(8);
+ cursor.insertText("*");
+ cursor.setPosition(4);
+ cursor.insertText("*");
+ cursor.setPosition(0);
+ cursor.insertText("*");
+ int cursorPositionAfter = cursor.position();
+ cursor.endEditBlock();
+
+ QVERIFY(doc->toPlainText() == "*AAAA*BBBB*CCCC*DDDD");
+ QCOMPARE(12, cursorPositionBefore);
+ QCOMPARE(1, cursorPositionAfter);
+
+ doc->undo(&cursor);
+ QVERIFY(doc->toPlainText() == "AAAABBBBCCCCDDDD");
+ QCOMPARE(cursor.position(), cursorPositionBefore);
+ doc->redo(&cursor);
+ QVERIFY(doc->toPlainText() == "*AAAA*BBBB*CCCC*DDDD");
+ QCOMPARE(cursor.position(), cursorPositionAfter);
+}
+
+void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo2()
+{
+ cursor.insertText("AAAABBBB");
+ int cursorPositionBefore = cursor.position();
+ cursor.setPosition(0, QTextCursor::KeepAnchor);
+ cursor.beginEditBlock();
+ cursor.removeSelectedText();
+ cursor.insertText("AAAABBBBCCCCDDDD");
+ cursor.endEditBlock();
+ doc->undo(&cursor);
+ QVERIFY(doc->toPlainText() == "AAAABBBB");
+ QCOMPARE(cursor.position(), cursorPositionBefore);
+
+ cursor.insertText("CCCC");
+ QVERIFY(doc->toPlainText() == "AAAABBBBCCCC");
+
+ cursorPositionBefore = cursor.position();
+ cursor.setPosition(0, QTextCursor::KeepAnchor);
+ cursor.beginEditBlock();
+ cursor.removeSelectedText();
+ cursor.insertText("AAAABBBBCCCCDDDD");
+ cursor.endEditBlock();
+
+ /* this undo now implicitely reinserts two segments, first "CCCCC", then
+ "AAAABBBB". The test ensures that the two are combined in order to
+ reconstruct the correct cursor position */
+ doc->undo(&cursor);
+
+
+ QVERIFY(doc->toPlainText() == "AAAABBBBCCCC");
+ QCOMPARE(cursor.position(), cursorPositionBefore);
+}
+
+void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo3()
+{
+ // verify that it's the position of the beginEditBlock that counts, and not the last edit position
+ cursor.insertText("AAAABBBB");
+ int cursorPositionBefore = cursor.position();
+ cursor.beginEditBlock();
+ cursor.setPosition(4);
+ QVERIFY(cursor.position() != cursorPositionBefore);
+ cursor.insertText("*");
+ cursor.endEditBlock();
+ QCOMPARE(cursor.position(), 5);
+ doc->undo(&cursor);
+ QCOMPARE(cursor.position(), cursorPositionBefore);
+}
+
+QTEST_MAIN(tst_QTextCursor)
+#include "tst_qtextcursor.moc"
diff --git a/tests/auto/gui/text/qtextdocument/.gitignore b/tests/auto/gui/text/qtextdocument/.gitignore
new file mode 100644
index 0000000000..c14f0e2422
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocument/.gitignore
@@ -0,0 +1 @@
+tst_qtextdocument
diff --git a/tests/auto/gui/text/qtextdocument/common.h b/tests/auto/gui/text/qtextdocument/common.h
new file mode 100644
index 0000000000..1eaefdbfbe
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocument/common.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QAbstractTextDocumentLayout>
+#include <private/qtextdocument_p.h>
+
+#ifndef COMMON_H
+#define COMMON_H
+
+class QTestDocumentLayout : public QAbstractTextDocumentLayout
+{
+ Q_OBJECT
+public:
+ QTestDocumentLayout(QTextDocument *doc) : QAbstractTextDocumentLayout(doc), f(-1), called(false) {}
+ virtual void draw(QPainter *, const PaintContext &) {}
+ virtual int hitTest(const QPointF &, Qt::HitTestAccuracy ) const { return 0; }
+
+ virtual void documentChanged(int from, int oldLength, int length)
+ {
+ called = true;
+ lastDocumentLengths.append(document()->docHandle()->length());
+
+ if (f < 0)
+ return;
+
+ if(from != f ||
+ o != oldLength ||
+ l != length) {
+ qDebug("checkDocumentChanged: got %d %d %d, expected %d %d %d", from, oldLength, length, f, o, l);
+ error = true;
+ }
+ }
+
+ virtual int pageCount() const { return 1; }
+ virtual QSizeF documentSize() const { return QSizeF(); }
+
+ virtual QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
+ virtual QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
+
+ int f;
+ int o;
+ int l;
+
+ void expect(int from, int oldLength, int length) {
+ f = from;
+ o = oldLength;
+ l = length;
+ error = false;
+ called = false;
+ }
+ bool error;
+ bool called;
+ QList<int> lastDocumentLengths;
+};
+
+#endif
diff --git a/tests/auto/gui/text/qtextdocument/qtextdocument.pro b/tests/auto/gui/text/qtextdocument/qtextdocument.pro
new file mode 100644
index 0000000000..69517589cc
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocument/qtextdocument.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += core-private gui-private xml
+HEADERS += common.h
+SOURCES += tst_qtextdocument.cpp
+
+
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
new file mode 100644
index 0000000000..c98a703acc
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -0,0 +1,2788 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qtextdocument.h>
+#include <qdebug.h>
+
+#include <qtextcursor.h>
+#include <qtextdocumentfragment.h>
+#include <qtextformat.h>
+#include <qtextobject.h>
+#include <qtexttable.h>
+#include <qabstracttextdocumentlayout.h>
+#include <qtextlist.h>
+#include <qtextcodec.h>
+#include <qurl.h>
+#include <qpainter.h>
+#include <qfontmetrics.h>
+#include <qimage.h>
+#include <qtextlayout.h>
+#include <QDomDocument>
+#include "common.h"
+
+
+QT_FORWARD_DECLARE_CLASS(QTextDocument)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTextDocument : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTextDocument();
+ virtual ~tst_QTextDocument();
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void isEmpty();
+ void find_data();
+ void find();
+ void find2();
+ void findWithRegExp_data();
+ void findWithRegExp();
+ void findMultiple();
+ void basicIsModifiedChecks();
+ void moreIsModified();
+ void isModified2();
+ void isModified3();
+ void isModified4();
+ void noundo_basicIsModifiedChecks();
+ void noundo_moreIsModified();
+ void noundo_isModified2();
+ void noundo_isModified3();
+ void mightBeRichText();
+ void mightBeRichText_data();
+
+ void task240325();
+
+ void stylesheetFont_data();
+ void stylesheetFont();
+
+ void toHtml_data();
+ void toHtml();
+ void toHtml2();
+
+ void setFragmentMarkersInHtmlExport();
+
+ void toHtmlBodyBgColor();
+ void toHtmlRootFrameProperties();
+ void capitalizationHtmlInExport();
+ void wordspacingHtmlExport();
+
+ void cursorPositionChanged();
+ void cursorPositionChangedOnSetText();
+
+ void textFrameIterator();
+
+ void codecForHtml();
+
+ void markContentsDirty();
+
+ void clonePreservesMetaInformation();
+ void clonePreservesPageSize();
+ void clonePreservesPageBreakPolicies();
+ void clonePreservesDefaultFont();
+ void clonePreservesRootFrameFormat();
+ void clonePreservesResources();
+ void clonePreservesUserStates();
+ void clonePreservesIndentWidth();
+ void blockCount();
+ void defaultStyleSheet();
+
+ void resolvedFontInEmptyFormat();
+
+ void defaultRootFrameMargin();
+
+ void clearResources();
+
+ void setPlainText();
+ void toPlainText();
+
+ void deleteTextObjectsOnClear();
+
+ void maximumBlockCount();
+ void adjustSize();
+ void initialUserData();
+
+ void html_defaultFont();
+
+ void blockCountChanged();
+
+ void nonZeroDocumentLengthOnClear();
+
+ void setTextPreservesUndoRedoEnabled();
+
+ void firstLast();
+
+ void backgroundImage_toHtml();
+ void backgroundImage_toHtml2();
+ void backgroundImage_clone();
+ void backgroundImage_copy();
+
+ void documentCleanup();
+
+ void characterAt();
+ void revisions();
+ void revisionWithUndoCompressionAndUndo();
+
+ void testUndoCommandAdded();
+
+ void testUndoBlocks();
+
+ void receiveCursorPositionChangedAfterContentsChange();
+ void escape_data();
+ void escape();
+
+ void copiedFontSize();
+
+ void htmlExportImportBlockCount();
+
+private:
+ void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
+
+ QTextDocument *doc;
+ QTextCursor cursor;
+ QFont defaultFont;
+ QString htmlHead;
+ QString htmlTail;
+};
+
+class MyAbstractTextDocumentLayout : public QAbstractTextDocumentLayout
+{
+public:
+ MyAbstractTextDocumentLayout(QTextDocument *doc) : QAbstractTextDocumentLayout(doc) {}
+ void draw(QPainter *, const PaintContext &) {}
+ int hitTest(const QPointF &, Qt::HitTestAccuracy) const { return 0; }
+ int pageCount() const { return 0; }
+ QSizeF documentSize() const { return QSizeF(); }
+ QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
+ QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
+ void documentChanged(int, int, int) {}
+};
+
+// Testing get/set functions
+void tst_QTextDocument::getSetCheck()
+{
+ QTextDocument obj1;
+ // QAbstractTextDocumentLayout * QTextDocument::documentLayout()
+ // void QTextDocument::setDocumentLayout(QAbstractTextDocumentLayout *)
+ QPointer<MyAbstractTextDocumentLayout> var1 = new MyAbstractTextDocumentLayout(0);
+ obj1.setDocumentLayout(var1);
+ QCOMPARE(static_cast<QAbstractTextDocumentLayout *>(var1), obj1.documentLayout());
+ obj1.setDocumentLayout((QAbstractTextDocumentLayout *)0);
+ QVERIFY(var1.isNull());
+ QVERIFY(obj1.documentLayout());
+
+ // bool QTextDocument::useDesignMetrics()
+ // void QTextDocument::setUseDesignMetrics(bool)
+ obj1.setUseDesignMetrics(false);
+ QCOMPARE(false, obj1.useDesignMetrics());
+ obj1.setUseDesignMetrics(true);
+ QCOMPARE(true, obj1.useDesignMetrics());
+}
+
+tst_QTextDocument::tst_QTextDocument()
+{
+ QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
+ img.save("foo.png");
+}
+
+tst_QTextDocument::~tst_QTextDocument()
+{
+ QFile::remove(QLatin1String("foo.png"));
+}
+
+void tst_QTextDocument::init()
+{
+ doc = new QTextDocument;
+ cursor = QTextCursor(doc);
+ defaultFont = QFont();
+
+ htmlHead = QString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+ "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+ "p, li { white-space: pre-wrap; }\n"
+ "</style></head>"
+ "<body style=\" font-family:'%1'; font-size:%2pt; font-weight:%3; font-style:%4;\">\n");
+ htmlHead = htmlHead.arg(defaultFont.family()).arg(defaultFont.pointSizeF()).arg(defaultFont.weight() * 8).arg((defaultFont.italic() ? "italic" : "normal"));
+
+ htmlTail = QString("</body></html>");
+}
+
+void tst_QTextDocument::cleanup()
+{
+ cursor = QTextCursor();
+ delete doc;
+ doc = 0;
+}
+
+void tst_QTextDocument::isEmpty()
+{
+ QVERIFY(doc->isEmpty());
+}
+
+void tst_QTextDocument::find_data()
+{
+ QTest::addColumn<QString>("haystack");
+ QTest::addColumn<QString>("needle");
+ QTest::addColumn<int>("flags");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("anchor");
+ QTest::addColumn<int>("position");
+
+ QTest::newRow("1") << "Hello World" << "World" << int(QTextDocument::FindCaseSensitively) << 0 << 6 << 11;
+
+ QTest::newRow("2") << QString::fromAscii("Hello") + QString(QChar::ParagraphSeparator) + QString::fromAscii("World")
+ << "World" << int(QTextDocument::FindCaseSensitively) << 1 << 6 << 11;
+
+ QTest::newRow("3") << QString::fromAscii("Hello") + QString(QChar::ParagraphSeparator) + QString::fromAscii("World")
+ << "Hello" << int(QTextDocument::FindCaseSensitively | QTextDocument::FindBackward) << 10 << 0 << 5;
+ QTest::newRow("4wholewords") << QString::fromAscii("Hello Blah World")
+ << "Blah" << int(QTextDocument::FindWholeWords) << 0 << 6 << 10;
+ QTest::newRow("5wholewords") << QString::fromAscii("HelloBlahWorld")
+ << "Blah" << int(QTextDocument::FindWholeWords) << 0 << -1 << -1;
+ QTest::newRow("6wholewords") << QString::fromAscii("HelloBlahWorld Blah Hah")
+ << "Blah" << int(QTextDocument::FindWholeWords) << 0 << 15 << 19;
+ QTest::newRow("7wholewords") << QString::fromAscii("HelloBlahWorld Blah Hah")
+ << "Blah" << int(QTextDocument::FindWholeWords | QTextDocument::FindBackward) << 23 << 15 << 19;
+ QTest::newRow("8wholewords") << QString::fromAscii("Hello: World\n")
+ << "orld" << int(QTextDocument::FindWholeWords) << 0 << -1 << -1;
+
+ QTest::newRow("across-paragraphs") << QString::fromAscii("First Parag\nSecond Parag with a lot more text")
+ << "Parag" << int(QTextDocument::FindBackward)
+ << 15 << 6 << 11;
+
+ QTest::newRow("nbsp") << "Hello" + QString(QChar(QChar::Nbsp)) +"World" << " " << int(QTextDocument::FindCaseSensitively) << 0 << 5 << 6;
+}
+
+void tst_QTextDocument::find()
+{
+ QFETCH(QString, haystack);
+ QFETCH(QString, needle);
+ QFETCH(int, flags);
+ QFETCH(int, from);
+ QFETCH(int, anchor);
+ QFETCH(int, position);
+
+ cursor.insertText(haystack);
+ cursor = doc->find(needle, from, QTextDocument::FindFlags(flags));
+
+ if (anchor != -1) {
+ QCOMPARE(cursor.anchor(), anchor);
+ QCOMPARE(cursor.position(), position);
+ } else {
+ QVERIFY(cursor.isNull());
+ }
+
+ //search using a regular expression
+ QRegExp expr(needle);
+ expr.setPatternSyntax(QRegExp::FixedString);
+ QTextDocument::FindFlags flg(flags);
+ expr.setCaseSensitivity((flg & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive);
+ cursor = doc->find(expr, from, flg);
+
+ if (anchor != -1) {
+ QCOMPARE(cursor.anchor(), anchor);
+ QCOMPARE(cursor.position(), position);
+ } else {
+ QVERIFY(cursor.isNull());
+ }
+}
+
+void tst_QTextDocument::findWithRegExp_data()
+{
+ QTest::addColumn<QString>("haystack");
+ QTest::addColumn<QString>("needle");
+ QTest::addColumn<int>("flags");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("anchor");
+ QTest::addColumn<int>("position");
+
+ // match integers 0 to 99
+ QTest::newRow("1") << "23" << "^\\d\\d?$" << int(QTextDocument::FindCaseSensitively) << 0 << 0 << 2;
+ // match ampersands but not &amp;
+ QTest::newRow("2") << "His &amp; hers & theirs" << "&(?!amp;)"<< int(QTextDocument::FindCaseSensitively) << 0 << 15 << 16;
+ //backward search
+ QTest::newRow("3") << QString::fromAscii("HelloBlahWorld Blah Hah")
+ << "h" << int(QTextDocument::FindBackward) << 18 << 8 << 9;
+
+}
+
+void tst_QTextDocument::findWithRegExp()
+{
+ QFETCH(QString, haystack);
+ QFETCH(QString, needle);
+ QFETCH(int, flags);
+ QFETCH(int, from);
+ QFETCH(int, anchor);
+ QFETCH(int, position);
+
+ cursor.insertText(haystack);
+ //search using a regular expression
+ QRegExp expr(needle);
+ QTextDocument::FindFlags flg(flags);
+ expr.setCaseSensitivity((flg & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive);
+ cursor = doc->find(expr, from, flg);
+
+ if (anchor != -1) {
+ QCOMPARE(cursor.anchor(), anchor);
+ QCOMPARE(cursor.position(), position);
+ } else {
+ QVERIFY(cursor.isNull());
+ }
+}
+
+void tst_QTextDocument::find2()
+{
+ doc->setPlainText("aaa");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QTextCursor hit = doc->find("a", cursor);
+ QCOMPARE(hit.position(), 2);
+ QCOMPARE(hit.anchor(), 1);
+}
+
+void tst_QTextDocument::findMultiple()
+{
+ const QString text("foo bar baz foo bar baz");
+ doc->setPlainText(text);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor = doc->find("bar", cursor);
+ QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
+ QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
+ cursor = doc->find("bar", cursor);
+ QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
+ QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
+
+ cursor.movePosition(QTextCursor::End);
+ cursor = doc->find("bar", cursor, QTextDocument::FindBackward);
+ QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
+ QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
+ cursor = doc->find("bar", cursor, QTextDocument::FindBackward);
+ QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
+ QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
+
+
+ QRegExp expr("bar");
+ expr.setPatternSyntax(QRegExp::FixedString);
+
+ cursor.movePosition(QTextCursor::End);
+ cursor = doc->find(expr, cursor, QTextDocument::FindBackward);
+ QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
+ QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
+ cursor = doc->find(expr, cursor, QTextDocument::FindBackward);
+ QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
+ QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor = doc->find(expr, cursor);
+ QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
+ QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
+ cursor = doc->find(expr, cursor);
+ QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
+ QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
+}
+
+void tst_QTextDocument::basicIsModifiedChecks()
+{
+ QSignalSpy spy(doc, SIGNAL(modificationChanged(bool)));
+
+ QVERIFY(!doc->isModified());
+ cursor.insertText("Hello World");
+ QVERIFY(doc->isModified());
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(spy.takeFirst().at(0).toBool());
+
+ doc->undo();
+ QVERIFY(!doc->isModified());
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!spy.takeFirst().at(0).toBool());
+
+ doc->redo();
+ QVERIFY(doc->isModified());
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(spy.takeFirst().at(0).toBool());
+}
+
+void tst_QTextDocument::moreIsModified()
+{
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+ QVERIFY(doc->isModified());
+
+ doc->undo();
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+
+ doc->undo();
+ QVERIFY(!doc->isModified());
+}
+
+void tst_QTextDocument::isModified2()
+{
+ // reported on qt4-preview-feedback
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+ QVERIFY(doc->isModified());
+
+ doc->setModified(false);
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+ QVERIFY(doc->isModified());
+}
+
+void tst_QTextDocument::isModified3()
+{
+ QVERIFY(!doc->isModified());
+
+ doc->setUndoRedoEnabled(false);
+ doc->setUndoRedoEnabled(true);
+
+ cursor.insertText("Hello");
+
+ QVERIFY(doc->isModified());
+ doc->undo();
+ QVERIFY(!doc->isModified());
+}
+
+void tst_QTextDocument::isModified4()
+{
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+ cursor.insertText("World");
+
+ doc->setModified(false);
+
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Again");
+ QVERIFY(doc->isModified());
+
+ doc->undo();
+ QVERIFY(!doc->isModified());
+ doc->undo();
+ QVERIFY(doc->isModified());
+
+ doc->redo();
+ QVERIFY(!doc->isModified());
+ doc->redo();
+ QVERIFY(doc->isModified());
+
+ doc->undo();
+ QVERIFY(!doc->isModified());
+ doc->undo();
+ QVERIFY(doc->isModified());
+
+ //task 197769
+ cursor.insertText("Hello");
+ QVERIFY(doc->isModified());
+}
+
+void tst_QTextDocument::noundo_basicIsModifiedChecks()
+{
+ doc->setUndoRedoEnabled(false);
+ QSignalSpy spy(doc, SIGNAL(modificationChanged(bool)));
+
+ QVERIFY(!doc->isModified());
+ cursor.insertText("Hello World");
+ QVERIFY(doc->isModified());
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(spy.takeFirst().at(0).toBool());
+
+ doc->undo();
+ QVERIFY(doc->isModified());
+ QCOMPARE(spy.count(), 0);
+
+ doc->redo();
+ QVERIFY(doc->isModified());
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QTextDocument::task240325()
+{
+ doc->setHtml("<html><img width=\"100\" height=\"100\" align=\"right\"/>Foobar Foobar Foobar Foobar</html>");
+
+ QImage img(1000, 7000, QImage::Format_ARGB32_Premultiplied);
+ QPainter p(&img);
+ QFontMetrics fm(p.font());
+
+ // Set page size to contain image and one "Foobar"
+ doc->setPageSize(QSize(100 + fm.width("Foobar")*2, 1000));
+
+ // Force layout
+ doc->drawContents(&p);
+
+ QCOMPARE(doc->blockCount(), 1);
+ for (QTextBlock block = doc->begin() ; block!=doc->end() ; block = block.next()) {
+ QTextLayout *layout = block.layout();
+ QCOMPARE(layout->lineCount(), 4);
+ for (int lineIdx=0;lineIdx<layout->lineCount();++lineIdx) {
+ QTextLine line = layout->lineAt(lineIdx);
+
+ QString text = block.text().mid(line.textStart(), line.textLength()).trimmed();
+
+ // Remove start token
+ if (lineIdx == 0)
+ text = text.mid(1);
+
+ QCOMPARE(text, QString::fromLatin1("Foobar"));
+ }
+ }
+}
+
+void tst_QTextDocument::stylesheetFont_data()
+{
+ QTest::addColumn<QString>("stylesheet");
+ QTest::addColumn<QFont>("font");
+
+ {
+ QFont font;
+ font.setBold(true);
+ font.setPixelSize(64);
+
+ QTest::newRow("Regular font specification")
+ << "font-size: 64px; font-weight: bold;"
+ << font;
+ }
+
+
+ {
+ QFont font;
+ font.setBold(true);
+ font.setPixelSize(64);
+
+ QTest::newRow("Shorthand font specification")
+ << "font: normal bold 64px Arial;"
+ << font;
+ }
+
+}
+
+void tst_QTextDocument::stylesheetFont()
+{
+ QFETCH(QString, stylesheet);
+ QFETCH(QFont, font);
+
+ QString html = QString::fromLatin1("<html>"
+ "<body>"
+ "<div style=\"%1\" >"
+ "Foobar"
+ "</div>"
+ "</body>"
+ "</html>").arg(stylesheet);
+
+ qDebug() << html;
+ doc->setHtml(html);
+ QCOMPARE(doc->blockCount(), 1);
+
+ // First and only block
+ QTextBlock block = doc->firstBlock();
+
+ QString text = block.text();
+ QCOMPARE(text, QString::fromLatin1("Foobar"));
+
+ QFont actualFont = block.charFormat().font();
+
+ QCOMPARE(actualFont.bold(), font.bold());
+ QCOMPARE(actualFont.pixelSize(), font.pixelSize());
+}
+
+void tst_QTextDocument::noundo_moreIsModified()
+{
+ doc->setUndoRedoEnabled(false);
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+ QVERIFY(doc->isModified());
+
+ doc->undo();
+ QVERIFY(doc->isModified());
+
+ cursor.insertText("Hello");
+
+ doc->undo();
+ QVERIFY(doc->isModified());
+}
+
+void tst_QTextDocument::noundo_isModified2()
+{
+ // reported on qt4-preview-feedback
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+ QVERIFY(doc->isModified());
+
+ doc->setModified(false);
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+ QVERIFY(doc->isModified());
+}
+
+void tst_QTextDocument::noundo_isModified3()
+{
+ doc->setUndoRedoEnabled(false);
+ QVERIFY(!doc->isModified());
+
+ cursor.insertText("Hello");
+
+ QVERIFY(doc->isModified());
+ doc->undo();
+ QVERIFY(doc->isModified());
+}
+
+void tst_QTextDocument::mightBeRichText_data()
+{
+ const char qtDocuHeader[] = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
+ "<!DOCTYPE html\n"
+ " PUBLIC ""-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">";
+ QVERIFY(Qt::mightBeRichText(QString::fromLatin1(qtDocuHeader)));
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<bool>("result");
+
+ QTest::newRow("documentation-header") << QString("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
+ "<!DOCTYPE html\n"
+ " PUBLIC ""-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">")
+ << true;
+ QTest::newRow("br-nospace") << QString("Test <br/> new line") << true;
+ QTest::newRow("br-space") << QString("Test <br /> new line") << true;
+ QTest::newRow("br-invalidspace") << QString("Test <br/ > new line") << false;
+ QTest::newRow("invalid closing tag") << QString("Test <br/ line") << false;
+}
+
+void tst_QTextDocument::mightBeRichText()
+{
+ QFETCH(QString, input);
+ QFETCH(bool, result);
+ QVERIFY(result == Qt::mightBeRichText(input));
+}
+
+Q_DECLARE_METATYPE(QTextDocumentFragment)
+
+#define CREATE_DOC_AND_CURSOR() \
+ QTextDocument doc; \
+ doc.setDefaultFont(defaultFont); \
+ QTextCursor cursor(&doc);
+
+void tst_QTextDocument::toHtml_data()
+{
+ QTest::addColumn<QTextDocumentFragment>("input");
+ QTest::addColumn<QString>("expectedOutput");
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertText("Blah");
+
+ QTest::newRow("simple") << QTextDocumentFragment(&doc) << QString("<p DEFAULTBLOCKSTYLE>Blah</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertText("&<>");
+
+ QTest::newRow("entities") << QTextDocumentFragment(&doc) << QString("<p DEFAULTBLOCKSTYLE>&amp;&lt;&gt;</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setFontFamily("Times");
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("font-family") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-family:'Times';\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setFontFamily("Foo's Family");
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("font-family-with-quotes1") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-family:&quot;Foo's Family&quot;;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setFontFamily("Foo\"s Family");
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("font-family-with-quotes2") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-family:'Foo&quot;s Family';\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setNonBreakableLines(true);
+ cursor.insertBlock(fmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("pre") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<pre DEFAULTBLOCKSTYLE>Blah</pre>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setFontPointSize(40);
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("font-size") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-size:40pt;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setProperty(QTextFormat::FontSizeIncrement, 2);
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("logical-font-size") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-size:x-large;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertText("Foo");
+
+ QTextCharFormat fmt;
+ fmt.setFontPointSize(40);
+ cursor.insertBlock(QTextBlockFormat(), fmt);
+
+ fmt.clearProperty(QTextFormat::FontPointSize);
+ cursor.insertText("Blub", fmt);
+
+ QTest::newRow("no-font-size") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE>Foo</p>\n<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blub</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setLayoutDirection(Qt::RightToLeft);
+ cursor.insertBlock(fmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("rtl") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<p dir='rtl' DEFAULTBLOCKSTYLE>Blah</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setAlignment(Qt::AlignJustify);
+ cursor.insertBlock(fmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("blockalign") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<p align=\"justify\" DEFAULTBLOCKSTYLE>Blah</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setAlignment(Qt::AlignCenter);
+ cursor.insertBlock(fmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("blockalign2") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<p align=\"center\" DEFAULTBLOCKSTYLE>Blah</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
+ cursor.insertBlock(fmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("blockalign3") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<p align=\"right\" DEFAULTBLOCKSTYLE>Blah</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setBackground(QColor("#0000ff"));
+ cursor.insertBlock(fmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("bgcolor") << QTextDocumentFragment(&doc)
+ << QString("EMPTYBLOCK") +
+ QString("<p OPENDEFAULTBLOCKSTYLE background-color:#0000ff;\">Blah</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setFontWeight(40);
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("font-weight") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-weight:320;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setFontItalic(true);
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("font-italic") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-style:italic;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setFontUnderline(true);
+ fmt.setFontOverline(false);
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("text-decoration-1") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" text-decoration: underline;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setForeground(QColor("#00ff00"));
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("color") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" color:#00ff00;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setBackground(QColor("#00ff00"));
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("span-bgcolor") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" background-color:#00ff00;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setVerticalAlignment(QTextCharFormat::AlignSubScript);
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("valign-sub") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" vertical-align:sub;\">Blah</span></p>");
+
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("valign-super") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" vertical-align:super;\">Blah</span></p>");
+
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setAnchor(true);
+ fmt.setAnchorName("blub");
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("named anchor") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><a name=\"blub\"></a>Blah</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setAnchor(true);
+ fmt.setAnchorHref("http://www.kde.org/");
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("href anchor") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><a href=\"http://www.kde.org/\">Blah</a></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setAnchor(true);
+ fmt.setAnchorHref("http://www.kde.org/?a=1&b=2");
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("href anchor with &") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><a href=\"http://www.kde.org/?a=1&amp;b=2\">Blah</a></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setAnchor(true);
+ fmt.setAnchorHref("http://www.kde.org/?a='&b=\"");
+ cursor.insertText("Blah", fmt);
+
+ QTest::newRow("href anchor with ' and \"") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><a href=\"http://www.kde.org/?a='&amp;b=&quot;\">Blah</a></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertTable(2, 2);
+
+ QTest::newRow("simpletable") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTable *table = cursor.insertTable(1, 4);
+ table->mergeCells(0, 0, 1, 2);
+ table->mergeCells(0, 2, 1, 2);
+
+ QTest::newRow("tablespans") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "\n<tr>\n<td colspan=\"2\"></td>\n<td colspan=\"2\"></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTableFormat fmt;
+ fmt.setBorder(1);
+ fmt.setCellSpacing(3);
+ fmt.setCellPadding(3);
+ fmt.setBackground(QColor("#ff00ff"));
+ fmt.setWidth(QTextLength(QTextLength::PercentageLength, 50));
+ fmt.setAlignment(Qt::AlignHCenter);
+ fmt.setPosition(QTextFrameFormat::FloatRight);
+ cursor.insertTable(2, 2, fmt);
+
+ QTest::newRow("tableattrs") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" style=\" float: right;\" align=\"center\" width=\"50%\" cellspacing=\"3\" cellpadding=\"3\" bgcolor=\"#ff00ff\">"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTableFormat fmt;
+ fmt.setBorder(1);
+ fmt.setCellSpacing(3);
+ fmt.setCellPadding(3);
+ fmt.setBackground(QColor("#ff00ff"));
+ fmt.setWidth(QTextLength(QTextLength::PercentageLength, 50));
+ fmt.setAlignment(Qt::AlignHCenter);
+ fmt.setPosition(QTextFrameFormat::FloatRight);
+ fmt.setLeftMargin(25);
+ fmt.setBottomMargin(35);
+ cursor.insertTable(2, 2, fmt);
+
+ QTest::newRow("tableattrs2") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" style=\" float: right; margin-top:0px; margin-bottom:35px; margin-left:25px; margin-right:0px;\" align=\"center\" width=\"50%\" cellspacing=\"3\" cellpadding=\"3\" bgcolor=\"#ff00ff\">"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTableFormat fmt;
+ fmt.setHeaderRowCount(2);
+ cursor.insertTable(4, 2, fmt);
+
+ QTest::newRow("tableheader") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "<thead>\n<tr>\n<td></td>\n<td></td></tr>"
+ "\n<tr>\n<td></td>\n<td></td></tr></thead>"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTable *table = cursor.insertTable(2, 2);
+ QTextTable *subTable = table->cellAt(0, 1).firstCursorPosition().insertTable(1, 1);
+ subTable->cellAt(0, 0).firstCursorPosition().insertText("Hey");
+
+ QTest::newRow("nestedtable") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "\n<tr>\n<td></td>\n<td>\n<table border=\"1\" cellspacing=\"2\">\n<tr>\n<td>\n<p DEFAULTBLOCKSTYLE>Hey</p></td></tr></table></td></tr>"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTableFormat fmt;
+ QVector<QTextLength> widths;
+ widths.append(QTextLength());
+ widths.append(QTextLength(QTextLength::PercentageLength, 30));
+ widths.append(QTextLength(QTextLength::FixedLength, 40));
+ fmt.setColumnWidthConstraints(widths);
+ cursor.insertTable(1, 3, fmt);
+
+ QTest::newRow("colwidths") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "\n<tr>\n<td></td>\n<td width=\"30%\"></td>\n<td width=\"40\"></td></tr>"
+ "</table>");
+ }
+
+ // ### rowspan/colspan tests, once texttable api for that is back again
+ //
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTable *table = cursor.insertTable(1, 1);
+ QTextCursor cellCurs = table->cellAt(0, 0).firstCursorPosition();
+ QTextCharFormat fmt;
+ fmt.setBackground(QColor("#ffffff"));
+ cellCurs.mergeBlockCharFormat(fmt);
+
+ QTest::newRow("cellproperties") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "\n<tr>\n<td bgcolor=\"#ffffff\"></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ // ### fixme: use programmatic api as soon as we can create floats through it
+ const char html[] = "<html><body>Blah<img src=\"image.png\" width=\"10\" height=\"20\" style=\"float: right;\" />Blubb</body></html>";
+
+ QTest::newRow("image") << QTextDocumentFragment::fromHtml(QString::fromLatin1(html))
+ << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blah<img src=\"image.png\" width=\"10\" height=\"20\" style=\"float: right;\" />Blubb</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextImageFormat fmt;
+ fmt.setName("foo");
+ fmt.setVerticalAlignment(QTextCharFormat::AlignMiddle);
+ cursor.insertImage(fmt);
+
+ QTest::newRow("image-malign") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><img src=\"foo\" style=\"vertical-align: middle;\" /></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextImageFormat fmt;
+ fmt.setName("foo");
+ fmt.setVerticalAlignment(QTextCharFormat::AlignTop);
+ cursor.insertImage(fmt);
+
+ QTest::newRow("image-malign") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><img src=\"foo\" style=\"vertical-align: top;\" /></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextImageFormat fmt;
+ fmt.setName("foo");
+ cursor.insertImage(fmt);
+ cursor.insertImage(fmt);
+
+ QTest::newRow("2images") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><img src=\"foo\" /><img src=\"foo\" /></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QString txt = QLatin1String("Blah");
+ txt += QChar::LineSeparator;
+ txt += QLatin1String("Bar");
+ cursor.insertText(txt);
+
+ QTest::newRow("linebreaks") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE>Blah<br />Bar</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setTopMargin(10);
+ fmt.setBottomMargin(20);
+ fmt.setLeftMargin(30);
+ fmt.setRightMargin(40);
+ cursor.insertBlock(fmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("blockmargins") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<p style=\" margin-top:10px; margin-bottom:20px; margin-left:30px; margin-right:40px; -qt-block-indent:0; text-indent:0px;\">Blah</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextList *list = cursor.insertList(QTextListFormat::ListDisc);
+ cursor.insertText("Blubb");
+ cursor.insertBlock();
+ cursor.insertText("Blah");
+ QCOMPARE(list->count(), 2);
+
+ QTest::newRow("lists") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li DEFAULTBLOCKSTYLE>Blubb</li>\n<li DEFAULTBLOCKSTYLE>Blah</li></ul>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextList *list = cursor.insertList(QTextListFormat::ListDisc);
+ cursor.insertText("Blubb");
+
+ cursor.insertBlock();
+
+ QTextCharFormat blockCharFmt;
+ blockCharFmt.setForeground(QColor("#0000ff"));
+ cursor.mergeBlockCharFormat(blockCharFmt);
+
+ QTextCharFormat fmt;
+ fmt.setForeground(QColor("#ff0000"));
+ cursor.insertText("Blah", fmt);
+ QCOMPARE(list->count(), 2);
+
+ QTest::newRow("charfmt-for-list-item") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li DEFAULTBLOCKSTYLE>Blubb</li>\n<li style=\" color:#0000ff;\" DEFAULTBLOCKSTYLE><span style=\" color:#ff0000;\">Blah</span></li></ul>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setIndent(3);
+ fmt.setTextIndent(30);
+ cursor.insertBlock(fmt);
+ cursor.insertText("Test");
+
+ QTest::newRow("block-indent") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:3; text-indent:30px;\">Test</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::ListDisc);
+ fmt.setIndent(4);
+ cursor.insertList(fmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("list-indent") << QTextDocumentFragment(&doc)
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 4;\"><li DEFAULTBLOCKSTYLE>Blah</li></ul>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertBlock();
+
+
+ QTest::newRow("emptyblock") << QTextDocumentFragment(&doc)
+ // after insertBlock() we /do/ have two blocks in the document, so also expect
+ // these in the html output
+ << QString("EMPTYBLOCK") + QString("EMPTYBLOCK");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ // if you press enter twice in an empty textedit and then insert 'Test'
+ // you actually get three visible paragraphs, two empty leading ones and
+ // a third with the actual text. the corresponding html representation
+ // therefore should also contain three paragraphs.
+
+ cursor.insertBlock();
+ QTextCharFormat fmt;
+ fmt.setForeground(QColor("#00ff00"));
+ fmt.setProperty(QTextFormat::FontSizeIncrement, 1);
+ cursor.mergeBlockCharFormat(fmt);
+
+ fmt.setProperty(QTextFormat::FontSizeIncrement, 2);
+ cursor.insertText("Test", fmt);
+
+ QTest::newRow("blockcharfmt") << QTextDocumentFragment(&doc)
+ << QString("EMPTYBLOCK<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:x-large; color:#00ff00;\">Test</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setForeground(QColor("#00ff00"));
+ cursor.setBlockCharFormat(fmt);
+ fmt.setForeground(QColor("#0000ff"));
+ cursor.insertText("Test", fmt);
+
+ QTest::newRow("blockcharfmt2") << QTextDocumentFragment(&doc)
+ << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" color:#0000ff;\">Test</span></p>");
+ }
+
+ {
+ QTest::newRow("horizontal-ruler") << QTextDocumentFragment::fromHtml("<hr />")
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<hr />");
+ }
+ {
+ QTest::newRow("horizontal-ruler-with-width") << QTextDocumentFragment::fromHtml("<hr width=\"50%\"/>")
+ <<
+ QString("EMPTYBLOCK") +
+ QString("<hr width=\"50%\"/>");
+ }
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextFrame *mainFrame = cursor.currentFrame();
+
+ QTextFrameFormat ffmt;
+ ffmt.setBorder(1);
+ ffmt.setPosition(QTextFrameFormat::FloatRight);
+ ffmt.setMargin(2);
+ ffmt.setWidth(100);
+ ffmt.setHeight(50);
+ ffmt.setBackground(QColor("#00ff00"));
+ cursor.insertFrame(ffmt);
+ cursor.insertText("Hello World");
+ cursor = mainFrame->lastCursorPosition();
+
+ QTest::newRow("frame") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" style=\"-qt-table-type: frame; float: right; margin-top:2px; margin-bottom:2px; margin-left:2px; margin-right:2px;\" width=\"100\" height=\"50\" bgcolor=\"#00ff00\">\n<tr>\n<td style=\"border: none;\">\n<p DEFAULTBLOCKSTYLE>Hello World</p></td></tr></table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+ fmt.setForeground(QColor("#00ff00"));
+// fmt.setBackground(QColor("#0000ff"));
+ cursor.setBlockCharFormat(fmt);
+
+ fmt.setForeground(QBrush());
+// fmt.setBackground(QBrush());
+ cursor.insertText("Test", fmt);
+
+// QTest::newRow("nostylebrush") << QTextDocumentFragment(&doc) << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; color:#00ff00; -qt-blockcharfmt-background-color:#0000ff;\">Test</p>");
+ QTest::newRow("nostylebrush") << QTextDocumentFragment(&doc) << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Test</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->mergeCells(0, 0, 1, 2);
+ QTextTableFormat fmt = table->format();
+ QVector<QTextLength> widths;
+ widths.append(QTextLength(QTextLength::FixedLength, 20));
+ widths.append(QTextLength(QTextLength::FixedLength, 40));
+ fmt.setColumnWidthConstraints(widths);
+ table->setFormat(fmt);
+
+ QTest::newRow("mergedtablecolwidths") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "\n<tr>\n<td colspan=\"2\"></td></tr>"
+ "\n<tr>\n<td width=\"20\"></td>\n<td width=\"40\"></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextCharFormat fmt;
+
+ cursor.insertText("Blah\nGreen yellow green");
+ cursor.setPosition(0);
+ cursor.setPosition(23, QTextCursor::KeepAnchor);
+ fmt.setBackground(Qt::green);
+ cursor.mergeCharFormat(fmt);
+ cursor.clearSelection();
+ cursor.setPosition(11);
+ cursor.setPosition(17, QTextCursor::KeepAnchor);
+ fmt.setBackground(Qt::yellow);
+ cursor.mergeCharFormat(fmt);
+ cursor.clearSelection();
+
+ QTest::newRow("multiparagraph-bgcolor") << QTextDocumentFragment(&doc)
+ << QString("<p DEFAULTBLOCKSTYLE><span style=\" background-color:#00ff00;\">Blah</span></p>\n"
+ "<p DEFAULTBLOCKSTYLE><span style=\" background-color:#00ff00;\">Green </span>"
+ "<span style=\" background-color:#ffff00;\">yellow</span>"
+ "<span style=\" background-color:#00ff00;\"> green</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat fmt;
+ fmt.setBackground(QColor("#0000ff"));
+ cursor.insertBlock(fmt);
+
+ QTextCharFormat charfmt;
+ charfmt.setBackground(QColor("#0000ff"));
+ cursor.insertText("Blah", charfmt);
+
+ QTest::newRow("nospan-bgcolor") << QTextDocumentFragment(&doc)
+ << QString("EMPTYBLOCK") +
+ QString("<p OPENDEFAULTBLOCKSTYLE background-color:#0000ff;\"><span style=\" background-color:#0000ff;\">Blah</span></p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTable *table = cursor.insertTable(2, 2);
+ QTextCharFormat fmt = table->cellAt(0, 0).format();
+ fmt.setVerticalAlignment(QTextCharFormat::AlignMiddle);
+ table->cellAt(0, 0).setFormat(fmt);
+ fmt = table->cellAt(0, 1).format();
+ fmt.setVerticalAlignment(QTextCharFormat::AlignTop);
+ table->cellAt(0, 1).setFormat(fmt);
+ fmt = table->cellAt(1, 0).format();
+ fmt.setVerticalAlignment(QTextCharFormat::AlignBottom);
+ table->cellAt(1, 0).setFormat(fmt);
+
+ table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
+
+ QTest::newRow("table-vertical-alignment") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "\n<tr>\n<td style=\" vertical-align:middle;\">\n"
+ "<p DEFAULTBLOCKSTYLE>Blah</p></td>"
+ "\n<td style=\" vertical-align:top;\"></td></tr>"
+ "\n<tr>\n<td style=\" vertical-align:bottom;\"></td>"
+ "\n<td></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTable *table = cursor.insertTable(2, 2);
+ QTextTableCellFormat fmt = table->cellAt(0, 0).format().toTableCellFormat();
+ fmt.setLeftPadding(1);
+ table->cellAt(0, 0).setFormat(fmt);
+ fmt = table->cellAt(0, 1).format().toTableCellFormat();
+ fmt.setRightPadding(1);
+ table->cellAt(0, 1).setFormat(fmt);
+ fmt = table->cellAt(1, 0).format().toTableCellFormat();
+ fmt.setTopPadding(1);
+ table->cellAt(1, 0).setFormat(fmt);
+ fmt = table->cellAt(1, 1).format().toTableCellFormat();
+ fmt.setBottomPadding(1);
+ table->cellAt(1, 1).setFormat(fmt);
+
+ table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
+
+ QTest::newRow("table-cell-paddings") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" cellspacing=\"2\">"
+ "\n<tr>\n<td style=\" padding-left:1;\">\n"
+ "<p DEFAULTBLOCKSTYLE>Blah</p></td>"
+ "\n<td style=\" padding-right:1;\"></td></tr>"
+ "\n<tr>\n<td style=\" padding-top:1;\"></td>"
+ "\n<td style=\" padding-bottom:1;\"></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextTableFormat fmt;
+ fmt.setBorderBrush(QColor("#0000ff"));
+ fmt.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
+ cursor.insertTable(2, 2, fmt);
+
+ QTest::newRow("tableborder") << QTextDocumentFragment(&doc)
+ << QString("<table border=\"1\" style=\" border-color:#0000ff; border-style:solid;\" cellspacing=\"2\">"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "\n<tr>\n<td></td>\n<td></td></tr>"
+ "</table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertBlock();
+ cursor.insertText("Foo");
+
+ cursor.block().setUserState(42);
+
+ QTest::newRow("userstate") << QTextDocumentFragment(&doc)
+ << QString("EMPTYBLOCK") +
+ QString("<p OPENDEFAULTBLOCKSTYLE -qt-user-state:42;\">Foo</p>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextBlockFormat blockFmt;
+ blockFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore);
+
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("Foo");
+
+ blockFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore | QTextFormat::PageBreak_AlwaysAfter);
+
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("Bar");
+
+ QTextTableFormat tableFmt;
+ tableFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysAfter);
+
+ cursor.insertTable(1, 1, tableFmt);
+
+ QTest::newRow("pagebreak") << QTextDocumentFragment(&doc)
+ << QString("EMPTYBLOCK") +
+ QString("<p OPENDEFAULTBLOCKSTYLE page-break-before:always;\">Foo</p>"
+ "\n<p OPENDEFAULTBLOCKSTYLE page-break-before:always; page-break-after:always;\">Bar</p>"
+ "\n<table border=\"1\" style=\" page-break-after:always;\" cellspacing=\"2\">\n<tr>\n<td></td></tr></table>");
+ }
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ QTextListFormat listFmt;
+ listFmt.setStyle(QTextListFormat::ListDisc);
+
+ cursor.insertList(listFmt);
+ cursor.insertText("Blah");
+
+ QTest::newRow("list-ul-margin") << QTextDocumentFragment(&doc)
+ << QString("EMPTYBLOCK") +
+ QString("<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li DEFAULTBLOCKSTYLE>Blah</li></ul>");
+ }
+}
+
+void tst_QTextDocument::toHtml()
+{
+ QFETCH(QTextDocumentFragment, input);
+ QFETCH(QString, expectedOutput);
+
+ cursor.insertFragment(input);
+
+ expectedOutput.prepend(htmlHead);
+
+ expectedOutput.replace("OPENDEFAULTBLOCKSTYLE", "style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;");
+ expectedOutput.replace("DEFAULTBLOCKSTYLE", "style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"");
+ expectedOutput.replace("EMPTYBLOCK", "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n");
+ if (expectedOutput.endsWith(QLatin1Char('\n')))
+ expectedOutput.chop(1);
+ expectedOutput.append(htmlTail);
+
+ QString output = doc->toHtml();
+
+ QCOMPARE(output, expectedOutput);
+
+ QDomDocument document;
+ QVERIFY2(document.setContent(output), "Output was not valid XML");
+}
+
+void tst_QTextDocument::toHtml2()
+{
+ QTextDocument doc;
+ doc.setHtml("<p>text <img src=\"\"> text</p>"); // 4 spaces before the second 'text'
+ QTextBlock block = doc.firstBlock();
+ QTextBlock::Iterator iter = block.begin();
+ QTextFragment f = iter.fragment();
+ QVERIFY(f.isValid());
+ QCOMPARE(f.position(), 0);
+ QCOMPARE(f.length(), 5);
+ //qDebug() << block.text().mid(f.position(), f.length());
+
+ iter++;
+ f = iter.fragment();
+ QVERIFY(f.isValid());
+ QCOMPARE(f.position(), 5);
+ QCOMPARE(f.length(), 1);
+ //qDebug() << block.text().mid(f.position(), f.length());
+
+ iter++;
+ f = iter.fragment();
+ //qDebug() << block.text().mid(f.position(), f.length());
+ QVERIFY(f.isValid());
+ QCOMPARE(f.position(), 6);
+ QCOMPARE(f.length(), 5); // 1 space should be preserved.
+ QCOMPARE(block.text().mid(f.position(), f.length()), QString(" text"));
+
+ doc.setHtml("<table><tr><td> foo</td></tr></table> text"); // 4 spaces before the second 'text'
+ block = doc.firstBlock().next();
+ //qDebug() << block.text();
+ QCOMPARE(block.text(), QString("foo"));
+
+ block = block.next();
+ //qDebug() << block.text();
+ QCOMPARE(block.text(), QString("text"));
+}
+
+void tst_QTextDocument::setFragmentMarkersInHtmlExport()
+{
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertText("Leadin");
+ const int startPos = cursor.position();
+
+ cursor.insertText("Test");
+ QTextCharFormat fmt;
+ fmt.setForeground(QColor("#00ff00"));
+ cursor.insertText("Blah", fmt);
+
+ const int endPos = cursor.position();
+ cursor.insertText("Leadout", QTextCharFormat());
+
+ cursor.setPosition(startPos);
+ cursor.setPosition(endPos, QTextCursor::KeepAnchor);
+ QTextDocumentFragment fragment(cursor);
+
+ QString expected = htmlHead;
+ expected.replace(QRegExp("<body.*>"), QString("<body>"));
+ expected += QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><!--StartFragment-->Test<span style=\" color:#00ff00;\">Blah</span><!--EndFragment--></p>") + htmlTail;
+ QCOMPARE(fragment.toHtml(), expected);
+ }
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertText("Leadin");
+ const int startPos = cursor.position();
+
+ cursor.insertText("Test");
+
+ const int endPos = cursor.position();
+ cursor.insertText("Leadout", QTextCharFormat());
+
+ cursor.setPosition(startPos);
+ cursor.setPosition(endPos, QTextCursor::KeepAnchor);
+ QTextDocumentFragment fragment(cursor);
+
+ QString expected = htmlHead;
+ expected.replace(QRegExp("<body.*>"), QString("<body>"));
+ expected += QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><!--StartFragment-->Test<!--EndFragment--></p>") + htmlTail;
+ QCOMPARE(fragment.toHtml(), expected);
+ }
+}
+
+void tst_QTextDocument::toHtmlBodyBgColor()
+{
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertText("Blah");
+
+ QTextFrameFormat fmt = doc.rootFrame()->frameFormat();
+ fmt.setBackground(QColor("#0000ff"));
+ doc.rootFrame()->setFrameFormat(fmt);
+
+ QString expectedHtml("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+ "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+ "p, li { white-space: pre-wrap; }\n"
+ "</style></head>"
+ "<body style=\" font-family:'%1'; font-size:%2pt; font-weight:%3; font-style:%4;\""
+ " bgcolor=\"#0000ff\">\n"
+ "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blah</p>"
+ "</body></html>");
+
+ expectedHtml = expectedHtml.arg(defaultFont.family()).arg(defaultFont.pointSizeF()).arg(defaultFont.weight() * 8).arg((defaultFont.italic() ? "italic" : "normal"));
+
+ QCOMPARE(doc.toHtml(), expectedHtml);
+}
+
+void tst_QTextDocument::toHtmlRootFrameProperties()
+{
+ CREATE_DOC_AND_CURSOR();
+
+ QTextFrameFormat fmt = doc.rootFrame()->frameFormat();
+ fmt.setTopMargin(10);
+ fmt.setLeftMargin(10);
+ fmt.setBorder(2);
+ doc.rootFrame()->setFrameFormat(fmt);
+
+ cursor.insertText("Blah");
+
+ QString expectedOutput("<table border=\"2\" style=\"-qt-table-type: root; margin-top:10px; "
+ "margin-bottom:4px; margin-left:10px; margin-right:4px;\">\n"
+ "<tr>\n<td style=\"border: none;\">\n"
+ "<p DEFAULTBLOCKSTYLE>Blah</p></td></tr></table>");
+
+ expectedOutput.prepend(htmlHead);
+ expectedOutput.replace("DEFAULTBLOCKSTYLE", "style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"");
+ expectedOutput.append(htmlTail);
+
+ QCOMPARE(doc.toHtml(), expectedOutput);
+}
+
+void tst_QTextDocument::capitalizationHtmlInExport()
+{
+ doc->setPlainText("Test");
+
+ QRegExp re(".*span style=\"(.*)\">Test.*");
+ QVERIFY(re.exactMatch(doc->toHtml()) == false); // no span
+
+ QTextCursor cursor(doc);
+ cursor.setPosition(4, QTextCursor::KeepAnchor);
+ QTextCharFormat cf;
+ cf.setFontCapitalization(QFont::SmallCaps);
+ cursor.mergeCharFormat(cf);
+
+ const QString smallcaps = doc->toHtml();
+ QVERIFY(re.exactMatch(doc->toHtml()));
+ QCOMPARE(re.captureCount(), 1);
+ QCOMPARE(re.cap(1).trimmed(), QString("font-variant:small-caps;"));
+
+ cf.setFontCapitalization(QFont::AllUppercase);
+ cursor.mergeCharFormat(cf);
+ const QString uppercase = doc->toHtml();
+ QVERIFY(re.exactMatch(doc->toHtml()));
+ QCOMPARE(re.captureCount(), 1);
+ QCOMPARE(re.cap(1).trimmed(), QString("text-transform:uppercase;"));
+
+ cf.setFontCapitalization(QFont::AllLowercase);
+ cursor.mergeCharFormat(cf);
+ const QString lowercase = doc->toHtml();
+ QVERIFY(re.exactMatch(doc->toHtml()));
+ QCOMPARE(re.captureCount(), 1);
+ QCOMPARE(re.cap(1).trimmed(), QString("text-transform:lowercase;"));
+
+ doc->setHtml(smallcaps);
+ cursor.setPosition(1);
+ QCOMPARE(cursor.charFormat().fontCapitalization(), QFont::SmallCaps);
+ doc->setHtml(uppercase);
+ QCOMPARE(cursor.charFormat().fontCapitalization(), QFont::AllUppercase);
+ doc->setHtml(lowercase);
+ QCOMPARE(cursor.charFormat().fontCapitalization(), QFont::AllLowercase);
+}
+
+void tst_QTextDocument::wordspacingHtmlExport()
+{
+ doc->setPlainText("Test");
+
+ QRegExp re(".*span style=\"(.*)\">Test.*");
+ QVERIFY(re.exactMatch(doc->toHtml()) == false); // no span
+
+ QTextCursor cursor(doc);
+ cursor.setPosition(4, QTextCursor::KeepAnchor);
+ QTextCharFormat cf;
+ cf.setFontWordSpacing(4);
+ cursor.mergeCharFormat(cf);
+
+ QVERIFY(re.exactMatch(doc->toHtml()));
+ QCOMPARE(re.captureCount(), 1);
+ QCOMPARE(re.cap(1).trimmed(), QString("word-spacing:4px;"));
+
+ cf.setFontWordSpacing(-8.5);
+ cursor.mergeCharFormat(cf);
+
+ QVERIFY(re.exactMatch(doc->toHtml()));
+ QCOMPARE(re.captureCount(), 1);
+ QCOMPARE(re.cap(1).trimmed(), QString("word-spacing:-8.5px;"));
+}
+
+class CursorPosSignalSpy : public QObject
+{
+ Q_OBJECT
+public:
+ CursorPosSignalSpy(QTextDocument *doc)
+ {
+ calls = 0;
+ connect(doc, SIGNAL(cursorPositionChanged(const QTextCursor &)),
+ this, SLOT(cursorPositionChanged(const QTextCursor &)));
+ }
+
+ int calls;
+
+private slots:
+ void cursorPositionChanged(const QTextCursor &)
+ {
+ ++calls;
+ }
+};
+
+void tst_QTextDocument::cursorPositionChanged()
+{
+ CursorPosSignalSpy spy(doc);
+
+ cursor.insertText("Test");
+ QCOMPARE(spy.calls, 1);
+
+ spy.calls = 0;
+ QTextCursor unrelatedCursor(doc);
+ unrelatedCursor.insertText("Blah");
+ QCOMPARE(spy.calls, 2);
+
+ spy.calls = 0;
+ cursor.insertText("Blah");
+ QCOMPARE(spy.calls, 1);
+
+ spy.calls = 0;
+ cursor.movePosition(QTextCursor::PreviousCharacter);
+ QCOMPARE(spy.calls, 0);
+}
+
+void tst_QTextDocument::cursorPositionChangedOnSetText()
+{
+ CursorPosSignalSpy spy(doc);
+
+ // doc has one QTextCursor stored in the
+ // cursor member variable, thus the signal
+ // gets emitted once.
+
+ doc->setPlainText("Foo\nBar\nBaz\nBlub\nBlah");
+
+ QCOMPARE(spy.calls, 1);
+
+ spy.calls = 0;
+ doc->setHtml("<p>Foo<p>Bar<p>Baz<p>Blah");
+
+ QCOMPARE(spy.calls, 1);
+}
+
+void tst_QTextDocument::textFrameIterator()
+{
+ cursor.insertTable(1, 1);
+
+ int blockCount = 0;
+ int frameCount = 0;
+
+ for (QTextFrame::Iterator frameIt = doc->rootFrame()->begin();
+ !frameIt.atEnd(); ++frameIt) {
+ if (frameIt.currentFrame())
+ ++frameCount;
+ else if (frameIt.currentBlock().isValid())
+ ++blockCount;
+
+ }
+
+ QEXPECT_FAIL("", "This is currently worked around in the html export but needs fixing!", Continue);
+ QCOMPARE(blockCount, 0);
+ QCOMPARE(frameCount, 1);
+}
+
+void tst_QTextDocument::codecForHtml()
+{
+ const QByteArray header("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;charset=utf-16\">");
+ QTextCodec *c = Qt::codecForHtml(header);
+ QVERIFY(c);
+ QCOMPARE(c->name(), QByteArray("UTF-16"));
+}
+
+class TestSyntaxHighlighter : public QObject
+{
+ Q_OBJECT
+public:
+ inline TestSyntaxHighlighter(QTextDocument *doc) : QObject(doc), ok(false) {}
+
+ bool ok;
+
+private slots:
+ inline void markBlockDirty(int from, int charsRemoved, int charsAdded)
+ {
+ Q_UNUSED(charsRemoved);
+ Q_UNUSED(charsAdded);
+ QTextDocument *doc = static_cast<QTextDocument *>(parent());
+ QTextBlock block = doc->findBlock(from);
+
+ QTestDocumentLayout *lout = qobject_cast<QTestDocumentLayout *>(doc->documentLayout());
+ lout->called = false;
+
+ doc->markContentsDirty(block.position(), block.length());
+
+ ok = (lout->called == false);
+ }
+
+ inline void modifyBlockAgain(int from, int charsRemoved, int charsAdded)
+ {
+ Q_UNUSED(charsRemoved);
+ Q_UNUSED(charsAdded);
+ QTextDocument *doc = static_cast<QTextDocument *>(parent());
+ QTextBlock block = doc->findBlock(from);
+ QTextCursor cursor(block);
+
+ QTestDocumentLayout *lout = qobject_cast<QTestDocumentLayout *>(doc->documentLayout());
+ lout->called = false;
+
+ cursor.insertText("Foo");
+
+ ok = (lout->called == true);
+ }
+};
+
+void tst_QTextDocument::markContentsDirty()
+{
+ QTestDocumentLayout *lout = new QTestDocumentLayout(doc);
+ doc->setDocumentLayout(lout);
+ TestSyntaxHighlighter *highlighter = new TestSyntaxHighlighter(doc);
+ connect(doc, SIGNAL(contentsChange(int, int, int)),
+ highlighter, SLOT(markBlockDirty(int, int, int)));
+
+ highlighter->ok = false;
+ cursor.insertText("Some dummy text blah blah");
+ QVERIFY(highlighter->ok);
+
+ disconnect(doc, SIGNAL(contentsChange(int, int, int)),
+ highlighter, SLOT(markBlockDirty(int, int, int)));
+ connect(doc, SIGNAL(contentsChange(int, int, int)),
+ highlighter, SLOT(modifyBlockAgain(int, int, int)));
+ highlighter->ok = false;
+ cursor.insertText("FooBar");
+ QVERIFY(highlighter->ok);
+
+ lout->called = false;
+
+ doc->markContentsDirty(1, 4);
+
+ QVERIFY(lout->called);
+}
+
+void tst_QTextDocument::clonePreservesMetaInformation()
+{
+ const QString title("Foobar");
+ const QString url("about:blank");
+ doc->setHtml("<html><head><title>" + title + "</title></head><body>Hrm</body></html>");
+ doc->setMetaInformation(QTextDocument::DocumentUrl, url);
+ QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), title);
+ QCOMPARE(doc->metaInformation(QTextDocument::DocumentUrl), url);
+
+ QTextDocument *clone = doc->clone();
+ QCOMPARE(clone->metaInformation(QTextDocument::DocumentTitle), title);
+ QCOMPARE(clone->metaInformation(QTextDocument::DocumentUrl), url);
+ delete clone;
+}
+
+void tst_QTextDocument::clonePreservesPageSize()
+{
+ QSizeF sz(100., 100.);
+ doc->setPageSize(sz);
+ QTextDocument *clone = doc->clone();
+ QCOMPARE(clone->pageSize(), sz);
+ delete clone;
+}
+
+void tst_QTextDocument::clonePreservesPageBreakPolicies()
+{
+ QTextTableFormat tableFmt;
+ tableFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysAfter);
+
+ QTextBlockFormat blockFmt;
+ blockFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore);
+
+ QTextCursor cursor(doc);
+
+ cursor.setBlockFormat(blockFmt);
+ cursor.insertText("foo");
+ cursor.insertTable(2, 2, tableFmt);
+
+ QTextDocument *clone = doc->clone();
+ QCOMPARE(clone->begin().blockFormat().pageBreakPolicy(), QTextFormat::PageBreak_AlwaysBefore);
+ QVERIFY(!clone->rootFrame()->childFrames().isEmpty());
+ QCOMPARE(clone->rootFrame()->childFrames().first()->frameFormat().pageBreakPolicy(), QTextFormat::PageBreak_AlwaysAfter);
+ delete clone;
+}
+
+void tst_QTextDocument::clonePreservesDefaultFont()
+{
+ QFont f = doc->defaultFont();
+ QVERIFY(f.pointSize() != 100);
+ f.setPointSize(100);
+ doc->setDefaultFont(f);
+ QTextDocument *clone = doc->clone();
+ QCOMPARE(clone->defaultFont(), f);
+ delete clone;
+}
+
+void tst_QTextDocument::clonePreservesResources()
+{
+ QUrl testUrl(":/foobar");
+ QVariant testResource("hello world");
+
+ doc->addResource(QTextDocument::ImageResource, testUrl, testResource);
+ QTextDocument *clone = doc->clone();
+ QVERIFY(clone->resource(QTextDocument::ImageResource, testUrl) == testResource);
+ delete clone;
+}
+
+void tst_QTextDocument::clonePreservesUserStates()
+{
+ QTextCursor cursor(doc);
+ cursor.insertText("bla bla bla");
+ cursor.block().setUserState(1);
+ cursor.insertBlock();
+ cursor.insertText("foo bar");
+ cursor.block().setUserState(2);
+ cursor.insertBlock();
+ cursor.insertText("no user state");
+
+ QTextDocument *clone = doc->clone();
+ QTextBlock b1 = doc->begin(), b2 = clone->begin();
+ while (b1 != doc->end()) {
+ b1 = b1.next();
+ b2 = b2.next();
+ QCOMPARE(b1.userState(), b2.userState());
+ }
+ QVERIFY(b2 == clone->end());
+ delete clone;
+}
+
+void tst_QTextDocument::clonePreservesRootFrameFormat()
+{
+ doc->setPlainText("Hello");
+ QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
+ fmt.setMargin(200);
+ doc->rootFrame()->setFrameFormat(fmt);
+ QCOMPARE(doc->rootFrame()->frameFormat().margin(), qreal(200));
+ QTextDocument *copy = doc->clone();
+ QCOMPARE(copy->rootFrame()->frameFormat().margin(), qreal(200));
+ delete copy;
+}
+
+void tst_QTextDocument::clonePreservesIndentWidth()
+{
+ doc->setIndentWidth(42);
+ QTextDocument *clone = doc->clone();
+ QCOMPARE(clone->indentWidth(), qreal(42));
+ delete clone;
+}
+
+void tst_QTextDocument::blockCount()
+{
+ QCOMPARE(doc->blockCount(), 1);
+ cursor.insertBlock();
+ QCOMPARE(doc->blockCount(), 2);
+ cursor.insertBlock();
+ QCOMPARE(doc->blockCount(), 3);
+ cursor.insertText("blah blah");
+ QCOMPARE(doc->blockCount(), 3);
+ doc->undo();
+ doc->undo();
+ QCOMPARE(doc->blockCount(), 2);
+ doc->undo();
+ QCOMPARE(doc->blockCount(), 1);
+}
+
+void tst_QTextDocument::resolvedFontInEmptyFormat()
+{
+ QFont font;
+ font.setPointSize(42);
+ doc->setDefaultFont(font);
+ QTextCharFormat fmt = doc->begin().charFormat();
+ QVERIFY(fmt.properties().isEmpty());
+ QVERIFY(fmt.font() == font);
+}
+
+void tst_QTextDocument::defaultRootFrameMargin()
+{
+ QCOMPARE(doc->rootFrame()->frameFormat().margin(), 4.0);
+}
+
+class TestDocument : public QTextDocument
+{
+public:
+ inline TestDocument(const QUrl &testUrl, const QString &testString)
+ : url(testUrl), string(testString), resourceLoaded(false) {}
+
+ bool hasResourceCached();
+
+protected:
+ virtual QVariant loadResource(int type, const QUrl &name);
+
+private:
+ QUrl url;
+ QString string;
+ bool resourceLoaded;
+};
+
+bool TestDocument::hasResourceCached()
+{
+ resourceLoaded = false;
+ resource(QTextDocument::ImageResource, url);
+ return !resourceLoaded;
+}
+
+QVariant TestDocument::loadResource(int type, const QUrl &name)
+{
+ if (type == QTextDocument::ImageResource
+ && name == url) {
+ resourceLoaded = true;
+ return string;
+ }
+ return QTextDocument::loadResource(type, name);
+}
+
+void tst_QTextDocument::clearResources()
+{
+ // regular resource for QTextDocument
+ QUrl testUrl(":/foobar");
+ QVariant testResource("hello world");
+
+ // implicitly cached resource, initially loaded through TestDocument::loadResource()
+ QUrl cacheUrl(":/blub");
+ QString cacheResource("mah");
+
+ TestDocument doc(cacheUrl, cacheResource);
+ doc.addResource(QTextDocument::ImageResource, testUrl, testResource);
+
+ QVERIFY(doc.resource(QTextDocument::ImageResource, testUrl) == testResource);
+
+ doc.setPlainText("Hah");
+ QVERIFY(doc.resource(QTextDocument::ImageResource, testUrl) == testResource);
+
+ doc.setHtml("<b>Mooo</b><img src=\":/blub\"/>");
+ QVERIFY(doc.resource(QTextDocument::ImageResource, testUrl) == testResource);
+ QVERIFY(doc.resource(QTextDocument::ImageResource, cacheUrl) == cacheResource);
+
+ doc.clear();
+ QVERIFY(!doc.resource(QTextDocument::ImageResource, testUrl).isValid());
+ QVERIFY(!doc.hasResourceCached());
+ doc.clear();
+
+ doc.setHtml("<b>Mooo</b><img src=\":/blub\"/>");
+ QVERIFY(doc.resource(QTextDocument::ImageResource, cacheUrl) == cacheResource);
+
+ doc.setPlainText("Foob");
+ QVERIFY(!doc.hasResourceCached());
+}
+
+void tst_QTextDocument::setPlainText()
+{
+ doc->setPlainText("Hello World");
+ QString s("");
+ doc->setPlainText(s);
+ QCOMPARE(doc->toPlainText(), s);
+}
+
+void tst_QTextDocument::toPlainText()
+{
+ doc->setHtml("Hello&nbsp;World");
+ QCOMPARE(doc->toPlainText(), QLatin1String("Hello World"));
+}
+
+void tst_QTextDocument::deleteTextObjectsOnClear()
+{
+ QPointer<QTextTable> table = cursor.insertTable(2, 2);
+ QVERIFY(!table.isNull());
+ doc->clear();
+ QVERIFY(table.isNull());
+}
+
+void tst_QTextDocument::defaultStyleSheet()
+{
+ const QString sheet("p { background-color: green; }");
+ QVERIFY(doc->defaultStyleSheet().isEmpty());
+ doc->setDefaultStyleSheet(sheet);
+ QCOMPARE(doc->defaultStyleSheet(), sheet);
+
+ cursor.insertHtml("<p>test");
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+
+ doc->clear();
+ cursor.insertHtml("<p>test");
+ fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+
+ QTextDocument *clone = doc->clone();
+ QCOMPARE(clone->defaultStyleSheet(), sheet);
+ cursor = QTextCursor(clone);
+ cursor.insertHtml("<p>test");
+ fmt = clone->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+ delete clone;
+
+ cursor = QTextCursor(doc);
+ cursor.insertHtml("<p>test");
+ fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+
+ doc->clear();
+ cursor.insertHtml("<style>p { background-color: red; }</style><p>test");
+ fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("red"));
+
+ doc->clear();
+ doc->setDefaultStyleSheet("invalid style sheet....");
+ cursor.insertHtml("<p>test");
+ fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() != QColor("green"));
+}
+
+void tst_QTextDocument::maximumBlockCount()
+{
+ QCOMPARE(doc->maximumBlockCount(), 0);
+ QVERIFY(doc->isUndoRedoEnabled());
+
+ cursor.insertBlock();
+ cursor.insertText("Blah");
+ cursor.insertBlock();
+ cursor.insertText("Foo");
+ QCOMPARE(doc->blockCount(), 3);
+ QCOMPARE(doc->toPlainText(), QString("\nBlah\nFoo"));
+
+ doc->setMaximumBlockCount(1);
+ QVERIFY(!doc->isUndoRedoEnabled());
+
+ QCOMPARE(doc->blockCount(), 1);
+ QCOMPARE(doc->toPlainText(), QString("Foo"));
+
+ cursor.insertBlock();
+ cursor.insertText("Hello");
+ doc->setMaximumBlockCount(1);
+ QCOMPARE(doc->blockCount(), 1);
+ QCOMPARE(doc->toPlainText(), QString("Hello"));
+
+ doc->setMaximumBlockCount(100);
+ for (int i = 0; i < 1000; ++i) {
+ cursor.insertBlock();
+ cursor.insertText("Blah)");
+ QVERIFY(doc->blockCount() <= 100);
+ }
+
+ cursor.movePosition(QTextCursor::End);
+ QCOMPARE(cursor.blockNumber(), 99);
+ QTextCharFormat fmt;
+ fmt.setFontItalic(true);
+ cursor.setBlockCharFormat(fmt);
+ cursor.movePosition(QTextCursor::Start);
+ QVERIFY(!cursor.blockCharFormat().fontItalic());
+
+ doc->setMaximumBlockCount(1);
+ QVERIFY(cursor.blockCharFormat().fontItalic());
+
+ cursor.insertTable(2, 2);
+ QCOMPARE(doc->blockCount(), 6);
+ cursor.insertBlock();
+ QCOMPARE(doc->blockCount(), 1);
+}
+
+void tst_QTextDocument::adjustSize()
+{
+ // avoid ugly tooltips like in task 125583
+ QString text("Test Text");
+ doc->setPlainText(text);
+ doc->rootFrame()->setFrameFormat(QTextFrameFormat());
+ doc->adjustSize();
+ QCOMPARE(doc->size().width(), doc->idealWidth());
+}
+
+void tst_QTextDocument::initialUserData()
+{
+ doc->setPlainText("Hello");
+ QTextBlock block = doc->begin();
+ block.setUserData(new QTextBlockUserData);
+ QVERIFY(block.userData());
+ doc->documentLayout();
+ QVERIFY(block.userData());
+ doc->setDocumentLayout(new QTestDocumentLayout(doc));
+ QVERIFY(!block.userData());
+}
+
+void tst_QTextDocument::html_defaultFont()
+{
+ QFont f;
+ f.setItalic(true);
+ f.setWeight(QFont::Bold);
+ doc->setDefaultFont(f);
+ doc->setPlainText("Test");
+
+ QString bodyPart = QString::fromLatin1("<body style=\" font-family:'%1'; font-size:%2pt; font-weight:%3; font-style:italic;\">")
+ .arg(f.family()).arg(f.pointSizeF()).arg(f.weight() * 8);
+
+ QString html = doc->toHtml();
+ if (!html.contains(bodyPart)) {
+ qDebug() << "html:" << html;
+ qDebug() << "expected body:" << bodyPart;
+ QVERIFY(html.contains(bodyPart));
+ }
+
+ if (html.contains("span"))
+ qDebug() << "html:" << html;
+ QVERIFY(!html.contains("<span style"));
+}
+
+void tst_QTextDocument::blockCountChanged()
+{
+ QSignalSpy spy(doc, SIGNAL(blockCountChanged(int)));
+
+ doc->setPlainText("Foo");
+
+ QCOMPARE(doc->blockCount(), 1);
+ QCOMPARE(spy.count(), 0);
+
+ spy.clear();
+
+ doc->setPlainText("Foo\nBar");
+ QCOMPARE(doc->blockCount(), 2);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).value(0).toInt(), 2);
+
+ spy.clear();
+
+ cursor.movePosition(QTextCursor::End);
+ cursor.insertText("Blahblah");
+
+ QCOMPARE(spy.count(), 0);
+
+ cursor.insertBlock();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).value(0).toInt(), 3);
+
+ spy.clear();
+ doc->undo();
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).value(0).toInt(), 2);
+}
+
+void tst_QTextDocument::nonZeroDocumentLengthOnClear()
+{
+ QTestDocumentLayout *lout = new QTestDocumentLayout(doc);
+ doc->setDocumentLayout(lout);
+
+ doc->clear();
+ QVERIFY(lout->called);
+ QVERIFY(!lout->lastDocumentLengths.contains(0));
+}
+
+void tst_QTextDocument::setTextPreservesUndoRedoEnabled()
+{
+ QVERIFY(doc->isUndoRedoEnabled());
+
+ doc->setPlainText("Test");
+
+ QVERIFY(doc->isUndoRedoEnabled());
+
+ doc->setUndoRedoEnabled(false);
+ QVERIFY(!doc->isUndoRedoEnabled());
+ doc->setPlainText("Test2");
+ QVERIFY(!doc->isUndoRedoEnabled());
+
+ doc->setHtml("<p>hello");
+ QVERIFY(!doc->isUndoRedoEnabled());
+}
+
+void tst_QTextDocument::firstLast()
+{
+ QCOMPARE(doc->blockCount(), 1);
+ QVERIFY(doc->firstBlock() == doc->lastBlock());
+
+ doc->setPlainText("Hello\nTest\nWorld");
+
+ QCOMPARE(doc->blockCount(), 3);
+ QVERIFY(doc->firstBlock() != doc->lastBlock());
+
+ QCOMPARE(doc->firstBlock().text(), QString("Hello"));
+ QCOMPARE(doc->lastBlock().text(), QString("World"));
+
+ // manual forward loop
+ QTextBlock block = doc->firstBlock();
+
+ QVERIFY(block.isValid());
+ QCOMPARE(block.text(), QString("Hello"));
+
+ block = block.next();
+
+ QVERIFY(block.isValid());
+ QCOMPARE(block.text(), QString("Test"));
+
+ block = block.next();
+
+ QVERIFY(block.isValid());
+ QCOMPARE(block.text(), QString("World"));
+
+ block = block.next();
+ QVERIFY(!block.isValid());
+
+ // manual backward loop
+ block = doc->lastBlock();
+
+ QVERIFY(block.isValid());
+ QCOMPARE(block.text(), QString("World"));
+
+ block = block.previous();
+
+ QVERIFY(block.isValid());
+ QCOMPARE(block.text(), QString("Test"));
+
+ block = block.previous();
+
+ QVERIFY(block.isValid());
+ QCOMPARE(block.text(), QString("Hello"));
+
+ block = block.previous();
+ QVERIFY(!block.isValid());
+}
+
+const QString backgroundImage_html("<body><table><tr><td background=\"foo.png\">Blah</td></tr></table></body>");
+
+void tst_QTextDocument::backgroundImage_checkExpectedHtml(const QTextDocument &doc)
+{
+ QString expectedHtml("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+ "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+ "p, li { white-space: pre-wrap; }\n"
+ "</style></head>"
+ "<body style=\" font-family:'%1'; font-size:%2pt; font-weight:%3; font-style:%4;\">\n"
+ "<table border=\"0\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;\" cellspacing=\"2\" cellpadding=\"0\">"
+ "\n<tr>\n<td background=\"foo.png\">"
+ "\n<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blah</p>"
+ "</td></tr></table></body></html>");
+
+ expectedHtml = expectedHtml.arg(defaultFont.family()).arg(defaultFont.pointSizeF()).arg(defaultFont.weight() * 8).arg((defaultFont.italic() ? "italic" : "normal"));
+
+ QCOMPARE(doc.toHtml(), expectedHtml);
+}
+
+void tst_QTextDocument::backgroundImage_toHtml()
+{
+ CREATE_DOC_AND_CURSOR();
+
+ doc.setHtml(backgroundImage_html);
+ backgroundImage_checkExpectedHtml(doc);
+}
+
+void tst_QTextDocument::backgroundImage_toHtml2()
+{
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertHtml(backgroundImage_html);
+ backgroundImage_checkExpectedHtml(doc);
+}
+
+void tst_QTextDocument::backgroundImage_clone()
+{
+ CREATE_DOC_AND_CURSOR();
+
+ doc.setHtml(backgroundImage_html);
+ QTextDocument *clone = doc.clone();
+ backgroundImage_checkExpectedHtml(*clone);
+ delete clone;
+}
+
+void tst_QTextDocument::backgroundImage_copy()
+{
+ CREATE_DOC_AND_CURSOR();
+
+ doc.setHtml(backgroundImage_html);
+ QTextDocumentFragment fragment(&doc);
+
+ {
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertFragment(fragment);
+ backgroundImage_checkExpectedHtml(doc);
+ }
+}
+
+void tst_QTextDocument::documentCleanup()
+{
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ cursor.insertText("d\nfoo\nbar\n");
+ doc.documentLayout(); // forces relayout
+
+ // remove char 1
+ cursor.setPosition(0);
+ QSizeF size = doc.documentLayout()->documentSize();
+ cursor.deleteChar();
+ // the size should be unchanged.
+ QCOMPARE(doc.documentLayout()->documentSize(), size);
+}
+
+void tst_QTextDocument::characterAt()
+{
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ QString text("12345\n67890");
+ cursor.insertText(text);
+ int length = doc.characterCount();
+ QCOMPARE(length, text.length() + 1);
+ QCOMPARE(doc.characterAt(length-1), QChar(QChar::ParagraphSeparator));
+ QCOMPARE(doc.characterAt(-1), QChar());
+ QCOMPARE(doc.characterAt(length), QChar());
+ QCOMPARE(doc.characterAt(length + 1), QChar());
+ for (int i = 0; i < text.length(); ++i) {
+ QChar c = text.at(i);
+ if (c == QLatin1Char('\n'))
+ c = QChar(QChar::ParagraphSeparator);
+ QCOMPARE(doc.characterAt(i), c);
+ }
+}
+
+void tst_QTextDocument::revisions()
+{
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ QString text("Hello World");
+ QCOMPARE(doc.firstBlock().revision(), 0);
+ cursor.insertText(text);
+ QCOMPARE(doc.firstBlock().revision(), 1);
+ cursor.setPosition(6);
+ cursor.insertBlock();
+ QCOMPARE(cursor.block().previous().revision(), 2);
+ QCOMPARE(cursor.block().revision(), 2);
+ cursor.insertText("candle");
+ QCOMPARE(cursor.block().revision(), 3);
+ cursor.movePosition(QTextCursor::EndOfBlock);
+ cursor.insertBlock(); // we are at the block end
+ QCOMPARE(cursor.block().previous().revision(), 3);
+ QCOMPARE(cursor.block().revision(), 4);
+ cursor.insertText("lightbulb");
+ QCOMPARE(cursor.block().revision(), 5);
+ cursor.movePosition(QTextCursor::StartOfBlock);
+ cursor.insertBlock(); // we are the block start
+ QCOMPARE(cursor.block().previous().revision(), 6);
+ QCOMPARE(cursor.block().revision(), 5);
+}
+
+void tst_QTextDocument::revisionWithUndoCompressionAndUndo()
+{
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ cursor.insertText("This is the beginning of it all.");
+ QCOMPARE(doc.firstBlock().revision(), 1);
+ QCOMPARE(doc.revision(), 1);
+ cursor.insertBlock();
+ QCOMPARE(doc.revision(), 2);
+ cursor.insertText("this");
+ QCOMPARE(doc.revision(), 3);
+ cursor.insertText("is");
+ QCOMPARE(doc.revision(), 4);
+ cursor.insertText("compressed");
+ QCOMPARE(doc.revision(), 5);
+ doc.undo();
+ QCOMPARE(doc.revision(), 6);
+ QCOMPARE(doc.toPlainText(), QString("This is the beginning of it all.\n")) ;
+ cursor.setPosition(0);
+ QCOMPARE(doc.firstBlock().revision(), 1);
+ cursor.insertText("Very beginnig");
+ QCOMPARE(doc.firstBlock().revision(), 7);
+ doc.undo();
+ QCOMPARE(doc.revision(), 8);
+ QCOMPARE(doc.firstBlock().revision(), 1);
+
+ cursor.beginEditBlock();
+ cursor.insertText("Hello");
+ cursor.insertBlock();
+ cursor.insertText("world");
+ cursor.endEditBlock();
+ QCOMPARE(doc.revision(), 9);
+ doc.undo();
+ QCOMPARE(doc.revision(), 10);
+
+
+}
+
+void tst_QTextDocument::testUndoCommandAdded()
+{
+ QVERIFY(doc);
+ QSignalSpy spy(doc, SIGNAL(undoCommandAdded()));
+ QVERIFY(spy.isValid());
+ QVERIFY(spy.isEmpty());
+
+ cursor.insertText("a");
+ QCOMPARE(spy.count(), 1);
+ cursor.insertText("b"); // should be merged
+ QCOMPARE(spy.count(), 1);
+ cursor.insertText("c"); // should be merged
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(doc->toPlainText(), QString("abc"));
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString(""));
+
+ doc->clear();
+ spy.clear();
+ cursor.insertText("aaa");
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ cursor.insertText("aaaa\nbcd");
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ cursor.beginEditBlock();
+ cursor.insertText("aa");
+ cursor.insertText("bbb\n");
+ cursor.setCharFormat(QTextCharFormat());
+ cursor.insertText("\nccc");
+ QVERIFY(spy.isEmpty());
+ cursor.endEditBlock();
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ cursor.insertBlock();
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ cursor.setPosition(5);
+ QVERIFY(spy.isEmpty());
+ cursor.setCharFormat(QTextCharFormat());
+ QVERIFY(spy.isEmpty());
+ cursor.setPosition(10, QTextCursor::KeepAnchor);
+ QVERIFY(spy.isEmpty());
+ QTextCharFormat cf;
+ cf.setFontItalic(true);
+ cursor.mergeCharFormat(cf);
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ doc->undo();
+ QCOMPARE(spy.count(), 0);
+ doc->undo();
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+ doc->redo();
+ QCOMPARE(spy.count(), 0);
+ doc->redo();
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QTextDocument::testUndoBlocks()
+{
+ QVERIFY(doc);
+ cursor.insertText("Hello World");
+ cursor.insertText("period");
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString(""));
+ cursor.insertText("Hello World");
+ cursor.insertText("One\nTwo\nThree");
+ QCOMPARE(doc->toPlainText(), QString("Hello WorldOne\nTwo\nThree"));
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString("Hello World"));
+ cursor.insertText("One\nTwo\nThree");
+ cursor.insertText("Trailing text");
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString("Hello WorldOne\nTwo\nThree"));
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString("Hello World"));
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString(""));
+
+ cursor.insertText("quod");
+ cursor.beginEditBlock();
+ cursor.insertText(" erat");
+ cursor.endEditBlock();
+ cursor.insertText(" demonstrandum");
+ QCOMPARE(doc->toPlainText(), QString("quod erat demonstrandum"));
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString("quod erat"));
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString("quod"));
+ doc->undo();
+ QCOMPARE(doc->toPlainText(), QString(""));
+}
+
+class Receiver : public QObject
+{
+ Q_OBJECT
+ public:
+ QString first;
+ public slots:
+ void cursorPositionChanged() {
+ if (first.isEmpty())
+ first = QLatin1String("cursorPositionChanged");
+ }
+
+ void contentsChange() {
+ if (first.isEmpty())
+ first = QLatin1String("contentsChanged");
+ }
+};
+
+void tst_QTextDocument::receiveCursorPositionChangedAfterContentsChange()
+{
+ QVERIFY(doc);
+ doc->setDocumentLayout(new MyAbstractTextDocumentLayout(doc));
+ Receiver rec;
+ connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)),
+ &rec, SLOT(cursorPositionChanged()));
+ connect(doc, SIGNAL(contentsChange(int,int,int)),
+ &rec, SLOT(contentsChange()));
+ cursor.insertText("Hello World");
+ QCOMPARE(rec.first, QString("contentsChanged"));
+}
+
+void tst_QTextDocument::escape_data()
+{
+ QTest::addColumn<QString>("original");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("1") << "Hello World\n" << "Hello World\n";
+ QTest::newRow("2") << "#include <QtCore>" << "#include &lt;QtCore&gt;";
+ QTest::newRow("3") << "<p class=\"cool\"><a href=\"http://example.com/?foo=bar&amp;bar=foo\">plop --&gt; </a></p>"
+ << "&lt;p class=&quot;cool&quot;&gt;&lt;a href=&quot;http://example.com/?foo=bar&amp;amp;bar=foo&quot;&gt;plop --&amp;gt; &lt;/a&gt;&lt;/p&gt;";
+ QTest::newRow("4") << QString::fromUtf8("<\320\222\321\201>") << QString::fromUtf8("&lt;\320\222\321\201&gt;");
+}
+
+void tst_QTextDocument::escape()
+{
+ QFETCH(QString, original);
+ QFETCH(QString, expected);
+
+ QCOMPARE(Qt::escape(original), expected);
+}
+
+void tst_QTextDocument::copiedFontSize()
+{
+ QTextDocument documentInput;
+ QTextDocument documentOutput;
+
+ QFont fontInput;
+ fontInput.setPixelSize(24);
+
+ QTextCursor cursorInput(&documentInput);
+ QTextCharFormat formatInput = cursorInput.charFormat();
+ formatInput.setFont(fontInput);
+ cursorInput.insertText("Should be the same font", formatInput);
+ cursorInput.select(QTextCursor::Document);
+
+ QTextDocumentFragment fragmentInput(cursorInput);
+ QString html = fragmentInput.toHtml();
+
+ QTextCursor cursorOutput(&documentOutput);
+ QTextDocumentFragment fragmentOutput = QTextDocumentFragment::fromHtml(html);
+ cursorOutput.insertFragment(fragmentOutput);
+
+ QCOMPARE(cursorOutput.charFormat().font().pixelSize(), 24);
+}
+
+void tst_QTextDocument::htmlExportImportBlockCount()
+{
+ QTextDocument document;
+ {
+ QTextCursor cursor(&document);
+ cursor.insertText("Foo");
+ cursor.insertBlock();
+ cursor.insertBlock();
+ cursor.insertBlock();
+ cursor.insertBlock();
+ cursor.insertText("Bar");
+ }
+
+ QCOMPARE(document.blockCount(), 5);
+ QString html = document.toHtml();
+
+ document.clear();
+ document.setHtml(html);
+
+ QCOMPARE(document.blockCount(), 5);
+}
+
+QTEST_MAIN(tst_QTextDocument)
+#include "tst_qtextdocument.moc"
diff --git a/tests/auto/gui/text/qtextdocumentfragment/.gitignore b/tests/auto/gui/text/qtextdocumentfragment/.gitignore
new file mode 100644
index 0000000000..5c569834d3
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocumentfragment/.gitignore
@@ -0,0 +1 @@
+tst_qtextdocumentfragment
diff --git a/tests/auto/gui/text/qtextdocumentfragment/qtextdocumentfragment.pro b/tests/auto/gui/text/qtextdocumentfragment/qtextdocumentfragment.pro
new file mode 100644
index 0000000000..e6ddd45f85
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocumentfragment/qtextdocumentfragment.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT += core-private gui-private
+
+SOURCES += tst_qtextdocumentfragment.cpp
+
+
+
diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
new file mode 100644
index 0000000000..68c7a285ef
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -0,0 +1,4030 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qtextdocument.h>
+#include <qtextdocumentfragment.h>
+#include <qtexttable.h>
+#include <qtextlist.h>
+#include <qdebug.h>
+#include <private/qtextdocument_p.h>
+
+
+#include <qtextcursor.h>
+
+QT_FORWARD_DECLARE_CLASS(QTextDocument)
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/text/qtextdocumentfragment.h gui/text/qtextdocumentfragment.cpp gui/text/qtexthtmlparser.cpp gui/text/qtexthtmlparser_p.h
+
+class tst_QTextDocumentFragment : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTextDocumentFragment();
+ ~tst_QTextDocumentFragment();
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void listCopying();
+ void listZeroCopying();
+ void listCopying2();
+ void tableCopying();
+ void tableCopyingWithColSpans();
+ void tableColSpanAndWidth();
+ void tableImport();
+ void tableImport2();
+ void tableImport3();
+ void tableImport4();
+ void tableImport5();
+ void textCopy();
+ void copyWholeDocument();
+ void title();
+ void html_listIndents1();
+ void html_listIndents2();
+ void html_listIndents3();
+ void html_listIndents4();
+ void html_listIndents5();
+ void html_listIndents6();
+ void blockCharFormat();
+ void blockCharFormatCopied();
+ void initialBlock();
+ void clone();
+ void dontRemoveInitialBlockIfItHoldsObjectIndexedCharFormat();
+ void dosLineFeed();
+ void unorderedListEnumeration();
+ void resetHasBlockAfterClosedBlockTags();
+ void ignoreStyleTags();
+ void hrefAnchor();
+ void namedAnchorFragments();
+ void namedAnchorFragments2();
+ void namedAnchorFragments3();
+ void dontInheritAlignmentInTables();
+ void cellBlockCount();
+ void cellBlockCount2();
+ void emptyTable();
+ void emptyTable2();
+ void emptyTable3();
+ void doubleRowClose();
+ void mayNotHaveChildren();
+ void inheritAlignment();
+ void dontEmitEmptyNodeWhenEmptyTagIsFollowedByCloseTag();
+ void toPlainText();
+ void copyTableRow();
+ void copyTableColumn();
+ void copySubTable();
+ void html_textDecoration();
+ void html_infiniteLoop();
+ void html_blockIndent();
+ void html_listIndent();
+ void html_whitespace();
+ void html_whitespace_data();
+ void html_qt3Whitespace();
+ void html_qt3WhitespaceWithFragments();
+ void html_qt3WhitespaceAfterTags();
+ void html_listStart1();
+ void html_listStart2();
+ void html_cssMargin();
+ void html_hexEntities();
+ void html_decEntities();
+ void html_thCentered();
+ void orderedListNumbering();
+ void html_blockAfterList();
+ void html_subAndSuperScript();
+ void html_cssColors();
+ void obeyFragmentMarkersInImport();
+ void whitespaceWithFragmentMarkers();
+ void html_emptyParapgraphs1();
+ void html_emptyParapgraphs2();
+ void html_emptyParagraphs3();
+ void html_emptyParagraphs4();
+ void html_font();
+ void html_fontSize();
+ void html_fontSizeAdjustment();
+ void html_cssFontSize();
+ void html_cssShorthandFont();
+ void html_bodyBgColor();
+ void html_qtBgColor();
+ void html_blockLevelDiv();
+ void html_spanNesting();
+ void html_nestedLists();
+ void noSpecialCharactersInPlainText();
+ void html_doNotInheritBackground();
+ void html_inheritBackgroundToInlineElements();
+ void html_doNotInheritBackgroundFromBlockElements();
+ void html_nobr();
+ void fromPlainText();
+ void fromPlainText2();
+ void html_closingImageTag();
+ void html_emptyDocument();
+ void html_closingTag();
+ void html_anchorAroundImage();
+ void html_floatBorder();
+ void html_frameImport();
+ void html_frameImport2();
+ void html_dontAddMarginsAcrossTableCells();
+ void html_dontMergeCenterBlocks();
+ void html_tableCellBgColor();
+ void html_tableCellBgColor2();
+ void html_cellSkip();
+ void nonZeroMarginOnImport();
+ void html_charFormatPropertiesUnset();
+ void html_headings();
+ void html_quotedFontFamily();
+ void html_spanBackgroundColor();
+ void defaultFont();
+ void html_brokenTitle_data();
+ void html_brokenTitle();
+ void html_blockVsInline();
+ void html_tbody();
+ void html_nestedTables();
+ void html_rowSpans();
+ void html_rowSpans2();
+ void html_implicitParagraphs();
+ void html_missingCloseTag();
+ void html_anchorColor();
+ void html_lastParagraphClosing();
+ void html_tableHeaderBodyFootParent();
+ void html_columnWidths();
+ void html_bodyBackground();
+ void html_tableCellBackground();
+ void css_bodyBackground();
+ void css_tableCellBackground();
+ void css_fontWeight();
+ void css_float();
+ void css_textIndent();
+ void css_inline();
+ void css_external();
+ void css_import();
+ void css_selectors_data();
+ void css_selectors();
+ void css_nodeNameCaseInsensitivity();
+ void css_textUnderlineStyle_data();
+ void css_textUnderlineStyle();
+ void css_textUnderlineStyleAndDecoration();
+ void css_listStyleType();
+ void css_linkPseudo();
+ void css_pageBreaks();
+ void css_cellPaddings();
+ void universalSelectors_data();
+ void universalSelectors();
+ void screenMedia();
+ void htmlResourceLoading();
+ void someCaseInsensitiveAttributeValues();
+ void backgroundImage();
+ void dontMergePreAndNonPre();
+ void leftMarginInsideHtml();
+ void html_margins();
+ void newlineInsidePreShouldBecomeNewParagraph();
+ void invalidColspan();
+ void html_brokenTableWithJustTr();
+ void html_brokenTableWithJustTd();
+ void html_preNewlineHandling_data();
+ void html_preNewlineHandling();
+ void html_br();
+ void html_dl();
+ void html_tableStrangeNewline();
+ void html_tableStrangeNewline2();
+ void html_tableStrangeNewline3();
+ void html_caption();
+ void html_windowsEntities();
+ void html_eatenText();
+ void html_hr();
+ void html_hrMargins();
+ void html_blockQuoteMargins();
+ void html_definitionListMargins();
+ void html_listMargins();
+ void html_titleAttribute();
+ void html_compressDivs();
+ void completeToPlainText();
+ void copyContents();
+ void html_textAfterHr();
+ void blockTagClosing();
+ void isEmpty();
+ void html_alignmentInheritance();
+ void html_ignoreEmptyDivs();
+ void html_dontInheritAlignmentForFloatingImages();
+ void html_verticalImageAlignment();
+ void html_verticalCellAlignment();
+ void html_borderColor();
+ void html_borderStyle();
+ void html_borderWidth();
+ void html_userState();
+ void html_rootFrameProperties();
+ void html_alignmentPropertySet();
+ void html_appendList();
+ void html_appendList2();
+ void html_qt3RichtextWhitespaceMode();
+ void html_brAfterHr();
+ void html_unclosedHead();
+ void html_entities();
+ void html_entities_data();
+ void html_ignore_script();
+ void html_directionWithHtml();
+ void html_directionWithRichText();
+ void html_metaInBody();
+ void html_importImageWithoutAspectRatio();
+ void html_fromFirefox();
+
+private:
+ inline void setHtml(const QString &html)
+ // don't take the shortcut in QTextDocument::setHtml
+ { doc->clear(); QTextCursor(doc).insertFragment(QTextDocumentFragment::fromHtml(html)); }
+
+ inline void appendHtml(const QString &html)
+ {
+ QTextCursor cursor(doc);
+ cursor.movePosition(QTextCursor::End);
+ cursor.insertHtml(html);
+ }
+
+ QTextDocument *doc;
+ QTextCursor cursor;
+};
+
+tst_QTextDocumentFragment::tst_QTextDocumentFragment()
+{
+ QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
+ img.save("foo.png");
+}
+
+tst_QTextDocumentFragment::~tst_QTextDocumentFragment()
+{
+ QFile::remove(QLatin1String("foo.png"));
+}
+
+void tst_QTextDocumentFragment::init()
+{
+ doc = new QTextDocument;
+ cursor = QTextCursor(doc);
+}
+
+void tst_QTextDocumentFragment::cleanup()
+{
+ cursor = QTextCursor();
+ delete doc;
+ doc = 0;
+}
+
+#include <private/qtextdocument_p.h>
+#include <qdebug.h>
+static void dumpTable(const QTextDocumentPrivate *pt)
+{
+ qDebug() << "---dump----";
+ qDebug() << "all text:" << pt->buffer();
+ for (QTextDocumentPrivate::FragmentIterator it = pt->begin();
+ !it.atEnd(); ++it) {
+ qDebug() << "Fragment at text position" << it.position() << "; stringPosition" << it.value()->stringPosition << "; size" << it.value()->size_array[0] << "format :" << it.value()->format << "frag: " << it.n;
+ qDebug() << " text:" << pt->buffer().mid(it.value()->stringPosition, it.value()->size_array[0]);
+ }
+ qDebug() << "----begin block dump----";
+ for (QTextBlock it = pt->blocksBegin(); it.isValid(); it = it.next())
+ qDebug() << "block at" << it.position() << "with length" << it.length() << "block alignment" << it.blockFormat().alignment();
+ qDebug() << "---dump----";
+}
+static void dumpTable(QTextDocument *doc) { dumpTable(doc->docHandle()); }
+
+void tst_QTextDocumentFragment::listCopying()
+{
+ cursor.insertList(QTextListFormat::ListDecimal);
+
+ QTextFormat originalBlockFormat = cursor.blockFormat();
+ QVERIFY(originalBlockFormat.objectIndex() != -1);
+ int originalListItemIdx = cursor.blockFormat().objectIndex();
+
+ cursor.insertText("Hello World");
+
+ QTextDocumentFragment fragment(doc);
+
+ cursor.insertFragment(fragment);
+
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.blockFormat() != originalBlockFormat);
+ QVERIFY(cursor.blockFormat().objectIndex() != originalListItemIdx);
+}
+
+void tst_QTextDocumentFragment::listZeroCopying()
+{
+ // same testcase as above but using the zero-copying
+
+ cursor.insertList(QTextListFormat::ListDecimal);
+
+ QTextFormat originalBlockFormat = cursor.blockFormat();
+ int originalListItemIdx = cursor.blockFormat().objectIndex();
+
+ cursor.insertText("Hello World");
+
+ QTextDocumentFragment fragment(doc);
+ cursor.insertFragment(fragment);
+
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.blockFormat() != originalBlockFormat);
+ QVERIFY(cursor.blockFormat().objectIndex() != originalListItemIdx);
+}
+
+void tst_QTextDocumentFragment::listCopying2()
+{
+ cursor.insertList(QTextListFormat::ListDecimal);
+ cursor.insertText("Hello World");
+
+ cursor.insertList(QTextListFormat::ListDisc);
+ cursor.insertText("Hello World");
+
+ QTextDocumentFragment fragment(doc);
+
+ cursor.insertFragment(fragment);
+
+ cursor.movePosition(QTextCursor::Start);
+ int listItemCount = 0;
+ do {
+ if (cursor.currentList())
+ listItemCount++;
+ } while (cursor.movePosition(QTextCursor::NextBlock));
+
+ QCOMPARE(listItemCount, 4);
+
+ // we call this here because it used to cause a failing assertion in the
+ // list manager.
+ doc->undo();
+}
+
+void tst_QTextDocumentFragment::tableCopying()
+{
+ // this tests both, the fragment to use the direction insertion instead of using the
+ // cursor, which might adjuts its position when inserting a table step by step, as well
+ // as the pasiveness of the tablemanager.
+ QTextDocumentFragment fragment;
+ {
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+
+ QTextTableFormat fmt;
+ QTextTable *table = cursor.insertTable(2, 2, fmt);
+
+ table->cellAt(0, 0).firstCursorPosition().insertText("First Cell");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second Cell");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third Cell");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth Cell");
+
+ fragment = QTextDocumentFragment(&doc);
+ }
+ {
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+
+ cursor.insertText("FooBar");
+ cursor.insertBlock();
+ cursor.movePosition(QTextCursor::Left);
+
+ cursor.insertFragment(fragment);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+ }
+}
+
+void tst_QTextDocumentFragment::tableCopyingWithColSpans()
+{
+ const char html[] = ""
+"<table border>"
+" <tr>"
+" <td>First Cell"
+" <td>Second Cell"
+" </tr>"
+" <tr>"
+" <td colspan=\"2\">Third Cell"
+" </tr>"
+" <tr>"
+" <td>Fourth Cell"
+" <td>Fifth Cell"
+" </tr>"
+"</table>";
+ setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QVERIFY(table->columns() == 2 && table->rows() == 3);
+
+ cursor = table->cellAt(2, 0).lastCursorPosition();
+ cursor.setPosition(table->cellAt(0, 0).firstPosition(), QTextCursor::KeepAnchor);
+ QVERIFY(cursor.hasComplexSelection());
+
+ int firstRow = 0, numRows = 0, firstCol = 0, numCols = 0;
+ cursor.selectedTableCells(&firstRow, &numRows, &firstCol, &numCols);
+ QCOMPARE(firstRow, 0);
+ QCOMPARE(numRows, 3);
+ QCOMPARE(firstCol, 0);
+ QCOMPARE(numCols, 1);
+
+ QTextDocumentFragment frag = cursor.selection();
+ cleanup();
+ init();
+ cursor.insertFragment(frag);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ table = cursor.currentTable();
+ QVERIFY(table);
+ QVERIFY(table->columns() == 1 && table->rows() == 3);
+}
+
+void tst_QTextDocumentFragment::tableColSpanAndWidth()
+{
+ const char html[] = ""
+"<table border=\"0\">"
+" <tr>"
+" <td colspan=\"4\" width=\"400\">First Cell</td>"
+" </tr>"
+"</table>";
+ setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QVERIFY(table->columns() == 4 && table->rows() == 1);
+ // make sure its approx 400 and not a multiple due to the colspan
+ QVERIFY(doc->size().width()> 398.);
+ QVERIFY(doc->size().width() < 420.);
+}
+
+void tst_QTextDocumentFragment::tableImport()
+{
+ // used to cause a failing assertion, as HTMLImporter::closeTag was
+ // called twice with the last node.
+ QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(QString::fromLatin1("<table><tr><td>Hey</td><td>Blah"));
+ QVERIFY(!fragment.isEmpty());
+}
+
+void tst_QTextDocumentFragment::tableImport2()
+{
+ {
+ const char html[] = ""
+ "<table>"
+ "<tr><td>First Cell</td><td>Second Cell</td></tr>"
+ "<tr><td>Third Cell</td><td>Fourth Cell</td></tr>"
+ "</table>";
+
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 2);
+ }
+ {
+ const char html[] = ""
+ "<table>"
+ "<tr><td>First Cell</td><td>Second Cell</td></tr>"
+ "<tr><td>Third Cell</td><td>"
+ " <table>"
+ " <tr><td>First Nested Cell</td><td>Second Nested Cell</td></tr>"
+ " <tr><td>Third Nested Cell</td><td>Fourth Nested Cell</td></tr>"
+ " <tr><td>Fifth Nested Cell</td><td>Sixth Nested Cell</td></tr>"
+ " </table></td></tr>"
+ "</table>";
+
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 2);
+
+ /*
+ QTextCursor fourthCell = table->cellAt(1, 1).firstCursorPosition();
+ fourthCell.movePosition(QTextCursor::NextBlock);
+ table = fourthCell.currentTable();
+ QVERIFY(table);
+ QVERIFY(table != cursor.currentTable());
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 3);
+ */
+ }
+ {
+ const char buggyHtml[] = ""
+ "<table>"
+ "<tr><td>First Cell<td>Second Cell"
+ "<tr><td>Third Cell<td>Fourth Cell"
+ "</table>";
+
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(buggyHtml, sizeof(buggyHtml) / sizeof(buggyHtml[0]))));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 2);
+ }
+ {
+ const char buggyHtml[] = ""
+ "<table>"
+ "<tr><th>First Cell<th>Second Cell"
+ "<tr><td>Third Cell<td>Fourth Cell"
+ "</table>";
+
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(buggyHtml, sizeof(buggyHtml) / sizeof(buggyHtml[0]))));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 2);
+ }
+
+}
+
+void tst_QTextDocumentFragment::tableImport3()
+{
+ // ### would be better to have tree tests for QTextHtmlParser
+ // make sure the p is a child of the td. If not the following td
+ // ends up outside the table, causing an assertion
+ const char html[] = "<table><tr><td><p></p></td><td></td></tr></table>";
+ QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(QString::fromLatin1(html));
+ QVERIFY(!fragment.isEmpty());
+}
+
+void tst_QTextDocumentFragment::tableImport4()
+{
+ const char html[] = "<table>"
+ "<tr><td>blah</td></tr>"
+ "<tr><td>blah</td><td>blah</td></tr>"
+ "</table>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+ QCOMPARE(cursor.currentTable()->columns(), 2);
+}
+
+void tst_QTextDocumentFragment::tableImport5()
+{
+ const char html[] = "<table>"
+ "<tr>"
+ " <td>Foo</td>"
+ " <td>Bar</td>"
+ " <td>Bleh</td>"
+ " <td>Blub</td>"
+ "</tr>"
+ "<tr>"
+ " <td>Ahh</td>"
+ " <td colspan=5>Gah</td>"
+ "</tr>"
+ "</table>";
+
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+ QCOMPARE(cursor.currentTable()->rows(), 2);
+ QCOMPARE(cursor.currentTable()->columns(), 6);
+}
+
+void tst_QTextDocumentFragment::textCopy()
+{
+ /* this test used to cause failing assertions in QTextDocumentFragment */
+ /* copy&paste 'lo\bwor' */
+ cursor.insertText("Hello");
+ cursor.insertBlock();
+ cursor.insertText("World");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, 3);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 3);
+
+ QTextDocumentFragment fragment(cursor);
+ QVERIFY(!fragment.isEmpty());
+ cursor.insertFragment(fragment);
+}
+
+void tst_QTextDocumentFragment::copyWholeDocument()
+{
+ // used to cause the famous currentBlock.position() == pos + 1 failing assertion
+ cursor.insertText("\nHey\nBlah\n");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+
+ QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
+ fmt.setBackground(Qt::blue);
+ doc->rootFrame()->setFrameFormat(fmt);
+
+ QTextDocumentFragment fragment(cursor);
+ QVERIFY(true); // good if we reach this point :)
+
+ cleanup();
+ init();
+
+ fmt.setBackground(Qt::red);
+ doc->rootFrame()->setFrameFormat(fmt);
+
+ cursor.insertFragment(fragment);
+
+ QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::red);
+}
+
+void tst_QTextDocumentFragment::title()
+{
+ doc->setHtml(QString::fromLatin1("<html><head><title>Test</title></head><body>Blah</body></html>"));
+ QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), QString::fromLatin1("Test"));
+}
+
+void tst_QTextDocumentFragment::html_listIndents1()
+{
+ const char html[] = "<ul><li>Hey</li><li>Hah</li></ul>";
+ setHtml(QString::fromLatin1(html));
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextList *list = cursor.currentList();
+ QVERIFY(list);
+ QCOMPARE(list->format().indent(), 1);
+ QCOMPARE(cursor.block().blockFormat().indent(), 0);
+}
+
+void tst_QTextDocumentFragment::html_listIndents2()
+{
+ const char html[] = "<ul><li>Hey<p>Hah</ul>";
+ setHtml(QString::fromLatin1(html));
+ cursor.movePosition(QTextCursor::Start);
+ QTextList *list = cursor.currentList();
+ QVERIFY(list);
+ QCOMPARE(list->format().indent(), 1);
+ QCOMPARE(cursor.block().blockFormat().indent(), 0);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QCOMPARE(cursor.block().blockFormat().indent(), 1);
+}
+
+void tst_QTextDocumentFragment::html_listIndents3()
+{
+ const char html[] = "<ul><li><p>Hah</ul>";
+ setHtml(QString::fromLatin1(html));
+ cursor.movePosition(QTextCursor::Start);
+ QTextList *list = cursor.currentList();
+ QVERIFY(list);
+ QCOMPARE(list->format().indent(), 1);
+ QCOMPARE(cursor.block().blockFormat().indent(), 0);
+}
+
+void tst_QTextDocumentFragment::html_listIndents4()
+{
+ const char html[] = "<ul><li>Foo</ul><p>This should not have the same indent as Foo";
+ setHtml(QString::fromLatin1(html));
+ cursor.movePosition(QTextCursor::Start);
+ QTextList *list = cursor.currentList();
+ QVERIFY(list);
+ QCOMPARE(list->format().indent(), 1);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(!cursor.currentList());
+ QCOMPARE(cursor.blockFormat().indent(), 0);
+}
+
+void tst_QTextDocumentFragment::html_listIndents5()
+{
+ const char html[] = "<ul><li>Foo<p><li>Bar</li></ul>";
+ setHtml(QString::fromLatin1(html));
+ cursor.movePosition(QTextCursor::Start);
+ QTextList *list = cursor.currentList();
+ QVERIFY(list);
+ QCOMPARE(list->format().indent(), 1);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentList() == list);
+ QCOMPARE(cursor.blockFormat().indent(), 0);
+}
+
+void tst_QTextDocumentFragment::html_listIndents6()
+{
+ const char html[] = "<ul><li>Outer List<div class=\"testclass\"><ul><li>Nested Item 1</li></ul></div></li></ul>";
+ setHtml(QString::fromLatin1(html));
+ cursor.movePosition(QTextCursor::Start);
+ QTextList *list = cursor.currentList();
+ QVERIFY(list);
+ QCOMPARE(list->format().indent(), 1);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentList() != list);
+ list = cursor.currentList();
+ QVERIFY(list);
+ QCOMPARE(list->format().indent(), 2);
+
+ QCOMPARE(cursor.blockFormat().indent(), 0);
+}
+
+void tst_QTextDocumentFragment::blockCharFormat()
+{
+ const char html[] = "<p style=\"font-style:italic\"><span style=\"font-style:normal\">Test</span></p>";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(doc->begin().charFormat().fontItalic());
+}
+
+void tst_QTextDocumentFragment::blockCharFormatCopied()
+{
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::green);
+ cursor.setBlockCharFormat(fmt);
+ cursor.insertText("Test", QTextCharFormat());
+ QTextDocumentFragment frag(doc);
+ cleanup();
+ init();
+ cursor.insertFragment(frag);
+ QVERIFY(cursor.blockCharFormat() == fmt);
+}
+
+void tst_QTextDocumentFragment::initialBlock()
+{
+ const char html[] = "<p>Test</p>";
+ setHtml(QString::fromLatin1(html));
+ QCOMPARE(doc->blockCount(), 1);
+}
+
+void tst_QTextDocumentFragment::clone()
+{
+ QTextBlockFormat mod;
+ mod.setAlignment(Qt::AlignCenter);
+ cursor.mergeBlockFormat(mod);
+ cursor.insertText("Blah");
+ QVERIFY(cursor.blockFormat().alignment() == Qt::AlignCenter);
+ QTextDocumentFragment frag(doc);
+ cleanup();
+ init();
+ cursor.insertFragment(frag);
+ cursor.movePosition(QTextCursor::Start);
+ QVERIFY(cursor.blockFormat().alignment() == Qt::AlignCenter);
+}
+
+void tst_QTextDocumentFragment::dontRemoveInitialBlockIfItHoldsObjectIndexedCharFormat()
+{
+ const char html[] = "<table><tr><td>cell one<td>cell two</tr><tr><td>cell three<td>cell four</tr></table>";
+ QVERIFY(doc->begin().charFormat().objectIndex() == -1);
+ setHtml(QString::fromLatin1(html));
+ int cnt = 0;
+
+ int objectIndexOfLast = -1;
+ for (QTextBlock blk = doc->begin(); blk.isValid(); blk = blk.next()) {
+ ++cnt;
+ objectIndexOfLast = blk.charFormat().objectIndex();
+ }
+ // beginning of frame for first cell
+ // + beginning of frame for second cell
+ // + beginning of frame for third cell
+ // + beginning of frame for fourth cell
+ // + end of frame
+ // + initial block
+ // ==> 6
+ QCOMPARE(cnt, 6);
+ QVERIFY(objectIndexOfLast != -1);
+ QVERIFY(doc->begin().next().charFormat().objectIndex() != -1);
+}
+
+void tst_QTextDocumentFragment::dosLineFeed()
+{
+ const char html[] = "<pre>Test\r\n</pre>Bar";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(!doc->toPlainText().contains('\r'));
+ QCOMPARE(doc->toPlainText(), QString("Test\nBar"));
+}
+
+void tst_QTextDocumentFragment::unorderedListEnumeration()
+{
+ const char html[] = "<ul><ul><ul><li>Blah</li></ul></ul>";
+ setHtml(QString::fromLatin1(html));
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListCircle);
+
+ const char html2[] = "<ul><ul><ul type=disc><li>Blah</li></ul></ul>";
+ setHtml(QString::fromLatin1(html2));
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListDisc);
+
+}
+
+void tst_QTextDocumentFragment::resetHasBlockAfterClosedBlockTags()
+{
+ // when closing tags we have to make sure hasBlock in import() gets resetted
+ const char html[] = "<body><table><tr><td><td><p></table><p></body>";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(!doc->isEmpty());
+}
+
+void tst_QTextDocumentFragment::ignoreStyleTags()
+{
+ const char html[] = "<body><style>Blah</style>Hello</body>";
+ setHtml(QString::fromLatin1(html));
+ QCOMPARE(doc->toPlainText(), QString("Hello"));
+}
+
+void tst_QTextDocumentFragment::hrefAnchor()
+{
+ {
+ const char html[] = "<a href=\"test\">blah</a>";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(doc->begin().begin().fragment().charFormat().isAnchor());
+ QCOMPARE(doc->begin().begin().fragment().charFormat().anchorHref(), QString::fromAscii("test"));
+ QVERIFY(doc->begin().begin().fragment().charFormat().fontUnderline() == true);
+ }
+
+ {
+ // only hyperlinks should have special formatting
+ const char html[] = "<a>blah</a>";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(doc->begin().begin().fragment().charFormat().isAnchor());
+ QVERIFY(doc->begin().begin().fragment().charFormat().fontUnderline() == false);
+ }
+}
+
+void tst_QTextDocumentFragment::namedAnchorFragments()
+{
+ // named anchors should be 'invisible', but the fragment right after it should
+ // hold the attribute
+ const char html[] = "a<a name=\"test\" />blah";
+ setHtml(QString::fromLatin1(html));
+
+ QTextBlock firstBlock = doc->begin();
+ QVERIFY(firstBlock.isValid());
+
+ QTextBlock::Iterator it = firstBlock.begin();
+ QVERIFY(!it.atEnd());
+
+ // the 'a'
+ QVERIFY(it.fragment().isValid());
+ QCOMPARE(it.fragment().text(), QString::fromAscii("a"));
+ QVERIFY(it.fragment().charFormat().isAnchor() == false);
+
+ // the 'b' of 'blah' as separate fragment with the anchor attribute
+ ++it;
+ QVERIFY(it.fragment().isValid());
+ QCOMPARE(it.fragment().text(), QString::fromAscii("b"));
+ QVERIFY(it.fragment().charFormat().isAnchor());
+
+ // the 'lah' of 'blah' as remainder
+ ++it;
+ QVERIFY(it.fragment().isValid());
+ QVERIFY(it.fragment().text().startsWith("lah"));
+ QVERIFY(it.fragment().charFormat().isAnchor() == false);
+}
+
+void tst_QTextDocumentFragment::namedAnchorFragments2()
+{
+ const char html[] = "<p> <a name=\"foo\"> Hello";
+ setHtml(QString::fromLatin1(html));
+
+ QCOMPARE(doc->toPlainText(), QString("Hello"));
+
+ QTextBlock::Iterator it = doc->begin().begin();
+ QVERIFY(!it.atEnd());
+
+ QCOMPARE(it.fragment().text(), QString::fromAscii("H"));
+ QVERIFY(it.fragment().charFormat().isAnchor());
+
+ ++it;
+
+ QCOMPARE(it.fragment().text(), QString::fromAscii("ello"));
+ QVERIFY(!it.fragment().charFormat().isAnchor());
+}
+
+void tst_QTextDocumentFragment::namedAnchorFragments3()
+{
+ setHtml("<a name=\"target\" /><a name=\"target2\"/><span>Text</span>");
+
+ QCOMPARE(doc->toPlainText(), QString("Text"));
+
+ QTextBlock::Iterator it = doc->begin().begin();
+ QVERIFY(!it.atEnd());
+
+ QCOMPARE(it.fragment().text(), QString::fromAscii("T"));
+ QVERIFY(it.fragment().charFormat().isAnchor());
+ QCOMPARE(it.fragment().charFormat().anchorName(), QString("target"));
+ QStringList targets; targets << "target" << "target2";
+ QCOMPARE(it.fragment().charFormat().anchorNames(), targets);
+
+ ++it;
+
+ QCOMPARE(it.fragment().text(), QString::fromAscii("ext"));
+ QVERIFY(!it.fragment().charFormat().isAnchor());
+}
+
+void tst_QTextDocumentFragment::dontInheritAlignmentInTables()
+{
+ const char html[] = "<table align=center><tr><td>Hey</td></tr></table>";
+ setHtml(QString::fromLatin1(html));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+ QVERIFY(cursor.currentTable()->cellAt(0, 0).isValid());
+ QVERIFY(cursor.currentTable()->cellAt(0, 0).firstCursorPosition().block().next().blockFormat().alignment() != Qt::AlignHCenter);
+}
+
+void tst_QTextDocumentFragment::cellBlockCount()
+{
+ const char html[] = "<table><tr><td>Hey</td></tr></table>";
+ setHtml(QString::fromLatin1(html));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+
+ QTextTableCell cell = cursor.currentTable()->cellAt(0, 0);
+ QVERIFY(cell.isValid());
+
+ int blockCount = 0;
+ for (QTextFrame::iterator it = cell.begin(); !it.atEnd(); ++it) {
+ QVERIFY(it.currentFrame() == 0);
+ QVERIFY(it.currentBlock().isValid());
+ ++blockCount;
+ }
+ QCOMPARE(blockCount, 1);
+}
+
+void tst_QTextDocumentFragment::cellBlockCount2()
+{
+ const char html[] = "<table><tr><td><p>Hey</p></td></tr></table>";
+ setHtml(QString::fromLatin1(html));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+
+ QTextTableCell cell = cursor.currentTable()->cellAt(0, 0);
+ QVERIFY(cell.isValid());
+
+ int blockCount = 0;
+ for (QTextFrame::iterator it = cell.begin(); !it.atEnd(); ++it) {
+ QVERIFY(it.currentFrame() == 0);
+ QVERIFY(it.currentBlock().isValid());
+ ++blockCount;
+ }
+ QCOMPARE(blockCount, 1);
+}
+
+void tst_QTextDocumentFragment::emptyTable()
+{
+ const char html[] = "<table></table>";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(true); // don't crash with a failing assertion
+}
+
+void tst_QTextDocumentFragment::emptyTable2()
+{
+ const char html[] = "<table></td></tr></table><p>blah</p>";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(true); // don't crash with a failing assertion
+}
+
+void tst_QTextDocumentFragment::emptyTable3()
+{
+ const char html[] = "<table><tr><td><table></table></td><td>Foobar</td></tr></table>";
+ setHtml(QString::fromLatin1(html));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 2);
+ QTextTableCell cell = table->cellAt(0, 0);
+ QVERIFY(cell.isValid());
+ QVERIFY(cell.firstPosition() == cell.lastPosition());
+ cell = table->cellAt(0, 1);
+ QTextCursor cursor = cell.firstCursorPosition();
+ cursor.setPosition(cell.lastPosition(), QTextCursor::KeepAnchor);
+ QCOMPARE(cursor.selectedText(), QString("Foobar"));
+}
+
+void tst_QTextDocumentFragment::doubleRowClose()
+{
+ const char html[] = "<table><tr><td>Blah</td></tr></tr><tr><td>Hm</td></tr></table>";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(true); // don't crash with a failing assertion
+}
+
+void tst_QTextDocumentFragment::mayNotHaveChildren()
+{
+ // make sure the Hey does not end up as tag text for the img tag
+ const char html[] = "<img />Hey";
+ setHtml(QString::fromLatin1(html));
+ QCOMPARE(doc->toPlainText().mid(1), QString::fromAscii("Hey"));
+}
+
+void tst_QTextDocumentFragment::inheritAlignment()
+{
+ // make sure attributes from the body tag get inherited
+ const char html[] = "<body align=right><p>Hey";
+ setHtml(QString::fromLatin1(html));
+ // html alignment is absolute
+ QVERIFY(doc->begin().blockFormat().alignment() == Qt::Alignment(Qt::AlignRight|Qt::AlignAbsolute));
+}
+
+void tst_QTextDocumentFragment::dontEmitEmptyNodeWhenEmptyTagIsFollowedByCloseTag()
+{
+ // make sure the Hey does not end up as tag text for the img tag
+ const char html[] = "<body align=right><p align=left>Blah<img></img><p>Hey";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(doc->begin().blockFormat().alignment() == Qt::Alignment(Qt::AlignLeft|Qt::AlignAbsolute));
+ QVERIFY(doc->begin().next().blockFormat().alignment() == Qt::Alignment(Qt::AlignRight|Qt::AlignAbsolute));
+}
+
+void tst_QTextDocumentFragment::toPlainText()
+{
+ QString input = "Hello\nWorld";
+ input += QChar::ParagraphSeparator;
+ input += "Blah";
+ doc->setPlainText(input);
+ QCOMPARE(doc->blockCount(), 3);
+}
+
+void tst_QTextDocumentFragment::copyTableRow()
+{
+ QTextDocumentFragment frag;
+ {
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
+
+ // select second row
+ cursor = table->cellAt(1, 1).firstCursorPosition();
+ cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::KeepAnchor);
+
+ QCOMPARE(table->cellAt(cursor.position()).row(), 1);
+ QCOMPARE(table->cellAt(cursor.position()).column(), 0);
+ QCOMPARE(table->cellAt(cursor.anchor()).row(), 1);
+ QCOMPARE(table->cellAt(cursor.anchor()).column(), 1);
+
+ frag = QTextDocumentFragment(cursor);
+ }
+ {
+ QTextDocument doc2;
+ cursor = QTextCursor(&doc2);
+ cursor.insertFragment(frag);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 1);
+
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Bar"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Hah"));
+ }
+}
+
+void tst_QTextDocumentFragment::copyTableColumn()
+{
+ QTextDocumentFragment frag;
+ {
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
+
+ // select second column
+ cursor = table->cellAt(0, 1).firstCursorPosition();
+ cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
+
+ QCOMPARE(table->cellAt(cursor.anchor()).row(), 0);
+ QCOMPARE(table->cellAt(cursor.anchor()).column(), 1);
+ QCOMPARE(table->cellAt(cursor.position()).row(), 1);
+ QCOMPARE(table->cellAt(cursor.position()).column(), 1);
+
+ frag = QTextDocumentFragment(cursor);
+ }
+ {
+ QTextDocument doc2;
+ cursor = QTextCursor(&doc2);
+ cursor.insertFragment(frag);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->rows(), 2);
+
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Foo"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Hah"));
+ }
+}
+
+void tst_QTextDocumentFragment::copySubTable()
+{
+ QTextDocumentFragment frag;
+ {
+ QTextTableFormat fmt;
+ QVector<QTextLength> constraints;
+ constraints << QTextLength(QTextLength::PercentageLength, 16);
+ constraints << QTextLength(QTextLength::PercentageLength, 28);
+ constraints << QTextLength(QTextLength::PercentageLength, 28);
+ constraints << QTextLength(QTextLength::PercentageLength, 28);
+ fmt.setColumnWidthConstraints(constraints);
+
+ QTextTable *table = cursor.insertTable(4, 4, fmt);
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ table->cellAt(row, col).firstCursorPosition().insertText(QString("%1/%2").arg(row).arg(col));
+
+ QCOMPARE(table->format().columnWidthConstraints().count(), table->columns());
+
+ // select 2x2 subtable
+ cursor = table->cellAt(1, 1).firstCursorPosition();
+ cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
+
+ QCOMPARE(table->cellAt(cursor.anchor()).row(), 1);
+ QCOMPARE(table->cellAt(cursor.anchor()).column(), 1);
+ QCOMPARE(table->cellAt(cursor.position()).row(), 2);
+ QCOMPARE(table->cellAt(cursor.position()).column(), 2);
+
+ frag = QTextDocumentFragment(cursor);
+ }
+ {
+ QTextDocument doc2;
+ cursor = QTextCursor(&doc2);
+ cursor.insertFragment(frag);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+
+ QVERIFY(table);
+ QVERIFY(table->format().columnWidthConstraints().isEmpty());
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 2);
+
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("1/1"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("1/2"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("2/1"));
+ QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("2/2"));
+ }
+}
+
+void tst_QTextDocumentFragment::html_textDecoration()
+{
+ const char html[] = "<span style='text-decoration: overline line-through underline'>Blah</span>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().fontUnderline());
+ QVERIFY(cursor.charFormat().fontOverline());
+ QVERIFY(cursor.charFormat().fontStrikeOut());
+}
+
+void tst_QTextDocumentFragment::html_infiniteLoop()
+{
+ {
+ // used to cause an infinite loop due to the lack of a space after the
+ // tag name
+ const char html[] = "<ahref=\"argl\">Link</a>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+ QVERIFY(true);
+ }
+
+ {
+ const char html[] = "<a href=\"\"a<";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+ QVERIFY(true);
+ }
+}
+
+void tst_QTextDocumentFragment::html_blockIndent()
+{
+ const char html[] = "<p style=\"-qt-block-indent:3;\">Test</p>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+ QCOMPARE(cursor.blockFormat().indent(), 3);
+}
+
+void tst_QTextDocumentFragment::html_listIndent()
+{
+ const char html[] = "<ul style=\"-qt-list-indent:4;\"><li>Blah</ul>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+ QVERIFY(cursor.currentList());
+ QCOMPARE(cursor.currentList()->format().indent(), 4);
+}
+
+void tst_QTextDocumentFragment::html_whitespace_data()
+{
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<QString>("expectedPlainText");
+
+ QTest::newRow("1") << QString("<span>This is some test</span><span> with spaces between words</span>")
+ << QString("This is some test with spaces between words");
+
+ QTest::newRow("2") << QString("<span> </span><span>nowhitespacehereplease</span>")
+ << QString::fromLatin1("nowhitespacehereplease");
+
+ QTest::newRow("3") << QString("<span style=\"white-space: pre;\"> white space here </span>")
+ << QString::fromLatin1(" white space here ");
+
+ QTest::newRow("4") << QString("<span style=\"white-space: pre-wrap;\"> white space here </span>")
+ << QString::fromLatin1(" white space here ");
+
+ QTest::newRow("5") << QString("<a href=\"One.html\">One</a> <a href=\"Two.html\">Two</a> <b>Three</b>\n"
+ "<b>Four</b>")
+ << QString::fromLatin1("One Two Three Four");
+
+ QTest::newRow("6") << QString("<p>Testing: <b><i><u>BoldItalic</u></i></b> <i>Italic</i></p>")
+ << QString("Testing: BoldItalic Italic");
+
+ QTest::newRow("7") << QString("<table><tr><td>Blah</td></tr></table> <table border><tr><td>Foo</td></tr></table>")
+ << QString("\nBlah\n\nFoo\n");
+
+ QTest::newRow("8") << QString("<table><tr><td><i>Blah</i></td></tr></table> <i>Blub</i>")
+ << QString("\nBlah\nBlub");
+
+ QTest::newRow("task116492") << QString("<p>a<font=\"Times\"> b </font>c</p>")
+ << QString("a b c");
+
+ QTest::newRow("task121653") << QString("abc<b> def</b>")
+ << QString("abc def");
+
+ QTest::newRow("task122650") << QString("<p>Foo</p> Bar")
+ << QString("Foo\nBar");
+
+ QTest::newRow("task122650-2") << QString("<p>Foo</p> <p> Bar")
+ << QString("Foo \nBar");
+
+ QTest::newRow("task122650-3") << QString("<html>Before<pre>\nTest</pre>")
+ << QString("Before\nTest");
+
+ QTest::newRow("br-with-whitespace") << QString("Foo<br>\nBlah")
+ << QString("Foo\nBlah");
+
+ QTest::newRow("collapse-p-with-newline") << QString("Foo<p>\n<p>\n<p>\n<p>\n<p>\n<p>\nBar")
+ << QString("Foo\nBar");
+
+ QTest::newRow("table") << QString("<table><tr><td>Blah</td></tr></table>\nTest")
+ << QString("\nBlah\nTest");
+
+ QTest::newRow("table2") << QString("<table><tr><td><pre>\nTest\n</pre></td>\n </tr></table>")
+ << QString("\nTest\n");
+
+ QTest::newRow("table3") << QString("<table><tr><td><pre>\nTest\n</pre> \n \n </td></tr></table>")
+ << QString("\nTest \n");
+}
+
+void tst_QTextDocumentFragment::html_whitespace()
+{
+ QFETCH(QString, html);
+ QFETCH(QString, expectedPlainText);
+
+ setHtml(html);
+
+ QCOMPARE(doc->toPlainText(), expectedPlainText);
+}
+
+void tst_QTextDocumentFragment::html_qt3Whitespace()
+{
+ QString text = "This text has some whitespace"
+ "\n and \nnewlines that \n should be ignored\n\n";
+ const QString html = QString("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>")
+ + text
+ + QString("</body></html>");
+
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+
+ text.remove(QChar::fromLatin1('\n'));
+
+ QCOMPARE(doc->toPlainText(), text);
+}
+
+void tst_QTextDocumentFragment::html_qt3WhitespaceWithFragments()
+{
+ QString text = "This text has some whitespace"
+ "\n and \nnewlines that \n should be ignored\n\n";
+ const QString html = QString("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>"
+ "blah blah<!--StartFragment--><span>")
+ + text
+ + QString("</span><!--EndFragment--></body></html>");
+
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+
+ text.remove(QChar::fromLatin1('\n'));
+
+ QCOMPARE(doc->toPlainText(), text);
+}
+
+void tst_QTextDocumentFragment::html_qt3WhitespaceAfterTags()
+{
+ QString text = " This text has some whitespace ";
+ const QString html = QString("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body><span>")
+ + text
+ + QString("</span></body></html>");
+
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+
+ QCOMPARE(doc->toPlainText(), text);
+}
+
+void tst_QTextDocumentFragment::html_listStart1()
+{
+ // don't create a block for the <ul> element, even if there's some whitespace between
+ // it and the <li>
+ const char html[] = "<ul> <li>list item</li><ul>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
+
+ QCOMPARE(doc->blockCount(), 1);
+}
+
+void tst_QTextDocumentFragment::html_listStart2()
+{
+ // unlike with html_listStart1 we want a block showing the 'buggy' text here
+ const char html[] = "<ul>buggy, but text should appear<li>list item</li><ul>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
+
+ QCOMPARE(doc->blockCount(), 2);
+}
+
+void tst_QTextDocumentFragment::html_cssMargin()
+{
+ const char html[] = "<p style=\"margin-top: 1px; margin-bottom: 2px; margin-left: 3px; margin-right: 4px\">Test</p>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+ const QTextBlockFormat fmt = cursor.blockFormat();
+ QCOMPARE(fmt.topMargin(), qreal(1));
+ QCOMPARE(fmt.bottomMargin(), qreal(2));
+ QCOMPARE(fmt.leftMargin(), qreal(3));
+ QCOMPARE(fmt.rightMargin(), qreal(4));
+}
+
+void tst_QTextDocumentFragment::html_hexEntities()
+{
+ const char html[] = "&#x00040;";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+ QCOMPARE(doc->begin().begin().fragment().text(), QString("@"));
+}
+
+void tst_QTextDocumentFragment::html_decEntities()
+{
+ const char html[] = "&#64;";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+ QCOMPARE(doc->begin().begin().fragment().text(), QString("@"));
+}
+
+void tst_QTextDocumentFragment::html_thCentered()
+{
+ const char html[] = "<table><tr><th>This should be centered</th></tr></table>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+
+ cursor.movePosition(QTextCursor::PreviousBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QVERIFY(table->cellAt(0, 0).begin().currentBlock().blockFormat().alignment() == Qt::AlignCenter);
+}
+
+void tst_QTextDocumentFragment::orderedListNumbering()
+{
+ // Supporter issue 45941 - make sure _two_ separate lists
+ // are imported, which have their own numbering
+ const char html[] = "<html><body>"
+ "<ol><li>elem 1</li></ol>"
+ "<ol><li>elem 1</li></ol>"
+ "</body></html>";
+
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+
+ int numberOfLists = 0;
+
+ cursor.movePosition(QTextCursor::Start);
+ QTextList *lastList = 0;
+ do {
+ QTextList *list = cursor.currentList();
+ if (list && list != lastList) {
+ lastList = list;
+ ++numberOfLists;
+ }
+ } while (cursor.movePosition(QTextCursor::NextBlock));
+
+ QCOMPARE(numberOfLists, 2);
+}
+
+void tst_QTextDocumentFragment::html_blockAfterList()
+{
+ const char html[] = "<ul><li>Foo</ul>This should be a separate paragraph and not be indented at the same level as Foo";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
+
+ cursor.movePosition(QTextCursor::Start);
+
+ QVERIFY(cursor.currentList());
+ QCOMPARE(cursor.currentList()->format().indent(), 1);
+
+ QVERIFY(cursor.movePosition(QTextCursor::NextBlock));
+ QVERIFY(!cursor.currentList());
+ QCOMPARE(cursor.blockFormat().indent(), 0);
+}
+
+void tst_QTextDocumentFragment::html_subAndSuperScript()
+{
+ const char subHtml[] = "<sub>Subby</sub>";
+ const char superHtml[] = "<sup>Super</sup>";
+ const char subHtmlCss[] = "<span style=\"vertical-align: sub\">Subby</span>";
+ const char superHtmlCss[] = "<span style=\"vertical-align: super\">Super</span>";
+ const char alignmentInherited[] = "<sub><font face=\"Verdana\">Subby</font></sub>";
+
+ setHtml(subHtml);
+ QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSubScript);
+
+ setHtml(subHtmlCss);
+ QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSubScript);
+
+ setHtml(superHtml);
+ QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSuperScript);
+
+ setHtml(superHtmlCss);
+ QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSuperScript);
+
+ setHtml(alignmentInherited);
+ QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSubScript);
+}
+
+void tst_QTextDocumentFragment::html_cssColors()
+{
+ const char color[] = "<span style=\"color:red\"><span style=\"color:blue\">Blue</span></span>";
+ setHtml(color);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
+
+ const char rgbColor[] = "<span style=\"color:red\"><span style=\"color:rgb(0, 0, 255)\">Blue</span></span>";
+ setHtml(rgbColor);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
+}
+
+void tst_QTextDocumentFragment::obeyFragmentMarkersInImport()
+{
+ const char html[] = "This leading text should not appear<!--StartFragment--><span>Text</span><!--EndFragment-->This text at the end should not appear";
+ setHtml(html);
+
+ QCOMPARE(doc->toPlainText(), QString("Text"));
+}
+
+void tst_QTextDocumentFragment::whitespaceWithFragmentMarkers()
+{
+ QString text(" text with leading and trailing whitespace ");
+ const char html[] = "This leading text should not appear<!--StartFragment-->%1<!--EndFragment-->This text at the end should not appear";
+ setHtml(QString::fromLatin1(html).arg(text));
+
+ QString expected("text with leading and trailing whitespace ");
+ QCOMPARE(doc->toPlainText(), expected);
+}
+
+void tst_QTextDocumentFragment::html_emptyParapgraphs1()
+{
+ const char html[] = "<p style=\"-qt-paragraph-type:empty;\">&nbsp;</p><p>Two paragraphs</p>";
+ setHtml(html);
+
+ QCOMPARE(doc->blockCount(), 2);
+ QVERIFY(doc->begin().text().isEmpty());
+ QCOMPARE(doc->begin().next().text(), QString("Two paragraphs"));
+}
+
+void tst_QTextDocumentFragment::html_emptyParapgraphs2()
+{
+ const char html[] = "<p style=\"margin-left:80px\"></p><p>One paragraph</p>";
+ setHtml(html);
+
+ QCOMPARE(doc->blockCount(), 1);
+ QCOMPARE(cursor.blockFormat().leftMargin(), qreal(0));
+
+ const char html2[] = "<p style=\"margin-left:80px\"></p>One paragraph";
+ setHtml(html2);
+ QCOMPARE(doc->blockCount(), 1);
+ QCOMPARE(cursor.blockFormat().leftMargin(), qreal(0));
+
+ const char html3[] = "<p style=\"margin-left:80px\">Foo</p><p></p>Two paragraphs";
+ setHtml(html3);
+ QCOMPARE(doc->blockCount(), 2);
+ cursor = QTextCursor(doc);
+ QCOMPARE(cursor.blockFormat().leftMargin(), qreal(80));
+ QCOMPARE(cursor.block().next().blockFormat().leftMargin(), qreal(0));
+}
+
+void tst_QTextDocumentFragment::html_emptyParagraphs3()
+{
+ const char html[] = "<ul><p>Foo</p><p></p></ul><h4>Bar</h4>";
+
+ setHtml(html);
+
+ QCOMPARE(doc->blockCount(), 2);
+
+ cursor = QTextCursor(doc);
+ QCOMPARE(cursor.block().next().blockFormat().indent(), 0);
+}
+
+void tst_QTextDocumentFragment::html_emptyParagraphs4()
+{
+ const char html[] = "<p>foo</p><p style=\"page-break-before: always\"></p><p>bar</p>";
+ setHtml(html);
+
+ QTextBlock block = doc->begin();
+ QVERIFY(block.isValid());
+ QCOMPARE(block.text(), QString("foo"));
+ block = block.next();
+ QVERIFY(block.isValid());
+ QTextBlockFormat bf = block.blockFormat();
+ QVERIFY(bf.hasProperty(QTextFormat::PageBreakPolicy));
+ QCOMPARE(bf.pageBreakPolicy(), QTextFormat::PageBreak_AlwaysBefore);
+ QCOMPARE(block.text(), QString("bar"));
+
+ const char html2[] = "<p>foo</p><p style=\"page-break-after: always\"></p><p>bar</p>";
+ setHtml(html2);
+
+ block = doc->begin();
+ QVERIFY(block.isValid());
+ QCOMPARE(block.text(), QString("foo"));
+ block = block.next();
+ QVERIFY(block.isValid());
+ bf = block.blockFormat();
+ QVERIFY(bf.hasProperty(QTextFormat::PageBreakPolicy));
+ QCOMPARE(bf.pageBreakPolicy(), QTextFormat::PageBreak_AlwaysBefore); // after the empty line means it should appear for 'bar'
+ QCOMPARE(block.text(), QString("bar"));
+}
+
+void tst_QTextDocumentFragment::html_font()
+{
+ const char html[] = "<font color=\"blue\"><p>Hah</p></font>";
+ setHtml(html);
+
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
+ QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue);
+}
+
+void tst_QTextDocumentFragment::html_fontSize()
+{
+ const char html[] = "<font size=\"2\">Hah</font>";
+ setHtml(html);
+
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), -1);
+}
+
+void tst_QTextDocumentFragment::html_fontSizeAdjustment()
+{
+ const char html[] = "<font size=\"7\"><b>Hah</b></font>";
+ setHtml(html);
+
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), 4);
+ QCOMPARE(cursor.charFormat().fontWeight(), int(QFont::Bold));
+}
+
+void tst_QTextDocumentFragment::html_cssFontSize()
+{
+ const char html[] = "<span style=\"font-size: 50pt\">Foo</span>";
+ setHtml(html);
+
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 50);
+
+ const char html2[] = "<span style=\"font-size: 50px\">Foo</span>";
+ setHtml(html2);
+
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontPixelSize).toInt(), 50);
+
+ const char html3[] = "<span style=\"font-size: large\">Foo</span>";
+ setHtml(html3);
+
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), 1);
+}
+
+void tst_QTextDocumentFragment::html_cssShorthandFont()
+{
+ {
+ const char html[] = "<span style=\"font: 50px sans-serif\">Foo</span>";
+ setHtml(html);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontPixelSize).toInt(), 50);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("sans-serif"));
+ }
+ {
+ const char html[] = "<span style=\"font: 50pt sans-serif\">Foo</span>";
+ setHtml(html);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 50);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("sans-serif"));
+ }
+ {
+ const char html[] = "<span style='font:7.0pt \"Times New Roman\"'>Foo</span>";
+ setHtml(html);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 7);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("Times New Roman"));
+ }
+ {
+ const char html[] = "<span style='font:bold 7.0pt'>Foo</span>";
+ setHtml(html);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontWeight).toInt(), int(QFont::Bold));
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 7);
+ }
+ {
+ const char html[] = "<span style='font:bold italic 7.0pt'>Foo</span>";
+ setHtml(html);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontWeight).toInt(), int(QFont::Bold));
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontItalic).toBool(), true);
+ }
+}
+
+void tst_QTextDocumentFragment::html_bodyBgColor()
+{
+ const char html[] = "<body bgcolor=\"blue\">Foo</body>";
+ doc->setHtml(html);
+
+ QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue);
+}
+
+void tst_QTextDocumentFragment::html_qtBgColor()
+{
+ const char html[] = "<qt bgcolor=\"blue\">Foo</qt>";
+ doc->setHtml(html);
+
+ QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue);
+}
+
+void tst_QTextDocumentFragment::html_bodyBackground()
+{
+ const char html[] = "<body background=\"foo.png\">Foo</body>";
+ doc->setHtml(html);
+
+ QVERIFY(doc->rootFrame()->frameFormat().background().style() == Qt::TexturePattern);
+}
+
+void tst_QTextDocumentFragment::html_tableCellBackground()
+{
+ const char html[] = "<body><table><tr><td background=\"foo.png\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QVERIFY(cell.format().background().style() == Qt::TexturePattern);
+}
+
+void tst_QTextDocumentFragment::css_bodyBackground()
+{
+ const char html[] = "<body style=\"background-image:url('foo.png')\">Foo</body>";
+ doc->setHtml(html);
+
+ QVERIFY(doc->rootFrame()->frameFormat().background().style() == Qt::TexturePattern);
+}
+
+void tst_QTextDocumentFragment::css_tableCellBackground()
+{
+ const char html[] = "<body><table><tr><td style=\"background-image:url('foo.png')\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QVERIFY(cell.format().background().style() == Qt::TexturePattern);
+}
+
+void tst_QTextDocumentFragment::css_cellPaddings()
+{
+ const char html[] = "<body><table><tr><td style=\"padding-left:1\">Foo</td>"
+ "<td style=\"padding-right:1\"></td><td style=\"padding-top:10\"></td>"
+ "<td style=\"padding-bottom:5\"></td><td style=\"padding:15\"></td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QCOMPARE(cell.format().toTableCellFormat().leftPadding(), qreal(1));
+ cell = table->cellAt(0, 1);
+ QCOMPARE(cell.format().toTableCellFormat().rightPadding(), qreal(1));
+ cell = table->cellAt(0, 2);
+ QCOMPARE(cell.format().toTableCellFormat().topPadding(), qreal(10));
+ cell = table->cellAt(0, 3);
+ QCOMPARE(cell.format().toTableCellFormat().bottomPadding(), qreal(5));
+ cell = table->cellAt(0, 4);
+ QCOMPARE(cell.format().toTableCellFormat().leftPadding(), qreal(15));
+ QCOMPARE(cell.format().toTableCellFormat().rightPadding(), qreal(15));
+ QCOMPARE(cell.format().toTableCellFormat().topPadding(), qreal(15));
+ QCOMPARE(cell.format().toTableCellFormat().bottomPadding(), qreal(15));
+}
+
+void tst_QTextDocumentFragment::html_blockLevelDiv()
+{
+ const char html[] = "<div align=right><b>Hello World";
+ setHtml(html);
+
+ QCOMPARE(doc->begin().blockFormat().alignment(), Qt::AlignRight|Qt::AlignAbsolute);
+ QVERIFY(doc->begin().next() == doc->end());
+}
+
+void tst_QTextDocumentFragment::html_spanNesting()
+{
+ const char html[] = "<span style=\"color:black\">a<span style=\"color:red\">b<span style=\"color:black\">c</span></span>d</span>";
+ setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground() == Qt::black);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground() == Qt::red);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground() == Qt::black);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground() == Qt::black);
+}
+
+void tst_QTextDocumentFragment::html_nestedLists()
+{
+ const char html[] = "<p><ul><li>Foo<ul><li>In nested list</li></ul></li><li>Last item</li></ul></p>";
+ setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ QTextList *firstList = cursor.currentList();
+ QVERIFY(firstList);
+ QCOMPARE(firstList->format().indent(), 1);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextList *secondList = cursor.currentList();
+ QVERIFY(secondList);
+ QVERIFY(secondList != firstList);
+ QCOMPARE(cursor.currentList()->format().indent(), 2);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextList *thirdList = cursor.currentList();
+ QVERIFY(thirdList);
+ QVERIFY(thirdList == firstList);
+}
+
+void tst_QTextDocumentFragment::noSpecialCharactersInPlainText()
+{
+ cursor.insertTable(2, 2);
+ cursor.insertBlock();
+ cursor.insertText(QString(QChar::LineSeparator));
+ cursor.insertText(QString(QChar::Nbsp));
+
+ QString plain = doc->toPlainText();
+ QVERIFY(!plain.contains(QChar::ParagraphSeparator));
+ QVERIFY(!plain.contains(QChar::Nbsp));
+ QVERIFY(!plain.contains(QTextBeginningOfFrame));
+ QVERIFY(!plain.contains(QTextEndOfFrame));
+ QVERIFY(!plain.contains(QChar::LineSeparator));
+
+ plain = QTextDocumentFragment(doc).toPlainText();
+ QVERIFY(!plain.contains(QChar::ParagraphSeparator));
+ QVERIFY(!plain.contains(QChar::Nbsp));
+ QVERIFY(!plain.contains(QTextBeginningOfFrame));
+ QVERIFY(!plain.contains(QTextEndOfFrame));
+ QVERIFY(!plain.contains(QChar::LineSeparator));
+}
+
+void tst_QTextDocumentFragment::html_doNotInheritBackground()
+{
+ const char html[] = "<html><body bgcolor=\"blue\"><p>Blah</p></body></html>";
+ doc->setHtml(html);
+
+ for (QTextBlock block = doc->begin();
+ block.isValid(); block = block.next()) {
+ QVERIFY(block.blockFormat().hasProperty(QTextFormat::BackgroundBrush) == false);
+ }
+
+ QVERIFY(doc->rootFrame()->frameFormat().hasProperty(QTextFormat::BackgroundBrush));
+ QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue);
+}
+
+void tst_QTextDocumentFragment::html_inheritBackgroundToInlineElements()
+{
+ const char html[] = "<span style=\"background: blue\">Foo<span>Bar</span></span>";
+ doc->setHtml(html);
+
+ int fragmentCount = 0;
+
+ QTextBlock block = doc->begin();
+ for (QTextBlock::Iterator it = block.begin();
+ !it.atEnd(); ++it, ++fragmentCount) {
+
+ const QTextFragment fragment = it.fragment();
+ if (fragmentCount == 0) {
+ QCOMPARE(fragment.text(), QString("FooBar"));
+ QVERIFY(fragment.charFormat().background().color() == Qt::blue);
+ }
+ }
+
+ QCOMPARE(fragmentCount, 1);
+}
+
+void tst_QTextDocumentFragment::html_doNotInheritBackgroundFromBlockElements()
+{
+ const char html[] = "<p style=\"background: blue\"><span>Foo</span></span>";
+ doc->setHtml(html);
+
+ int fragmentCount = 0;
+
+ QTextBlock block = doc->begin();
+ for (QTextBlock::Iterator it = block.begin();
+ !it.atEnd(); ++it, ++fragmentCount) {
+
+ const QTextFragment fragment = it.fragment();
+ if (fragmentCount == 0) {
+ QCOMPARE(fragment.text(), QString("Foo"));
+ QVERIFY(!fragment.charFormat().hasProperty(QTextFormat::BackgroundBrush));
+ }
+ }
+
+ QCOMPARE(fragmentCount, 1);
+}
+void tst_QTextDocumentFragment::html_nobr()
+{
+ const QString input = "Blah Foo Bar";
+ const QString html = QString::fromLatin1("<html><body><p><nobr>") + input + QString::fromLatin1("</nobr></p></body></html>");
+ setHtml(html);
+
+ QString text = doc->begin().begin().fragment().text();
+ QString expectedText = input;
+ expectedText.replace(QRegExp("\\s+"), QString(QChar::Nbsp));
+ QCOMPARE(text, expectedText);
+}
+
+void tst_QTextDocumentFragment::fromPlainText()
+{
+ QString plainText;
+ plainText = "Hello\nWorld\r\nBlub";
+ plainText += QChar::ParagraphSeparator;
+ // TextEdit on OS 10 gives us OS 9 style linefeeds
+ // when copy & pasteing multi-line plaintext.
+ plainText += "OS9IsOldSchool\r";
+ plainText += "Last Parag";
+
+ doc->setPlainText(plainText);
+
+ int blockCount = 0;
+ for (QTextBlock block = doc->begin(); block.isValid(); block = block.next()) {
+ QVERIFY(!block.text().contains(QLatin1Char('\n')));
+ QVERIFY(!block.text().contains(QLatin1Char('\r')));
+ QVERIFY(!block.text().contains(QChar::ParagraphSeparator));
+
+ if (blockCount == 0)
+ QCOMPARE(block.text(), QString("Hello"));
+ else if (blockCount == 1)
+ QCOMPARE(block.text(), QString("World"));
+ else if (blockCount == 2)
+ QCOMPARE(block.text(), QString("Blub"));
+ else if (blockCount == 3)
+ QCOMPARE(block.text(), QString("OS9IsOldSchool"));
+ else if (blockCount == 4)
+ QCOMPARE(block.text(), QString("Last Parag"));
+
+
+ ++blockCount;
+ }
+
+ QCOMPARE(blockCount, 5);
+}
+
+void tst_QTextDocumentFragment::fromPlainText2()
+{
+ doc->setPlainText("Hello World");
+ QCOMPARE(QTextDocumentFragment(doc).toPlainText(), doc->toPlainText());
+}
+
+void tst_QTextDocumentFragment::html_closingImageTag()
+{
+ const char html[] = "<span style=\"font-size: 10pt\"><span style=\"font-size: 40pt\">Blah<img src=\"blah\"></img>Foo</span></span>";
+ setHtml(html);
+
+ int fragmentCount = 0;
+
+ QTextBlock block = doc->begin();
+ for (QTextBlock::Iterator it = block.begin();
+ !it.atEnd(); ++it, ++fragmentCount) {
+
+ const QTextFragment fragment = it.fragment();
+ if (fragmentCount == 0) {
+ QCOMPARE(fragment.text(), QString("Blah"));
+ QCOMPARE(fragment.charFormat().fontPointSize(), qreal(40));
+ } else if (fragmentCount == 1) {
+ QCOMPARE(fragment.text(), QString(QChar::ObjectReplacementCharacter));
+ } else if (fragmentCount == 2) {
+ QCOMPARE(fragment.text(), QString("Foo"));
+ QCOMPARE(fragment.charFormat().fontPointSize(), qreal(40));
+ }
+ }
+
+ QCOMPARE(fragmentCount, 3);
+}
+
+void tst_QTextDocumentFragment::html_emptyDocument()
+{
+ const char html[] = "<html><body><p style=\"-qt-paragraph-type:empty;\"></p></body></html>";
+ setHtml(html);
+ QCOMPARE(doc->blockCount(), 1);
+}
+
+void tst_QTextDocumentFragment::html_closingTag()
+{
+ const char html[] = "<i />text";
+ setHtml(html);
+
+ QVERIFY(!cursor.charFormat().fontItalic());
+}
+
+void tst_QTextDocumentFragment::html_anchorAroundImage()
+{
+ const char html[] = "<a href=\"http://www.troll.no\"><img src=test.png></a>";
+ setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QTextImageFormat fmt = cursor.charFormat().toImageFormat();
+ QCOMPARE(fmt.name(), QString("test.png"));
+ QVERIFY(fmt.isAnchor());
+ QCOMPARE(fmt.anchorHref(), QString("http://www.troll.no"));
+}
+
+void tst_QTextDocumentFragment::html_floatBorder()
+{
+ const char html[] = "<table border=1.2><tr><td>Foo";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+ QCOMPARE(cursor.currentTable()->format().border(), qreal(1.2));
+}
+
+void tst_QTextDocumentFragment::html_frameImport()
+{
+ QTextFrameFormat ffmt;
+ ffmt.setBorder(1);
+ ffmt.setPosition(QTextFrameFormat::FloatRight);
+ ffmt.setMargin(2);
+ ffmt.setWidth(100);
+ ffmt.setHeight(50);
+ ffmt.setBackground(QColor("#00ff00"));
+ cursor.insertFrame(ffmt);
+ cursor.insertText("Hello World");
+
+ QTextDocumentFragment frag(doc);
+ cleanup();
+ init();
+ frag = QTextDocumentFragment::fromHtml(frag.toHtml());
+ cursor.insertFragment(frag);
+
+ QList<QTextFrame *> childFrames = doc->rootFrame()->childFrames();
+ QVERIFY(childFrames.count() == 1);
+ QTextFrame *frame = childFrames.first();
+ QCOMPARE(frame->frameFormat().margin(), ffmt.margin());
+ QCOMPARE(frame->frameFormat().border(), ffmt.border());
+}
+
+void tst_QTextDocumentFragment::html_frameImport2()
+{
+ QTextFrameFormat ffmt;
+ ffmt.setBorder(1);
+ ffmt.setPosition(QTextFrameFormat::FloatRight);
+ ffmt.setLeftMargin(200);
+ ffmt.setTopMargin(100);
+ ffmt.setBottomMargin(50);
+ ffmt.setRightMargin(250);
+ ffmt.setWidth(100);
+ ffmt.setHeight(50);
+ ffmt.setBackground(QColor("#00ff00"));
+ cursor.insertFrame(ffmt);
+ cursor.insertText("Hello World");
+
+ QTextDocumentFragment frag(doc);
+ cleanup();
+ init();
+ frag = QTextDocumentFragment::fromHtml(frag.toHtml());
+ cursor.insertFragment(frag);
+
+ QList<QTextFrame *> childFrames = doc->rootFrame()->childFrames();
+ QVERIFY(childFrames.count() == 1);
+ QTextFrame *frame = childFrames.first();
+ QCOMPARE(frame->frameFormat().topMargin(), ffmt.topMargin());
+ QCOMPARE(frame->frameFormat().bottomMargin(), ffmt.bottomMargin());
+ QCOMPARE(frame->frameFormat().leftMargin(), ffmt.leftMargin());
+ QCOMPARE(frame->frameFormat().rightMargin(), ffmt.rightMargin());
+ QCOMPARE(frame->frameFormat().border(), ffmt.border());
+}
+
+void tst_QTextDocumentFragment::html_dontAddMarginsAcrossTableCells()
+{
+ const char html[] = "<table style=\"margin-left: 100px;\"><tr><td><p style=\"margin-left:50px;\">Foo</p></td></tr></table>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+
+ QList<QTextFrame *> childFrames = doc->rootFrame()->childFrames();
+ QVERIFY(childFrames.count() == 1);
+ QTextFrame *frame = childFrames.first();
+ cursor = frame->firstCursorPosition();
+ QCOMPARE(cursor.blockFormat().leftMargin(), qreal(50.0));
+}
+
+void tst_QTextDocumentFragment::html_dontMergeCenterBlocks()
+{
+ const char html[] = "<center>This should be centered</center>And this should not be centered anymore";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+
+ QCOMPARE(doc->blockCount(), 2);
+ QTextBlock blk = doc->begin();
+ QVERIFY(blk.blockFormat().alignment() == Qt::AlignCenter);
+ blk = blk.next();
+ QVERIFY(blk.blockFormat().alignment() != Qt::AlignCenter);
+}
+
+void tst_QTextDocumentFragment::html_tableCellBgColor()
+{
+ const char html[] = "<table><tr><td bgcolor=\"blue\">Test<p>Second Parag</p></td></tr></table>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QVERIFY(cell.format().background().color() == Qt::blue);
+}
+
+void tst_QTextDocumentFragment::html_tableCellBgColor2()
+{
+ const char html[] = "<table><tr><td bgcolor=\"blue\"><table><tr><td>Blah</td></tr></table></td></tr></table>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QVERIFY(cell.format().background().color() == Qt::blue);
+
+ QTextFrame::Iterator it = cell.begin();
+ QVERIFY(!it.atEnd());
+ QVERIFY(it.currentFrame() == 0);
+ QVERIFY(it.currentBlock().isValid());
+
+ ++it;
+ QVERIFY(!it.atEnd());
+ QVERIFY(it.currentFrame() != 0);
+ QVERIFY(!it.currentBlock().isValid());
+
+ ++it;
+ QVERIFY(!it.atEnd());
+ QVERIFY(it.currentFrame() == 0);
+ QVERIFY(it.currentBlock().isValid());
+ QVERIFY(it.currentBlock().blockFormat().background() == QBrush(Qt::NoBrush));
+
+ ++it;
+ QVERIFY(it.atEnd());
+}
+
+void tst_QTextDocumentFragment::html_cellSkip()
+{
+ const char html[] = ""
+"<table border>"
+" <tr>"
+" <td>First Cell</td>"
+" </tr>"
+" <tr>"
+" <td>Second Cell</td>"
+" <td>Third Cell</td>"
+" </tr>"
+"</table>";
+
+ setHtml(html);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QVERIFY(table->columns() == 2 && table->rows() == 2);
+
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
+ QVERIFY(table->cellAt(0, 1).firstCursorPosition().block().text().isEmpty());
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Second Cell"));
+ QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Third Cell"));
+}
+
+void tst_QTextDocumentFragment::nonZeroMarginOnImport()
+{
+ // specify bgcolor so that the html import creates a root frame format
+ setHtml("<html><body bgcolor=\"#00ff00\"><b>Hello World</b></body></html>");
+ QVERIFY(doc->rootFrame()->frameFormat().margin() > 0.0);
+}
+
+void tst_QTextDocumentFragment::html_charFormatPropertiesUnset()
+{
+ setHtml("Hello World");
+ QVERIFY(doc->begin().begin().fragment().charFormat().properties().isEmpty());
+}
+
+void tst_QTextDocumentFragment::html_headings()
+{
+ setHtml("<h1>foo</h1>bar");
+ QCOMPARE(doc->blockCount(), 2);
+}
+
+void tst_QTextDocumentFragment::html_quotedFontFamily()
+{
+ setHtml("<div style=\"font-family: 'Foo Bar';\">Test</div>");
+ QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
+
+ setHtml("<div style='font-family: \"Foo Bar\";'>Test</div>");
+ QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
+
+ setHtml("<div style='font-family: \"Foo Bar\";'>Test</div>");
+ QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
+
+ setHtml("<div style='font-family: Foo\n Bar;'>Test</div>");
+ QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
+
+ setHtml("<div style='font-family: Foo\n Bar, serif, \"bar foo\";'>Test</div>");
+ QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar,serif,bar foo"));
+
+}
+
+void tst_QTextDocumentFragment::defaultFont()
+{
+ QFont f;
+ f.setFamily("Courier New");
+ f.setBold(true);
+ f.setItalic(true);
+ f.setStrikeOut(true); // set here but deliberately ignored for the html export
+ f.setPointSize(100);
+ doc->setDefaultFont(f);
+ doc->setPlainText("Hello World");
+ const QString html = doc->toHtml();
+ QLatin1String str("<body style=\" font-family:'Courier New'; font-size:100pt; font-weight:600; font-style:italic;\">");
+ QVERIFY(html.contains(str));
+}
+
+void tst_QTextDocumentFragment::html_spanBackgroundColor()
+{
+ setHtml("<span style=\"background-color: blue\">Foo</span>");
+ QVERIFY(doc->begin().begin().fragment().charFormat().background().color() == QColor(Qt::blue));
+}
+
+void tst_QTextDocumentFragment::html_brokenTitle_data()
+{
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<QString>("expectedBody");
+ QTest::addColumn<QString>("expectedTitle");
+
+ QTest::newRow("brokentitle") << QString("<html><head><title>Foo<b>bar</b></title></head><body>Blah</body></html>")
+ << QString("Blah") << QString("Foo");
+ QTest::newRow("brokentitle2") << QString("<html><head><title>Foo<font color=red>i</font>t<font color=red>i</font>Blub</title></head><body>Blah</body></html>")
+ << QString("Blah") << QString("Foo");
+ QTest::newRow("entities") << QString("<html><head><title>Foo&lt;bar</title></head><body>Blah</body></html>")
+ << QString("Blah") << QString("Foo<bar");
+ QTest::newRow("unclosedtitle") << QString("<html><head><title>Foo</head><body>Blah</body></html>")
+ << QString("Blah") << QString("Foo");
+}
+
+void tst_QTextDocumentFragment::html_brokenTitle()
+{
+ QFETCH(QString, html);
+ QFETCH(QString, expectedBody);
+ QFETCH(QString, expectedTitle);
+ doc->setHtml(html);
+ QCOMPARE(doc->toPlainText(), expectedBody);
+ QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), expectedTitle);
+}
+
+void tst_QTextDocumentFragment::html_blockVsInline()
+{
+ {
+ setHtml("<html><body><div><b>Foo<div>Bar");
+ QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
+ }
+ {
+ setHtml("<html><body><p><b>Foo<p>Bar");
+ QVERIFY(cursor.charFormat().fontWeight() != QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() != QFont::Bold);
+ }
+ {
+ setHtml("<html><body><b><center>Foo</center></b>");
+ QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
+ }
+ {
+ setHtml("<html><body><b><p>Foo");
+ QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
+ }
+ {
+ setHtml("<html><body><b><p>Foo<p>Bar");
+ QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
+ }
+ {
+ setHtml("<div><b>Foo<div>Bar");
+ QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
+ }
+ {
+ setHtml("<p><b>Foo<p>Bar");
+ QVERIFY(cursor.charFormat().fontWeight() != QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() != QFont::Bold);
+ }
+ {
+ setHtml("<b><center>Foo</center></b>");
+ QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
+ }
+ {
+ setHtml("<b><p>Foo");
+ QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
+ }
+ {
+ setHtml("<b><p>Foo<p>Bar");
+ QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
+ QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
+ }
+}
+
+void tst_QTextDocumentFragment::html_tbody()
+{
+ setHtml("<table><thead><tr><td>First Cell</td></tr></thead><tbody><tr><td>Second Cell</td></tr></tbody></table>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->format().headerRowCount(), 1);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Second Cell"));
+}
+
+void tst_QTextDocumentFragment::html_nestedTables()
+{
+ setHtml("<table>"
+ " <tr><td>"
+ ""
+ " <table>"
+ " <tr><td>Hello</td></tr>"
+ " </table>"
+ ""
+ " <table>"
+ " <tr><td>World</td></tr>"
+ " </table>"
+ ""
+ " </td></tr>"
+ "</table>"
+ );
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 1);
+
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ cursor.movePosition(QTextCursor::NextBlock);
+
+ QTextTable *firstNestedTable = cursor.currentTable();
+ QVERIFY(firstNestedTable);
+ QVERIFY(firstNestedTable->parentFrame() == table);
+ QCOMPARE(firstNestedTable->rows(), 1);
+ QCOMPARE(firstNestedTable->columns(), 1);
+ QCOMPARE(firstNestedTable->cellAt(0, 0).firstCursorPosition().block().text(), QString("Hello"));
+
+ while (cursor.currentTable() == firstNestedTable
+ && cursor.movePosition(QTextCursor::NextBlock))
+ ;
+
+ QVERIFY(!cursor.isNull());
+ QVERIFY(cursor.currentTable() == table);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+
+ QTextTable *secondNestedTable = cursor.currentTable();
+ QVERIFY(secondNestedTable);
+ QVERIFY(secondNestedTable->parentFrame() == table);
+ QCOMPARE(secondNestedTable->rows(), 1);
+ QCOMPARE(secondNestedTable->columns(), 1);
+ QCOMPARE(secondNestedTable->cellAt(0, 0).firstCursorPosition().block().text(), QString("World"));
+}
+
+void tst_QTextDocumentFragment::html_rowSpans()
+{
+ setHtml(""
+ "<table border=\"1\" width=\"100%\">"
+ " <tr>"
+ " <td rowspan=\"2\">blah</td>"
+ " <td rowspan=\"2\">foo</td>"
+ " </tr>"
+ " <tr></tr>"
+ " <tr>"
+ " <td rowspan=\"2\">blubb</td>"
+ " <td rowspan=\"2\">baz</td>"
+ " </tr>"
+ " <tr></tr>"
+ "</table>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 4);
+ QCOMPARE(table->columns(), 2);
+
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("blah"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("foo"));
+
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("blah"));
+ QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("foo"));
+
+ QCOMPARE(table->cellAt(2, 0).firstCursorPosition().block().text(), QString("blubb"));
+ QCOMPARE(table->cellAt(2, 1).firstCursorPosition().block().text(), QString("baz"));
+
+ QCOMPARE(table->cellAt(3, 0).firstCursorPosition().block().text(), QString("blubb"));
+ QCOMPARE(table->cellAt(3, 1).firstCursorPosition().block().text(), QString("baz"));
+}
+
+void tst_QTextDocumentFragment::html_rowSpans2()
+{
+ setHtml(""
+ "<html><body>"
+ "<table border=\"1\">"
+ "<tr>"
+ "<td>Row 1 col 1</td>"
+ "</tr>"
+ "<tr>"
+ "<td rowspan=\"3\">Row 2 col 1, rowspan 3</td>"
+ "<td>Row 2 col 2</td>"
+ "</tr>"
+ "<tr>"
+ "<td rowspan=\"2\">Row 3 col 2, rowspan 2</td>"
+ "</tr>"
+ "<tr>"
+ "</tr>"
+ "</table>"
+ "</body></html>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 4);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 1).rowSpan(), 1);
+ QCOMPARE(table->cellAt(1, 0).rowSpan(), 3);
+ QCOMPARE(table->cellAt(2, 1).rowSpan(), 2);
+}
+
+void tst_QTextDocumentFragment::html_implicitParagraphs()
+{
+ setHtml("<p>foo</p>bar");
+ QCOMPARE(doc->blockCount(), 2);
+}
+
+void tst_QTextDocumentFragment::html_missingCloseTag()
+{
+ setHtml("<font color=\"red\"><span style=\"color:blue\">blue</span></span>&nbsp;red</font>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
+ cursor.movePosition(QTextCursor::NextWord);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
+}
+
+void tst_QTextDocumentFragment::html_anchorColor()
+{
+ setHtml("<span style=\"color: red;\">Red</span>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
+
+ setHtml("<span style=\"color: red;\"><a href=\"http://www.kde.org/\">Blue</a></span>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground().color() == QApplication::palette().link().color());
+
+ setHtml("<span style=\"color: red;\"><a href=\"http://www.kde.org/\" style=\"color: yellow;\">Green</a></span>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::yellow);
+}
+
+void tst_QTextDocumentFragment::html_lastParagraphClosing()
+{
+ setHtml("<p>Foo<b>Bar</b>Baz");
+ QCOMPARE(doc->blockCount(), 1);
+}
+
+void tst_QTextDocumentFragment::html_tableHeaderBodyFootParent()
+{
+ // don't get confused by strange tags, keep tbody/thead/tfoot children of
+ // the table tag
+ setHtml("<table><col><col><col><tbody><tr><td>Hey</td></tr></tbody></table>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Hey"));
+
+ setHtml("<table><col><col><col><thead><tr><td>Hey</td></tr></thead></table>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Hey"));
+
+ setHtml("<table><col><col><col><tfoot><tr><td>Hey</td></tr></tfoot></table>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Hey"));
+}
+
+void tst_QTextDocumentFragment::html_columnWidths()
+{
+ setHtml("<table>"
+ " <tr>"
+ " <td colspan=\"2\">Foo</td>"
+ " </tr>"
+ " <tr>"
+ " <td>Bar</td>"
+ " <td width=\"1%\">Baz</td>"
+ " </tr>"
+ "</table>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 2);
+ QTextTableFormat fmt = table->format();
+
+ const QVector<QTextLength> columnWidths = fmt.columnWidthConstraints();
+ QCOMPARE(columnWidths.count(), 2);
+ QVERIFY(columnWidths.at(0).type() == QTextLength::VariableLength);
+ QVERIFY(columnWidths.at(1).type() == QTextLength::PercentageLength);
+ QVERIFY(columnWidths.at(1).rawValue() == 1);
+}
+
+void tst_QTextDocumentFragment::css_fontWeight()
+{
+ setHtml("<p style=\"font-weight:bold\">blah</p>");
+ QVERIFY(doc->begin().charFormat().fontWeight() == QFont::Bold);
+ setHtml("<p style=\"font-weight:600\">blah</p>");
+ QVERIFY(doc->begin().charFormat().fontWeight() == QFont::Bold);
+
+}
+
+void tst_QTextDocumentFragment::css_float()
+{
+ setHtml("<img src=\"foo\" style=\"float: right\">");
+ QTextCharFormat fmt = doc->begin().begin().fragment().charFormat();
+ QVERIFY(fmt.isImageFormat());
+ QTextObject *o = doc->objectForFormat(fmt);
+ QVERIFY(o);
+ QTextFormat f = o->format();
+ QVERIFY(f.isFrameFormat());
+ QVERIFY(f.toFrameFormat().position() == QTextFrameFormat::FloatRight);
+
+ setHtml("<img src=\"foo\" align=right>");
+ fmt = doc->begin().begin().fragment().charFormat();
+ QVERIFY(fmt.isImageFormat());
+ o = doc->objectForFormat(fmt);
+ QVERIFY(o);
+ f = o->format();
+ QVERIFY(f.isFrameFormat());
+ QVERIFY(f.toFrameFormat().position() == QTextFrameFormat::FloatRight);
+
+ setHtml("<img src=\"foo\" align=left>");
+ fmt = doc->begin().begin().fragment().charFormat();
+ QVERIFY(fmt.isImageFormat());
+ o = doc->objectForFormat(fmt);
+ QVERIFY(o);
+ f = o->format();
+ QVERIFY(f.isFrameFormat());
+ QVERIFY(f.toFrameFormat().position() == QTextFrameFormat::FloatLeft);
+}
+
+void tst_QTextDocumentFragment::css_textIndent()
+{
+ setHtml("<p style=\"text-indent: 42px\">foo</p>");
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ QCOMPARE(fmt.textIndent(), qreal(42));
+}
+
+void tst_QTextDocumentFragment::css_inline()
+{
+ setHtml(""
+ "<style>"
+ " p { background-color: green;}"
+ "</style>"
+ "<p>test</p>"
+ );
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+}
+
+void tst_QTextDocumentFragment::css_external()
+{
+ doc->addResource(QTextDocument::StyleSheetResource, QUrl("test.css"), QString("p { background-color: green; }"));
+ doc->setHtml(""
+ "<link href=\"test.css\" type=\"text/css\" />"
+ "<p>test</p>"
+ );
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+}
+
+void tst_QTextDocumentFragment::css_import()
+{
+ doc->addResource(QTextDocument::StyleSheetResource, QUrl("test.css"), QString("@import \"other.css\";"));
+ doc->addResource(QTextDocument::StyleSheetResource, QUrl("other.css"), QString("@import url(\"other2.css\");"));
+ doc->addResource(QTextDocument::StyleSheetResource, QUrl("other2.css"), QString("p { background-color: green; }"));
+ doc->setHtml(""
+ "<link href=\"test.css\" type=\"text/css\" />"
+ "<p>test</p>"
+ );
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+
+ doc->setHtml(""
+ "<style>@import \"test.css\" screen;</style>"
+ "<p>test</p>"
+ );
+ fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+}
+
+void tst_QTextDocumentFragment::css_selectors_data()
+{
+ QTest::addColumn<bool>("match");
+ QTest::addColumn<QString>("selector");
+ QTest::addColumn<QString>("attributes");
+
+ QTest::newRow("plain") << true << QString() << QString();
+
+ QTest::newRow("class") << true << QString(".foo") << QString("class=foo");
+ QTest::newRow("notclass") << false << QString(".foo") << QString("class=bar");
+
+ QTest::newRow("attrset") << true << QString("[justset]") << QString("justset");
+ QTest::newRow("notattrset") << false << QString("[justset]") << QString("otherattribute");
+
+ QTest::newRow("attrmatch") << true << QString("[foo=bar]") << QString("foo=bar");
+ QTest::newRow("noattrmatch") << false << QString("[foo=bar]") << QString("foo=xyz");
+
+ QTest::newRow("contains") << true << QString("[foo~=bar]") << QString("foo=\"baz bleh bar\"");
+ QTest::newRow("notcontains") << false << QString("[foo~=bar]") << QString("foo=\"test\"");
+
+ QTest::newRow("beingswith") << true << QString("[foo|=bar]") << QString("foo=\"bar-bleh\"");
+ QTest::newRow("notbeingswith") << false << QString("[foo|=bar]") << QString("foo=\"bleh-bar\"");
+
+ QTest::newRow("attr2") << true << QString("[bar=foo]") << QString("bleh=bar bar=foo");
+}
+
+void tst_QTextDocumentFragment::css_selectors()
+{
+ QFETCH(bool, match);
+ QFETCH(QString, selector);
+ QFETCH(QString, attributes);
+
+ QString html = QString(""
+ "<style>"
+ " p { background-color: green }"
+ " p%1 { background-color: red }"
+ "</style>"
+ "<p %2>test</p>"
+ ).arg(selector).arg(attributes);
+ setHtml(html);
+
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ if (match)
+ QVERIFY(fmt.background().color() == QColor("red"));
+ else
+ QVERIFY(fmt.background().color() == QColor("green"));
+}
+
+void tst_QTextDocumentFragment::css_nodeNameCaseInsensitivity()
+{
+ setHtml("<style>"
+ "P { background-color: green }"
+ "</style>"
+ "<p>test</p>");
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+}
+
+void tst_QTextDocumentFragment::css_textUnderlineStyle_data()
+{
+ QTest::addColumn<QString>("styleName");
+ QTest::addColumn<int>("expectedStyle");
+
+ QTest::newRow("none") << QString("none") << int(QTextCharFormat::NoUnderline);
+ QTest::newRow("solid") << QString("solid") << int(QTextCharFormat::SingleUnderline);
+ QTest::newRow("dash") << QString("dashed") << int(QTextCharFormat::DashUnderline);
+ QTest::newRow("dot") << QString("dotted") << int(QTextCharFormat::DotLine);
+ QTest::newRow("dashdot") << QString("dot-dash") << int(QTextCharFormat::DashDotLine);
+ QTest::newRow("dashdotdot") << QString("dot-dot-dash") << int(QTextCharFormat::DashDotDotLine);
+ QTest::newRow("wave") << QString("wave") << int(QTextCharFormat::WaveUnderline);
+}
+
+void tst_QTextDocumentFragment::css_textUnderlineStyle()
+{
+ QFETCH(QString, styleName);
+ QFETCH(int, expectedStyle);
+
+ QString html = QString::fromLatin1("<span style=\"text-underline-style: %1\">Blah</span>").arg(styleName);
+ doc->setHtml(html);
+
+ QTextFragment fragment = doc->begin().begin().fragment();
+ QVERIFY(fragment.isValid());
+ QCOMPARE(int(fragment.charFormat().underlineStyle()), expectedStyle);
+}
+
+void tst_QTextDocumentFragment::css_textUnderlineStyleAndDecoration()
+{
+ doc->setHtml("<span style=\"text-decoration: overline; text-underline-style: solid\">Test</span>");
+
+ QTextFragment fragment = doc->begin().begin().fragment();
+ QVERIFY(fragment.isValid());
+ QVERIFY(fragment.charFormat().underlineStyle() == QTextCharFormat::SingleUnderline);
+ QVERIFY(fragment.charFormat().fontOverline());
+
+ doc->setHtml("<span style=\"text-underline-style: solid; text-decoration: overline\">Test</span>");
+
+ fragment = doc->begin().begin().fragment();
+ QVERIFY(fragment.isValid());
+ QVERIFY(fragment.charFormat().underlineStyle() == QTextCharFormat::SingleUnderline);
+ QVERIFY(fragment.charFormat().fontOverline());
+}
+
+void tst_QTextDocumentFragment::css_listStyleType()
+{
+ doc->setHtml("<ol style=\"list-style-type: disc\"><li>Blah</li></ol>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListDisc);
+
+ doc->setHtml("<ul style=\"list-style-type: square\"><li>Blah</li></ul>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListSquare);
+
+ doc->setHtml("<ul style=\"list-style-type: circle\"><li>Blah</li></ul>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListCircle);
+
+ doc->setHtml("<ul style=\"list-style-type: decimal\"><li>Blah</li></ul>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListDecimal);
+
+ doc->setHtml("<ul style=\"list-style-type: lower-alpha\"><li>Blah</li></ul>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListLowerAlpha);
+
+ doc->setHtml("<ul style=\"list-style-type: upper-alpha\"><li>Blah</li></ul>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListUpperAlpha);
+
+ doc->setHtml("<ul style=\"list-style-type: upper-roman\"><li>Blah</li></ul>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListUpperRoman);
+
+ doc->setHtml("<ul style=\"list-style-type: lower-roman\"><li>Blah</li></ul>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListLowerRoman);
+
+ // ignore the unsupported list-style-position inside the list-style shorthand property
+ doc->setHtml("<ul style=\"list-style: outside decimal\"><li>Blah</li></ul>");
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListDecimal);
+}
+
+void tst_QTextDocumentFragment::css_linkPseudo()
+{
+ doc->setHtml("<a href=\"foobar\">Blah</a>");
+ QVERIFY(doc->begin().begin().fragment().charFormat().fontUnderline());
+
+ doc->setHtml("<style>a { text-decoration: none; }</style><a href=\"foobar\">Blah</a>");
+ QVERIFY(!doc->begin().begin().fragment().charFormat().fontUnderline());
+
+ doc->setHtml("<style>a:link { text-decoration: none; }</style><a href=\"foobar\">Blah</a>");
+ QVERIFY(!doc->begin().begin().fragment().charFormat().fontUnderline());
+}
+
+void tst_QTextDocumentFragment::css_pageBreaks()
+{
+ doc->setHtml("<p>Foo</p>");
+ QVERIFY(doc->begin().blockFormat().pageBreakPolicy() == QTextFormat::PageBreak_Auto);
+
+ doc->setHtml("<p style=\" page-break-before:always;\">Foo</p>");
+ QVERIFY(doc->begin().blockFormat().pageBreakPolicy() == QTextFormat::PageBreak_AlwaysBefore);
+
+ doc->setHtml("<p style=\" page-break-after:always;\">Foo</p>");
+ QVERIFY(doc->begin().blockFormat().pageBreakPolicy() == QTextFormat::PageBreak_AlwaysAfter);
+
+ doc->setHtml("<p style=\" page-break-before:always; page-break-after:always;\">Foo</p>");
+ QVERIFY(doc->begin().blockFormat().pageBreakPolicy() == (QTextFormat::PageBreak_AlwaysAfter | QTextFormat::PageBreak_AlwaysBefore));
+}
+
+void tst_QTextDocumentFragment::universalSelectors_data()
+{
+ QTest::addColumn<bool>("match");
+ QTest::addColumn<QString>("selector");
+ QTest::addColumn<QString>("attributes");
+
+ QTest::newRow("1") << true << QString("*") << QString();
+ QTest::newRow("2") << false << QString() << QString(); // invalid totally empty selector
+
+ QTest::newRow("3") << false << QString("*[foo=bar]") << QString("foo=bleh");
+ QTest::newRow("4") << true << QString("*[foo=bar]") << QString("foo=bar");
+
+ QTest::newRow("5") << false << QString("[foo=bar]") << QString("foo=bleh");
+ QTest::newRow("6") << true << QString("[foo=bar]") << QString("foo=bar");
+
+ QTest::newRow("7") << true << QString(".charfmt1") << QString("class=charfmt1");
+}
+
+void tst_QTextDocumentFragment::universalSelectors()
+{
+ QFETCH(bool, match);
+ QFETCH(QString, selector);
+ QFETCH(QString, attributes);
+
+ QString html = QString(""
+ "<style>"
+ "%1 { background-color: green }"
+ "</style>"
+ "<p %2>test</p>"
+ ).arg(selector).arg(attributes);
+
+ setHtml(html);
+
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ if (match)
+ QVERIFY(fmt.background().color() == QColor("green"));
+ else
+ QVERIFY(!fmt.hasProperty(QTextFormat::BackgroundBrush));
+}
+
+void tst_QTextDocumentFragment::screenMedia()
+{
+ setHtml("<style>"
+ "@media screen {"
+ "p { background-color: green }"
+ "}"
+ "</style>"
+ "<p>test</p>"
+ "");
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+
+ setHtml("<style>"
+ "@media foobar {"
+ "p { background-color: green }"
+ "}"
+ "</style>"
+ "<p>test</p>"
+ "");
+ fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() != QColor("green"));
+
+ setHtml("<style>"
+ "@media sCrEeN {"
+ "p { background-color: green }"
+ "}"
+ "</style>"
+ "<p>test</p>"
+ "");
+ fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+}
+
+void tst_QTextDocumentFragment::htmlResourceLoading()
+{
+ const QString html("<link href=\"test.css\" type=\"text/css\" />"
+ "<p>test</p>");
+
+ QTextDocument tmp;
+ tmp.addResource(QTextDocument::StyleSheetResource, QUrl("test.css"), QString("p { background-color: green; }"));
+ QTextDocumentFragment frag = QTextDocumentFragment::fromHtml(html, &tmp);
+ doc->clear();
+ QTextCursor(doc).insertFragment(frag);
+ QTextBlockFormat fmt = doc->begin().blockFormat();
+ QVERIFY(fmt.background().color() == QColor("green"));
+}
+
+void tst_QTextDocumentFragment::someCaseInsensitiveAttributeValues()
+{
+ const char html1[] = "<ul type=sQUarE><li>Blah</li></ul>";
+ setHtml(QString::fromLatin1(html1));
+ cursor.movePosition(QTextCursor::End);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListSquare);
+
+ const char html2[] = "<div align=ceNTeR><b>Hello World";
+ setHtml(html2);
+
+ QCOMPARE(doc->begin().blockFormat().alignment(), Qt::AlignHCenter);
+
+ const char html3[] = "<p dir=rTL><b>Hello World";
+ setHtml(html3);
+
+ QCOMPARE(doc->begin().blockFormat().layoutDirection(), Qt::RightToLeft);
+}
+
+class TestDocument : public QTextDocument
+{
+public:
+ inline TestDocument() {}
+
+ QPixmap testPixmap;
+
+ virtual QVariant loadResource(int type, const QUrl &name) {
+ if (name.toString() == QLatin1String("testPixmap")) {
+ return testPixmap;
+ }
+ return QTextDocument::loadResource(type, name);
+ }
+};
+
+void tst_QTextDocumentFragment::backgroundImage()
+{
+ TestDocument doc;
+ doc.testPixmap = QPixmap(100, 100);
+ doc.testPixmap.fill(Qt::blue);
+ doc.setHtml("<p style=\"background-image: url(testPixmap)\">Hello</p>");
+ QBrush bg = doc.begin().blockFormat().background();
+ QVERIFY(bg.style() == Qt::TexturePattern);
+ QVERIFY(bg.texture().serialNumber() == doc.testPixmap.serialNumber());
+}
+
+void tst_QTextDocumentFragment::dontMergePreAndNonPre()
+{
+ doc->setHtml("<pre>Pre text</pre>Text that should be wrapped");
+ QCOMPARE(doc->blockCount(), 2);
+ QCOMPARE(doc->begin().text(), QString("Pre text"));
+ QCOMPARE(doc->begin().next().text(), QString("Text that should be wrapped"));
+}
+
+void tst_QTextDocumentFragment::leftMarginInsideHtml()
+{
+ doc->setHtml("<html><dl><dd>Blah");
+ QCOMPARE(doc->blockCount(), 1);
+ QVERIFY(doc->begin().blockFormat().leftMargin() > 0);
+}
+
+void tst_QTextDocumentFragment::html_margins()
+{
+ doc->setHtml("<p style=\"margin-left: 42px\">Test");
+ QCOMPARE(doc->blockCount(), 1);
+ QCOMPARE(doc->begin().blockFormat().topMargin(), 12.);
+ QCOMPARE(doc->begin().blockFormat().bottomMargin(), 12.);
+ QCOMPARE(doc->begin().blockFormat().leftMargin(), 42.);
+}
+
+void tst_QTextDocumentFragment::newlineInsidePreShouldBecomeNewParagraph()
+{
+ // rationale: we used to map newlines inside <pre> to QChar::LineSeparator, but
+ // if you display a lot of text inside pre it all ended up inside one single paragraph,
+ // which doesn't scale very well with our text engine. Paragraphs spanning thousands of
+ // lines are not a common use-case otherwise.
+
+ doc->setHtml("<pre>Foo\nBar</pre>");
+ QCOMPARE(doc->blockCount(), 2);
+ QTextBlock block = doc->begin();
+ QCOMPARE(block.blockFormat().topMargin(), qreal(12));
+ QVERIFY(qIsNull(block.blockFormat().bottomMargin()));
+
+ block = block.next();
+
+ QVERIFY(qIsNull(block.blockFormat().topMargin()));
+ QCOMPARE(block.blockFormat().bottomMargin(), qreal(12));
+
+ doc->setHtml("<pre style=\"margin-top: 32px; margin-bottom: 45px; margin-left: 50px\">Foo\nBar</pre>");
+ QCOMPARE(doc->blockCount(), 2);
+ block = doc->begin();
+ QCOMPARE(block.blockFormat().topMargin(), qreal(32));
+ QVERIFY(qIsNull(block.blockFormat().bottomMargin()));
+ QCOMPARE(block.blockFormat().leftMargin(), qreal(50));
+
+ block = block.next();
+
+ QVERIFY(qIsNull(block.blockFormat().topMargin()));
+ QCOMPARE(block.blockFormat().bottomMargin(), qreal(45));
+ QCOMPARE(block.blockFormat().leftMargin(), qreal(50));
+
+}
+
+void tst_QTextDocumentFragment::invalidColspan()
+{
+ doc->setHtml("<table><tr rowspan=-1><td colspan=-1>Blah</td></tr></table>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->rows(), 1);
+}
+
+void tst_QTextDocumentFragment::html_brokenTableWithJustTr()
+{
+ doc->setHtml("<tr><td>First Cell</td><tr><td>Second Cell");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Second Cell"));
+
+ doc->setHtml(""
+ "<col width=286 style='mso-width-source:userset;mso-width-alt:10459;width:215pt'>"
+ "<col width=64 span=3 style='width:48pt'>"
+ "<tr height=17 style='height:12.75pt'>"
+ "<td height=17 width=286 style='height:12.75pt;width:215pt'>1a</td>"
+ "<td width=64 style='width:48pt'>1b</td>"
+ "<td width=64 style='width:48pt'>1c</td>"
+ "<td width=64 style='width:48pt'>1d</td>"
+ "</tr>"
+ "<tr height=17 style='height:12.75pt'>"
+ "<td height=17 style='height:12.75pt'>|2a</td>"
+ "<td>2b</td>"
+ "<td>2c</td>"
+ "<td>2d</td>"
+ "</tr>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 4);
+}
+
+void tst_QTextDocumentFragment::html_brokenTableWithJustTd()
+{
+ doc->setHtml("<td>First Cell</td><td>Second Cell");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second Cell"));
+
+ doc->setHtml("<td height=17 width=286 style='height:12.75pt;width:215pt'>1a</td>"
+ "<td width=64 style='width:48pt'>1b</td>"
+ "<td width=64 style='width:48pt'>1c</td>"
+ "<td width=64 style='width:48pt'>1d</td>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 4);
+}
+
+void tst_QTextDocumentFragment::html_preNewlineHandling_data()
+{
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<QString>("expectedPlainText");
+
+ QTest::newRow("pre1") << QString("Foo<pre>Bar")
+ << QString("Foo\nBar");
+ QTest::newRow("pre2") << QString("Foo<pre>\nBar")
+ << QString("Foo\nBar");
+ QTest::newRow("pre2") << QString("Foo<pre>\n\nBar")
+ << QString("Foo\n\nBar");
+ QTest::newRow("pre4") << QString("<html>Foo<pre>\nBar")
+ << QString("Foo\nBar");
+ QTest::newRow("pre5") << QString("<pre>Foo\n</pre>\nBar")
+ << QString("Foo\nBar");
+ QTest::newRow("pre6") << QString("<pre>Foo<b>Bar</b>Blah\n</pre>\nMooh")
+ << QString("FooBarBlah\nMooh");
+ QTest::newRow("pre7") << QString("<pre>\nPara1\n</pre>\n<pre>\nPara2\n</pre>")
+ << QString("Para1\nPara2");
+}
+
+void tst_QTextDocumentFragment::html_preNewlineHandling()
+{
+ QFETCH(QString, html);
+
+ doc->setHtml(html);
+ QTEST(doc->toPlainText(), "expectedPlainText");
+}
+
+void tst_QTextDocumentFragment::html_br()
+{
+ doc->setHtml("Foo<br><br><br>Blah");
+ QCOMPARE(doc->toPlainText(), QString("Foo\n\n\nBlah"));
+}
+
+void tst_QTextDocumentFragment::html_dl()
+{
+ doc->setHtml("<dl><dt>term<dd>data</dl>Text afterwards");
+ QCOMPARE(doc->toPlainText(), QString("term\ndata\nText afterwards"));
+}
+
+void tst_QTextDocumentFragment::html_tableStrangeNewline()
+{
+ doc->setHtml("<table><tr><td>Foo</td></tr>\n</table>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 1);
+ const QTextTableCell cell = table->cellAt(0, 0);
+ QCOMPARE(cell.firstCursorPosition().block().text(), QString("Foo"));
+ QVERIFY(cell.firstCursorPosition().block() == cell.lastCursorPosition().block());
+}
+
+void tst_QTextDocumentFragment::html_tableStrangeNewline2()
+{
+ doc->setHtml("<table><tr><td>Foo</td></tr><tr>\n<td/></tr></table>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 1);
+ const QTextTableCell cell = table->cellAt(0, 0);
+ QCOMPARE(cell.firstCursorPosition().block().text(), QString("Foo"));
+ QVERIFY(cell.firstCursorPosition().block() == cell.lastCursorPosition().block());
+}
+
+void tst_QTextDocumentFragment::html_tableStrangeNewline3()
+{
+ doc->setHtml("<table border>"
+ "<tr>"
+ "<td>"
+ "<ul>"
+ "<li>Meh</li>"
+ "</ul>"
+ "</td>"
+ "<td>\n"
+ "<ul>"
+ "<li>Foo</li>"
+ "</ul>"
+ "</td>"
+ "</tr>"
+ "</table>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 2);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QCOMPARE(cell.firstCursorPosition().block().text(), QString("Meh"));
+ QVERIFY(cell.firstCursorPosition().block() == cell.lastCursorPosition().block());
+
+ cell = table->cellAt(0, 1);
+ QCOMPARE(cell.firstCursorPosition().block().text(), QString("Foo"));
+ QVERIFY(cell.firstCursorPosition().block() == cell.lastCursorPosition().block());
+}
+
+void tst_QTextDocumentFragment::html_caption()
+{
+ doc->setHtml("<table border align=center>"
+ "<caption>This <b> is a</b> Caption!</caption>"
+ "<tr><td>Blah</td></tr>"
+ "</table>");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+
+ QCOMPARE(cursor.block().text(), QString("This is a Caption!"));
+ QVERIFY(cursor.blockFormat().alignment() == Qt::AlignHCenter);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 1);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QCOMPARE(cell.firstCursorPosition().block().text(), QString("Blah"));
+}
+
+static const uint windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
+ 0x20ac, // 0x80
+ 0x0081, // 0x81 direct mapping
+ 0x201a, // 0x82
+ 0x0192, // 0x83
+ 0x201e, // 0x84
+ 0x2026, // 0x85
+ 0x2020, // 0x86
+ 0x2021, // 0x87
+ 0x02C6, // 0x88
+ 0x2030, // 0x89
+ 0x0160, // 0x8A
+ 0x2039, // 0x8B
+ 0x0152, // 0x8C
+ 0x008D, // 0x8D direct mapping
+ 0x017D, // 0x8E
+ 0x008F, // 0x8F directmapping
+ 0x0090, // 0x90 directmapping
+ 0x2018, // 0x91
+ 0x2019, // 0x92
+ 0x201C, // 0x93
+ 0X201D, // 0x94
+ 0x2022, // 0x95
+ 0x2013, // 0x96
+ 0x2014, // 0x97
+ 0x02DC, // 0x98
+ 0x2122, // 0x99
+ 0x0161, // 0x9A
+ 0x203A, // 0x9B
+ 0x0153, // 0x9C
+ 0x009D, // 0x9D direct mapping
+ 0x017E, // 0x9E
+ 0x0178 // 0x9F
+};
+
+void tst_QTextDocumentFragment::html_windowsEntities()
+{
+ for (uint i = 0; i < sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0]); ++i) {
+ QString html = QString::number(i + 0x80);
+ html.prepend("<p>&#");
+ html.append(";");
+ doc->setHtml(html);
+ QCOMPARE(doc->toPlainText(), QString(QChar(windowsLatin1ExtendedCharacters[i])));
+ }
+}
+
+void tst_QTextDocumentFragment::html_eatenText()
+{
+ doc->setHtml("<h1>Test1</h1>\nTest2<h1>Test3</h1>");
+ cursor.movePosition(QTextCursor::Start);
+ QCOMPARE(cursor.block().text(), QString("Test1"));
+ cursor.movePosition(QTextCursor::NextBlock);
+ QCOMPARE(cursor.block().text(), QString("Test2"));
+ cursor.movePosition(QTextCursor::NextBlock);
+ QCOMPARE(cursor.block().text(), QString("Test3"));
+}
+
+void tst_QTextDocumentFragment::html_hr()
+{
+ doc->setHtml("<hr />");
+ QCOMPARE(doc->blockCount(), 1);
+ QVERIFY(doc->begin().blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth));
+}
+
+void tst_QTextDocumentFragment::html_hrMargins()
+{
+ doc->setHtml("<p>Test<hr/>Blah");
+ QCOMPARE(doc->blockCount(), 3);
+
+ cursor.movePosition(QTextCursor::Start);
+ QTextBlock block = cursor.block();
+ QCOMPARE(block.text(), QString("Test"));
+ QVERIFY(block.blockFormat().bottomMargin() <= qreal(12.));
+ QTextBlock first = block;
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ block = cursor.block();
+ QTextBlock hr = block;
+ QVERIFY(qMax(first.blockFormat().bottomMargin(), block.blockFormat().topMargin()) > 0);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ block = cursor.block();
+
+ QCOMPARE(block.text(), QString("Blah"));
+}
+
+void tst_QTextDocumentFragment::html_blockQuoteMargins()
+{
+ doc->setHtml("<blockquote>Bar</blockquote>");
+ QCOMPARE(doc->blockCount(), 1);
+ cursor.movePosition(QTextCursor::Start);
+ QTextBlock block = cursor.block();
+ QCOMPARE(block.text(), QString("Bar"));
+ QCOMPARE(block.blockFormat().leftMargin(), qreal(40.));
+ QCOMPARE(block.blockFormat().rightMargin(), qreal(40.));
+ QCOMPARE(block.blockFormat().topMargin(), qreal(12.));
+ QCOMPARE(block.blockFormat().bottomMargin(), qreal(12.));
+}
+
+void tst_QTextDocumentFragment::html_definitionListMargins()
+{
+ doc->setHtml("Foo<dl><dt>tag<dd>data</dl>Bar");
+ QCOMPARE(doc->blockCount(), 4);
+
+ cursor.movePosition(QTextCursor::Start);
+ QTextBlock block = cursor.block();
+ QCOMPARE(block.text(), QString("Foo"));
+
+ block = block.next();
+ QCOMPARE(block.text(), QString("tag"));
+ QCOMPARE(block.blockFormat().topMargin(), qreal(8.));
+
+ block = block.next();
+ QCOMPARE(block.text(), QString("data"));
+ QCOMPARE(block.blockFormat().bottomMargin(), qreal(8.));
+
+ block = block.next();
+ QCOMPARE(block.text(), QString("Bar"));
+}
+
+void tst_QTextDocumentFragment::html_listMargins()
+{
+ doc->setHtml("Foo<ol><li>First<li>Second</ol>Bar");
+ QCOMPARE(doc->blockCount(), 4);
+
+ cursor.movePosition(QTextCursor::Start);
+ QTextBlock block = cursor.block();
+ QCOMPARE(block.text(), QString("Foo"));
+
+ block = block.next();
+ QCOMPARE(block.text(), QString("First"));
+ QCOMPARE(block.blockFormat().topMargin(), qreal(12.));
+
+ block = block.next();
+ QCOMPARE(block.text(), QString("Second"));
+ QCOMPARE(block.blockFormat().bottomMargin(), qreal(12.));
+
+ block = block.next();
+ QCOMPARE(block.text(), QString("Bar"));
+}
+
+void tst_QTextDocumentFragment::html_titleAttribute()
+{
+ doc->setHtml("<span title=\"this is my title\">Test</span>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().toolTip(), QString("this is my title"));
+}
+
+void tst_QTextDocumentFragment::html_compressDivs()
+{
+ doc->setHtml("<p/><div/><div/><div/><div/>Test");
+ QCOMPARE(doc->blockCount(), 1);
+ QCOMPARE(doc->begin().text(), QString("Test"));
+}
+
+void tst_QTextDocumentFragment::completeToPlainText()
+{
+ doc->setPlainText("Hello\nWorld");
+ QCOMPARE(doc->toPlainText(), QString("Hello\nWorld"));
+ QTextDocumentFragment fragment(doc);
+ QCOMPARE(fragment.toPlainText(), QString("Hello\nWorld"));
+}
+
+void tst_QTextDocumentFragment::copyContents()
+{
+ doc->setPlainText("Hello");
+ QFont f;
+ doc->setDefaultFont(f);
+ QTextFragment fragment = doc->begin().begin().fragment();
+ QCOMPARE(fragment.text(), QString("Hello"));
+ QCOMPARE(fragment.charFormat().font().pointSize(), f.pointSize());
+
+ QTextDocumentFragment frag(doc);
+ doc->clear();
+ f.setPointSize(48);
+ doc->setDefaultFont(f);
+ QTextCursor(doc).insertFragment(QTextDocumentFragment::fromHtml(frag.toHtml()));
+ fragment = doc->begin().begin().fragment();
+ QCOMPARE(fragment.text(), QString("Hello"));
+ QCOMPARE(fragment.charFormat().font().pointSize(), f.pointSize());
+}
+
+void tst_QTextDocumentFragment::html_textAfterHr()
+{
+ doc->setHtml("<hr><nobr><b>After the centered text</b></nobr>");
+ QCOMPARE(doc->blockCount(), 2);
+ QTextBlock block = doc->begin();
+ QVERIFY(block.text().isEmpty());
+ QVERIFY(block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth));
+ block = block.next();
+
+ QString txt("After the centered text");
+ txt.replace(QLatin1Char(' '), QChar::Nbsp);
+ QCOMPARE(block.text(), txt);
+ QVERIFY(!block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth));
+}
+
+void tst_QTextDocumentFragment::blockTagClosing()
+{
+ doc->setHtml("<p>foo<p>bar<span>baz</span>");
+ QCOMPARE(doc->blockCount(), 2);
+ QTextBlock block = doc->begin();
+ QCOMPARE(block.text(), QString("foo"));
+ block = block.next();
+ QCOMPARE(block.text(), QString("barbaz"));
+}
+
+void tst_QTextDocumentFragment::isEmpty()
+{
+ QTextDocumentFragment frag;
+ QVERIFY(frag.isEmpty());
+ frag = QTextDocumentFragment::fromHtml("test");
+ QVERIFY(!frag.isEmpty());
+ frag = QTextDocumentFragment::fromHtml("<hr />");
+ QVERIFY(!frag.isEmpty());
+}
+
+void tst_QTextDocumentFragment::html_alignmentInheritance()
+{
+ doc->setHtml("<center>Centered text<hr></center><b>After the centered text</b>");
+ QCOMPARE(doc->blockCount(), 3);
+ QTextBlock block = doc->begin();
+ QVERIFY(block.blockFormat().alignment() & Qt::AlignHCenter);
+ block = block.next();
+ QVERIFY(block.blockFormat().alignment() & Qt::AlignHCenter);
+ block = block.next();
+ QVERIFY(!(block.blockFormat().alignment() & Qt::AlignHCenter));
+}
+
+void tst_QTextDocumentFragment::html_ignoreEmptyDivs()
+{
+ doc->setHtml("<p><div/><b>Foo</b>");
+ QCOMPARE(doc->blockCount(), 1);
+ QCOMPARE(doc->begin().text(), QString("Foo"));
+}
+
+void tst_QTextDocumentFragment::html_dontInheritAlignmentForFloatingImages()
+{
+ doc->setHtml("<p align=right><img align=unknownignored src=\"foo\" /></p>");
+ QTextCharFormat fmt = doc->begin().begin().fragment().charFormat();
+ QVERIFY(fmt.isImageFormat());
+ QTextObject *o = doc->objectForFormat(fmt);
+ QVERIFY(o);
+ QTextFormat f = o->format();
+ QVERIFY(f.isFrameFormat());
+ QVERIFY(f.toFrameFormat().position() == QTextFrameFormat::InFlow);
+}
+
+void tst_QTextDocumentFragment::html_verticalImageAlignment()
+{
+ doc->setHtml("<img src=\"foo\"/>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().isImageFormat());
+ QTextImageFormat fmt = cursor.charFormat().toImageFormat();
+ QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignNormal);
+
+ doc->setHtml("<img src=\"foo\" align=middle />");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().isImageFormat());
+ fmt = cursor.charFormat().toImageFormat();
+ QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignMiddle);
+
+ doc->setHtml("<img src=\"foo\" style=\"vertical-align: middle\" />");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().isImageFormat());
+ fmt = cursor.charFormat().toImageFormat();
+ QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignMiddle);
+
+ doc->setHtml("<img src=\"foo\" align=top />");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().isImageFormat());
+ fmt = cursor.charFormat().toImageFormat();
+ QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignTop);
+
+ doc->setHtml("<img src=\"foo\" style=\"vertical-align: top\" />");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().isImageFormat());
+ fmt = cursor.charFormat().toImageFormat();
+ QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignTop);
+}
+
+void tst_QTextDocumentFragment::html_verticalCellAlignment()
+{
+ const char *alt[] =
+ {
+ // vertical-align property
+ "<table>"
+ "<tr>"
+ "<td style=\"vertical-align: middle\"></td>"
+ "<td style=\"vertical-align: top\"></td>"
+ "<td style=\"vertical-align: bottom\"></td>"
+ "</tr>"
+ "</table>",
+ // valign property
+ "<table>"
+ "<tr>"
+ "<td valign=\"middle\"></td>"
+ "<td valign=\"top\"></td>"
+ "<td valign=\"bottom\"></td>"
+ "</tr>"
+ "</table>",
+ // test td override of tr property
+ "<table>"
+ "<tr valign=\"bottom\">"
+ "<td valign=\"middle\"></td>"
+ "<td valign=\"top\"></td>"
+ "<td></td>"
+ "</tr>"
+ "</table>"
+ };
+
+ const int numTestCases = sizeof(alt) / sizeof(*alt);
+ for (int i = 0; i < numTestCases; ++i) {
+ doc->setHtml(alt[i]);
+
+ QTextTable *table = qobject_cast<QTextTable *>(doc->rootFrame()->childFrames().at(0));
+ QVERIFY(table);
+
+ QCOMPARE(table->cellAt(0, 0).format().verticalAlignment(), QTextCharFormat::AlignMiddle);
+ QCOMPARE(table->cellAt(0, 1).format().verticalAlignment(), QTextCharFormat::AlignTop);
+ QCOMPARE(table->cellAt(0, 2).format().verticalAlignment(), QTextCharFormat::AlignBottom);
+ }
+}
+
+void tst_QTextDocumentFragment::html_borderColor()
+{
+ const char html[] = "<table border=1 style=\"border-color:#0000ff;\"><tr><td>Foo</td></tr></table>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+ QCOMPARE(cursor.currentTable()->format().borderStyle(), QTextFrameFormat::BorderStyle_Outset);
+ QCOMPARE(cursor.currentTable()->format().borderBrush(), QBrush(QColor("#0000ff")));
+}
+
+void tst_QTextDocumentFragment::html_borderStyle()
+{
+ const char html[] = "<table border=1 style=\"border-style:solid;\"><tr><td>Foo</td></tr></table>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+ QCOMPARE(cursor.currentTable()->format().borderStyle(), QTextFrameFormat::BorderStyle_Solid);
+ QCOMPARE(cursor.currentTable()->format().borderBrush(), QBrush(Qt::darkGray));
+}
+
+void tst_QTextDocumentFragment::html_borderWidth()
+{
+ const char *html[2] = { "<table style=\"border-width:2;\"><tr><td>Foo</td></tr></table>",
+ "<table style=\"border-width:2px;\"><tr><td>Foo</td></tr></table>" };
+
+ for (int i = 0; i < 2; ++i) {
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html[i])));
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentTable());
+ QCOMPARE(cursor.currentTable()->format().border(), qreal(2));
+ }
+}
+
+void tst_QTextDocumentFragment::html_userState()
+{
+ const char html[] = "<p style=\"-qt-user-state:42;\">A</p><p style=\"-qt-user-state:0;\">B</p><p>C</p>";
+ cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
+ QTextBlock block = doc->begin();
+ QCOMPARE(block.userState(), 42);
+ QCOMPARE(block.next().userState(), 0);
+ QCOMPARE(block.next().next().userState(), -1);
+}
+
+void tst_QTextDocumentFragment::html_rootFrameProperties()
+{
+ const char html[] = "<table border=1 style=\"-qt-table-type:root; margin-top:10px;\"><tr><td>Foo</tr></td>";
+ doc->setHtml(html);
+
+ QCOMPARE(doc->rootFrame()->childFrames().size(), 0);
+
+ QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
+ QCOMPARE(fmt.topMargin(), qreal(10));
+ QCOMPARE(fmt.bottomMargin(), qreal(0));
+ QCOMPARE(fmt.leftMargin(), qreal(0));
+ QCOMPARE(fmt.rightMargin(), qreal(0));
+ QCOMPARE(fmt.border(), qreal(1));
+
+ QString normalFrameHtml = QLatin1String(html);
+ normalFrameHtml.replace(QLatin1String("root"), QLatin1String("frame"));
+
+ doc->setHtml(normalFrameHtml);
+ QCOMPARE(doc->rootFrame()->childFrames().size(), 1);
+}
+
+void tst_QTextDocumentFragment::html_appendList()
+{
+ appendHtml("<p>foo</p>");
+ appendHtml("<ul><li>Line 1</li><li>Line 2</li></ul>");
+
+ QCOMPARE(doc->blockCount(), 3);
+ QVERIFY(doc->begin().next().textList() != 0);
+}
+
+void tst_QTextDocumentFragment::html_appendList2()
+{
+ appendHtml("1");
+ appendHtml("<ul><li><img src=\"/foo/bar\" /></li></ul>");
+
+ QCOMPARE(doc->blockCount(), 2);
+ QVERIFY(doc->begin().next().textList() != 0);
+}
+
+void tst_QTextDocumentFragment::html_alignmentPropertySet()
+{
+ const char html[] = "<p>Test</p>";
+ setHtml(QString::fromLatin1(html));
+ QVERIFY(!doc->begin().blockFormat().hasProperty(QTextFormat::BlockAlignment));
+}
+
+void tst_QTextDocumentFragment::html_qt3RichtextWhitespaceMode()
+{
+ setHtml(QString::fromLatin1("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><p> line with whitespace</p><p> another line with whitespace</p></body></html>"));
+ QCOMPARE(doc->blockCount(), 2);
+
+ QTextBlock block = doc->begin();
+ QVERIFY(block.text().startsWith(" "));
+
+ block = block.next();
+ QVERIFY(block.text().startsWith(" "));
+}
+
+void tst_QTextDocumentFragment::html_brAfterHr()
+{
+ setHtml(QString::fromLatin1("Text A<br><hr><br>Text B<hr>"));
+
+ QCOMPARE(doc->blockCount(), 4);
+
+ QTextBlock block = doc->begin();
+ QCOMPARE(block.text(), QString("Text A") + QChar(QChar::LineSeparator));
+
+ block = block.next();
+ QVERIFY(block.text().isEmpty());
+
+ block = block.next();
+ QCOMPARE(block.text(), QChar(QChar::LineSeparator) + QString("Text B"));
+
+ block = block.next();
+ QVERIFY(block.text().isEmpty());
+}
+
+void tst_QTextDocumentFragment::html_unclosedHead()
+{
+ doc->setHtml(QString::fromLatin1("<html><head><title>Test</title><body>Blah</body></html>"));
+ QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), QString::fromLatin1("Test"));
+ QCOMPARE(doc->toPlainText(), QString::fromLatin1("Blah"));
+}
+
+// duplicated from qtexthtmlparser.cpp
+#define MAX_ENTITY 258
+static const struct { const char *name; quint16 code; } entities[MAX_ENTITY]= {
+ { "AElig", 0x00c6 },
+ { "Aacute", 0x00c1 },
+ { "Acirc", 0x00c2 },
+ { "Agrave", 0x00c0 },
+ { "Alpha", 0x0391 },
+ { "AMP", 38 },
+ { "Aring", 0x00c5 },
+ { "Atilde", 0x00c3 },
+ { "Auml", 0x00c4 },
+ { "Beta", 0x0392 },
+ { "Ccedil", 0x00c7 },
+ { "Chi", 0x03a7 },
+ { "Dagger", 0x2021 },
+ { "Delta", 0x0394 },
+ { "ETH", 0x00d0 },
+ { "Eacute", 0x00c9 },
+ { "Ecirc", 0x00ca },
+ { "Egrave", 0x00c8 },
+ { "Epsilon", 0x0395 },
+ { "Eta", 0x0397 },
+ { "Euml", 0x00cb },
+ { "Gamma", 0x0393 },
+ { "GT", 62 },
+ { "Iacute", 0x00cd },
+ { "Icirc", 0x00ce },
+ { "Igrave", 0x00cc },
+ { "Iota", 0x0399 },
+ { "Iuml", 0x00cf },
+ { "Kappa", 0x039a },
+ { "Lambda", 0x039b },
+ { "LT", 60 },
+ { "Mu", 0x039c },
+ { "Ntilde", 0x00d1 },
+ { "Nu", 0x039d },
+ { "OElig", 0x0152 },
+ { "Oacute", 0x00d3 },
+ { "Ocirc", 0x00d4 },
+ { "Ograve", 0x00d2 },
+ { "Omega", 0x03a9 },
+ { "Omicron", 0x039f },
+ { "Oslash", 0x00d8 },
+ { "Otilde", 0x00d5 },
+ { "Ouml", 0x00d6 },
+ { "Phi", 0x03a6 },
+ { "Pi", 0x03a0 },
+ { "Prime", 0x2033 },
+ { "Psi", 0x03a8 },
+ { "QUOT", 34 },
+ { "Rho", 0x03a1 },
+ { "Scaron", 0x0160 },
+ { "Sigma", 0x03a3 },
+ { "THORN", 0x00de },
+ { "Tau", 0x03a4 },
+ { "Theta", 0x0398 },
+ { "Uacute", 0x00da },
+ { "Ucirc", 0x00db },
+ { "Ugrave", 0x00d9 },
+ { "Upsilon", 0x03a5 },
+ { "Uuml", 0x00dc },
+ { "Xi", 0x039e },
+ { "Yacute", 0x00dd },
+ { "Yuml", 0x0178 },
+ { "Zeta", 0x0396 },
+ { "aacute", 0x00e1 },
+ { "acirc", 0x00e2 },
+ { "acute", 0x00b4 },
+ { "aelig", 0x00e6 },
+ { "agrave", 0x00e0 },
+ { "alefsym", 0x2135 },
+ { "alpha", 0x03b1 },
+ { "amp", 38 },
+ { "and", 0x22a5 },
+ { "ang", 0x2220 },
+ { "apos", 0x0027 },
+ { "aring", 0x00e5 },
+ { "asymp", 0x2248 },
+ { "atilde", 0x00e3 },
+ { "auml", 0x00e4 },
+ { "bdquo", 0x201e },
+ { "beta", 0x03b2 },
+ { "brvbar", 0x00a6 },
+ { "bull", 0x2022 },
+ { "cap", 0x2229 },
+ { "ccedil", 0x00e7 },
+ { "cedil", 0x00b8 },
+ { "cent", 0x00a2 },
+ { "chi", 0x03c7 },
+ { "circ", 0x02c6 },
+ { "clubs", 0x2663 },
+ { "cong", 0x2245 },
+ { "copy", 0x00a9 },
+ { "crarr", 0x21b5 },
+ { "cup", 0x222a },
+ { "curren", 0x00a4 },
+ { "dArr", 0x21d3 },
+ { "dagger", 0x2020 },
+ { "darr", 0x2193 },
+ { "deg", 0x00b0 },
+ { "delta", 0x03b4 },
+ { "diams", 0x2666 },
+ { "divide", 0x00f7 },
+ { "eacute", 0x00e9 },
+ { "ecirc", 0x00ea },
+ { "egrave", 0x00e8 },
+ { "empty", 0x2205 },
+ { "emsp", 0x2003 },
+ { "ensp", 0x2002 },
+ { "epsilon", 0x03b5 },
+ { "equiv", 0x2261 },
+ { "eta", 0x03b7 },
+ { "eth", 0x00f0 },
+ { "euml", 0x00eb },
+ { "euro", 0x20ac },
+ { "exist", 0x2203 },
+ { "fnof", 0x0192 },
+ { "forall", 0x2200 },
+ { "frac12", 0x00bd },
+ { "frac14", 0x00bc },
+ { "frac34", 0x00be },
+ { "frasl", 0x2044 },
+ { "gamma", 0x03b3 },
+ { "ge", 0x2265 },
+ { "gt", 62 },
+ { "hArr", 0x21d4 },
+ { "harr", 0x2194 },
+ { "hearts", 0x2665 },
+ { "hellip", 0x2026 },
+ { "iacute", 0x00ed },
+ { "icirc", 0x00ee },
+ { "iexcl", 0x00a1 },
+ { "igrave", 0x00ec },
+ { "image", 0x2111 },
+ { "infin", 0x221e },
+ { "int", 0x222b },
+ { "iota", 0x03b9 },
+ { "iquest", 0x00bf },
+ { "isin", 0x2208 },
+ { "iuml", 0x00ef },
+ { "kappa", 0x03ba },
+ { "lArr", 0x21d0 },
+ { "lambda", 0x03bb },
+ { "lang", 0x2329 },
+ { "laquo", 0x00ab },
+ { "larr", 0x2190 },
+ { "lceil", 0x2308 },
+ { "ldquo", 0x201c },
+ { "le", 0x2264 },
+ { "lfloor", 0x230a },
+ { "lowast", 0x2217 },
+ { "loz", 0x25ca },
+ { "lrm", 0x200e },
+ { "lsaquo", 0x2039 },
+ { "lsquo", 0x2018 },
+ { "lt", 60 },
+ { "macr", 0x00af },
+ { "mdash", 0x2014 },
+ { "micro", 0x00b5 },
+ { "middot", 0x00b7 },
+ { "minus", 0x2212 },
+ { "mu", 0x03bc },
+ { "nabla", 0x2207 },
+ { "nbsp", 0x00a0 },
+ { "ndash", 0x2013 },
+ { "ne", 0x2260 },
+ { "ni", 0x220b },
+ { "not", 0x00ac },
+ { "notin", 0x2209 },
+ { "nsub", 0x2284 },
+ { "ntilde", 0x00f1 },
+ { "nu", 0x03bd },
+ { "oacute", 0x00f3 },
+ { "ocirc", 0x00f4 },
+ { "oelig", 0x0153 },
+ { "ograve", 0x00f2 },
+ { "oline", 0x203e },
+ { "omega", 0x03c9 },
+ { "omicron", 0x03bf },
+ { "oplus", 0x2295 },
+ { "or", 0x22a6 },
+ { "ordf", 0x00aa },
+ { "ordm", 0x00ba },
+ { "oslash", 0x00f8 },
+ { "otilde", 0x00f5 },
+ { "otimes", 0x2297 },
+ { "ouml", 0x00f6 },
+ { "para", 0x00b6 },
+ { "part", 0x2202 },
+ { "percnt", 0x0025 },
+ { "permil", 0x2030 },
+ { "perp", 0x22a5 },
+ { "phi", 0x03c6 },
+ { "pi", 0x03c0 },
+ { "piv", 0x03d6 },
+ { "plusmn", 0x00b1 },
+ { "pound", 0x00a3 },
+ { "prime", 0x2032 },
+ { "prod", 0x220f },
+ { "prop", 0x221d },
+ { "psi", 0x03c8 },
+ { "quot", 34 },
+ { "rArr", 0x21d2 },
+ { "radic", 0x221a },
+ { "rang", 0x232a },
+ { "raquo", 0x00bb },
+ { "rarr", 0x2192 },
+ { "rceil", 0x2309 },
+ { "rdquo", 0x201d },
+ { "real", 0x211c },
+ { "reg", 0x00ae },
+ { "rfloor", 0x230b },
+ { "rho", 0x03c1 },
+ { "rlm", 0x200f },
+ { "rsaquo", 0x203a },
+ { "rsquo", 0x2019 },
+ { "sbquo", 0x201a },
+ { "scaron", 0x0161 },
+ { "sdot", 0x22c5 },
+ { "sect", 0x00a7 },
+ { "shy", 0x00ad },
+ { "sigma", 0x03c3 },
+ { "sigmaf", 0x03c2 },
+ { "sim", 0x223c },
+ { "spades", 0x2660 },
+ { "sub", 0x2282 },
+ { "sube", 0x2286 },
+ { "sum", 0x2211 },
+ { "sup1", 0x00b9 },
+ { "sup2", 0x00b2 },
+ { "sup3", 0x00b3 },
+ { "sup", 0x2283 },
+ { "supe", 0x2287 },
+ { "szlig", 0x00df },
+ { "tau", 0x03c4 },
+ { "there4", 0x2234 },
+ { "theta", 0x03b8 },
+ { "thetasym", 0x03d1 },
+ { "thinsp", 0x2009 },
+ { "thorn", 0x00fe },
+ { "tilde", 0x02dc },
+ { "times", 0x00d7 },
+ { "trade", 0x2122 },
+ { "uArr", 0x21d1 },
+ { "uacute", 0x00fa },
+ { "uarr", 0x2191 },
+ { "ucirc", 0x00fb },
+ { "ugrave", 0x00f9 },
+ { "uml", 0x00a8 },
+ { "upsih", 0x03d2 },
+ { "upsilon", 0x03c5 },
+ { "uuml", 0x00fc },
+ { "weierp", 0x2118 },
+ { "xi", 0x03be },
+ { "yacute", 0x00fd },
+ { "yen", 0x00a5 },
+ { "yuml", 0x00ff },
+ { "zeta", 0x03b6 },
+ { "zwj", 0x200d },
+ { "zwnj", 0x200c }
+};
+
+void tst_QTextDocumentFragment::html_entities_data()
+{
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<quint16>("code");
+
+ for (int i = 0; i < MAX_ENTITY; ++i) {
+ QTest::newRow(entities[i].name) << QString("<pre>&") + QString::fromLatin1(entities[i].name) + QString(";</pre>")
+ << entities[i].code;
+ }
+}
+
+void tst_QTextDocumentFragment::html_entities()
+{
+ QFETCH(QString, html);
+ QFETCH(quint16, code);
+
+ setHtml(html);
+ QCOMPARE(doc->blockCount(), 1);
+ QString txt = doc->begin().text();
+ QCOMPARE(txt.length(), 1);
+ QCOMPARE(txt.at(0).unicode(), code);
+}
+
+void tst_QTextDocumentFragment::html_ignore_script()
+{
+ doc->setHtml(QString::fromLatin1("<html><script>Test</script><body>Blah</body></html>"));
+ QCOMPARE(doc->toPlainText(), QString("Blah"));
+}
+
+void tst_QTextDocumentFragment::html_directionWithHtml()
+{
+ doc->setHtml(QString::fromLatin1("<html><body><p>Test<p dir=rtl>RTL<p dir=ltr>LTR"));
+ QCOMPARE(doc->blockCount(), 3);
+
+ QTextBlock block = doc->firstBlock();
+ QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
+ QVERIFY(block.blockFormat().layoutDirection() == Qt::LeftToRight); // HTML default
+
+ block = block.next();
+ QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
+ QVERIFY(block.blockFormat().layoutDirection() == Qt::RightToLeft);
+
+ block = block.next();
+ QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
+ QVERIFY(block.blockFormat().layoutDirection() == Qt::LeftToRight);
+}
+
+void tst_QTextDocumentFragment::html_directionWithRichText()
+{
+ doc->setHtml(QString::fromLatin1("<p>Test<p dir=rtl>RTL<p dir=ltr>LTR"));
+ QCOMPARE(doc->blockCount(), 3);
+
+ QTextBlock block = doc->firstBlock();
+ QVERIFY(!block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
+
+ block = block.next();
+ QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
+ QVERIFY(block.blockFormat().layoutDirection() == Qt::RightToLeft);
+
+ block = block.next();
+ QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
+ QVERIFY(block.blockFormat().layoutDirection() == Qt::LeftToRight);
+}
+
+void tst_QTextDocumentFragment::html_metaInBody()
+{
+ setHtml("<body>Hello<meta>World</body>");
+ QCOMPARE(doc->toPlainText(), QString("HelloWorld"));
+}
+
+void tst_QTextDocumentFragment::html_importImageWithoutAspectRatio()
+{
+ doc->setHtml("<img src=\"foo\" width=\"100%\" height=\"43\">");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().isImageFormat());
+ QTextImageFormat fmt = cursor.charFormat().toImageFormat();
+ // qDebug() << fmt.width() << fmt.height();
+ QVERIFY (fmt.hasProperty(QTextFormat::ImageWidth));
+ QCOMPARE (fmt.height(), 43.);
+
+ doc->setHtml("<img src=\"foo\" height=\"43\">");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().isImageFormat());
+ fmt = cursor.charFormat().toImageFormat();
+ QVERIFY (! fmt.hasProperty(QTextFormat::ImageWidth));
+ QCOMPARE (fmt.height(), 43.);
+
+ doc->setHtml("<img src=\"foo\" width=\"200\">");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QVERIFY(cursor.charFormat().isImageFormat());
+ fmt = cursor.charFormat().toImageFormat();
+ QVERIFY (! fmt.hasProperty(QTextFormat::ImageHeight));
+ QCOMPARE (fmt.width(), 200.);
+}
+
+void tst_QTextDocumentFragment::html_fromFirefox()
+{
+ // if you have a html loaded in firefox like <html>Test\nText</html> then selecting all and copying will
+ // result in the following text on the clipboard (for text/html)
+ doc->setHtml(QString::fromLatin1("<!--StartFragment-->Test\nText\n\n<!--EndFragment-->"));
+ QCOMPARE(doc->toPlainText(), QString::fromLatin1("Test Text "));
+}
+
+QTEST_MAIN(tst_QTextDocumentFragment)
+#include "tst_qtextdocumentfragment.moc"
diff --git a/tests/auto/gui/text/qtextdocumentlayout/.gitignore b/tests/auto/gui/text/qtextdocumentlayout/.gitignore
new file mode 100644
index 0000000000..80671c70d0
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocumentlayout/.gitignore
@@ -0,0 +1 @@
+tst_qtextdocumentlayout
diff --git a/tests/auto/gui/text/qtextdocumentlayout/qtextdocumentlayout.pro b/tests/auto/gui/text/qtextdocumentlayout/qtextdocumentlayout.pro
new file mode 100644
index 0000000000..32b05ce061
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocumentlayout/qtextdocumentlayout.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtextdocumentlayout.cpp
+
+
diff --git a/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp b/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp
new file mode 100644
index 0000000000..f5c72cd4d0
--- /dev/null
+++ b/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp
@@ -0,0 +1,276 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qtextdocument.h>
+#include <qabstracttextdocumentlayout.h>
+#include <qdebug.h>
+#include <qpainter.h>
+#include <qtexttable.h>
+#include <qtextedit.h>
+#include <qscrollbar.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/text/qtextdocumentlayout_p.h gui/text/qtextdocumentlayout.cpp
+
+class tst_QTextDocumentLayout : public QObject
+{
+ Q_OBJECT
+public:
+ inline tst_QTextDocumentLayout() {}
+ virtual ~tst_QTextDocumentLayout() {}
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void defaultPageSizeHandling();
+ void idealWidth();
+ void lineSeparatorFollowingTable();
+ void wrapAtWordBoundaryOrAnywhere();
+ void inlineImage();
+ void clippedTableCell();
+ void floatingTablePageBreak();
+
+private:
+ QTextDocument *doc;
+};
+
+void tst_QTextDocumentLayout::init()
+{
+ doc = new QTextDocument;
+}
+
+void tst_QTextDocumentLayout::cleanup()
+{
+ delete doc;
+ doc = 0;
+}
+
+void tst_QTextDocumentLayout::defaultPageSizeHandling()
+{
+ QAbstractTextDocumentLayout *layout = doc->documentLayout();
+ QVERIFY(layout);
+
+ QVERIFY(!doc->pageSize().isValid());
+ QSizeF docSize = layout->documentSize();
+ QVERIFY(docSize.width() > 0 && docSize.width() < 1000);
+ QVERIFY(docSize.height() > 0 && docSize.height() < 1000);
+
+ doc->setPlainText("Some text\nwith a few lines\nand not real information\nor anything otherwise useful");
+
+ docSize = layout->documentSize();
+ QVERIFY(docSize.isValid());
+ QVERIFY(docSize.width() != INT_MAX);
+ QVERIFY(docSize.height() != INT_MAX);
+}
+
+void tst_QTextDocumentLayout::idealWidth()
+{
+ doc->setPlainText("Some text\nwith a few lines\nand not real information\nor anything otherwise useful");
+ doc->setTextWidth(1000);
+ QCOMPARE(doc->textWidth(), qreal(1000));
+ QCOMPARE(doc->size().width(), doc->textWidth());
+ QVERIFY(doc->idealWidth() < doc->textWidth());
+ QVERIFY(doc->idealWidth() > 0);
+
+ QTextBlockFormat fmt;
+ fmt.setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
+ QTextCursor cursor(doc);
+ cursor.select(QTextCursor::Document);
+ cursor.mergeBlockFormat(fmt);
+
+ QCOMPARE(doc->textWidth(), qreal(1000));
+ QCOMPARE(doc->size().width(), doc->textWidth());
+ QVERIFY(doc->idealWidth() < doc->textWidth());
+ QVERIFY(doc->idealWidth() > 0);
+}
+
+// none of the QTextLine items in the document should intersect with the margin rect
+void tst_QTextDocumentLayout::lineSeparatorFollowingTable()
+{
+ QString html_begin("<html><table border=1><tr><th>Column 1</th></tr><tr><td>Data</td></tr></table><br>");
+ QString html_text("bla bla bla bla bla bla bla bla<br>");
+ QString html_end("<table border=1><tr><th>Column 1</th></tr><tr><td>Data</td></tr></table></html>");
+
+ QString html = html_begin;
+
+ for (int i = 0; i < 80; ++i)
+ html += html_text;
+
+ html += html_end;
+
+ doc->setHtml(html);
+
+ QTextCursor cursor(doc);
+ cursor.movePosition(QTextCursor::Start);
+
+ const int margin = 87;
+ const int pageWidth = 873;
+ const int pageHeight = 1358;
+
+ QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
+ fmt.setMargin(margin);
+ doc->rootFrame()->setFrameFormat(fmt);
+
+ QFont font(doc->defaultFont());
+ font.setPointSize(10);
+ doc->setDefaultFont(font);
+ doc->setPageSize(QSizeF(pageWidth, pageHeight));
+
+ QRectF marginRect(QPointF(0, pageHeight - margin), QSizeF(pageWidth, 2 * margin));
+
+ // force layouting
+ doc->pageCount();
+
+ for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) {
+ QTextLayout *layout = block.layout();
+ for (int i = 0; i < layout->lineCount(); ++i) {
+ QTextLine line = layout->lineAt(i);
+ QRectF rect = line.rect().translated(layout->position());
+ QVERIFY(!rect.intersects(marginRect));
+ }
+ }
+}
+
+void tst_QTextDocumentLayout::wrapAtWordBoundaryOrAnywhere()
+{
+ //task 150562
+ QTextEdit edit;
+ edit.setText("<table><tr><td>hello hello hello"
+ "thisisabigwordthisisabigwordthisisabigwordthisisabigwordthisisabigword"
+ "hello hello hello</td></tr></table>");
+ edit.setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+ edit.resize(100, 100);
+ edit.show();
+ QVERIFY(!edit.horizontalScrollBar()->isVisible());
+}
+
+void tst_QTextDocumentLayout::inlineImage()
+{
+ doc->setPageSize(QSizeF(800, 500));
+
+ QImage img(400, 400, QImage::Format_RGB32);
+ QLatin1String name("bigImage");
+
+ doc->addResource(QTextDocument::ImageResource, QUrl(name), img);
+
+ QTextImageFormat imgFormat;
+ imgFormat.setName(name);
+ imgFormat.setWidth(img.width());
+
+ QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
+ qreal height = doc->pageSize().height() - fmt.topMargin() - fmt.bottomMargin();
+ imgFormat.setHeight(height);
+
+ QTextCursor cursor(doc);
+ cursor.insertImage(imgFormat);
+
+ QCOMPARE(doc->pageCount(), 1);
+}
+
+void tst_QTextDocumentLayout::clippedTableCell()
+{
+ const char *html =
+ "<table style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\""
+ "border=\"0\" margin=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td></td></tr></table>";
+
+ doc->setHtml(html);
+ doc->pageSize();
+
+ QTextCursor cursor(doc);
+ cursor.movePosition(QTextCursor::Right);
+
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextCursor cellCursor = table->cellAt(0, 0).firstCursorPosition();
+ QImage src(16, 16, QImage::Format_ARGB32_Premultiplied);
+ src.fill(0xffff0000);
+ cellCursor.insertImage(src);
+
+ QTextBlock block = cellCursor.block();
+ QRectF r = doc->documentLayout()->blockBoundingRect(block);
+
+ QRectF rect(0, 0, r.left() + 1, 64);
+
+ QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0x0);
+ QImage expected = img;
+ QPainter p(&img);
+ doc->drawContents(&p, rect);
+ p.end();
+ p.begin(&expected);
+ r.setWidth(1);
+ p.fillRect(r, Qt::red);
+ p.end();
+
+ img.save("img.png");
+ expected.save("expected.png");
+ QCOMPARE(img, expected);
+}
+
+void tst_QTextDocumentLayout::floatingTablePageBreak()
+{
+ doc->clear();
+
+ QTextCursor cursor(doc);
+
+ QTextTableFormat tableFormat;
+ tableFormat.setPosition(QTextFrameFormat::FloatLeft);
+ QTextTable *table = cursor.insertTable(50, 1, tableFormat);
+ Q_UNUSED(table);
+
+ // Make height of document 2/3 of the table, fitting the table into two pages
+ QSizeF documentSize = doc->size();
+ documentSize.rheight() *= 2.0 / 3.0;
+
+ doc->setPageSize(documentSize);
+
+ QCOMPARE(doc->pageCount(), 2);
+}
+
+
+QTEST_MAIN(tst_QTextDocumentLayout)
+#include "tst_qtextdocumentlayout.moc"
diff --git a/tests/auto/gui/text/qtextformat/.gitignore b/tests/auto/gui/text/qtextformat/.gitignore
new file mode 100644
index 0000000000..3e3be422fe
--- /dev/null
+++ b/tests/auto/gui/text/qtextformat/.gitignore
@@ -0,0 +1 @@
+tst_qtextformat
diff --git a/tests/auto/gui/text/qtextformat/qtextformat.pro b/tests/auto/gui/text/qtextformat/qtextformat.pro
new file mode 100644
index 0000000000..30f6e50c61
--- /dev/null
+++ b/tests/auto/gui/text/qtextformat/qtextformat.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qtextformat.h
+############################################################
+
+load(qttest_p4)
+
+SOURCES += tst_qtextformat.cpp
+
+
diff --git a/tests/auto/gui/text/qtextformat/tst_qtextformat.cpp b/tests/auto/gui/text/qtextformat/tst_qtextformat.cpp
new file mode 100644
index 0000000000..b235b112b6
--- /dev/null
+++ b/tests/auto/gui/text/qtextformat/tst_qtextformat.cpp
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qsettings.h>
+#include <qtextformat.h>
+#include <qtextdocument.h>
+#include <qtextcursor.h>
+#include <qtextobject.h>
+#include <qtextlayout.h>
+#include <qabstracttextdocumentlayout.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTextFormat : public QObject
+{
+Q_OBJECT
+
+private slots:
+ void getSetCheck();
+ void defaultAlignment();
+ void testQTextCharFormat() const;
+ void testUnderlinePropertyPrecedence();
+ void toFormat();
+ void resolveFont();
+ void getSetTabs();
+ void testTabsUsed();
+ void testFontStyleSetters();
+};
+
+/*! \internal
+ This (used to) trigger a crash in:
+
+ QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
+
+ which is most easily produced through QSettings.
+ */
+void tst_QTextFormat::testQTextCharFormat() const
+{
+ QSettings settings("test", "test");
+ QTextCharFormat test;
+
+ settings.value("test", test);
+}
+
+// Testing get/set functions
+void tst_QTextFormat::getSetCheck()
+{
+ QTextFormat obj1;
+ // int QTextFormat::objectIndex()
+ // void QTextFormat::setObjectIndex(int)
+ obj1.setObjectIndex(0);
+ QCOMPARE(0, obj1.objectIndex());
+ obj1.setObjectIndex(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.objectIndex());
+ obj1.setObjectIndex(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.objectIndex());
+}
+
+void tst_QTextFormat::defaultAlignment()
+{
+ QTextBlockFormat fmt;
+ QVERIFY(!fmt.hasProperty(QTextFormat::BlockAlignment));
+ QCOMPARE(fmt.intProperty(QTextFormat::BlockAlignment), 0);
+ QVERIFY(fmt.alignment() == Qt::AlignLeft);
+}
+
+void tst_QTextFormat::testUnderlinePropertyPrecedence()
+{
+ QTextCharFormat format;
+ // use normal accessors and check internal state
+ format.setUnderlineStyle(QTextCharFormat::NoUnderline);
+ QCOMPARE(format.property(QTextFormat::FontUnderline).isNull(), false);
+ QCOMPARE(format.property(QTextFormat::TextUnderlineStyle).isNull(), false);
+ QCOMPARE(format.property(QTextFormat::FontUnderline).toBool(), false);
+ QCOMPARE(format.property(QTextFormat::TextUnderlineStyle).toInt(), 0);
+
+ format = QTextCharFormat();
+ format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+ QCOMPARE(format.property(QTextFormat::FontUnderline).isNull(), false);
+ QCOMPARE(format.property(QTextFormat::TextUnderlineStyle).isNull(), false);
+ QCOMPARE(format.property(QTextFormat::FontUnderline).toBool(), true);
+ QCOMPARE(format.property(QTextFormat::TextUnderlineStyle).toInt(), 1);
+
+ format = QTextCharFormat();
+ format.setUnderlineStyle(QTextCharFormat::DotLine);
+ QCOMPARE(format.property(QTextFormat::FontUnderline).isNull(), false);
+ QCOMPARE(format.property(QTextFormat::TextUnderlineStyle).isNull(), false);
+ QCOMPARE(format.property(QTextFormat::FontUnderline).toBool(), false);
+ QVERIFY(format.property(QTextFormat::TextUnderlineStyle).toInt() > 0);
+
+ // override accessors and use setProperty to create a false state.
+ // then check font()
+ format = QTextCharFormat();
+ format.setProperty(QTextCharFormat::FontUnderline, true);
+ QCOMPARE(format.property(QTextFormat::FontUnderline).isNull(), false);
+ QCOMPARE(format.property(QTextFormat::TextUnderlineStyle).isNull(), true);
+ QCOMPARE(format.fontUnderline(), true);
+ QCOMPARE(format.font().underline(), true);
+
+ format = QTextCharFormat();
+ // create conflict. Should use the new property
+ format.setProperty(QTextCharFormat::TextUnderlineStyle, QTextCharFormat::SingleUnderline);
+ format.setProperty(QTextCharFormat::FontUnderline, false);
+ QCOMPARE(format.fontUnderline(), true);
+ QCOMPARE(format.font().underline(), true);
+
+ format = QTextCharFormat();
+ // create conflict. Should use the new property
+ format.setProperty(QTextCharFormat::TextUnderlineStyle, QTextCharFormat::NoUnderline);
+ format.setProperty(QTextCharFormat::FontUnderline, true);
+ QCOMPARE(format.fontUnderline(), false);
+ QCOMPARE(format.font().underline(), false);
+
+ // do it again, but reverse the ordering (we use a QVector internally, so test a LOT ;)
+ // create conflict. Should use the new property
+ format.setProperty(QTextCharFormat::FontUnderline, false);
+ format.setProperty(QTextCharFormat::TextUnderlineStyle, QTextCharFormat::SingleUnderline);
+ QCOMPARE(format.fontUnderline(), true);
+ QCOMPARE(format.font().underline(), true);
+
+ format = QTextCharFormat();
+ // create conflict. Should use the new property
+ format.setProperty(QTextCharFormat::FontUnderline, true);
+ format.setProperty(QTextCharFormat::TextUnderlineStyle, QTextCharFormat::NoUnderline);
+ QCOMPARE(format.fontUnderline(), false);
+ QCOMPARE(format.font().underline(), false);
+}
+
+void tst_QTextFormat::toFormat()
+{
+ {
+ QTextFormat fmt = QTextFrameFormat();
+ QCOMPARE(fmt.toFrameFormat().type(), int(QTextFormat::FrameFormat));
+ }
+
+ {
+ QTextFormat fmt = QTextTableFormat();
+ QCOMPARE(fmt.toTableFormat().type(), int(QTextFormat::FrameFormat));
+ QCOMPARE(fmt.toTableFormat().objectType(), int(QTextFormat::TableObject));
+ }
+
+ {
+ QTextFormat fmt = QTextBlockFormat();
+ QCOMPARE(fmt.toBlockFormat().type(), int(QTextFormat::BlockFormat));
+ }
+
+ {
+ QTextFormat fmt = QTextCharFormat();
+ QCOMPARE(fmt.toCharFormat().type(), int(QTextFormat::CharFormat));
+ }
+
+ {
+ QTextFormat fmt = QTextListFormat();
+ QCOMPARE(fmt.toListFormat().type(), int(QTextFormat::ListFormat));
+ }
+}
+
+void tst_QTextFormat::resolveFont()
+{
+ QTextDocument doc;
+
+ QTextCharFormat fmt;
+ fmt.setProperty(QTextFormat::ForegroundBrush, Qt::blue);
+ fmt.setProperty(QTextFormat::FontItalic, true);
+ QTextCursor(&doc).insertText("Test", fmt);
+
+ QVector<QTextFormat> formats = doc.allFormats();
+ QCOMPARE(formats.count(), 3);
+
+ QVERIFY(formats.at(2).type() == QTextFormat::CharFormat);
+ fmt = formats.at(2).toCharFormat();
+
+ QVERIFY(!fmt.font().underline());
+ QVERIFY(fmt.hasProperty(QTextFormat::ForegroundBrush));
+
+ QFont f;
+ f.setUnderline(true);
+ doc.setDefaultFont(f);
+ formats = doc.allFormats();
+ fmt = formats.at(2).toCharFormat();
+
+ QVERIFY(fmt.font().underline());
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
+
+ // verify that deleting a non-existent property does not affect the font resolving
+
+ QVERIFY(!fmt.hasProperty(QTextFormat::BackgroundBrush));
+ fmt.clearProperty(QTextFormat::BackgroundBrush);
+ QVERIFY(!fmt.hasProperty(QTextFormat::BackgroundBrush));
+
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
+ QVERIFY(fmt.font().underline());
+
+ // verify that deleting an existent but font _unrelated_ property does not affect the font resolving
+
+ QVERIFY(fmt.hasProperty(QTextFormat::ForegroundBrush));
+ fmt.clearProperty(QTextFormat::ForegroundBrush);
+ QVERIFY(!fmt.hasProperty(QTextFormat::ForegroundBrush));
+
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
+ QVERIFY(fmt.font().underline());
+
+ // verify that removing a font property _does_ clear the resolving
+
+ QVERIFY(fmt.hasProperty(QTextFormat::FontItalic));
+ fmt.clearProperty(QTextFormat::FontItalic);
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontItalic));
+
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
+ QVERIFY(!fmt.font().underline());
+ QVERIFY(!fmt.font().italic());
+
+ // reset
+ fmt = formats.at(2).toCharFormat();
+
+ QVERIFY(fmt.font().underline());
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
+
+ // verify that _setting_ an unrelated property does _not_ affect the resolving
+
+ QVERIFY(!fmt.hasProperty(QTextFormat::IsAnchor));
+ fmt.setProperty(QTextFormat::IsAnchor, true);
+ QVERIFY(fmt.hasProperty(QTextFormat::IsAnchor));
+
+ QVERIFY(fmt.font().underline());
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
+
+ // verify that setting a _related_ font property does affect the resolving
+ //
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontStrikeOut));
+ fmt.setProperty(QTextFormat::FontStrikeOut, true);
+ QVERIFY(fmt.hasProperty(QTextFormat::FontStrikeOut));
+
+ QVERIFY(!fmt.font().underline());
+ QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
+ QVERIFY(fmt.font().strikeOut());
+}
+
+void tst_QTextFormat::getSetTabs()
+{
+ class Comparator {
+ public:
+ Comparator(const QList<QTextOption::Tab> &tabs, const QList<QTextOption::Tab> &tabs2)
+ {
+ QCOMPARE(tabs.count(), tabs2.count());
+ for(int i=0; i < tabs.count(); i++) {
+ QTextOption::Tab t1 = tabs[i];
+ QTextOption::Tab t2 = tabs2[i];
+ QCOMPARE(t1.position, t2.position);
+ QCOMPARE(t1.type, t2.type);
+ QCOMPARE(t1.delimiter, t2.delimiter);
+ }
+ }
+ };
+
+ QList<QTextOption::Tab> tabs;
+ QTextBlockFormat format;
+ format.setTabPositions(tabs);
+ Comparator c1(tabs, format.tabPositions());
+
+ QTextOption::Tab tab1;
+ tab1.position = 1234;
+ tabs.append(tab1);
+ format.setTabPositions(tabs);
+ Comparator c2(tabs, format.tabPositions());
+
+ QTextOption::Tab tab2(3456, QTextOption::RightTab, QChar('x'));
+ tabs.append(tab2);
+ format.setTabPositions(tabs);
+ Comparator c3(tabs, format.tabPositions());
+}
+
+void tst_QTextFormat::testTabsUsed()
+{
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+
+ QList<QTextOption::Tab> tabs;
+ QTextBlockFormat format;
+ QTextOption::Tab tab;
+ tab.position = 100;
+ tabs.append(tab);
+ format.setTabPositions(tabs);
+ cursor.mergeBlockFormat(format);
+ cursor.insertText("foo\tbar");
+ //doc.setPageSize(QSizeF(200, 200));
+ doc.documentLayout()->pageCount(); // force layout;
+
+ QTextBlock block = doc.begin();
+ QTextLayout *layout = block.layout();
+ QVERIFY(layout);
+ QCOMPARE(layout->lineCount(), 1);
+ QTextLine line = layout->lineAt(0);
+ QCOMPARE(line.cursorToX(4), 100.);
+
+ QTextOption option = layout->textOption();
+ QCOMPARE(option.tabs().count(), tabs.count());
+
+}
+
+void tst_QTextFormat::testFontStyleSetters()
+{
+ QTextCharFormat format;
+
+ // test the setters
+ format.setFontStyleHint(QFont::Serif);
+ QCOMPARE(format.font().styleHint(), QFont::Serif);
+ QCOMPARE(format.font().styleStrategy(), QFont::PreferDefault);
+ format.setFontStyleStrategy(QFont::PreferOutline);
+ QCOMPARE(format.font().styleStrategy(), QFont::PreferOutline);
+
+ // test setting properties through setFont()
+ QFont font;
+ font.setStyleHint(QFont::SansSerif, QFont::PreferAntialias);
+ format.setFont(font);
+ QCOMPARE(format.font().styleHint(), QFont::SansSerif);
+ QCOMPARE(format.font().styleStrategy(), QFont::PreferAntialias);
+
+ // test kerning
+ format.setFontKerning(false);
+ QCOMPARE(format.font().kerning(), false);
+ format.setFontKerning(true);
+ QCOMPARE(format.font().kerning(), true);
+ font.setKerning(false);
+ format.setFont(font);
+ QCOMPARE(format.font().kerning(), false);
+}
+
+QTEST_MAIN(tst_QTextFormat)
+#include "tst_qtextformat.moc"
diff --git a/tests/auto/gui/text/qtextlayout/.gitignore b/tests/auto/gui/text/qtextlayout/.gitignore
new file mode 100644
index 0000000000..11758969db
--- /dev/null
+++ b/tests/auto/gui/text/qtextlayout/.gitignore
@@ -0,0 +1 @@
+tst_qtextlayout
diff --git a/tests/auto/gui/text/qtextlayout/qtextlayout.pro b/tests/auto/gui/text/qtextlayout/qtextlayout.pro
new file mode 100644
index 0000000000..6bf0065e4f
--- /dev/null
+++ b/tests/auto/gui/text/qtextlayout/qtextlayout.pro
@@ -0,0 +1,12 @@
+load(qttest_p4)
+QT += core-private gui-private
+HEADERS +=
+SOURCES += tst_qtextlayout.cpp
+DEFINES += QT_COMPILES_IN_HARFBUZZ
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
+
+symbian {
+ TARGET.EPOCHEAPSIZE = 100000 20000000
+}
+
+qpa:contains(QT_CONFIG,qpa):CONFIG+=insignificant_test # QTBUG-20979
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
new file mode 100644
index 0000000000..2414ab3e37
--- /dev/null
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -0,0 +1,1506 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+/*
+ !!!!!! Warning !!!!!
+ Please don't save this file in emacs. It contains utf8 text sequences emacs will
+ silently convert to a series of question marks.
+ */
+#include <QtTest/QtTest>
+
+
+
+#include <private/qtextengine_p.h>
+#include <qtextlayout.h>
+
+#include <qdebug.h>
+
+
+#define TESTFONT_SIZE 12
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTextLayout : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTextLayout();
+ virtual ~tst_QTextLayout();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void lineBreaking();
+ void simpleBoundingRect();
+ void threeLineBoundingRect();
+ void boundingRectWithLongLineAndNoWrap();
+ void forcedBreaks();
+ void breakAny();
+ void noWrap();
+ void cursorToXForInlineObjects();
+ void cursorToXForSetColumns();
+ void defaultWordSeparators_data();
+ void defaultWordSeparators();
+ void cursorMovementFromInvalidPositions();
+ void cursorMovementInsideSpaces();
+ void charWordStopOnLineSeparator();
+ void xToCursorAtEndOfLine();
+ void boundingRectTopLeft();
+ void charStopForSurrogatePairs();
+ void tabStops();
+ void integerOverflow();
+ void testDefaultTabs();
+ void testTabs();
+ void testMultilineTab();
+ void testRightTab();
+ void testTabsInAlignedParag();
+ void testCenteredTab();
+ void testDelimiterTab();
+ void testMultiTab();
+ void testTabDPIScale();
+ void tabsForRtl();
+ void tabHeight();
+ void capitalization_allUpperCase();
+ void capitalization_allLowerCase();
+ void capitalization_smallCaps();
+ void capitalization_capitalize();
+ void longText();
+ void widthOfTabs();
+ void columnWrapWithTabs();
+ void boundingRectForUnsetLineWidth();
+ void boundingRectForSetLineWidth();
+ void glyphLessItems();
+
+ // QTextLine stuff
+ void setNumColumnsWrapAtWordBoundaryOrAnywhere();
+ void setNumColumnsWordWrap();
+ void smallTextLengthNoWrap();
+ void smallTextLengthWordWrap();
+ void smallTextLengthWrapAtWordBoundaryOrAnywhere();
+ void testLineBreakingAllSpaces();
+ void lineWidthFromBOM();
+ void textWidthVsWIdth();
+ void textWithSurrogates_qtbug15679();
+ void textWidthWithStackedTextEngine();
+ void textWidthWithLineSeparator();
+ void cursorInLigatureWithMultipleLines();
+ void xToCursorForLigatures();
+
+private:
+ QFont testFont;
+};
+
+// Testing get/set functions
+void tst_QTextLayout::getSetCheck()
+{
+ QString str("Bogus text");
+ QTextLayout layout(str, testFont);
+ layout.beginLayout();
+ QTextEngine *engine = layout.engine();
+ QTextInlineObject obj1(0, engine);
+ // qreal QTextInlineObject::width()
+ // void QTextInlineObject::setWidth(qreal)
+ obj1.setWidth(0.0);
+ QCOMPARE(0.0, obj1.width());
+ obj1.setWidth(1.2);
+ QVERIFY(1.0 < obj1.width());
+
+ // qreal QTextInlineObject::ascent()
+ // void QTextInlineObject::setAscent(qreal)
+ obj1.setAscent(0.0);
+ QCOMPARE(0.0, obj1.ascent());
+ obj1.setAscent(1.2);
+ QVERIFY(1.0 < obj1.ascent());
+
+ // qreal QTextInlineObject::descent()
+ // void QTextInlineObject::setDescent(qreal)
+ obj1.setDescent(0.0);
+ QCOMPARE(0.0, obj1.descent());
+ obj1.setDescent(1.2);
+ QVERIFY(1.0 < obj1.descent());
+
+ QTextLayout obj2;
+ // bool QTextLayout::cacheEnabled()
+ // void QTextLayout::setCacheEnabled(bool)
+ obj2.setCacheEnabled(false);
+ QCOMPARE(false, obj2.cacheEnabled());
+ obj2.setCacheEnabled(true);
+ QCOMPARE(true, obj2.cacheEnabled());
+}
+
+QT_BEGIN_NAMESPACE
+extern void qt_setQtEnableTestFont(bool value);
+QT_END_NAMESPACE
+
+tst_QTextLayout::tst_QTextLayout()
+{
+ qt_setQtEnableTestFont(true);
+}
+
+tst_QTextLayout::~tst_QTextLayout()
+{
+}
+
+void tst_QTextLayout::init()
+{
+ testFont = QFont();
+ testFont.setFamily("__Qt__Box__Engine__");
+ testFont.setPixelSize(TESTFONT_SIZE);
+ testFont.setWeight(QFont::Normal);
+ QCOMPARE(QFontMetrics(testFont).width('a'), testFont.pixelSize());
+}
+
+void tst_QTextLayout::cleanup()
+{
+ testFont = QFont();
+}
+
+
+void tst_QTextLayout::lineBreaking()
+{
+#if defined(Q_WS_X11)
+ struct Breaks {
+ const char *utf8;
+ uchar breaks[32];
+ };
+ Breaks brks[] = {
+ { "11", { false, 0xff } },
+ { "aa", { false, 0xff } },
+ { "++", { false, 0xff } },
+ { "--", { false, 0xff } },
+ { "((", { false, 0xff } },
+ { "))", { false, 0xff } },
+ { "..", { false, 0xff } },
+ { "\"\"", { false, 0xff } },
+ { "$$", { false, 0xff } },
+ { "!!", { false, 0xff } },
+ { "??", { false, 0xff } },
+ { ",,", { false, 0xff } },
+
+ { ")()", { true, false, 0xff } },
+ { "?!?", { false, false, 0xff } },
+ { ".,.", { false, false, 0xff } },
+ { "+-+", { false, false, 0xff } },
+ { "+=+", { false, false, 0xff } },
+ { "+(+", { false, false, 0xff } },
+ { "+)+", { false, false, 0xff } },
+
+ { "a b", { false, true, 0xff } },
+ { "a(b", { false, false, 0xff } },
+ { "a)b", { false, false, 0xff } },
+ { "a-b", { false, true, 0xff } },
+ { "a.b", { false, false, 0xff } },
+ { "a+b", { false, false, 0xff } },
+ { "a?b", { false, false, 0xff } },
+ { "a!b", { false, false, 0xff } },
+ { "a$b", { false, false, 0xff } },
+ { "a,b", { false, false, 0xff } },
+ { "a/b", { false, false, 0xff } },
+ { "1/2", { false, false, 0xff } },
+ { "./.", { false, false, 0xff } },
+ { ",/,", { false, false, 0xff } },
+ { "!/!", { false, false, 0xff } },
+ { "\\/\\", { false, false, 0xff } },
+ { "1 2", { false, true, 0xff } },
+ { "1(2", { false, false, 0xff } },
+ { "1)2", { false, false, 0xff } },
+ { "1-2", { false, false, 0xff } },
+ { "1.2", { false, false, 0xff } },
+ { "1+2", { false, false, 0xff } },
+ { "1?2", { false, true, 0xff } },
+ { "1!2", { false, true, 0xff } },
+ { "1$2", { false, false, 0xff } },
+ { "1,2", { false, false, 0xff } },
+ { "1/2", { false, false, 0xff } },
+ { "\330\260\331\216\331\204\331\220\331\203\331\216", { false, false, false, false, false, 0xff } },
+ { "\330\247\331\204\331\205 \330\247\331\204\331\205", { false, false, false, true, false, false, 0xff } },
+ { "1#2", { false, false, 0xff } },
+ { "!#!", { false, false, 0xff } },
+ { 0, {} }
+ };
+ Breaks *b = brks;
+ while (b->utf8) {
+ QString str = QString::fromUtf8(b->utf8);
+ QTextEngine engine(str, QFont());
+ const HB_CharAttributes *attrs = engine.attributes();
+ int i;
+ for (i = 0; i < (int)str.length() - 1; ++i) {
+ QVERIFY(b->breaks[i] != 0xff);
+ if ( (attrs[i].lineBreakType != HB_NoBreak) != (bool)b->breaks[i] ) {
+ qDebug("test case \"%s\" failed at char %d; break type: %d", b->utf8, i, attrs[i].lineBreakType);
+ QCOMPARE( (attrs[i].lineBreakType != HB_NoBreak), (bool)b->breaks[i] );
+ }
+ }
+ QVERIFY(attrs[i].lineBreakType == HB_ForcedBreak);
+ QCOMPARE(b->breaks[i], (uchar)0xff);
+ ++b;
+ }
+#else
+ QSKIP("This test can not be run on non-X11 platforms", SkipAll);
+#endif
+}
+
+void tst_QTextLayout::simpleBoundingRect()
+{
+ /* just check if boundingRect() gives sane values. The text is not broken. */
+
+ QString hello("hello world");
+
+ const int width = hello.length() * testFont.pixelSize();
+
+ QTextLayout layout(hello, testFont);
+ layout.beginLayout();
+
+ QTextLine line = layout.createLine();
+ line.setLineWidth(width);
+ QCOMPARE(line.textLength(), hello.length());
+ QCOMPARE(layout.boundingRect(), QRectF(0, 0, width, QFontMetrics(testFont).height()));
+}
+
+void tst_QTextLayout::threeLineBoundingRect()
+{
+#if defined(Q_WS_MAC)
+ QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
+#endif
+ /* stricter check. break text into three lines */
+
+ QString firstWord("hello");
+ QString secondWord("world");
+ QString thirdWord("test");
+ QString text(firstWord + ' ' + secondWord + ' ' + thirdWord);
+
+ const int firstLineWidth = firstWord.length() * testFont.pixelSize();
+ const int secondLineWidth = secondWord.length() * testFont.pixelSize();
+ const int thirdLineWidth = thirdWord.length() * testFont.pixelSize();
+
+ const int longestLine = qMax(firstLineWidth, qMax(secondLineWidth, thirdLineWidth));
+
+ QTextLayout layout(text, testFont);
+ layout.beginLayout();
+
+ int pos = 0;
+ int y = 0;
+ QTextLine line = layout.createLine();
+ line.setLineWidth(firstLineWidth);
+ line.setPosition(QPoint(0, y));
+ QCOMPARE(line.textStart(), pos);
+ // + 1 for trailing space
+ QCOMPARE(line.textLength(), firstWord.length() + 1);
+ QCOMPARE(qRound(line.naturalTextWidth()), firstLineWidth);
+
+ pos += line.textLength();
+ y += qRound(line.ascent() + line.descent());
+
+ line = layout.createLine();
+ line.setLineWidth(secondLineWidth);
+ line.setPosition(QPoint(0, y));
+ // + 1 for trailing space
+ QCOMPARE(line.textStart(), pos);
+ QCOMPARE(line.textLength(), secondWord.length() + 1);
+ QCOMPARE(qRound(line.naturalTextWidth()), secondLineWidth);
+
+ pos += line.textLength();
+ y += qRound(line.ascent() + line.descent());
+
+ line = layout.createLine();
+ line.setLineWidth(secondLineWidth);
+ line.setPosition(QPoint(0, y));
+ // no trailing space here!
+ QCOMPARE(line.textStart(), pos);
+ QCOMPARE(line.textLength(), thirdWord.length());
+ QCOMPARE(qRound(line.naturalTextWidth()), thirdLineWidth);
+ y += qRound(line.ascent() + line.descent());
+
+ QCOMPARE(layout.boundingRect(), QRectF(0, 0, longestLine, y + 1));
+}
+
+void tst_QTextLayout::boundingRectWithLongLineAndNoWrap()
+{
+ QString longString("thisisaverylongstringthatcannotbewrappedatallitjustgoesonandonlikeonebigword");
+
+ const int width = longString.length() * testFont.pixelSize() / 20; // very small widthx
+
+ QTextLayout layout(longString, testFont);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(width);
+
+ QVERIFY(layout.boundingRect().width() >= line.width());
+ QCOMPARE(layout.boundingRect().width(), line.naturalTextWidth());
+}
+
+void tst_QTextLayout::forcedBreaks()
+{
+ QString text = "A\n\nB\nC";
+ text.replace('\n', QChar::LineSeparator);
+
+ QTextLayout layout(text, testFont);
+
+ layout.beginLayout();
+
+ int pos = 0;
+
+ QTextLine line = layout.createLine();
+ line.setLineWidth(0x10000);
+ QCOMPARE(line.textStart(), pos);
+ QCOMPARE(line.textLength(),2);
+ QCOMPARE(qRound(line.naturalTextWidth()),testFont.pixelSize());
+ QCOMPARE((int) line.height(), testFont.pixelSize() + 1); // + 1 baseline
+ QCOMPARE(line.xToCursor(0), line.textStart());
+ pos += line.textLength();
+
+ line = layout.createLine();
+ line.setLineWidth(0x10000);
+ QCOMPARE(line.textStart(),pos);
+ QCOMPARE(line.textLength(),1);
+ QCOMPARE(qRound(line.naturalTextWidth()), 0);
+ QCOMPARE((int) line.height(), testFont.pixelSize() + 1); // + 1 baseline
+ QCOMPARE(line.xToCursor(0), line.textStart());
+ pos += line.textLength();
+
+ line = layout.createLine();
+ line.setLineWidth(0x10000);
+ QCOMPARE(line.textStart(),pos);
+ QCOMPARE(line.textLength(),2);
+ QCOMPARE(qRound(line.naturalTextWidth()),testFont.pixelSize());
+ QCOMPARE(qRound(line.height()), testFont.pixelSize() + 1); // + 1 baseline
+ QCOMPARE(line.xToCursor(0), line.textStart());
+ pos += line.textLength();
+
+ line = layout.createLine();
+ line.setLineWidth(0x10000);
+ QCOMPARE(line.textStart(),pos);
+ QCOMPARE(line.textLength(),1);
+ QCOMPARE(qRound(line.naturalTextWidth()), testFont.pixelSize());
+ QCOMPARE((int) line.height(), testFont.pixelSize() + 1); // + 1 baseline
+ QCOMPARE(line.xToCursor(0), line.textStart());
+}
+
+void tst_QTextLayout::breakAny()
+{
+#if defined(Q_WS_MAC)
+ QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
+#endif
+ QString text = "ABCD";
+
+ QTextLayout layout(text, testFont);
+ QTextLine line;
+
+ QTextOption opt;
+ opt.setWrapMode(QTextOption::WrapAnywhere);
+ layout.setTextOption(opt);
+ layout.beginLayout();
+
+ line = layout.createLine();
+ line.setLineWidth(testFont.pixelSize() * 2);
+ QCOMPARE(line.textStart(), 0);
+ QCOMPARE(line.textLength(), 2);
+
+ line = layout.createLine();
+ line.setLineWidth(testFont.pixelSize() * 2);
+ QCOMPARE(line.textStart(), 2);
+ QCOMPARE(line.textLength(), 2);
+
+ line = layout.createLine();
+ QVERIFY(!line.isValid());
+
+ layout.endLayout();
+
+ text = "ABCD EFGH";
+ layout.setText(text);
+ layout.beginLayout();
+
+ line = layout.createLine();
+ line.setLineWidth(testFont.pixelSize() * 7);
+ QCOMPARE(line.textStart(), 0);
+ QCOMPARE(line.textLength(), 7);
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::noWrap()
+{
+#if defined(Q_WS_MAC)
+ QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
+#endif
+ QString text = "AB CD";
+
+ QTextLayout layout(text, testFont);
+ QTextLine line;
+
+ QTextOption opt;
+ opt.setWrapMode(QTextOption::NoWrap);
+ layout.setTextOption(opt);
+ layout.beginLayout();
+
+ line = layout.createLine();
+ line.setLineWidth(testFont.pixelSize() * 2);
+ QCOMPARE(line.textStart(), 0);
+ QCOMPARE(line.textLength(), 5);
+
+ line = layout.createLine();
+ QVERIFY(!line.isValid());
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::cursorToXForInlineObjects()
+{
+ QChar ch(QChar::ObjectReplacementCharacter);
+ QString text(ch);
+ QTextLayout layout(text, testFont);
+ layout.beginLayout();
+
+ QTextEngine *engine = layout.engine();
+ const int item = engine->findItem(0);
+ engine->layoutData->items[item].width = 32;
+
+ QTextLine line = layout.createLine();
+ line.setLineWidth(0x10000);
+
+ QCOMPARE(line.cursorToX(0), qreal(0));
+ QCOMPARE(line.cursorToX(1), qreal(32));
+}
+
+void tst_QTextLayout::cursorToXForSetColumns()
+{
+ QTextLayout lay("abc", testFont);
+ QTextOption o = lay.textOption();
+ o.setWrapMode(QTextOption::WrapAnywhere);
+
+ // enable/disable this line for full effect ;)
+ o.setAlignment(Qt::AlignHCenter);
+
+ lay.setTextOption(o);
+ lay.beginLayout();
+ QTextLine line = lay.createLine();
+ line.setNumColumns(1);
+ lay.endLayout();
+ QCOMPARE(line.cursorToX(0), 0.);
+ QCOMPARE(line.cursorToX(1), (qreal) TESTFONT_SIZE);
+}
+
+void tst_QTextLayout::defaultWordSeparators_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("startPos");
+ QTest::addColumn<int>("endPos");
+
+ QString separators(".,:;-<>[](){}=/+%&^*");
+ separators += QLatin1String("!?");
+ for (int i = 0; i < separators.count(); ++i) {
+ QTest::newRow(QString::number(i).toAscii().data())
+ << QString::fromLatin1("abcd") + separators.at(i) + QString::fromLatin1("efgh")
+ << 0 << 4;
+ }
+
+ QTest::newRow("nbsp")
+ << QString::fromLatin1("abcd") + QString(QChar::Nbsp) + QString::fromLatin1("efgh")
+ << 0 << 5;
+
+ QTest::newRow("tab")
+ << QString::fromLatin1("abcd") + QString::fromLatin1("\t") + QString::fromLatin1("efgh")
+ << 0 << 5;
+
+ QTest::newRow("lineseparator")
+ << QString::fromLatin1("abcd") + QString(QChar::LineSeparator) + QString::fromLatin1("efgh")
+ << 0 << 5;
+
+ QTest::newRow("empty")
+ << QString()
+ << 0 << 0;
+}
+
+void tst_QTextLayout::defaultWordSeparators()
+{
+ QFETCH(QString, text);
+ QFETCH(int, startPos);
+ QFETCH(int, endPos);
+ QTextLayout layout(text, testFont);
+
+ QCOMPARE(layout.nextCursorPosition(startPos, QTextLayout::SkipWords), endPos);
+ QCOMPARE(layout.previousCursorPosition(endPos, QTextLayout::SkipWords), startPos);
+}
+
+void tst_QTextLayout::cursorMovementFromInvalidPositions()
+{
+ int badpos = 10000;
+
+ QTextLayout layout("ABC", testFont);
+
+ QCOMPARE(layout.previousCursorPosition(-badpos, QTextLayout::SkipCharacters), -badpos);
+ QCOMPARE(layout.nextCursorPosition(-badpos, QTextLayout::SkipCharacters), -badpos);
+
+ QCOMPARE(layout.previousCursorPosition(badpos, QTextLayout::SkipCharacters), badpos);
+ QCOMPARE(layout.nextCursorPosition(badpos, QTextLayout::SkipCharacters), badpos);
+}
+
+void tst_QTextLayout::cursorMovementInsideSpaces()
+{
+ QTextLayout layout("ABC DEF", testFont);
+
+ QCOMPARE(layout.previousCursorPosition(6, QTextLayout::SkipWords), 0);
+ QCOMPARE(layout.nextCursorPosition(6, QTextLayout::SkipWords), 15);
+
+
+ QTextLayout layout2("ABC\t\t\t\t\t\t\t\t\t\t\t\tDEF", testFont);
+
+ QCOMPARE(layout2.previousCursorPosition(6, QTextLayout::SkipWords), 0);
+ QCOMPARE(layout2.nextCursorPosition(6, QTextLayout::SkipWords), 15);
+}
+
+void tst_QTextLayout::charWordStopOnLineSeparator()
+{
+ const QChar lineSeparator(QChar::LineSeparator);
+ QString txt;
+ txt.append(lineSeparator);
+ txt.append(lineSeparator);
+ QTextLayout layout(txt, testFont);
+ QTextEngine *engine = layout.engine();
+ const HB_CharAttributes *attrs = engine->attributes();
+ QVERIFY(attrs);
+ QVERIFY(attrs[1].charStop);
+}
+
+void tst_QTextLayout::xToCursorAtEndOfLine()
+{
+#if defined(Q_WS_MAC)
+ QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
+#endif
+ QString text = "FirstLine SecondLine";
+ text.replace('\n', QChar::LineSeparator);
+
+ const qreal firstLineWidth = QString("FirstLine").length() * testFont.pixelSize();
+
+ QTextLayout layout(text, testFont);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ QVERIFY(line.isValid());
+ line.setLineWidth(firstLineWidth);
+ QVERIFY(layout.createLine().isValid());
+ QVERIFY(!layout.createLine().isValid());
+ layout.endLayout();
+
+ line = layout.lineAt(0);
+ QCOMPARE(line.xToCursor(100000), 9);
+ line = layout.lineAt(1);
+ QCOMPARE(line.xToCursor(100000), 20);
+}
+
+void tst_QTextLayout::boundingRectTopLeft()
+{
+ QString text = "FirstLine\nSecondLine";
+ text.replace('\n', QChar::LineSeparator);
+
+ QTextLayout layout(text, testFont);
+
+ layout.beginLayout();
+ QTextLine firstLine = layout.createLine();
+ QVERIFY(firstLine.isValid());
+ firstLine.setPosition(QPointF(10, 10));
+ QTextLine secondLine = layout.createLine();
+ QVERIFY(secondLine.isValid());
+ secondLine.setPosition(QPointF(20, 20));
+ layout.endLayout();
+
+ QCOMPARE(layout.boundingRect().topLeft(), firstLine.position());
+}
+
+void tst_QTextLayout::charStopForSurrogatePairs()
+{
+ QString txt;
+ txt.append("a");
+ txt.append(0xd87e);
+ txt.append(0xdc25);
+ txt.append("b");
+ QTextLayout layout(txt, testFont);
+ QTextEngine *engine = layout.engine();
+ const HB_CharAttributes *attrs = engine->attributes();
+ QVERIFY(attrs);
+ QVERIFY(attrs[0].charStop);
+ QVERIFY(attrs[1].charStop);
+ QVERIFY(!attrs[2].charStop);
+ QVERIFY(attrs[3].charStop);
+}
+
+void tst_QTextLayout::tabStops()
+{
+#if defined(Q_WS_MAC)
+ QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
+#endif
+ QString txt("Hello there\tworld");
+ QTextLayout layout(txt, testFont);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+
+ QVERIFY(line.isValid());
+ line.setNumColumns(11);
+ QCOMPARE(line.textLength(), TESTFONT_SIZE);
+
+ line = layout.createLine();
+ QVERIFY(line.isValid());
+ line.setNumColumns(5);
+ QCOMPARE(line.textLength(), 5);
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::integerOverflow()
+{
+ QString txt("Hello world... ");
+
+ for (int i = 0; i < 8; ++i)
+ txt += txt;
+
+ QTextLayout layout(txt, testFont);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+
+ QVERIFY(line.isValid());
+ line.setLineWidth(INT_MAX);
+ QCOMPARE(line.textLength(), txt.length());
+
+ QVERIFY(!layout.createLine().isValid());
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::setNumColumnsWrapAtWordBoundaryOrAnywhere()
+{
+ QString txt("This is a small test text");
+ QTextLayout layout(txt, testFont);
+ QTextOption option = layout.textOption();
+ option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line1 = layout.createLine();
+ QVERIFY(line1.isValid());
+ line1.setNumColumns(1);
+
+ // qDebug() << line1.naturalTextWidth();
+ QCOMPARE(line1.textLength(), 1);
+ QVERIFY(line1.naturalTextWidth() == testFont.pixelSize()); // contains only one character
+
+ QTextLine line2 = layout.createLine();
+ QVERIFY(line2.isValid());
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::setNumColumnsWordWrap()
+{
+ QString txt("This is a small test text");
+ QTextLayout layout(txt, testFont);
+ QTextOption option = layout.textOption();
+ option.setWrapMode(QTextOption::WordWrap);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line1 = layout.createLine();
+ QVERIFY(line1.isValid());
+ line1.setNumColumns(1);
+
+ // qDebug() << line1.naturalTextWidth();
+ QCOMPARE(line1.textLength(), 5);
+ QVERIFY(line1.naturalTextWidth() > 20.0); // contains the whole first word.
+
+ QTextLine line2 = layout.createLine();
+ QVERIFY(line2.isValid());
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::smallTextLengthNoWrap()
+{
+ QString txt("This is a small test text");
+ QTextLayout layout(txt, testFont);
+ QTextOption option = layout.textOption();
+ option.setWrapMode(QTextOption::NoWrap);
+ layout.setTextOption(option);
+
+ /// NoWrap
+ layout.beginLayout();
+ QTextLine line1 = layout.createLine();
+ QVERIFY(line1.isValid());
+ line1.setLineWidth(5); // most certainly too short for the word 'This' to fit.
+
+ QCOMPARE(line1.width(), 5.0);
+ QVERIFY(line1.naturalTextWidth() > 70); // contains all the text.
+
+ QTextLine line2 = layout.createLine();
+ QVERIFY(! line2.isValid());
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::smallTextLengthWordWrap()
+{
+ QString txt("This is a small test text");
+ QTextLayout layout(txt, testFont);
+ QTextOption option = layout.textOption();
+ option.setWrapMode(QTextOption::WordWrap);
+ layout.setTextOption(option);
+
+ /// WordWrap
+ layout.beginLayout();
+ QTextLine line1 = layout.createLine();
+ QVERIFY(line1.isValid());
+ line1.setLineWidth(5); // most certainly too short for the word 'This' to fit.
+
+ QCOMPARE(line1.width(), 5.0);
+ QVERIFY(line1.naturalTextWidth() > 20.0); // contains the whole first word.
+ QCOMPARE(line1.textLength(), 5);
+
+ QTextLine line2 = layout.createLine();
+ QVERIFY(line2.isValid());
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::smallTextLengthWrapAtWordBoundaryOrAnywhere()
+{
+ QString txt("This is a small test text");
+ QTextLayout layout(txt, testFont);
+ QTextOption option = layout.textOption();
+ option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line1 = layout.createLine();
+ QVERIFY(line1.isValid());
+ line1.setLineWidth(5); // most certainly too short for the word 'This' to fit.
+
+ QCOMPARE(line1.width(), 5.0);
+ // qDebug() << line1.naturalTextWidth();
+ QCOMPARE(line1.textLength(), 1);
+ QVERIFY(line1.naturalTextWidth() == testFont.pixelSize()); // contains just the characters that fit.
+
+ QTextLine line2 = layout.createLine();
+ QVERIFY(line2.isValid());
+
+ layout.endLayout();
+}
+
+void tst_QTextLayout::testDefaultTabs()
+{
+ QTextLayout layout("Foo\tBar\ta slightly longer text\tend.", testFont);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(1000);
+ layout.endLayout();
+
+ //qDebug() << "After the tab: " << line.cursorToX(4);
+ QCOMPARE(line.cursorToX(4), 80.); // default tab is 80
+ QCOMPARE(line.cursorToX(8), 160.);
+ QCOMPARE(line.cursorToX(31), 480.);
+
+ QTextOption option = layout.textOption();
+ option.setTabStop(90);
+ layout.setTextOption(option);
+ layout.beginLayout();
+ line = layout.createLine();
+ line.setLineWidth(1000);
+ layout.endLayout();
+
+ QCOMPARE(line.cursorToX(4), 90.);
+ QCOMPARE(line.cursorToX(8), 180.);
+ QCOMPARE(line.cursorToX(31), 450.);
+
+ QList<QTextOption::Tab> tabs;
+ QTextOption::Tab tab;
+ tab.position = 110; // set one tab to 110, but since the rest is unset they will be at the normal interval again.
+ tabs.append(tab);
+ option.setTabs(tabs);
+ layout.setTextOption(option);
+ layout.beginLayout();
+ line = layout.createLine();
+ line.setLineWidth(1000);
+ layout.endLayout();
+
+ QCOMPARE(line.cursorToX(4), 110.);
+ QCOMPARE(line.cursorToX(8), 180.);
+ QCOMPARE(line.cursorToX(31), 450.);
+}
+
+void tst_QTextLayout::testTabs()
+{
+ QTextLayout layout("Foo\tBar.", testFont);
+ QTextOption option = layout.textOption();
+ option.setTabStop(150);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(200.);
+ layout.endLayout();
+
+ QVERIFY(line.naturalTextWidth() > 150);
+ QCOMPARE(line.cursorToX(4), 150.);
+}
+
+void tst_QTextLayout::testMultilineTab()
+{
+ QTextLayout layout("Lorem ipsum dolor sit\tBar.", testFont);
+ // test if this works on the second line.
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(220.); // moves 'sit' to next line.
+ line = layout.createLine();
+ line.setLineWidth(220.);
+ layout.endLayout();
+
+ QCOMPARE(line.cursorToX(22), 80.);
+}
+
+void tst_QTextLayout::testMultiTab()
+{
+ QTextLayout layout("Foo\t\t\tBar.", testFont);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(1000.);
+ layout.endLayout();
+
+ QCOMPARE(line.cursorToX(6), 80. * 3);
+}
+
+void tst_QTextLayout::testTabsInAlignedParag()
+{
+ QTextLayout layout("Foo\tsome more words", testFont);
+ QTextOption option = layout.textOption();
+ // right
+ option.setAlignment(Qt::AlignRight);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(300.);
+ layout.endLayout();
+
+ const qreal textWidth = 80 + 15 * TESTFONT_SIZE; // 15 chars right of the tab
+ QCOMPARE(line.naturalTextWidth(), textWidth);
+ QCOMPARE(line.cursorToX(0), 300. - textWidth);
+
+ // centered
+ option.setAlignment(Qt::AlignCenter);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ line = layout.createLine();
+ line.setLineWidth(300.);
+ layout.endLayout();
+
+ QCOMPARE(line.naturalTextWidth(), textWidth);
+ QCOMPARE(line.cursorToX(0), (300. - textWidth) / 2.);
+
+ // justified
+ option.setAlignment(Qt::AlignJustify);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ line = layout.createLine();
+ line.setLineWidth(textWidth - 10); // make the last word slip to the next line so justification actually happens.
+ layout.endLayout();
+
+ QCOMPARE(line.cursorToX(0), 0.);
+ QCOMPARE(line.cursorToX(4), 80.);
+
+ //QTextLayout layout2("Foo\tUt wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis", testFont); // means it will be more then one line long.
+}
+
+void tst_QTextLayout::testRightTab()
+{
+ QTextLayout layout("Foo\tLorem ipsum te sit\tBar baz\tText\tEnd", testFont);
+ /* ^ a ^ b ^ c ^ d
+ a = 4, b = 22, c = 30, d = 35 (position)
+
+ I expect the output to be:
+ Foo Lorem ipsum te
+ sit Bar Baz
+ Text End
+
+ a) tab replaced with a single space due to the text not fitting before the tab.
+ b) tab takes space so the text until the 3th tab fits to the tab pos.
+ c) tab is after last tab (both auto and defined) and thus moves text to start of next line.
+ d) tab takes space so text until enter fits to tab pos.
+ */
+
+ QTextOption option = layout.textOption();
+ QList<QTextOption::Tab> tabs;
+ QTextOption::Tab tab;
+ tab.type = QTextOption::RightTab;
+ tab.position = 190; // which means only 15(.8) chars of our test font fit left of it.
+ tabs.append(tab);
+ option.setTabs(tabs);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line1 = layout.createLine();
+ line1.setLineWidth(220.);
+ // qDebug() << "=====line 2";
+ QTextLine line2 = layout.createLine();
+ QVERIFY(line2.isValid());
+ line2.setLineWidth(220.);
+ // qDebug() << "=====line 3";
+ QTextLine line3 = layout.createLine();
+ QVERIFY(line3.isValid());
+ line3.setLineWidth(220.);
+ // qDebug() << "=====line 4";
+ QTextLine line4 = layout.createLine();
+ QVERIFY(! line4.isValid());
+ layout.endLayout();
+ // qDebug() << "--------";
+
+ QCOMPARE(line1.cursorToX(4), 3. * TESTFONT_SIZE ); // a
+ QCOMPARE(line1.textLength(), 19);
+ QCOMPARE(line2.cursorToX(23), 190. - 7. * TESTFONT_SIZE); // b
+ QCOMPARE(line2.textLength(), 12);
+ QCOMPARE(line3.cursorToX(31), 0.); // c
+ QCOMPARE(line3.cursorToX(36), 190 - 3. * TESTFONT_SIZE); // d
+}
+
+void tst_QTextLayout::testCenteredTab()
+{
+ QTextLayout layout("Foo\tBar", testFont);
+ // test if centering the tab works. We expect the center of 'Bar.' to be at the tab point.
+ QTextOption option = layout.textOption();
+ QList<QTextOption::Tab> tabs;
+ QTextOption::Tab tab(150, QTextOption::CenterTab);
+ tabs.append(tab);
+ option.setTabs(tabs);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(200.);
+ layout.endLayout();
+
+ const qreal wordLength = 3 * TESTFONT_SIZE; // the length of 'Bar'
+ QCOMPARE(line.cursorToX(4), 150 - wordLength / 2.);
+}
+
+void tst_QTextLayout::testDelimiterTab()
+{
+ QTextLayout layout("Foo\tBar. Barrabas", testFont);
+ // try the different delimiter characters to see if the alignment works there.
+ QTextOption option = layout.textOption();
+ QList<QTextOption::Tab> tabs;
+ QTextOption::Tab tab(100, QTextOption::DelimiterTab, QChar('.'));
+ tabs.append(tab);
+ option.setTabs(tabs);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(200.);
+ layout.endLayout();
+
+ const qreal distanceBeforeTab = 3.5 * TESTFONT_SIZE; // the length of 'bar' and half the width of the dot.
+ QCOMPARE(line.cursorToX(4), 100 - distanceBeforeTab);
+}
+
+void tst_QTextLayout::testLineBreakingAllSpaces()
+{
+ QTextLayout layout(" 123", testFont); // thats 20 spaces
+ const qreal firstLineWidth = 17 * TESTFONT_SIZE;
+ layout.beginLayout();
+ QTextLine line1 = layout.createLine();
+ line1.setLineWidth(firstLineWidth);
+ QTextLine line2 = layout.createLine();
+ line2.setLineWidth(1000); // the rest
+ layout.endLayout();
+ QCOMPARE(line1.width(), firstLineWidth);
+ QCOMPARE(line1.naturalTextWidth(), 0.); // spaces don't take space
+ QCOMPARE(line1.textLength(), 20);
+ QCOMPARE(line2.textLength(), 3);
+ QCOMPARE(line2.naturalTextWidth(), 3. * TESTFONT_SIZE);
+}
+
+void tst_QTextLayout::tabsForRtl()
+{
+ QString word(QChar(0x5e9)); // a hebrew character
+ word = word + word + word; // 3 hebrew characters ;)
+
+ QTextLayout layout(word +'\t'+ word +'\t'+ word +'\t'+ word, testFont);
+//QTextLayout layout(word +' '+ word +' '+ word +' '+ word, testFont);// tester ;)
+ /* ^ a ^ b ^ c
+ a = 4, b = 8, c = 12, d = 16 (position)
+
+ a) Left tab in RTL is a righ tab; so a is at width - 80
+ b) Like a
+ c) right tab on RTL is a left tab; so its at width - 240
+ d) center tab is still a centered tab.
+ */
+
+ QTextOption option = layout.textOption();
+ QList<QTextOption::Tab> tabs;
+ QTextOption::Tab tab;
+ tab.position = 80;
+ tabs.append(tab);
+ tab.position = 160;
+ tabs.append(tab);
+ tab.position = 240;
+ tab.type = QTextOption::RightTab;
+ tabs.append(tab);
+ option.setTabs(tabs);
+ option.setTextDirection(Qt::RightToLeft);
+ option.setAlignment(Qt::AlignRight);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ const qreal WIDTH = 400.;
+ line.setLineWidth(WIDTH);
+ layout.endLayout();
+
+//qDebug() << "layout ended --------------";
+
+ QCOMPARE(line.cursorToX(0), WIDTH);
+ QCOMPARE(line.cursorToX(1), WIDTH - TESTFONT_SIZE); // check its right-aligned
+ QCOMPARE(line.cursorToX(4), WIDTH - 80 + 3 * TESTFONT_SIZE);
+ QCOMPARE(line.cursorToX(8), WIDTH - 160 + 3 * TESTFONT_SIZE);
+ QCOMPARE(line.cursorToX(12), WIDTH - 240);
+}
+
+QT_BEGIN_NAMESPACE
+extern int qt_defaultDpiY();
+QT_END_NAMESPACE
+
+void tst_QTextLayout::testTabDPIScale()
+{
+ class MyPaintDevice : public QPaintDevice {
+ QPaintEngine *paintEngine () const { return 0; }
+ int metric (QPaintDevice::PaintDeviceMetric metric) const {
+ switch(metric) {
+ case QPaintDevice::PdmWidth:
+ case QPaintDevice::PdmHeight:
+ case QPaintDevice::PdmWidthMM:
+ case QPaintDevice::PdmHeightMM:
+ case QPaintDevice::PdmNumColors:
+ return INT_MAX;
+ case QPaintDevice::PdmDepth:
+ return 32;
+ case QPaintDevice::PdmDpiX:
+ case QPaintDevice::PdmDpiY:
+ case QPaintDevice::PdmPhysicalDpiX:
+ case QPaintDevice::PdmPhysicalDpiY:
+ return 72;
+ }
+ return 0;
+ }
+ };
+
+ MyPaintDevice pd;
+
+ QTextLayout layout("text1\ttext2\ttext3\tend", testFont, &pd);
+
+ QTextOption option = layout.textOption();
+ QList<QTextOption::Tab> tabs;
+ QTextOption::Tab tab;
+ tab.position = 300;
+ tabs.append(tab);
+
+ tab.position = 600;
+ tab.type = QTextOption::RightTab;
+ tabs.append(tab);
+
+ tab.position = 800;
+ tab.type = QTextOption::CenterTab;
+ tabs.append(tab);
+ option.setTabs(tabs);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(1500.);
+ layout.endLayout();
+ QCOMPARE(line.cursorToX(0), 0.);
+ QCOMPARE(line.cursorToX(1), (double) TESTFONT_SIZE); // check that the font does not resize
+ qreal scale = 72 / (qreal) qt_defaultDpiY();
+ // lets do the transformation of deminishing resolution that QFixed has as effect.
+ int fixedScale = (int)( scale * qreal(64)); // into a QFixed
+ scale = ((qreal)fixedScale)/(qreal)64; // and out of a QFixed
+
+ QCOMPARE(line.cursorToX(6), tabs.at(0).position * scale);
+ QCOMPARE(line.cursorToX(12), tabs.at(1).position * scale - TESTFONT_SIZE * 5);
+ QCOMPARE(line.cursorToX(18), tabs.at(2).position * scale - TESTFONT_SIZE * 3 / 2.0);
+}
+
+void tst_QTextLayout::tabHeight()
+{
+ QTextLayout layout("\t", testFont);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ QCOMPARE(qRound(line.ascent()), QFontMetrics(testFont).ascent());
+ QCOMPARE(qRound(line.descent()), QFontMetrics(testFont).descent());
+}
+
+void tst_QTextLayout::capitalization_allUpperCase()
+{
+ QFont font(testFont);
+ font.setCapitalization(QFont::AllUppercase);
+ QTextLayout layout("Test", font);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ QTextEngine *engine = layout.engine();
+ engine->itemize();
+ QCOMPARE(engine->layoutData->items.count(), 1);
+ QVERIFY(engine->layoutData->items.at(0).analysis.flags == QScriptAnalysis::Uppercase);
+}
+
+void tst_QTextLayout::capitalization_allLowerCase()
+{
+ QFont font(testFont);
+ font.setCapitalization(QFont::AllLowercase);
+ QTextLayout layout("Test", font);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ QTextEngine *engine = layout.engine();
+ engine->itemize();
+ QCOMPARE(engine->layoutData->items.count(), 1);
+ QVERIFY(engine->layoutData->items.at(0).analysis.flags == QScriptAnalysis::Lowercase);
+}
+
+void tst_QTextLayout::capitalization_smallCaps()
+{
+ QFont font(testFont);
+ font.setCapitalization(QFont::SmallCaps);
+ QTextLayout layout("Test", font);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ QTextEngine *engine = layout.engine();
+ engine->itemize();
+ QCOMPARE(engine->layoutData->items.count(), 2);
+ QVERIFY(engine->layoutData->items.at(0).analysis.flags == QScriptAnalysis::None);
+ QVERIFY(engine->layoutData->items.at(1).analysis.flags == QScriptAnalysis::SmallCaps);
+}
+
+void tst_QTextLayout::capitalization_capitalize()
+{
+ QFont font(testFont);
+ font.setCapitalization(QFont::Capitalize);
+ QTextLayout layout("hello\tworld", font);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ QTextEngine *engine = layout.engine();
+ engine->itemize();
+ QCOMPARE(engine->layoutData->items.count(), 5);
+ QVERIFY(engine->layoutData->items.at(0).analysis.flags == QScriptAnalysis::Uppercase);
+ QVERIFY(engine->layoutData->items.at(1).analysis.flags == QScriptAnalysis::None);
+ QVERIFY(engine->layoutData->items.at(2).analysis.flags == QScriptAnalysis::Tab);
+ QVERIFY(engine->layoutData->items.at(3).analysis.flags == QScriptAnalysis::Uppercase);
+ QVERIFY(engine->layoutData->items.at(4).analysis.flags == QScriptAnalysis::None);
+}
+
+void tst_QTextLayout::longText()
+{
+ QString longText(128000, 'a');
+
+ {
+ QTextLayout layout(longText, testFont);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+ QVERIFY(line.isValid());
+ QVERIFY(line.cursorToX(line.textLength() - 1) > 0);
+ }
+
+ for (int cap = QFont::MixedCase; cap < QFont::Capitalize + 1; ++cap) {
+ QFont f(testFont);
+ f.setCapitalization(QFont::Capitalization(cap));
+ QTextLayout layout(longText, f);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+ QVERIFY(line.isValid());
+ QVERIFY(line.cursorToX(line.textLength() - 1) > 0);
+ }
+
+ {
+ QTextLayout layout(longText, testFont);
+ layout.setFlags(Qt::TextForceLeftToRight);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+ QVERIFY(line.isValid());
+ QVERIFY(line.cursorToX(line.textLength() - 1) > 0);
+ }
+
+ {
+ QTextLayout layout(longText, testFont);
+ layout.setFlags(Qt::TextForceRightToLeft);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+ QVERIFY(line.isValid());
+ QVERIFY(line.cursorToX(line.textLength() - 1) > 0);
+ }
+}
+
+void tst_QTextLayout::widthOfTabs()
+{
+ QTextEngine engine("ddd\t\t", testFont);
+ engine.ignoreBidi = true;
+ engine.itemize();
+ QCOMPARE(qRound(engine.width(0, 5)), qRound(engine.boundingBox(0, 5).width));
+}
+
+void tst_QTextLayout::columnWrapWithTabs()
+{
+ QTextLayout textLayout;
+ {
+ QTextOption textOption;
+ textOption.setWrapMode(QTextOption::WordWrap);
+ textLayout.setTextOption(textOption);
+ }
+
+ // Make sure string with spaces does not break
+ {
+ QString text = "Foo bar foo bar foo bar";
+ textLayout.setText(text);
+
+ textLayout.beginLayout();
+ QTextLine line = textLayout.createLine();
+ line.setNumColumns(30);
+ QCOMPARE(line.textLength(), text.length());
+ textLayout.endLayout();
+ }
+
+ // Make sure string with tabs breaks
+ {
+ QString text = "Foo\tbar\tfoo\tbar\tfoo\tbar";
+ textLayout.setText(text);
+ textLayout.beginLayout();
+ QTextLine line = textLayout.createLine();
+ line.setNumColumns(30);
+ QVERIFY(line.textLength() < text.length());
+ textLayout.endLayout();
+ }
+
+}
+
+void tst_QTextLayout::boundingRectForUnsetLineWidth()
+{
+ QTextLayout layout("FOOBAR");
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ QCOMPARE(layout.boundingRect().width(), line.naturalTextWidth());
+}
+
+void tst_QTextLayout::boundingRectForSetLineWidth()
+{
+ QTextLayout layout("FOOBAR");
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(QFIXED_MAX - 1);
+ layout.endLayout();
+
+ QCOMPARE(layout.boundingRect().width(), qreal(QFIXED_MAX - 1));
+}
+
+void tst_QTextLayout::lineWidthFromBOM()
+{
+ const QString string(QChar(0xfeff)); // BYTE ORDER MARK
+ QTextLayout layout(string);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(INT_MAX / 256);
+ layout.endLayout();
+
+ // Don't spin into an infinite loop
+ }
+
+void tst_QTextLayout::glyphLessItems()
+{
+ {
+ QTextLayout layout;
+ layout.setText("\t\t");
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+ }
+
+ {
+ QTextLayout layout;
+ layout.setText(QString::fromLatin1("AA") + QChar(QChar::LineSeparator));
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+ }
+}
+
+void tst_QTextLayout::textWidthVsWIdth()
+{
+ QTextLayout layout;
+ QTextOption opt;
+ opt.setWrapMode(QTextOption::WrapAnywhere);
+ layout.setTextOption(opt);
+ layout.setText(QString::fromLatin1(
+ "g++ -c -m64 -pipe -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -W -D_REENTRANT -fPIC -DCORE_LIBRARY -DIDE_LIBRARY_BASENAME=\"lib\" -DWITH_TESTS "
+ "-DQT_NO_CAST_TO_ASCII -DQT_USE_FAST_OPERATOR_PLUS -DQT_USE_FAST_CONCATENATION -DQT_PLUGIN -DQT_TESTLIB_LIB -DQT_SCRIPT_LIB -DQT_SVG_LIB -DQT_SQL_LIB -DQT_XM"
+ "L_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I../../../../qt-qml/mkspecs/linux-g++-64 -I. -I../../../../qt-qml/include/QtCore -I../../../."
+ "./qt-qml/include/QtNetwork -I../../../../qt-qml/include/QtGui -I../../../../qt-qml/include/QtXml -I../../../../qt-qml/include/QtSql -I../../../../qt-qml/inc"
+ "lude/QtSvg -I../../../../qt-qml/include/QtScript -I../../../../qt-qml/include/QtTest -I../../../../qt-qml/include -I../../../../qt-qml/include/QtHelp -I../."
+ "./libs -I/home/ettrich/dev/creator/tools -I../../plugins -I../../shared/scriptwrapper -I../../libs/3rdparty/botan/build -Idialogs -Iactionmanager -Ieditorma"
+ "nager -Iprogressmanager -Iscriptmanager -I.moc/debug-shared -I.uic -o .obj/debug-shared/sidebar.o sidebar.cpp"));
+
+ // textWidth includes right bearing, but it should never be LARGER than width if there is space for at least one character
+ for (int width = 100; width < 1000; ++width) {
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(width);
+ layout.endLayout();
+
+ qreal textWidthIsLargerBy = qMax(qreal(0), line.naturalTextWidth() - line.width());
+ qreal thisMustBeZero = 0;
+ QCOMPARE(textWidthIsLargerBy, thisMustBeZero);
+ }
+}
+
+void tst_QTextLayout::textWithSurrogates_qtbug15679()
+{
+ QString str = QString::fromUtf8("🀀a🀀");
+ QTextLayout layout(str);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ qreal x[6];
+ for (int i = 0; i < 6; i++)
+ x[i] = line.cursorToX(i);
+
+ // If the first and third character are using the same
+ // font, they must have the same advance (since they
+ // are surrogate pairs, we need to add two for each
+ // character)
+ QCOMPARE(x[2] - x[0], x[5] - x[3]);
+}
+
+void tst_QTextLayout::textWidthWithStackedTextEngine()
+{
+ QString text = QString::fromUtf8("คลิภถัดไป เพื่อดำเนินà¸à¸²à¸£à¸•à¹ˆà¸­");
+ QTextLayout layout(text);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+ QFontMetricsF fm(layout.font());
+ QCOMPARE(line.naturalTextWidth(), fm.width(text));
+}
+
+void tst_QTextLayout::textWidthWithLineSeparator()
+{
+ QString s1("Save Project"), s2("Save Project\ntest");
+ s2.replace('\n', QChar::LineSeparator);
+
+ QTextLayout layout1(s1), layout2(s2);
+ layout1.beginLayout();
+ layout2.beginLayout();
+
+ QTextLine line1 = layout1.createLine();
+ QTextLine line2 = layout2.createLine();
+ line1.setLineWidth(0x1000);
+ line2.setLineWidth(0x1000);
+ QCOMPARE(line1.naturalTextWidth(), line2.naturalTextWidth());
+}
+
+void tst_QTextLayout::cursorInLigatureWithMultipleLines()
+{
+#if !defined(Q_WS_MAC)
+ QSKIP("This test can not be run on Mac", SkipAll);
+#endif
+ QTextLayout layout("first line finish", QFont("Times", 20));
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setLineWidth(70);
+ line = layout.createLine();
+ layout.endLayout();
+
+ // The second line will be "finish", with "fi" as a ligature
+ QVERIFY(line.cursorToX(0) != line.cursorToX(1));
+}
+
+void tst_QTextLayout::xToCursorForLigatures()
+{
+#if !defined(Q_WS_MAC)
+ QSKIP("This test can not be run on Mac", SkipAll);
+#endif
+ QTextLayout layout("fi", QFont("Times", 20));
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ QVERIFY(line.xToCursor(0) != line.xToCursor(line.naturalTextWidth() / 2));
+
+ // U+0061 U+0308
+ QTextLayout layout2(QString::fromUtf8("\x61\xCC\x88"), QFont("Times", 20));
+
+ layout2.beginLayout();
+ line = layout2.createLine();
+ layout2.endLayout();
+
+ qreal width = line.naturalTextWidth();
+ QVERIFY(line.xToCursor(0) == line.xToCursor(width / 2) ||
+ line.xToCursor(width) == line.xToCursor(width / 2));
+}
+
+QTEST_MAIN(tst_QTextLayout)
+#include "tst_qtextlayout.moc"
diff --git a/tests/auto/gui/text/qtextlist/.gitignore b/tests/auto/gui/text/qtextlist/.gitignore
new file mode 100644
index 0000000000..f1c4f6acab
--- /dev/null
+++ b/tests/auto/gui/text/qtextlist/.gitignore
@@ -0,0 +1 @@
+tst_qtextlist
diff --git a/tests/auto/gui/text/qtextlist/qtextlist.pro b/tests/auto/gui/text/qtextlist/qtextlist.pro
new file mode 100644
index 0000000000..f66fb96dd0
--- /dev/null
+++ b/tests/auto/gui/text/qtextlist/qtextlist.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += core-private gui-private
+
+SOURCES += tst_qtextlist.cpp
+HEADERS += ../qtextdocument/common.h
+
+
+
diff --git a/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp b/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
new file mode 100644
index 0000000000..164dd6fc68
--- /dev/null
+++ b/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qtextdocument.h>
+#include <qtextdocumentfragment.h>
+#include <qtextlist.h>
+#include <qabstracttextdocumentlayout.h>
+#include <qtextcursor.h>
+#include "../qtextdocument/common.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTextList : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTextList();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void item();
+ void autoNumbering();
+ void autoNumberingRTL();
+ void autoNumberingPrefixAndSuffix();
+ void autoNumberingPrefixAndSuffixRTL();
+ void autoNumberingPrefixAndSuffixHtmlExportImport();
+ void romanNumbering();
+ void romanNumberingLimit();
+ void formatChange();
+ void cursorNavigation();
+ void partialRemoval();
+ void formatReferenceChange();
+ void ensureItemOrder();
+ void add();
+ void defaultIndent();
+ void blockUpdate();
+ void numbering_data();
+ void numbering();
+
+private:
+ QTextDocument *doc;
+ QTextCursor cursor;
+ QTestDocumentLayout *layout;
+};
+
+tst_QTextList::tst_QTextList()
+{}
+
+void tst_QTextList::init()
+{
+ doc = new QTextDocument();
+ layout = new QTestDocumentLayout(doc);
+ doc->setDocumentLayout(layout);
+ cursor = QTextCursor(doc);
+}
+
+void tst_QTextList::cleanup()
+{
+ cursor = QTextCursor();
+ delete doc;
+ doc = 0;
+}
+
+void tst_QTextList::item()
+{
+ // this is basically a test for the key() + 1 in QTextList::item.
+ QTextList *list = cursor.createList(QTextListFormat());
+ QVERIFY(list->item(0).blockFormat().objectIndex() != -1);
+}
+
+void tst_QTextList::autoNumbering()
+{
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::ListLowerAlpha);
+ QTextList *list = cursor.createList(fmt);
+ QVERIFY(list);
+
+ for (int i = 0; i < 27; ++i)
+ cursor.insertBlock();
+
+ QVERIFY(list->count() == 28);
+
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->itemNumber(cursor.block()) == 27);
+ QVERIFY(cursor.currentList()->itemText(cursor.block()) == "ab.");
+}
+
+void tst_QTextList::autoNumberingPrefixAndSuffix()
+{
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::ListLowerAlpha);
+ fmt.setNumberPrefix("-");
+ fmt.setNumberSuffix(")");
+ QTextList *list = cursor.createList(fmt);
+ QVERIFY(list);
+
+ for (int i = 0; i < 27; ++i)
+ cursor.insertBlock();
+
+ QVERIFY(list->count() == 28);
+
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->itemNumber(cursor.block()) == 27);
+ QVERIFY(cursor.currentList()->itemText(cursor.block()) == "-ab)");
+}
+
+void tst_QTextList::autoNumberingPrefixAndSuffixRTL()
+{
+ QTextBlockFormat bfmt;
+ bfmt.setLayoutDirection(Qt::RightToLeft);
+ cursor.setBlockFormat(bfmt);
+
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::ListUpperAlpha);
+ fmt.setNumberPrefix("-");
+ fmt.setNumberSuffix("*");
+ QTextList *list = cursor.createList(fmt);
+ QVERIFY(list);
+
+ cursor.insertBlock();
+
+ QVERIFY(list->count() == 2);
+
+ QVERIFY(cursor.currentList()->itemText(cursor.block()) == "*B-");
+}
+
+void tst_QTextList::autoNumberingPrefixAndSuffixHtmlExportImport()
+{
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::ListLowerAlpha);
+ fmt.setNumberPrefix("\"");
+ fmt.setNumberSuffix("#");
+ fmt.setIndent(10);
+ // FIXME: Would like to test "'" but there's a problem in the css parser (Scanner::preprocess
+ // is called before the values are being parsed), so the quoting does not work.
+ QTextList *list = cursor.createList(fmt);
+ QVERIFY(list);
+
+ for (int i = 0; i < 27; ++i)
+ cursor.insertBlock();
+
+ QVERIFY(list->count() == 28);
+
+ QString htmlExport = doc->toHtml();
+ QTextDocument importDoc;
+ importDoc.setHtml(htmlExport);
+
+ QTextCursor importCursor(&importDoc);
+ for (int i = 0; i < 27; ++i)
+ importCursor.movePosition(QTextCursor::NextBlock);
+
+ QVERIFY(importCursor.currentList());
+ QVERIFY(importCursor.currentList()->itemNumber(importCursor.block()) == 27);
+ QVERIFY(importCursor.currentList()->itemText(importCursor.block()) == "\"ab#");
+ QVERIFY(importCursor.currentList()->format().indent() == 10);
+}
+
+void tst_QTextList::autoNumberingRTL()
+{
+ QTextBlockFormat bfmt;
+ bfmt.setLayoutDirection(Qt::RightToLeft);
+ cursor.setBlockFormat(bfmt);
+
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::ListUpperAlpha);
+ QTextList *list = cursor.createList(fmt);
+ QVERIFY(list);
+
+ cursor.insertBlock();
+
+ QVERIFY(list->count() == 2);
+
+ QVERIFY(cursor.currentList()->itemText(cursor.block()) == ".B");
+}
+
+void tst_QTextList::romanNumbering()
+{
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::ListUpperRoman);
+ QTextList *list = cursor.createList(fmt);
+ QVERIFY(list);
+
+ for (int i = 0; i < 4998; ++i)
+ cursor.insertBlock();
+
+ QVERIFY(list->count() == 4999);
+
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->itemNumber(cursor.block()) == 4998);
+ QVERIFY(cursor.currentList()->itemText(cursor.block()) == "MMMMCMXCIX.");
+}
+
+void tst_QTextList::romanNumberingLimit()
+{
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::ListLowerRoman);
+ QTextList *list = cursor.createList(fmt);
+ QVERIFY(list);
+
+ for (int i = 0; i < 4999; ++i)
+ cursor.insertBlock();
+
+ QVERIFY(list->count() == 5000);
+
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->itemNumber(cursor.block()) == 4999);
+ QVERIFY(cursor.currentList()->itemText(cursor.block()) == "?.");
+}
+
+void tst_QTextList::formatChange()
+{
+ // testing the formatChanged slot in QTextListManager
+
+ /* <initial block>
+ * 1.
+ * 2.
+ */
+ QTextList *list = cursor.insertList(QTextListFormat::ListDecimal);
+ QTextList *firstList = list;
+ cursor.insertBlock();
+
+ QVERIFY(list && list->count() == 2);
+
+ QTextBlockFormat bfmt = cursor.blockFormat();
+// QVERIFY(bfmt.object() == list);
+
+ bfmt.setObjectIndex(-1);
+ cursor.setBlockFormat(bfmt);
+
+ QVERIFY(firstList->count() == 1);
+}
+
+void tst_QTextList::cursorNavigation()
+{
+ // testing some cursor list methods
+
+ /* <initial block>
+ * 1.
+ * 2.
+ */
+ cursor.insertList(QTextListFormat::ListDecimal);
+ cursor.insertBlock();
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.currentList());
+ cursor.movePosition(QTextCursor::PreviousBlock);
+ QVERIFY(cursor.currentList());
+ QVERIFY(cursor.currentList()->itemNumber(cursor.block()) == 0);
+}
+
+void tst_QTextList::partialRemoval()
+{
+ /* this is essentially a test for PieceTable::removeBlock to not miss any
+ blocks with the blockChanged signal emission that actually get removed.
+
+ It creates two lists, like this:
+
+ 1. Hello World
+ a. Foobar
+
+ and then removes from within the 'Hello World' into the 'Foobar' .
+ There used to be no emission for the removal of the second (a.) block,
+ causing list inconsistencies.
+
+ */
+
+ QTextList *firstList = cursor.insertList(QTextListFormat::ListDecimal);
+
+ QTextCursor selStart = cursor;
+ selStart.movePosition(QTextCursor::PreviousCharacter);
+
+ cursor.insertText("Hello World");
+
+ // position it well into the 'hello world' text.
+ selStart.movePosition(QTextCursor::NextCharacter);
+ selStart.movePosition(QTextCursor::NextCharacter);
+ selStart.clearSelection();
+
+ QPointer<QTextList> secondList = cursor.insertList(QTextListFormat::ListCircle);
+ cursor.insertText("Foobar");
+
+ // position it into the 'foo bar' text.
+ cursor.movePosition(QTextCursor::PreviousCharacter);
+ QTextCursor selEnd = cursor;
+
+ // this creates a selection that includes parts of both text-fragments and also the list item of the second list.
+ QTextCursor selection = selStart;
+ selection.setPosition(selEnd.position(), QTextCursor::KeepAnchor);
+
+ selection.deleteChar(); // deletes the second list
+
+ QVERIFY(!secondList);
+ QVERIFY(!firstList->isEmpty());
+
+ doc->undo();
+}
+
+void tst_QTextList::formatReferenceChange()
+{
+ QTextList *list = cursor.insertList(QTextListFormat::ListDecimal);
+ cursor.insertText("Some Content...");
+ cursor.insertBlock(QTextBlockFormat());
+
+ cursor.setPosition(list->item(0).position());
+ int listItemStartPos = cursor.position();
+ cursor.movePosition(QTextCursor::NextBlock);
+ int listItemLen = cursor.position() - listItemStartPos;
+ layout->expect(listItemStartPos, listItemLen, listItemLen);
+
+ QTextListFormat fmt = list->format();
+ fmt.setStyle(QTextListFormat::ListCircle);
+ list->setFormat(fmt);
+
+ QVERIFY(layout->called);
+ QVERIFY(!layout->error);
+}
+
+void tst_QTextList::ensureItemOrder()
+{
+ /*
+ * Insert a new list item before the first one and verify the blocks
+ * are sorted after that.
+ */
+ QTextList *list = cursor.insertList(QTextListFormat::ListDecimal);
+
+ QTextBlockFormat fmt = cursor.blockFormat();
+ cursor.movePosition(QTextCursor::Start);
+ cursor.insertBlock(fmt);
+
+ QCOMPARE(list->item(0).position(), 1);
+ QCOMPARE(list->item(1).position(), 2);
+}
+
+void tst_QTextList::add()
+{
+ QTextList *list = cursor.insertList(QTextListFormat::ListDecimal);
+ cursor.insertBlock(QTextBlockFormat());
+ QCOMPARE(list->count(), 1);
+ cursor.insertBlock(QTextBlockFormat());
+ list->add(cursor.block());
+ QCOMPARE(list->count(), 2);
+}
+
+// Task #72036
+void tst_QTextList::defaultIndent()
+{
+ QTextListFormat fmt;
+ QCOMPARE(fmt.indent(), 1);
+}
+
+void tst_QTextList::blockUpdate()
+{
+ // three items
+ QTextList *list = cursor.insertList(QTextListFormat::ListDecimal);
+ cursor.insertBlock();
+ cursor.insertBlock();
+
+ // remove second, needs also update on the third
+ // since the numbering might have changed
+ const int len = cursor.position() + cursor.block().length() - 1;
+ layout->expect(1, len, len);
+ list->remove(list->item(1));
+ QVERIFY(!layout->error);
+}
+
+void tst_QTextList::numbering_data()
+{
+ QTest::addColumn<int>("format");
+ QTest::addColumn<int>("number");
+ QTest::addColumn<QString>("result");
+
+ QTest::newRow("E.") << int(QTextListFormat::ListUpperAlpha) << 5 << "E.";
+ QTest::newRow("abc.") << int(QTextListFormat::ListLowerAlpha) << (26 + 2) * 26 + 3 << "abc.";
+ QTest::newRow("12.") << int(QTextListFormat::ListDecimal) << 12 << "12.";
+ QTest::newRow("XXIV.") << int(QTextListFormat::ListUpperRoman) << 24 << "XXIV.";
+ QTest::newRow("VIII.") << int(QTextListFormat::ListUpperRoman) << 8 << "VIII.";
+ QTest::newRow("xxx.") << int(QTextListFormat::ListLowerRoman) << 30 << "xxx.";
+ QTest::newRow("xxix.") << int(QTextListFormat::ListLowerRoman) << 29 << "xxix.";
+// QTest::newRow("xxx. alpha") << int(QTextListFormat::ListLowerAlpha) << (24 * 26 + 24) * 26 + 24 << "xxx."; //Too slow
+}
+
+void tst_QTextList::numbering()
+{
+ QFETCH(int, format);
+ QFETCH(int, number);
+ QFETCH(QString, result);
+
+
+ QTextListFormat fmt;
+ fmt.setStyle(QTextListFormat::Style(format));
+ QTextList *list = cursor.createList(fmt);
+ QVERIFY(list);
+
+ for (int i = 1; i < number; ++i)
+ cursor.insertBlock();
+
+ QCOMPARE(list->count(), number);
+
+ QVERIFY(cursor.currentList());
+ QCOMPARE(cursor.currentList()->itemNumber(cursor.block()), number - 1);
+ QCOMPARE(cursor.currentList()->itemText(cursor.block()), result);
+}
+
+QTEST_MAIN(tst_QTextList)
+#include "tst_qtextlist.moc"
diff --git a/tests/auto/gui/text/qtextobject/.gitignore b/tests/auto/gui/text/qtextobject/.gitignore
new file mode 100644
index 0000000000..6a3da09549
--- /dev/null
+++ b/tests/auto/gui/text/qtextobject/.gitignore
@@ -0,0 +1 @@
+tst_qtextobject
diff --git a/tests/auto/gui/text/qtextobject/qtextobject.pro b/tests/auto/gui/text/qtextobject/qtextobject.pro
new file mode 100644
index 0000000000..e87a364ab6
--- /dev/null
+++ b/tests/auto/gui/text/qtextobject/qtextobject.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qtextobject.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtextobject.cpp
+
+
diff --git a/tests/auto/gui/text/qtextobject/tst_qtextobject.cpp b/tests/auto/gui/text/qtextobject/tst_qtextobject.cpp
new file mode 100644
index 0000000000..0d1773e3fa
--- /dev/null
+++ b/tests/auto/gui/text/qtextobject/tst_qtextobject.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qtextobject.h>
+#include <qtextdocument.h>
+#include <qtextedit.h>
+#include <qtextcursor.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTextObject : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QTextObject();
+ virtual ~tst_QTextObject();
+
+private slots:
+ void getSetCheck();
+ void testStandAloneTextObject();
+};
+
+tst_QTextObject::tst_QTextObject()
+{
+}
+
+tst_QTextObject::~tst_QTextObject()
+{
+}
+
+// Testing get/set functions
+void tst_QTextObject::getSetCheck()
+{
+ QTextEdit edit;
+ QTextFrame obj1(edit.document());
+ // QTextFrameLayoutData * QTextFrame::layoutData()
+ // void QTextFrame::setLayoutData(QTextFrameLayoutData *)
+ QTextFrameLayoutData *var1 = new QTextFrameLayoutData;
+ obj1.setLayoutData(var1);
+ QCOMPARE(var1, obj1.layoutData());
+ obj1.setLayoutData((QTextFrameLayoutData *)0);
+ QCOMPARE((QTextFrameLayoutData *)0, obj1.layoutData());
+ // delete var1; // No delete, since QTextFrame takes ownership
+
+ QTextBlock obj2 = edit.textCursor().block();
+ // QTextBlockUserData * QTextBlock::userData()
+ // void QTextBlock::setUserData(QTextBlockUserData *)
+ QTextBlockUserData *var2 = new QTextBlockUserData;
+ obj2.setUserData(var2);
+ QCOMPARE(var2, obj2.userData());
+ obj2.setUserData((QTextBlockUserData *)0);
+ QCOMPARE((QTextBlockUserData *)0, obj2.userData());
+
+ // int QTextBlock::userState()
+ // void QTextBlock::setUserState(int)
+ obj2.setUserState(0);
+ QCOMPARE(0, obj2.userState());
+ obj2.setUserState(INT_MIN);
+ QCOMPARE(INT_MIN, obj2.userState());
+ obj2.setUserState(INT_MAX);
+ QCOMPARE(INT_MAX, obj2.userState());
+}
+
+class TestTextObject : public QTextObject
+{
+public:
+ TestTextObject(QTextDocument *document) : QTextObject(document) {}
+};
+
+void tst_QTextObject::testStandAloneTextObject()
+{
+ QTextDocument document;
+ TestTextObject textObject(&document);
+
+ QCOMPARE(textObject.document(), &document);
+ // don't crash
+ textObject.format();
+ textObject.formatIndex();
+ QCOMPARE(textObject.objectIndex(), -1);
+}
+
+QTEST_MAIN(tst_QTextObject)
+#include "tst_qtextobject.moc"
diff --git a/tests/auto/gui/text/qtextodfwriter/.gitignore b/tests/auto/gui/text/qtextodfwriter/.gitignore
new file mode 100644
index 0000000000..791445d7a9
--- /dev/null
+++ b/tests/auto/gui/text/qtextodfwriter/.gitignore
@@ -0,0 +1 @@
+tst_qtextodfwriter
diff --git a/tests/auto/gui/text/qtextodfwriter/qtextodfwriter.pro b/tests/auto/gui/text/qtextodfwriter/qtextodfwriter.pro
new file mode 100644
index 0000000000..25bb5a5ed0
--- /dev/null
+++ b/tests/auto/gui/text/qtextodfwriter/qtextodfwriter.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += core-private gui-private
+SOURCES += tst_qtextodfwriter.cpp
+
+!symbian:DEFINES += SRCDIR=\\\"$$PWD\\\"
+symbian:INCLUDEPATH+=$$[QT_INSTALL_PREFIX]/include/QtGui/private
diff --git a/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp b/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp
new file mode 100644
index 0000000000..765afce66e
--- /dev/null
+++ b/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp
@@ -0,0 +1,426 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QTextBlock>
+#include <QTextList>
+#include <QTextTable>
+#include <QBuffer>
+#include <QDebug>
+
+#ifdef Q_OS_SYMBIAN
+#define SRCDIR "."
+#endif
+
+#include <private/qtextodfwriter_p.h>
+
+class tst_QTextOdfWriter : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void testWriteParagraph_data();
+ void testWriteParagraph();
+ void testWriteStyle1_data();
+ void testWriteStyle1();
+ void testWriteStyle2();
+ void testWriteList();
+ void testWriteList2();
+ void createArchive();
+ void testWriteAll();
+ void testWriteSection();
+ void testWriteTable();
+
+private:
+ /// closes the document and returns the part of the XML stream that the test wrote
+ QString getContentFromXml();
+
+private:
+ QTextDocument *document;
+ QXmlStreamWriter *xmlWriter;
+ QTextOdfWriter *odfWriter;
+ QBuffer *buffer;
+};
+
+void tst_QTextOdfWriter::init()
+{
+ document = new QTextDocument();
+ odfWriter = new QTextOdfWriter(*document, 0);
+
+ buffer = new QBuffer();
+ buffer->open(QIODevice::WriteOnly);
+ xmlWriter = new QXmlStreamWriter(buffer);
+ xmlWriter->writeNamespace(odfWriter->officeNS, "office");
+ xmlWriter->writeNamespace(odfWriter->textNS, "text");
+ xmlWriter->writeNamespace(odfWriter->styleNS, "style");
+ xmlWriter->writeNamespace(odfWriter->foNS, "fo");
+ xmlWriter->writeNamespace(odfWriter->tableNS, "table");
+ xmlWriter->writeStartDocument();
+ xmlWriter->writeStartElement("dummy");
+}
+
+void tst_QTextOdfWriter::cleanup()
+{
+ delete document;
+ delete odfWriter;
+ delete xmlWriter;
+ delete buffer;
+}
+
+QString tst_QTextOdfWriter::getContentFromXml()
+{
+ xmlWriter->writeEndDocument();
+ buffer->close();
+ QString stringContent = QString::fromUtf8(buffer->data());
+ QString ret;
+ int index = stringContent.indexOf("<dummy");
+ if (index > 0) {
+ index = stringContent.indexOf('>', index);
+ if (index > 0)
+ ret = stringContent.mid(index+1, stringContent.length() - index - 10);
+ }
+ return ret;
+}
+
+void tst_QTextOdfWriter::testWriteParagraph_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("xml");
+
+ QTest::newRow("empty") << "" <<
+ "<text:p text:style-name=\"p1\"/>";
+ QTest::newRow("spaces") << "foobar word" <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">foobar <text:s text:c=\"2\"/>word</text:span></text:p>";
+ QTest::newRow("starting spaces") << " starting spaces" <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\"><text:s text:c=\"2\"/>starting spaces</text:span></text:p>";
+ QTest::newRow("trailing spaces") << "trailing spaces " <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">trailing spaces <text:s/></text:span></text:p>";
+ QTest::newRow("tab") << "word\ttab x" <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">word<text:tab/>tab x</text:span></text:p>";
+ QTest::newRow("tab2") << "word\t\ttab\tx" <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">word<text:tab/><text:tab/>tab<text:tab/>x</text:span></text:p>";
+ QTest::newRow("misc") << "foobar word\ttab x" <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">foobar <text:s text:c=\"2\"/>word<text:tab/>tab x</text:span></text:p>";
+ QTest::newRow("misc2") << "\t \tFoo" <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\"><text:tab/> <text:s text:c=\"4\"/><text:tab/>Foo</text:span></text:p>";
+ QTest::newRow("linefeed") << QString("line1%1line2").arg(QChar(0x2028)) <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">line1<text:line-break/>line2</text:span></text:p>";
+ QTest::newRow("spaces") << "The quick brown fox jumped over the lazy dog" <<
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">The quick brown fox jumped over the lazy dog</text:span></text:p>";
+}
+
+void tst_QTextOdfWriter::testWriteParagraph()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, xml);
+
+ QTextCursor cursor(document);
+ cursor.insertText(input);
+
+ odfWriter->writeBlock(*xmlWriter, document->begin());
+ QCOMPARE( getContentFromXml(), xml);
+}
+
+void tst_QTextOdfWriter::testWriteStyle1_data()
+{
+ QTest::addColumn<QString>("htmlInput");
+ QTest::addColumn<int>("cursorPosition");
+ QTest::addColumn<QString>("xml");
+
+ QString text1 = "Normal<b>bold</b><i>italic</i><b><i>Bold/Italic</i></b>";
+ QTest::newRow("normal") << text1 << 2 <<
+ "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\"/></style:style>";
+ QTest::newRow("bold") << text1 << 10 <<
+ "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-weight=\"bold\" fo:font-family=\"Sans\"/></style:style>";
+ QTest::newRow("italic") << text1 << 14 <<
+ "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-style=\"italic\" fo:font-family=\"Sans\"/></style:style>";
+ QTest::newRow("bold+italic") << text1 << 25 <<
+ "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-style=\"italic\" fo:font-weight=\"bold\" fo:font-family=\"Sans\"/></style:style>";
+ QString colorText = "<span style=\"color: #00FF00; background-color: #FF0000;\"> Color Text </span>";
+ QTest::newRow("green/red") << colorText << 3 <<
+ "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\" fo:color=\"#00ff00\" fo:background-color=\"#ff0000\"/></style:style>";
+
+}
+
+void tst_QTextOdfWriter::testWriteStyle1()
+{
+ QFETCH(QString, htmlInput);
+ QFETCH(int, cursorPosition);
+ QFETCH(QString, xml);
+ document->setHtml(htmlInput);
+
+ QTextCursor cursor(document);
+ cursor.setPosition(cursorPosition);
+ odfWriter->writeCharacterFormat(*xmlWriter, cursor.charFormat(), 4);
+ QCOMPARE( getContentFromXml(), xml);
+}
+
+void tst_QTextOdfWriter::testWriteStyle2()
+{
+ QTextBlockFormat bf; // = cursor.blockFormat();
+ QList<QTextOption::Tab> tabs;
+ QTextOption::Tab tab1(40, QTextOption::RightTab);
+ tabs << tab1;
+ QTextOption::Tab tab2(80, QTextOption::DelimiterTab, 'o');
+ tabs << tab2;
+ bf.setTabPositions(tabs);
+
+ odfWriter->writeBlockFormat(*xmlWriter, bf, 1);
+ QString xml = QString::fromLatin1(
+ "<style:style style:name=\"p1\" style:family=\"paragraph\">"
+ "<style:paragraph-properties>"
+ "<style:tab-stops>"
+ "<style:tab-stop style:position=\"30pt\" style:type=\"right\"/>"
+ "<style:tab-stop style:position=\"60pt\" style:type=\"char\" style:char=\"o\"/>"
+ "</style:tab-stops>"
+ "</style:paragraph-properties>"
+ "</style:style>");
+ QCOMPARE(getContentFromXml(), xml);
+}
+
+void tst_QTextOdfWriter::testWriteList()
+{
+ QTextCursor cursor(document);
+ QTextList *list = cursor.createList(QTextListFormat::ListDisc);
+ cursor.insertText("ListItem 1");
+ list->add(cursor.block());
+ cursor.insertBlock();
+ cursor.insertText("ListItem 2");
+ list->add(cursor.block());
+
+ odfWriter->writeBlock(*xmlWriter, cursor.block());
+ QString xml = QString::fromLatin1(
+ "<text:list text:style-name=\"L2\">"
+ "<text:list-item>"
+ //"<text:numbered-paragraph text:style-name=\"L2\" text:level=\"1\">"
+ //"<text:number>")+ QChar(0x25cf) + QString::fromLatin1("</text:number>" // 0x25cf is a bullet
+ "<text:p text:style-name=\"p3\"><text:span text:style-name=\"c0\">ListItem 2</text:span></text:p>"
+ "</text:list-item>"
+ "</text:list>");
+
+ QCOMPARE(getContentFromXml(), xml);
+}
+
+void tst_QTextOdfWriter::testWriteList2()
+{
+ QTextCursor cursor(document);
+ QTextList *list = cursor.createList(QTextListFormat::ListDisc);
+ cursor.insertText("Cars");
+ list->add(cursor.block());
+ cursor.insertBlock();
+ QTextListFormat level2;
+ level2.setStyle(QTextListFormat::ListSquare);
+ level2.setIndent(2);
+ QTextList *list2 = cursor.createList(level2);
+ cursor.insertText("Model T");
+ list2->add(cursor.block());
+ cursor.insertBlock();
+ cursor.insertText("Kitt");
+ list2->add(cursor.block());
+ cursor.insertBlock();
+ cursor.insertText("Animals");
+ list->add(cursor.block());
+
+ cursor.insertBlock(QTextBlockFormat(), QTextCharFormat()); // start a new completely unrelated list.
+ QTextList *list3 = cursor.createList(QTextListFormat::ListDecimal);
+ cursor.insertText("Foo");
+ list3->add(cursor.block());
+
+ // and another block thats NOT in a list.
+ cursor.insertBlock(QTextBlockFormat(), QTextCharFormat());
+ cursor.insertText("Bar");
+
+ odfWriter->writeFrame(*xmlWriter, document->rootFrame());
+ QString xml = QString::fromLatin1(
+ "<text:list text:style-name=\"L2\">"
+ "<text:list-item>"
+ //"<text:numbered-paragraph text:style-name=\"L2\" text:level=\"1\">"
+ //"<text:number>")+ QChar(0x25cf) + QString::fromLatin1("</text:number>" // 0x25cf is a bullet
+ "<text:p text:style-name=\"p3\"><text:span text:style-name=\"c0\">Cars</text:span></text:p>"
+ "</text:list-item>"
+ "<text:list-item>"
+ "<text:list text:style-name=\"L4\">"
+ "<text:list-item>"
+ "<text:p text:style-name=\"p5\"><text:span text:style-name=\"c0\">Model T</text:span></text:p>"
+ "</text:list-item>"
+ "<text:list-item>"
+ "<text:p text:style-name=\"p5\"><text:span text:style-name=\"c0\">Kitt</text:span></text:p>"
+ "</text:list-item>"
+ "</text:list>"
+ "</text:list-item>"
+ "<text:list-item>"
+ "<text:p text:style-name=\"p3\"><text:span text:style-name=\"c0\">Animals</text:span></text:p>"
+ "</text:list-item>"
+ "</text:list>"
+ "<text:list text:style-name=\"L6\">"
+ "<text:list-item>"
+ "<text:p text:style-name=\"p7\"><text:span text:style-name=\"c0\">Foo</text:span></text:p>"
+ "</text:list-item>"
+ "</text:list>"
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">Bar</text:span></text:p>");
+
+ // QString x = getContentFromXml();
+ // for (int i=0; i < x.length(); i+=150) qDebug() << x.mid(i, 150);
+ QCOMPARE(getContentFromXml(), xml);
+}
+
+
+void tst_QTextOdfWriter::createArchive()
+{
+ document->setPlainText("a"); // simple doc is enough ;)
+ QTextOdfWriter writer(*document, buffer);
+ QCOMPARE(writer.createArchive(), true); // default
+ writer.writeAll();
+/*
+QFile file("createArchive-odt");
+file.open(QIODevice::WriteOnly);
+file.write(buffer->data());
+file.close();
+*/
+ QVERIFY(buffer->data().length() > 80);
+ QCOMPARE(buffer->data()[0], 'P'); // its a zip :)
+ QCOMPARE(buffer->data()[1], 'K');
+ QString mimetype(buffer->data().mid(38, 39));
+ QCOMPARE(mimetype, QString::fromLatin1("application/vnd.oasis.opendocument.text"));
+}
+
+void tst_QTextOdfWriter::testWriteAll()
+{
+ document->setPlainText("a"); // simple doc is enough ;)
+ QTextOdfWriter writer(*document, buffer);
+ QCOMPARE(writer.createArchive(), true);
+ writer.setCreateArchive(false);
+ writer.writeAll();
+ QString result = QString(buffer->data());
+ // details we check elsewhere, all we have to do is check availability.
+ QVERIFY(result.indexOf("office:automatic-styles") >= 0);
+ QVERIFY(result.indexOf("<style:style style:name=\"p1\"") >= 0);
+ QVERIFY(result.indexOf("<style:style style:name=\"c0\"") >= 0);
+ QVERIFY(result.indexOf("office:body") >= 0);
+ QVERIFY(result.indexOf("office:text") >= 0);
+ QVERIFY(result.indexOf("style:style") >= 0);
+}
+
+void tst_QTextOdfWriter::testWriteSection()
+{
+ QTextCursor cursor(document);
+ cursor.insertText("foo\nBar");
+ QTextFrameFormat ff;
+ cursor.insertFrame(ff);
+ cursor.insertText("baz");
+
+ odfWriter->writeFrame(*xmlWriter, document->rootFrame());
+ QString xml = QString::fromLatin1(
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">foo</text:span></text:p>"
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">Bar</text:span></text:p>"
+ "<text:section>"
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">baz</text:span></text:p>"
+ "</text:section>"
+ "<text:p text:style-name=\"p1\"/>");
+
+ QCOMPARE(getContentFromXml(), xml);
+}
+
+void tst_QTextOdfWriter::testWriteTable()
+{
+ // create table with merged cells
+ QTextCursor cursor(document);
+ QTextTable * table = cursor.insertTable(3, 3);
+ table->mergeCells(1, 0, 2, 2);
+ table->mergeCells(0, 1, 1, 2);
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ cursor.insertText("a");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("b");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("c");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("d");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("e");
+ /*
+ +-+---+
+ |a|b |
+ +-+-+-+
+ |c |d|
+ + +-+
+ | |e|
+ +-+-+-+
+ */
+
+ odfWriter->writeFrame(*xmlWriter, document->rootFrame());
+ QString xml = QString::fromLatin1(
+ "<text:p text:style-name=\"p1\"/>"
+ "<table:table>"
+ "<table:table-column table:number-columns-repeated=\"3\"/>"
+ "<table:table-row>"
+ "<table:table-cell table:style-name=\"T3\">"
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">a</text:span></text:p>"
+ "</table:table-cell>"
+ "<table:table-cell table:number-columns-spanned=\"2\" table:style-name=\"T6\">"
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c7\">b</text:span></text:p>"
+ "</table:table-cell>"
+ "</table:table-row>"
+ "<table:table-row>"
+ "<table:table-cell table:number-columns-spanned=\"2\" table:number-rows-spanned=\"2\" table:style-name=\"T5\">"
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c8\">c</text:span></text:p>"
+ "</table:table-cell>"
+ "<table:table-cell table:style-name=\"T3\">"
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">d</text:span></text:p>"
+ "</table:table-cell>"
+ "</table:table-row>"
+ "<table:table-row>"
+ "<table:table-cell table:style-name=\"T3\">"
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">e</text:span></text:p>"
+ "</table:table-cell>"
+ "</table:table-row>"
+ "</table:table>"
+ "<text:p text:style-name=\"p1\"/>");
+
+ QCOMPARE(getContentFromXml(), xml);
+}
+
+QTEST_MAIN(tst_QTextOdfWriter)
+#include "tst_qtextodfwriter.moc"
diff --git a/tests/auto/gui/text/qtextpiecetable/.gitignore b/tests/auto/gui/text/qtextpiecetable/.gitignore
new file mode 100644
index 0000000000..720b01f79f
--- /dev/null
+++ b/tests/auto/gui/text/qtextpiecetable/.gitignore
@@ -0,0 +1 @@
+tst_qtextpiecetable
diff --git a/tests/auto/gui/text/qtextpiecetable/qtextpiecetable.pro b/tests/auto/gui/text/qtextpiecetable/qtextpiecetable.pro
new file mode 100644
index 0000000000..cfbbe2bca5
--- /dev/null
+++ b/tests/auto/gui/text/qtextpiecetable/qtextpiecetable.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qtextpiecetable.cpp
+HEADERS += ../qtextdocument/common.h
+
+requires(!win32)
+requires(contains(QT_CONFIG,private_tests))
+
diff --git a/tests/auto/gui/text/qtextpiecetable/tst_qtextpiecetable.cpp b/tests/auto/gui/text/qtextpiecetable/tst_qtextpiecetable.cpp
new file mode 100644
index 0000000000..ddaf84134d
--- /dev/null
+++ b/tests/auto/gui/text/qtextpiecetable/tst_qtextpiecetable.cpp
@@ -0,0 +1,1155 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#define protected public
+
+#include <qtextdocument.h>
+#undef protected
+#include <private/qtextdocument_p.h>
+#include <qabstracttextdocumentlayout.h>
+#include <qtextobject.h>
+#include <qdebug.h>
+#include <stdlib.h>
+#include <qtextcursor.h>
+#include "../qtextdocument/common.h"
+
+//TESTED_FILES=gui/text/qtextdocument_p.cpp gui/text/qtextdocument_p.h
+
+class tst_QTextPieceTable : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTextPieceTable();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void insertion1();
+ void insertion2();
+ void insertion3();
+ void insertion4();
+ void insertion5();
+
+ void removal1();
+ void removal2();
+ void removal3();
+ void removal4();
+
+ void undoRedo1();
+ void undoRedo2();
+ void undoRedo3();
+ void undoRedo4();
+ void undoRedo5();
+ void undoRedo6();
+ void undoRedo7();
+ void undoRedo8();
+ void undoRedo9();
+ void undoRedo10();
+ void undoRedo11();
+
+ void checkDocumentChanged();
+ void checkDocumentChanged2();
+ void setBlockFormat();
+
+ void blockInsertion();
+ void blockInsertion2();
+
+ void blockRemoval1();
+ void blockRemoval2();
+ void blockRemoval3();
+ void blockRemoval4();
+ void blockRemoval5();
+
+ void checkBlockSeparation();
+
+ void checkFrames1();
+ void removeFrameDirect();
+ void removeWithChildFrame();
+ void clearWithFrames();
+
+private:
+ QTextDocument *doc;
+ QTextDocumentPrivate *table;
+ int blockFormatIndex;
+ int charFormatIndex;
+};
+
+tst_QTextPieceTable::tst_QTextPieceTable()
+{ doc = 0; table = 0; }
+
+
+void tst_QTextPieceTable::init()
+{
+ doc = new QTextDocument(0);
+ table = doc->docHandle();
+ blockFormatIndex = table->formatCollection()->indexForFormat(QTextBlockFormat());
+ charFormatIndex = table->formatCollection()->indexForFormat(QTextCharFormat());
+}
+
+void tst_QTextPieceTable::cleanup()
+{
+ delete doc;
+ doc = 0;
+}
+
+void tst_QTextPieceTable::insertion1()
+{
+ table->insert(0, "aacc", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("aacc"));
+ table->insert(2, "bb", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("aabbcc"));
+ table->insert(1, "1", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("a1abbcc"));
+ table->insert(6, "d", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("a1abbcdc"));
+ table->insert(8, "z", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("a1abbcdcz"));
+}
+
+void tst_QTextPieceTable::insertion2()
+{
+ table->insert(0, "bb", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("bb"));
+}
+
+void tst_QTextPieceTable::insertion3()
+{
+ QString compare;
+ for (int i = 0; i < 20000; ++i) {
+ int pos = rand() % (i+1);
+ QChar c((unsigned short)(i & 0xff) + 1);
+ QString str;
+ str += c;
+ table->insert(pos, str, charFormatIndex);
+ compare.insert(pos, str);
+ }
+ QVERIFY(table->plainText() == compare);
+}
+
+void tst_QTextPieceTable::insertion4()
+{
+ QString compare;
+ for (int i = 0; i < 20000; ++i) {
+ int pos = rand() % (i+1);
+ QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
+ QString str;
+ str += c;
+ str += c;
+ table->insert(pos, str, charFormatIndex);
+ compare.insert(pos, str);
+ // if (table->text() != compare) {
+ // qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->text().latin1());
+ // exit(12);
+ // }
+ }
+ QVERIFY(table->plainText() == compare);
+}
+
+void tst_QTextPieceTable::insertion5()
+{
+ QString compare;
+ for (int i = 0; i < 20000; ++i) {
+ int pos = rand() % (i+1);
+ QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
+ QString str;
+ str += c;
+ str += c;
+ if (c == 'a') {
+ table->insertBlock(pos, blockFormatIndex, charFormatIndex);
+ str = QChar(QChar::ParagraphSeparator);
+ } else {
+ table->insert(pos, str, charFormatIndex);
+ }
+ compare.insert(pos, str);
+ }
+ QVERIFY(table->plainText() == compare);
+ for (QTextBlock it = table->blocksBegin(); it != table->blocksEnd(); it = it.next()) {
+ QTextDocumentPrivate::FragmentIterator fit = table->find(it.position());
+ QVERIFY(fit.position() == it.position());
+ }
+}
+
+void tst_QTextPieceTable::removal1()
+{
+ table->insert(0, "abbccc", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("abbccc"));
+ table->remove(1, 2);
+ QCOMPARE(table->plainText(), QString("accc"));
+ table->insert(1, "1", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("a1ccc"));
+ table->remove(4, 1);
+ QCOMPARE(table->plainText(), QString("a1cc"));
+ table->insert(4, "z", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("a1ccz"));
+}
+
+void tst_QTextPieceTable::removal2()
+{
+ table->insert(0, "bb", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("bb"));
+ table->remove(0, 2);
+ QCOMPARE(table->plainText(), QString(""));
+ table->insertBlock(0, blockFormatIndex, charFormatIndex);
+ QCOMPARE(table->plainText(), QString(QChar(QChar::ParagraphSeparator)));
+ table->remove(0, 1);
+ QCOMPARE(table->plainText(), QString(""));
+
+ table->insert(0, "bb", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("bb"));
+ table->insertBlock(1, blockFormatIndex, charFormatIndex);
+ QCOMPARE(table->plainText(), QString("b") + QString(QChar(QChar::ParagraphSeparator)) + QString("b"));
+ table->remove(1, 1);
+ QCOMPARE(table->plainText(), QString("bb"));
+}
+
+void tst_QTextPieceTable::removal3()
+{
+ QString compare;
+ int l = 0;
+ for (int i = 0; i < 20000; ++i) {
+ bool remove = l && (rand() % 2);
+ int pos = rand() % (remove ? l : (l+1));
+ QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
+ QString str;
+ str += c;
+ str += c;
+ if (remove && pos < table->length()) {
+ compare.remove(pos, 1);
+ table->remove(pos, 1);
+ } else {
+ compare.insert(pos, str);
+ table->insert(pos, str, charFormatIndex);
+ }
+ l += remove ? -1 : 2;
+ // if (table->text() != compare) {
+ // qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->text().latin1());
+ // exit(12);
+ // }
+ }
+ QVERIFY(table->plainText() == compare);
+}
+
+void tst_QTextPieceTable::removal4()
+{
+ QString compare;
+ int l = 0;
+ for (int i = 0; i < 20000; ++i) {
+ bool remove = l && (rand() % 2);
+ int pos = (l > 1) ? rand() % (remove ? l-1 : l) : 0;
+ QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
+ QString str;
+ if (c != 'a') {
+ str += c;
+ str += c;
+ } else {
+ str = QChar(QChar::ParagraphSeparator);
+ }
+ if (remove && pos < table->length() - 1) {
+ compare.remove(pos, 1);
+ table->remove(pos, 1);
+ } else {
+ if (str[0] == QChar(QChar::ParagraphSeparator))
+ table->insertBlock(pos, blockFormatIndex, charFormatIndex);
+ else
+ table->insert(pos, str, charFormatIndex);
+ compare.insert(pos, str);
+ }
+ l += remove ? -1 : 2;
+// if (table->plainText() != compare) {
+// qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->plainText().latin1());
+// exit(12);
+// }
+ }
+ QVERIFY(table->plainText() == compare);
+}
+
+void tst_QTextPieceTable::undoRedo1()
+{
+ table->insert(0, "01234567", charFormatIndex);
+ table->insert(0, "a", charFormatIndex);
+ table->insert(1, "b", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("ab01234567"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString("01234567"));
+ table->redo();
+ QCOMPARE(table->plainText(), QString("ab01234567"));
+ table->undo();
+ table->insert(1, "c", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("0c1234567"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString("01234567"));
+ table->undo();
+ QVERIFY(table->plainText().isEmpty());
+}
+
+void tst_QTextPieceTable::undoRedo2()
+{
+ table->insert(0, "01", charFormatIndex);
+ table->insert(1, "a", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("0a1"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString("01"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString(""));
+ table->redo();
+ QCOMPARE(table->plainText(), QString("01"));
+ table->redo();
+ QCOMPARE(table->plainText(), QString("0a1"));
+}
+
+void tst_QTextPieceTable::undoRedo3()
+{
+ table->insert(0, "01", charFormatIndex);
+ table->insert(2, "ab", charFormatIndex);
+ table->remove(2, 1);
+ QCOMPARE(table->plainText(), QString("01b"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString("01ab"));
+ table->undo();
+ QVERIFY(table->plainText().isEmpty());
+ table->redo();
+ QCOMPARE(table->plainText(), QString("01ab"));
+ table->redo();
+ QCOMPARE(table->plainText(), QString("01b"));
+}
+
+void tst_QTextPieceTable::undoRedo4()
+{
+ table->insert(0, "01", charFormatIndex);
+ table->insert(0, "ab", charFormatIndex);
+ table->remove(0, 1);
+ QCOMPARE(table->plainText(), QString("b01"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString("ab01"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString("01"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString(""));
+ table->redo();
+ QCOMPARE(table->plainText(), QString("01"));
+ table->redo();
+ QCOMPARE(table->plainText(), QString("ab01"));
+ table->redo();
+ QCOMPARE(table->plainText(), QString("b01"));
+}
+
+void tst_QTextPieceTable::undoRedo5()
+{
+ table->beginEditBlock();
+ table->insert(0, "01", charFormatIndex);
+ table->remove(1, 1);
+ table->endEditBlock();
+ QCOMPARE(table->plainText(), QString("0"));
+ table->undo();
+ QCOMPARE(table->plainText(), QString(""));
+}
+
+void tst_QTextPieceTable::undoRedo6()
+{
+ // this is essentially a test for the undoStack[undoPosition - 1].block = false in PieceTable::endUndoBlock()
+ QTextDocument doc;
+ QTextCursor cursor(&doc);
+ cursor.insertText("Hello World");
+
+ cursor.insertBlock();
+ cursor.insertText("Hello World2");
+
+ cursor.movePosition(QTextCursor::Start);
+ QTextBlockFormat bfmt;
+ bfmt.setAlignment(Qt::AlignHCenter);
+ cursor.setBlockFormat(bfmt);
+ QVERIFY(cursor.blockFormat().alignment() == Qt::AlignHCenter);
+
+ QTextCursor range = cursor;
+ range.clearSelection();
+ range.movePosition(QTextCursor::Start);
+ range.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+
+ QTextCharFormat modifier;
+ modifier.setFontItalic(true);
+ range.mergeCharFormat(modifier);
+
+ cursor.movePosition(QTextCursor::Start);
+ QVERIFY(cursor.blockFormat().alignment() == Qt::AlignHCenter);
+
+ doc.undo();
+
+ QVERIFY(cursor.blockFormat().alignment() == Qt::AlignHCenter);
+}
+
+void tst_QTextPieceTable::undoRedo7()
+{
+ table->insert(0, "a", charFormatIndex);
+ table->insert(1, "b", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("ab"));
+
+ table->undo();
+ QVERIFY(table->plainText().isEmpty());
+}
+
+void tst_QTextPieceTable::undoRedo8()
+{
+ table->insert(0, "a", charFormatIndex);
+ table->insert(1, "b", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("ab"));
+
+ table->remove(0, 1);
+ table->remove(0, 1);
+
+ QVERIFY(table->plainText().isEmpty());
+ table->undo();
+ QCOMPARE(table->plainText(), QString("ab"));
+}
+
+void tst_QTextPieceTable::undoRedo9()
+{
+ table->insert(0, "a", charFormatIndex);
+ table->insert(1, "b", charFormatIndex);
+ QCOMPARE(table->plainText(), QString("ab"));
+
+ table->remove(1, 1);
+ table->remove(0, 1);
+
+ QVERIFY(table->plainText().isEmpty());
+ table->undo();
+ QCOMPARE(table->plainText(), QString("ab"));
+}
+
+void tst_QTextPieceTable::undoRedo10()
+{
+ // testcase for the beginUndoBlock/endUndoBlock calls being surrounded by an if (undoEnabled)
+ QTextCharFormat cf;
+ cf.setForeground(Qt::blue);
+ int cfIdx = table->formatCollection()->indexForFormat(cf);
+
+ QTextBlockFormat f;
+ int idx = table->formatCollection()->indexForFormat(f);
+
+ table->insert(0, "a", cfIdx);
+ table->insertBlock(1, idx, cfIdx);
+ table->insert(1, "b", cfIdx);
+
+ cf.setForeground(Qt::red);
+ int newCfIdx = table->formatCollection()->indexForFormat(cf);
+
+ table->setCharFormat(0, 3, cf, QTextDocumentPrivate::MergeFormat);
+
+ QCOMPARE(table->find(0).value()->format, newCfIdx);
+
+ table->undo();
+
+ QCOMPARE(table->find(0).value()->format, cfIdx);
+}
+
+void tst_QTextPieceTable::undoRedo11()
+{
+ srand(3);
+ const int loops = 20;
+ QString compare;
+ int l = 0;
+ for (int i = 0; i < loops; ++i) {
+ bool remove = l && (rand() % 2);
+ int pos = (l > 1) ? rand() % (remove ? l-1 : l) : 0;
+ QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
+ QString str;
+ str += c;
+ str += c;
+ if (remove) {
+ compare.remove(pos, 1);
+ table->remove(pos, 1);
+ } else {
+ compare.insert(pos, str);
+ table->insert(pos, str, charFormatIndex);
+ }
+ l += remove ? -1 : 2;
+ }
+ QVERIFY(table->plainText() == compare);
+ for (int i = 0; i < loops; ++i)
+ table->undo();
+ QVERIFY(table->plainText() == QString(""));
+ for (int i = 0; i < loops; ++i)
+ table->redo();
+ QVERIFY(table->plainText() == compare);
+}
+
+
+void tst_QTextPieceTable::checkDocumentChanged()
+{
+ table->enableUndoRedo(false);
+ QTestDocumentLayout *layout = new QTestDocumentLayout(doc);
+ doc->setDocumentLayout(layout);
+
+ // single insert
+ layout->expect(0, 0, 15);
+ table->insert(0, "012345678901234", charFormatIndex);
+ QVERIFY(!layout->error);
+
+ // single remove
+ layout->expect(0, 5, 0);
+ table->remove(0, 5);
+ QVERIFY(!layout->error);
+
+ // symmetric insert/remove
+ layout->expect(0, 0, 0);
+ table->beginEditBlock();
+ table->insert(0, "01234", charFormatIndex);
+ table->remove(0, 5);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(0, 5, 5);
+ table->beginEditBlock();
+ table->remove(0, 5);
+ table->insert(0, "01234", charFormatIndex);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ // replace
+ layout->expect(0, 3, 5);
+ table->beginEditBlock();
+ table->remove(0, 3);
+ table->insert(0, "01234", charFormatIndex);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(0, 0, 2);
+ table->beginEditBlock();
+ table->insert(0, "01234", charFormatIndex);
+ table->remove(0, 3);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ // insert + remove inside insert block
+ layout->expect(0, 0, 2);
+ table->beginEditBlock();
+ table->insert(0, "01234", charFormatIndex);
+ table->remove(1, 3);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(0, 0, 2);
+ table->beginEditBlock();
+ table->insert(0, "01234", charFormatIndex);
+ table->remove(2, 3);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ // insert + remove partly outside
+ layout->expect(0, 1, 0);
+ table->beginEditBlock();
+ table->insert(1, "0", charFormatIndex);
+ table->remove(0, 2);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(0, 1, 1);
+ table->beginEditBlock();
+ table->insert(1, "01", charFormatIndex);
+ table->remove(0, 2);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(0, 1, 2);
+ table->beginEditBlock();
+ table->insert(1, "012", charFormatIndex);
+ table->remove(0, 2);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(1, 1, 0);
+ table->beginEditBlock();
+ table->insert(1, "0", charFormatIndex);
+ table->remove(1, 2);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(1, 1, 1);
+ table->beginEditBlock();
+ table->insert(1, "01", charFormatIndex);
+ table->remove(2, 2);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(1, 1, 2);
+ table->beginEditBlock();
+ table->insert(1, "012", charFormatIndex);
+ table->remove(3, 2);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ // insert + remove non overlapping
+ layout->expect(0, 1, 1);
+ table->beginEditBlock();
+ table->insert(1, "0", charFormatIndex);
+ table->remove(0, 1);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(0, 2, 2);
+ table->beginEditBlock();
+ table->insert(2, "1", charFormatIndex);
+ table->remove(0, 1);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(0, 2, 2);
+ table->beginEditBlock();
+ table->remove(0, 1);
+ table->insert(1, "0", charFormatIndex);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ layout->expect(0, 3, 3);
+ table->beginEditBlock();
+ table->remove(0, 1);
+ table->insert(2, "1", charFormatIndex);
+ table->endEditBlock();
+
+
+ layout->expect(0, 3, 3);
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ table->beginEditBlock();
+ table->setCharFormat(0, 1, fmt);
+ table->setCharFormat(2, 1, fmt);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+}
+
+void tst_QTextPieceTable::checkDocumentChanged2()
+{
+ QTestDocumentLayout *layout = new QTestDocumentLayout(doc);
+ doc->setDocumentLayout(layout);
+
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ int anotherCharFormatIndex = table->formatCollection()->indexForFormat(fmt);
+
+ layout->expect(0, 0, 12);
+ table->beginEditBlock();
+ table->insert(0, "0123", charFormatIndex);
+ table->insert(4, "4567", anotherCharFormatIndex);
+ table->insert(8, "8901", charFormatIndex);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+
+ fmt.setFontItalic(true);
+
+ layout->expect(1, 10, 10);
+ table->beginEditBlock();
+ table->setCharFormat(8, 3, fmt);
+ table->setCharFormat(4, 4, fmt);
+ table->setCharFormat(1, 3, fmt);
+ table->endEditBlock();
+ QVERIFY(!layout->error);
+}
+
+void tst_QTextPieceTable::setBlockFormat()
+{
+ QTextBlockFormat bfmt;
+ int index = table->formatCollection()->indexForFormat(bfmt);
+
+ table->insertBlock(0, index, charFormatIndex);
+ table->insertBlock(0, index, charFormatIndex);
+ table->insertBlock(0, index, charFormatIndex);
+
+ QTextBlockFormat newbfmt = bfmt;
+ newbfmt.setAlignment(Qt::AlignRight);
+ index = table->formatCollection()->indexForFormat(bfmt);
+ QTextBlock b = table->blocksFind(1);
+ table->setBlockFormat(b, b, newbfmt);
+
+ QVERIFY(table->blocksFind(0).blockFormat() == bfmt);
+ QVERIFY(table->blocksFind(1).blockFormat() == newbfmt);
+ QVERIFY(table->blocksFind(2).blockFormat() == bfmt);
+}
+
+
+void tst_QTextPieceTable::blockInsertion()
+{
+ QTextBlockFormat fmt;
+ fmt.setTopMargin(100);
+ int idx = table->formatCollection()->indexForFormat(fmt);
+ int charFormat = table->formatCollection()->indexForFormat(QTextCharFormat());
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+
+ table->insertBlock(0, idx, charFormat);
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(1).blockFormat() == fmt);
+
+ table->undo();
+ QVERIFY(table->blockMap().length() == 1);
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+
+ table->redo();
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(1).blockFormat() == fmt);
+}
+
+void tst_QTextPieceTable::blockInsertion2()
+{
+ // caused evil failing assertion in fragmentmap
+ int pos = 0;
+ table->insertBlock(pos, blockFormatIndex, charFormatIndex);
+ pos += 1;
+ table->insert(pos, "a", charFormatIndex);
+ pos += 1;
+
+ pos -= 1;
+ table->insertBlock(pos, blockFormatIndex, charFormatIndex);
+ QCOMPARE(table->blocksFind(0).position(), 0);
+ QCOMPARE(table->blocksFind(1).position(), 1);
+ QCOMPARE(table->blocksFind(2).position(), 2);
+}
+
+/*
+ Tests correct removal behaviour when deleting over block boundaries or complete blocks.
+*/
+
+void tst_QTextPieceTable::blockRemoval1()
+{
+ QTextBlockFormat fmt1;
+ fmt1.setTopMargin(100);
+ QTextBlockFormat fmt2;
+ fmt2.setAlignment(Qt::AlignRight);
+ int idx1 = table->formatCollection()->indexForFormat(fmt1);
+ int idx2 = table->formatCollection()->indexForFormat(fmt2);
+
+ table->insert(0, "0123", charFormatIndex);
+ table->insertBlock(4, idx1, charFormatIndex);
+ table->insert(5, "5678", charFormatIndex);
+ table->insertBlock(9, idx2, charFormatIndex);
+ table->insert(10, "0123", charFormatIndex);
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->beginEditBlock();
+ table->remove(5, 5);
+ table->endEditBlock();
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(4).position() == 0);
+ QVERIFY(table->blocksFind(5).position() == 5);
+
+ table->undo();
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->redo();
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(4).position() == 0);
+ QVERIFY(table->blocksFind(5).position() == 5);
+}
+
+void tst_QTextPieceTable::blockRemoval2()
+{
+ QTextBlockFormat fmt1;
+ fmt1.setTopMargin(100);
+ QTextBlockFormat fmt2;
+ fmt2.setAlignment(Qt::AlignRight);
+ int idx1 = table->formatCollection()->indexForFormat(fmt1);
+ int idx2 = table->formatCollection()->indexForFormat(fmt2);
+
+ table->insert(0, "0123", charFormatIndex);
+ table->insertBlock(4, idx1, charFormatIndex);
+ table->insert(5, "5678", charFormatIndex);
+ table->insertBlock(9, idx2, charFormatIndex);
+ table->insert(10, "0123", charFormatIndex);
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->remove(4, 1);
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(6).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 0);
+
+ table->undo();
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->redo();
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(6).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 0);
+}
+
+void tst_QTextPieceTable::blockRemoval3()
+{
+ QTextBlockFormat fmt1;
+ fmt1.setTopMargin(100);
+ QTextBlockFormat fmt2;
+ fmt2.setAlignment(Qt::AlignRight);
+ int idx1 = table->formatCollection()->indexForFormat(fmt1);
+ int idx2 = table->formatCollection()->indexForFormat(fmt2);
+
+ table->insert(0, "0123", charFormatIndex);
+ table->insertBlock(4, idx1, charFormatIndex);
+ table->insert(5, "5678", charFormatIndex);
+ table->insertBlock(9, idx2, charFormatIndex);
+ table->insert(10, "0123", charFormatIndex);
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->beginEditBlock();
+ table->remove(3, 4);
+ table->endEditBlock();
+
+ QVERIFY(table->blocksFind(1).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(5).position() == 0);
+
+ table->undo();
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->redo();
+ QVERIFY(table->blocksFind(1).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(5).position() == 0);
+}
+
+void tst_QTextPieceTable::blockRemoval4()
+{
+#if 0
+ QTextBlockFormat fmt1;
+ fmt1.setTopMargin(100);
+ QTextBlockFormat fmt2;
+ fmt2.setAlignment(Qt::AlignRight);
+ int idx1 = table->formatCollection()->indexForFormat(fmt1);
+ int idx2 = table->formatCollection()->indexForFormat(fmt2);
+
+ table->insert(0, "0123", charFormatIndex);
+ table->insertBlock(4, idx1, charFormatIndex);
+ table->insert(5, "5678", charFormatIndex);
+ table->insertBlock(9, idx2, charFormatIndex);
+ table->insert(10, "0123", charFormatIndex);
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->remove(3, 7);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(5).position() == 0);
+ QVERIFY(table->blocksFind(1).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == QTextBlockFormat());
+
+ table->undo();
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->redo();
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(5).position() == 0);
+ QVERIFY(table->blocksFind(1).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == QTextBlockFormat());
+#endif
+}
+
+void tst_QTextPieceTable::blockRemoval5()
+{
+ QTextBlockFormat fmt1;
+ fmt1.setTopMargin(100);
+ QTextBlockFormat fmt2;
+ fmt2.setAlignment(Qt::AlignRight);
+ int idx1 = table->formatCollection()->indexForFormat(fmt1);
+ int idx2 = table->formatCollection()->indexForFormat(fmt2);
+
+ table->insert(0, "0123", charFormatIndex);
+ table->insertBlock(4, idx1, charFormatIndex);
+ table->insert(5, "5678", charFormatIndex);
+ table->insertBlock(9, idx2, charFormatIndex);
+ table->insert(10, "0123", charFormatIndex);
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->beginEditBlock();
+ table->remove(3, 8);
+ table->endEditBlock();
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(5).position() == 0);
+
+ table->undo();
+
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(4).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == fmt1);
+ QVERIFY(table->blocksFind(10).blockFormat() == fmt2);
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(6).position() == 5);
+ QVERIFY(table->blocksFind(11).position() == 10);
+
+ table->redo();
+ QVERIFY(table->blocksFind(0).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(5).blockFormat() == QTextBlockFormat());
+ QVERIFY(table->blocksFind(1).position() == 0);
+ QVERIFY(table->blocksFind(5).position() == 0);
+}
+
+
+void tst_QTextPieceTable::checkBlockSeparation()
+{
+ table->insertBlock(0, blockFormatIndex, charFormatIndex);
+ table->insertBlock(1, blockFormatIndex, charFormatIndex);
+
+ QVERIFY(table->find(0) != table->find(1));
+}
+
+void tst_QTextPieceTable::checkFrames1()
+{
+ QTextFrameFormat ffmt;
+ table->insert(0, "Hello", charFormatIndex);
+ QPointer<QTextFrame> frame = table->insertFrame(1, 3, ffmt);
+ QTextFrame *root = table->rootFrame();
+
+ QVERIFY(root == frame->parentFrame());
+
+ QVERIFY(root);
+ QVERIFY(root->parentFrame() == 0);
+
+ QVERIFY(root->childFrames().count() == 1);
+ QVERIFY(frame->format() == ffmt);
+ QVERIFY(frame->firstPosition() == 2);
+ QVERIFY(frame->lastPosition() == 4);
+
+
+ QPointer<QTextFrame> frame2 = table->insertFrame(2, 3, ffmt);
+
+ QVERIFY(root->childFrames().count() == 1);
+ QVERIFY(root->childFrames().at(0) == frame);
+ QVERIFY(frame->childFrames().count() == 1);
+ QVERIFY(frame2->childFrames().count() == 0);
+ QVERIFY(frame2->parentFrame() == frame);
+ QVERIFY(frame2->firstPosition() == 3);
+ QVERIFY(frame2->lastPosition() == 4);
+
+ QVERIFY(frame->format() == ffmt);
+ QVERIFY(frame->firstPosition() == 2);
+ QVERIFY(frame->lastPosition() == 6);
+
+ table->removeFrame(frame);
+
+ QVERIFY(root->childFrames().count() == 1);
+ QVERIFY(root->childFrames().at(0) == frame2);
+ QVERIFY(!frame);
+ QVERIFY(frame2->childFrames().count() == 0);
+ QVERIFY(frame2->parentFrame() == root);
+ QVERIFY(frame2->firstPosition() == 2);
+ QVERIFY(frame2->lastPosition() == 3);
+
+ table->undo();
+
+ frame = table->frameAt(2);
+
+ QVERIFY(root->childFrames().count() == 1);
+ QVERIFY(root->childFrames().at(0) == frame);
+ QVERIFY(frame->childFrames().count() == 1);
+ QVERIFY(frame->childFrames().at(0) == frame2);
+ QVERIFY(frame2->childFrames().count() == 0);
+ QVERIFY(frame2->parentFrame() == frame);
+ QVERIFY(frame2->firstPosition() == 3);
+ QVERIFY(frame2->lastPosition() == 4);
+
+ QVERIFY(frame->firstPosition() == 2);
+ QVERIFY(frame->lastPosition() == 6);
+
+ table->undo();
+
+ QVERIFY(root->childFrames().count() == 1);
+ QVERIFY(root->childFrames().at(0) == frame);
+ QVERIFY(frame->childFrames().count() == 0);
+ QVERIFY(!frame2);
+
+ QVERIFY(frame->firstPosition() == 2);
+ QVERIFY(frame->lastPosition() == 4);
+}
+
+void tst_QTextPieceTable::removeFrameDirect()
+{
+ QTextFrameFormat ffmt;
+ table->insert(0, "Hello", charFormatIndex);
+
+ QTextFrame *frame = table->insertFrame(1, 5, ffmt);
+
+ QVERIFY(frame->parentFrame() == table->rootFrame());
+
+ const int start = frame->firstPosition() - 1;
+ const int end = frame->lastPosition();
+ const int length = end - start + 1;
+
+ table->remove(start, length);
+}
+
+void tst_QTextPieceTable::removeWithChildFrame()
+{
+ /*
+ The piecetable layout is:
+
+ ...
+ 1 BeginningOfFrame(first frame)
+ 2 text
+ 3 BeginningOfFrame(second frame)
+ 4 text
+ 5 text
+ 6 EndOfFrame(second frame)
+ 7 text
+ 8 text
+ 9 EndOfFrame(first frame)
+ ...
+
+ The idea is to remove from [2] until [6], basically some trailing text and the second frame.
+ In this case frameAt(2) != frameAt(6), so the assertion in remove() needed an adjustement.
+ */
+ QTextFrameFormat ffmt;
+ table->insert(0, "Hello World", charFormatIndex);
+
+ QTextFrame *frame = table->insertFrame(1, 6, ffmt);
+ QTextFrame *childFrame = table->insertFrame(3, 5, ffmt);
+ Q_UNUSED(frame);
+ Q_UNUSED(childFrame);
+
+ // used to give a failing assertion
+ table->remove(2, 5);
+ QVERIFY(true);
+}
+
+void tst_QTextPieceTable::clearWithFrames()
+{
+ /*
+ The piecetable layout is:
+
+ ...
+ 1 BeginningOfFrame(first frame)
+ 2 text
+ 3 EndOfFrame(first frame)
+ 4 BeginningOfFrame(second frame)
+ 5 text
+ 6 text
+ 7 EndOfFrame(second frame)
+ ...
+
+ The idea is to remove from [1] until [7].
+ */
+ QTextFrameFormat ffmt;
+ table->insert(0, "Hello World", charFormatIndex);
+
+ QTextFrame *firstFrame = table->insertFrame(1, 2, ffmt);
+ QTextFrame *secondFrame = table->insertFrame(4, 6, ffmt);
+
+ const int start = firstFrame->firstPosition() - 1;
+ const int end = secondFrame->lastPosition();
+ const int length = end - start + 1;
+ // used to give a failing assertion
+ table->remove(start, length);
+ QVERIFY(true);
+}
+
+QTEST_MAIN(tst_QTextPieceTable)
+
+
+#include "tst_qtextpiecetable.moc"
+
diff --git a/tests/auto/gui/text/qtextscriptengine/.gitignore b/tests/auto/gui/text/qtextscriptengine/.gitignore
new file mode 100644
index 0000000000..e51a335099
--- /dev/null
+++ b/tests/auto/gui/text/qtextscriptengine/.gitignore
@@ -0,0 +1 @@
+tst_qtextscriptengine
diff --git a/tests/auto/gui/text/qtextscriptengine/generate/generate.pro b/tests/auto/gui/text/qtextscriptengine/generate/generate.pro
new file mode 100644
index 0000000000..354e0e5cdf
--- /dev/null
+++ b/tests/auto/gui/text/qtextscriptengine/generate/generate.pro
@@ -0,0 +1,14 @@
+######################################################################
+# Automatically generated by qmake (1.07a) Fri Sep 30 15:20:45 2005
+######################################################################
+
+TEMPLATE = app
+CONFIG -= moc
+INCLUDEPATH += . /usr/include/freetype2
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
+
+# Input
+SOURCES += main.cpp
+CONFIG += qt warn_on debug thread create_prl link_prl
+
+
diff --git a/tests/auto/gui/text/qtextscriptengine/generate/main.cpp b/tests/auto/gui/text/qtextscriptengine/generate/main.cpp
new file mode 100644
index 0000000000..06caa34b4d
--- /dev/null
+++ b/tests/auto/gui/text/qtextscriptengine/generate/main.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QApplication>
+#include <QTextEdit>
+#include <QLineEdit>
+#include <QVBoxLayout>
+#include <QFontDialog>
+#include <QPushButton>
+
+#define private public
+#include <qfont.h>
+#include <private/qtextengine_p.h>
+#include <private/qfontengine_p.h>
+#include <qtextlayout.h>
+#undef private
+
+
+class MyEdit : public QTextEdit {
+ Q_OBJECT
+public:
+ MyEdit(QWidget *p) : QTextEdit(p) { setReadOnly(true); }
+public slots:
+ void setText(const QString &str);
+ void changeFont();
+public:
+ QLineEdit *lineEdit;
+};
+
+void MyEdit::setText(const QString &str)
+{
+ if (str.isEmpty()) {
+ clear();
+ return;
+ }
+ QTextLayout layout(str, lineEdit->font());
+ QTextEngine *e = layout.d;
+ e->itemize();
+ e->shape(0);
+
+ QString result;
+ result = "Using font '" + e->fontEngine(e->layoutData->items[0])->fontDef.family + "'\n\n";
+
+ result += "{ { ";
+ for (int i = 0; i < str.length(); ++i)
+ result += "0x" + QString::number(str.at(i).unicode(), 16) + ", ";
+ result += "0x0 },\n { ";
+ for (int i = 0; i < e->layoutData->items[0].num_glyphs; ++i)
+ result += "0x" + QString::number(e->layoutData->glyphLayout.glyphs[i], 16) + ", ";
+ result += "0x0 } }";
+
+ setPlainText(result);
+}
+
+void MyEdit::changeFont()
+{
+ bool ok;
+ QFont f = QFontDialog::getFont(&ok, lineEdit->font(), topLevelWidget());
+ if (ok)
+ lineEdit->setFont(f);
+}
+
+int main(int argc, char **argv)
+{
+ QApplication a(argc, argv);
+
+ QWidget *mw = new QWidget(0);
+ QVBoxLayout *l = new QVBoxLayout(mw);
+
+ QLineEdit *le = new QLineEdit(mw);
+ l->addWidget(le);
+
+ MyEdit *view = new MyEdit(mw);
+ view->lineEdit = le;
+ l->addWidget(view);
+
+ QPushButton *button = new QPushButton("Change Font", mw);
+ l->addWidget(button);
+
+ QObject::connect(le, SIGNAL(textChanged(QString)), view, SLOT(setText(QString)));
+ QObject::connect(button, SIGNAL(clicked()), view, SLOT(changeFont()));
+
+ mw->resize(500, 300);
+ mw->show();
+
+ return a.exec();
+}
+
+
+#include <main.moc>
diff --git a/tests/auto/gui/text/qtextscriptengine/qtextscriptengine.pro b/tests/auto/gui/text/qtextscriptengine/qtextscriptengine.pro
new file mode 100644
index 0000000000..0f5076e2ed
--- /dev/null
+++ b/tests/auto/gui/text/qtextscriptengine/qtextscriptengine.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+QT += core-private gui-private
+
+HEADERS +=
+SOURCES += tst_qtextscriptengine.cpp
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
diff --git a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
new file mode 100644
index 0000000000..cbed675cb7
--- /dev/null
+++ b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
@@ -0,0 +1,1304 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+#ifdef Q_WS_X11
+#define private public
+#endif
+
+// cannot do private -> public on windows since it seems to mess up some stl headers
+#include <qfont.h>
+
+#ifdef Q_WS_X11
+#undef private
+#endif
+
+#include <QtTest/QtTest>
+
+
+
+#if defined(Q_WS_X11) || defined(Q_WS_MAC)
+#define private public
+#include <private/qtextengine_p.h>
+#include <qtextlayout.h>
+#undef private
+#else
+#include <private/qtextengine_p.h>
+#include <qtextlayout.h>
+#endif
+
+#include <qfontdatabase.h>
+#include <qfontinfo.h>
+
+
+
+
+
+//TESTED_CLASS=
+//TESTED_FILES= gui/text/qscriptengine.cpp
+
+class tst_QTextScriptEngine : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QTextScriptEngine();
+ virtual ~tst_QTextScriptEngine();
+
+
+public slots:
+ void initTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void devanagari();
+ void bengali();
+ void gurmukhi();
+ // gujarati missing
+ void oriya();
+ void tamil();
+ void telugu();
+ void kannada();
+ void malayalam();
+ void sinhala();
+ void greek();
+
+ void khmer();
+ void linearB();
+ void controlInSyllable_qtbug14204();
+ void combiningMarks_qtbug15675();
+
+ void mirroredChars_data();
+ void mirroredChars();
+
+private:
+ bool haveTestFonts;
+};
+
+tst_QTextScriptEngine::tst_QTextScriptEngine()
+ : haveTestFonts(qgetenv("QT_HAVE_TEST_FONTS") == QByteArray("1"))
+{
+}
+
+tst_QTextScriptEngine::~tst_QTextScriptEngine()
+{
+}
+
+void tst_QTextScriptEngine::initTestCase()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ qWarning(
+ "Some of these tests depend on the internals of some test fonts which are not freely "
+ "distributable.\n"
+ "These tests will be skipped.\n"
+ "If you have the fonts available, set QT_HAVE_TEST_FONTS=1 in your environment and "
+ "run the test again."
+ );
+ }
+#endif
+}
+
+void tst_QTextScriptEngine::init()
+{
+}
+
+void tst_QTextScriptEngine::cleanup()
+{
+}
+
+struct ShapeTable {
+ unsigned short unicode[16];
+ unsigned short glyphs[16];
+};
+
+#if defined(Q_WS_X11)
+static bool shaping( const QFont &f, const ShapeTable *s)
+{
+ QString str = QString::fromUtf16( s->unicode );
+ QTextLayout layout(str, f);
+ QTextEngine *e = layout.d;
+ e->itemize();
+ e->shape(0);
+
+ int nglyphs = 0;
+ const unsigned short *g = s->glyphs;
+ while ( *g ) {
+ nglyphs++;
+ g++;
+ }
+
+ if( nglyphs != e->layoutData->items[0].num_glyphs )
+ goto error;
+
+ for (int i = 0; i < nglyphs; ++i) {
+ if ((e->layoutData->glyphLayout.glyphs[i] & 0xffffff) != s->glyphs[i])
+ goto error;
+ }
+ return true;
+ error:
+ str = "";
+ const unsigned short *uc = s->unicode;
+ while (*uc) {
+ str += QString("%1 ").arg(*uc, 4, 16);
+ ++uc;
+ }
+ qDebug("%s: shaping of string %s failed, nglyphs=%d, expected %d",
+ f.family().toLatin1().constData(),
+ str.toLatin1().constData(),
+ e->layoutData->items[0].num_glyphs, nglyphs);
+
+ str = "";
+ int i = 0;
+ while (i < e->layoutData->items[0].num_glyphs) {
+ str += QString("%1 ").arg(e->layoutData->glyphLayout.glyphs[i], 4, 16);
+ ++i;
+ }
+ qDebug(" glyph result = %s", str.toLatin1().constData());
+ return false;
+}
+#endif
+
+void tst_QTextScriptEngine::devanagari()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Devanagari).contains("Raghindi")) {
+ QFont f("Raghindi");
+ const ShapeTable shape_table [] = {
+ // Ka
+ { { 0x0915, 0x0 },
+ { 0x0080, 0x0 } },
+ // Ka Halant
+ { { 0x0915, 0x094d, 0x0 },
+ { 0x0080, 0x0051, 0x0 } },
+ // Ka Halant Ka
+ { { 0x0915, 0x094d, 0x0915, 0x0 },
+ { 0x00c8, 0x0080, 0x0 } },
+ // Ka MatraI
+ { { 0x0915, 0x093f, 0x0 },
+ { 0x01d1, 0x0080, 0x0 } },
+ // Ra Halant Ka
+ { { 0x0930, 0x094d, 0x0915, 0x0 },
+ { 0x0080, 0x005b, 0x0 } },
+ // Ra Halant Ka MatraI
+ { { 0x0930, 0x094d, 0x0915, 0x093f, 0x0 },
+ { 0x01d1, 0x0080, 0x005b, 0x0 } },
+ // MatraI
+ { { 0x093f, 0x0 },
+ { 0x01d4, 0x029c, 0x0 } },
+ // Ka Nukta
+ { { 0x0915, 0x093c, 0x0 },
+ { 0x00a4, 0x0 } },
+ // Ka Halant Ra
+ { { 0x0915, 0x094d, 0x0930, 0x0 },
+ { 0x0110, 0x0 } },
+ // Ka Halant Ra Halant Ka
+ { { 0x0915, 0x094d, 0x0930, 0x094d, 0x0915, 0x0 },
+ { 0x0158, 0x0080, 0x0 } },
+ { { 0x0930, 0x094d, 0x200d, 0x0 },
+ { 0x00e2, 0x0 } },
+ { { 0x0915, 0x094d, 0x0930, 0x094d, 0x200d, 0x0 },
+ { 0x0158, 0x0 } },
+
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Raghindi", SkipAll);
+ }
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Devanagari).contains("Mangal")) {
+ QFont f("Mangal");
+ const ShapeTable shape_table [] = {
+ // Ka
+ { { 0x0915, 0x0 },
+ { 0x0080, 0x0 } },
+ // Ka Halant
+ { { 0x0915, 0x094d, 0x0 },
+ { 0x0080, 0x0051, 0x0 } },
+ // Ka Halant Ka
+ { { 0x0915, 0x094d, 0x0915, 0x0 },
+ { 0x00c8, 0x0080, 0x0 } },
+ // Ka MatraI
+ { { 0x0915, 0x093f, 0x0 },
+ { 0x01d1, 0x0080, 0x0 } },
+ // Ra Halant Ka
+ { { 0x0930, 0x094d, 0x0915, 0x0 },
+ { 0x0080, 0x005b, 0x0 } },
+ // Ra Halant Ka MatraI
+ { { 0x0930, 0x094d, 0x0915, 0x093f, 0x0 },
+ { 0x01d1, 0x0080, 0x005b, 0x0 } },
+ // MatraI
+ { { 0x093f, 0x0 },
+ { 0x01d4, 0x029c, 0x0 } },
+ // Ka Nukta
+ { { 0x0915, 0x093c, 0x0 },
+ { 0x00a4, 0x0 } },
+ // Ka Halant Ra
+ { { 0x0915, 0x094d, 0x0930, 0x0 },
+ { 0x0110, 0x0 } },
+ // Ka Halant Ra Halant Ka
+ { { 0x0915, 0x094d, 0x0930, 0x094d, 0x0915, 0x0 },
+ { 0x0158, 0x0080, 0x0 } },
+
+ { { 0x92b, 0x94d, 0x930, 0x0 },
+ { 0x125, 0x0 } },
+ { { 0x92b, 0x93c, 0x94d, 0x930, 0x0 },
+ { 0x149, 0x0 } },
+ { {0}, {0} }
+ };
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find mangal", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+void tst_QTextScriptEngine::bengali()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Bengali).contains("Akaash")) {
+ QFont f("Akaash");
+ const ShapeTable shape_table [] = {
+ // Ka
+ { { 0x0995, 0x0 },
+ { 0x0151, 0x0 } },
+ // Ka Halant
+ { { 0x0995, 0x09cd, 0x0 },
+ { 0x0151, 0x017d, 0x0 } },
+ // Ka Halant Ka
+ { { 0x0995, 0x09cd, 0x0995, 0x0 },
+ { 0x019b, 0x0 } },
+ // Ka MatraI
+ { { 0x0995, 0x09bf, 0x0 },
+ { 0x0173, 0x0151, 0x0 } },
+ // Ra Halant Ka
+ { { 0x09b0, 0x09cd, 0x0995, 0x0 },
+ { 0x0151, 0x0276, 0x0 } },
+ // Ra Halant Ka MatraI
+ { { 0x09b0, 0x09cd, 0x0995, 0x09bf, 0x0 },
+ { 0x0173, 0x0151, 0x0276, 0x0 } },
+ // Ka Nukta
+ { { 0x0995, 0x09bc, 0x0 },
+ { 0x0151, 0x0171, 0x0 } },
+ // Ka Halant Ra
+ { { 0x0995, 0x09cd, 0x09b0, 0x0 },
+ { 0x01f4, 0x0 } },
+ // Ka Halant Ra Halant Ka
+ { { 0x0995, 0x09cd, 0x09b0, 0x09cd, 0x0995, 0x0 },
+ { 0x025c, 0x0276, 0x0151, 0x0 } },
+ // Ya + Halant
+ { { 0x09af, 0x09cd, 0x0 },
+ { 0x016a, 0x017d, 0x0 } },
+ // Da Halant Ya -> Da Ya-Phala
+ { { 0x09a6, 0x09cd, 0x09af, 0x0 },
+ { 0x01e5, 0x0 } },
+ // A Halant Ya -> A Ya-phala
+ { { 0x0985, 0x09cd, 0x09af, 0x0 },
+ { 0x0145, 0x01cf, 0x0 } },
+ // Na Halant Ka
+ { { 0x09a8, 0x09cd, 0x0995, 0x0 },
+ { 0x026f, 0x0151, 0x0 } },
+ // Na Halant ZWNJ Ka
+ { { 0x09a8, 0x09cd, 0x200c, 0x0995, 0x0 },
+ { 0x0164, 0x017d, 0x0151, 0x0 } },
+ // Na Halant ZWJ Ka
+ { { 0x09a8, 0x09cd, 0x200d, 0x0995, 0x0 },
+ { 0x026f, 0x0151, 0x0 } },
+ // Ka Halant ZWNJ Ka
+ { { 0x0995, 0x09cd, 0x200c, 0x0995, 0x0 },
+ { 0x0151, 0x017d, 0x0151, 0x0 } },
+ // Ka Halant ZWJ Ka
+ { { 0x0995, 0x09cd, 0x200d, 0x0995, 0x0 },
+ { 0x025c, 0x0151, 0x0 } },
+ // Na Halant Ra
+ { { 0x09a8, 0x09cd, 0x09b0, 0x0 },
+ { 0x0207, 0x0 } },
+ // Na Halant ZWNJ Ra
+ { { 0x09a8, 0x09cd, 0x200c, 0x09b0, 0x0 },
+ { 0x0164, 0x017d, 0x016b, 0x0 } },
+ // Na Halant ZWJ Ra
+ { { 0x09a8, 0x09cd, 0x200d, 0x09b0, 0x0 },
+ { 0x026f, 0x016b, 0x0 } },
+ // Na Halant Ba
+ { { 0x09a8, 0x09cd, 0x09ac, 0x0 },
+ { 0x022f, 0x0 } },
+ // Na Halant ZWNJ Ba
+ { { 0x09a8, 0x09cd, 0x200c, 0x09ac, 0x0 },
+ { 0x0164, 0x017d, 0x0167, 0x0 } },
+ // Na Halant ZWJ Ba
+ { { 0x09a8, 0x09cd, 0x200d, 0x09ac, 0x0 },
+ { 0x026f, 0x0167, 0x0 } },
+ // Na Halant Dha
+ { { 0x09a8, 0x09cd, 0x09a7, 0x0 },
+ { 0x01d3, 0x0 } },
+ // Na Halant ZWNJ Dha
+ { { 0x09a8, 0x09cd, 0x200c, 0x09a7, 0x0 },
+ { 0x0164, 0x017d, 0x0163, 0x0 } },
+ // Na Halant ZWJ Dha
+ { { 0x09a8, 0x09cd, 0x200d, 0x09a7, 0x0 },
+ { 0x026f, 0x0163, 0x0 } },
+ // Ra Halant Ka MatraAU
+ { { 0x09b0, 0x09cd, 0x0995, 0x09cc, 0x0 },
+ { 0x0179, 0x0151, 0x0276, 0x017e, 0x0 } },
+ // Ra Halant Ba Halant Ba
+ { { 0x09b0, 0x09cd, 0x09ac, 0x09cd, 0x09ac, 0x0 },
+ { 0x0232, 0x0276, 0x0 } },
+ { { 0x9b0, 0x9cd, 0x995, 0x9be, 0x982, 0x0 },
+ { 0x151, 0x276, 0x172, 0x143, 0x0 } },
+ { { 0x9b0, 0x9cd, 0x995, 0x9be, 0x983, 0x0 },
+ { 0x151, 0x276, 0x172, 0x144, 0x0 } },
+ // test decomposed two parts matras
+ { { 0x995, 0x9c7, 0x9be, 0x0 },
+ { 0x179, 0x151, 0x172, 0x0 } },
+ { { 0x995, 0x9c7, 0x9d7, 0x0 },
+ { 0x179, 0x151, 0x17e, 0x0 } },
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Akaash", SkipAll);
+ }
+ }
+ {
+ if (QFontDatabase().families(QFontDatabase::Bengali).contains("Mukti Narrow")) {
+ QFont f("Mukti Narrow");
+ const ShapeTable shape_table [] = {
+ // Ka
+ { { 0x0995, 0x0 },
+ { 0x0073, 0x0 } },
+ // Ka Halant
+ { { 0x0995, 0x09cd, 0x0 },
+ { 0x00b9, 0x0 } },
+ // Ka Halant Ka
+ { { 0x0995, 0x09cd, 0x0995, 0x0 },
+ { 0x0109, 0x0 } },
+ // Ka MatraI
+ { { 0x0995, 0x09bf, 0x0 },
+ { 0x0095, 0x0073, 0x0 } },
+ // Ra Halant Ka
+ { { 0x09b0, 0x09cd, 0x0995, 0x0 },
+ { 0x0073, 0x00e1, 0x0 } },
+ // Ra Halant Ka MatraI
+ { { 0x09b0, 0x09cd, 0x0995, 0x09bf, 0x0 },
+ { 0x0095, 0x0073, 0x00e1, 0x0 } },
+ // MatraI
+ { { 0x09bf, 0x0 },
+ { 0x0095, 0x01c8, 0x0 } },
+ // Ka Nukta
+ { { 0x0995, 0x09bc, 0x0 },
+ { 0x0073, 0x0093, 0x0 } },
+ // Ka Halant Ra
+ { { 0x0995, 0x09cd, 0x09b0, 0x0 },
+ { 0x00e5, 0x0 } },
+ // Ka Halant Ra Halant Ka
+ { { 0x995, 0x9cd, 0x9b0, 0x9cd, 0x995, 0x0 },
+ { 0x234, 0x24e, 0x73, 0x0 } },
+ // Ya + Halant
+ { { 0x09af, 0x09cd, 0x0 },
+ { 0x00d2, 0x0 } },
+ // Da Halant Ya -> Da Ya-Phala
+ { { 0x09a6, 0x09cd, 0x09af, 0x0 },
+ { 0x0084, 0x00e2, 0x0 } },
+ // A Halant Ya -> A Ya-phala
+ { { 0x0985, 0x09cd, 0x09af, 0x0 },
+ { 0x0067, 0x00e2, 0x0 } },
+ // Na Halant Ka
+ { { 0x09a8, 0x09cd, 0x0995, 0x0 },
+ { 0x0188, 0x0 } },
+ // Na Halant ZWNJ Ka
+ { { 0x9a8, 0x9cd, 0x200c, 0x995, 0x0 },
+ { 0xcc, 0x73, 0x0 } },
+ // Na Halant ZWJ Ka
+ { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 },
+ { 0x247, 0x73, 0x0 } },
+ // Ka Halant ZWNJ Ka
+ { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 },
+ { 0x247, 0x73, 0x0 } },
+ // Ka Halant ZWJ Ka
+ { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 },
+ { 0x247, 0x73, 0x0 } },
+ // Na Halant Ra
+ { { 0x09a8, 0x09cd, 0x09b0, 0x0 },
+ { 0x00f8, 0x0 } },
+ // Na Halant ZWNJ Ra
+ { { 0x09a8, 0x09cd, 0x200c, 0x09b0, 0x0 },
+ { 0xcc, 0x8d, 0x0 } },
+ // Na Halant ZWJ Ra
+ { { 0x9a8, 0x9cd, 0x200d, 0x9b0, 0x0 },
+ { 0x247, 0x8d, 0x0 } },
+ // Na Halant Ba
+ { { 0x09a8, 0x09cd, 0x09ac, 0x0 },
+ { 0x0139, 0x0 } },
+ // Na Halant ZWNJ Ba
+ { { 0x9a8, 0x9cd, 0x200c, 0x9ac, 0x0 },
+ { 0xcc, 0x89, 0x0 } },
+ // Na Halant ZWJ Ba
+ { { 0x9a8, 0x9cd, 0x200d, 0x9ac, 0x0 },
+ { 0x247, 0x89, 0x0 } },
+ // Na Halant Dha
+ { { 0x09a8, 0x09cd, 0x09a7, 0x0 },
+ { 0x0145, 0x0 } },
+ // Na Halant ZWNJ Dha
+ { { 0x09a8, 0x09cd, 0x200c, 0x09a7, 0x0 },
+ { 0xcc, 0x85, 0x0 } },
+ // Na Halant ZWJ Dha
+ { { 0x09a8, 0x09cd, 0x200d, 0x09a7, 0x0 },
+ { 0x247, 0x85, 0x0 } },
+ // Ra Halant Ka MatraAU
+ { { 0x9b0, 0x9cd, 0x995, 0x9cc, 0x0 },
+ { 0x232, 0x73, 0xe1, 0xa0, 0x0 } },
+ // Ra Halant Ba Halant Ba
+ { { 0x09b0, 0x09cd, 0x09ac, 0x09cd, 0x09ac, 0x0 },
+ { 0x013b, 0x00e1, 0x0 } },
+
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Mukti", SkipAll);
+ }
+ }
+ {
+ if (QFontDatabase().families(QFontDatabase::Bengali).contains("Likhan")) {
+ QFont f("Likhan");
+ const ShapeTable shape_table [] = {
+ { { 0x9a8, 0x9cd, 0x9af, 0x0 },
+ { 0x1ca, 0x0 } },
+ { { 0x09b8, 0x09cd, 0x09af, 0x0 },
+ { 0x020e, 0x0 } },
+ { { 0x09b6, 0x09cd, 0x09af, 0x0 },
+ { 0x01f4, 0x0 } },
+ { { 0x09b7, 0x09cd, 0x09af, 0x0 },
+ { 0x01fe, 0x0 } },
+ { { 0x09b0, 0x09cd, 0x09a8, 0x09cd, 0x200d, 0x0 },
+ { 0x10b, 0x167, 0x0 } },
+
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Likhan", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+void tst_QTextScriptEngine::gurmukhi()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Gurmukhi).contains("Lohit Punjabi")) {
+ QFont f("Lohit Punjabi");
+ const ShapeTable shape_table [] = {
+ { { 0xA15, 0xA4D, 0xa39, 0x0 },
+ { 0x3b, 0x8b, 0x0 } },
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Lohit Punjabi", SkipAll);
+ }
+ }
+#endif
+}
+
+void tst_QTextScriptEngine::oriya()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Oriya).contains("utkal")) {
+ QFont f("utkal");
+ const ShapeTable shape_table [] = {
+ { { 0xb15, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 },
+ { 0x150, 0x125, 0x0 } },
+ { { 0xb24, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 },
+ { 0x151, 0x120, 0x0 } },
+ { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 },
+ { 0x152, 0x120, 0x0 } },
+ { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 },
+ { 0x152, 0x120, 0x0 } },
+ { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 },
+ { 0x176, 0x0 } },
+ { { 0xb38, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 },
+ { 0x177, 0x0 } },
+ { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb30, 0xb4d, 0xb2f, 0x0 },
+ { 0x176, 0x124, 0x0 } },
+ { {0}, {0} }
+
+ };
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find utkal", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+
+void tst_QTextScriptEngine::tamil()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Tamil).contains("AkrutiTml1")) {
+ QFont f("AkrutiTml1");
+ const ShapeTable shape_table [] = {
+ { { 0x0b95, 0x0bc2, 0x0 },
+ { 0x004e, 0x0 } },
+ { { 0x0bae, 0x0bc2, 0x0 },
+ { 0x009e, 0x0 } },
+ { { 0x0b9a, 0x0bc2, 0x0 },
+ { 0x0058, 0x0 } },
+ { { 0x0b99, 0x0bc2, 0x0 },
+ { 0x0053, 0x0 } },
+ { { 0x0bb0, 0x0bc2, 0x0 },
+ { 0x00a8, 0x0 } },
+ { { 0x0ba4, 0x0bc2, 0x0 },
+ { 0x008e, 0x0 } },
+ { { 0x0b9f, 0x0bc2, 0x0 },
+ { 0x0062, 0x0 } },
+ { { 0x0b95, 0x0bc6, 0x0 },
+ { 0x000a, 0x0031, 0x0 } },
+ { { 0x0b95, 0x0bca, 0x0 },
+ { 0x000a, 0x0031, 0x0007, 0x0 } },
+ { { 0x0b95, 0x0bc6, 0x0bbe, 0x0 },
+ { 0x000a, 0x0031, 0x007, 0x0 } },
+ { { 0x0b95, 0x0bcd, 0x0bb7, 0x0 },
+ { 0x0049, 0x0 } },
+ { { 0x0b95, 0x0bcd, 0x0bb7, 0x0bca, 0x0 },
+ { 0x000a, 0x0049, 0x007, 0x0 } },
+ { { 0x0b95, 0x0bcd, 0x0bb7, 0x0bc6, 0x0bbe, 0x0 },
+ { 0x000a, 0x0049, 0x007, 0x0 } },
+ { { 0x0b9f, 0x0bbf, 0x0 },
+ { 0x005f, 0x0 } },
+ { { 0x0b9f, 0x0bc0, 0x0 },
+ { 0x0060, 0x0 } },
+ { { 0x0bb2, 0x0bc0, 0x0 },
+ { 0x00ab, 0x0 } },
+ { { 0x0bb2, 0x0bbf, 0x0 },
+ { 0x00aa, 0x0 } },
+ { { 0x0bb0, 0x0bcd, 0x0 },
+ { 0x00a4, 0x0 } },
+ { { 0x0bb0, 0x0bbf, 0x0 },
+ { 0x00a5, 0x0 } },
+ { { 0x0bb0, 0x0bc0, 0x0 },
+ { 0x00a6, 0x0 } },
+ { { 0x0b83, 0x0 },
+ { 0x0025, 0x0 } },
+ { { 0x0b83, 0x0b95, 0x0 },
+ { 0x0025, 0x0031, 0x0 } },
+ { { 0xb95, 0xbc6, 0xbbe, 0x0 },
+ { 0xa, 0x31, 0x7, 0x0 } },
+ { { 0xb95, 0xbc7, 0xbbe, 0x0 },
+ { 0xb, 0x31, 0x7, 0x0 } },
+ { { 0xb95, 0xbc6, 0xbd7, 0x0 },
+ { 0xa, 0x31, 0x40, 0x0 } },
+
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find AkrutiTml1", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+
+void tst_QTextScriptEngine::telugu()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Telugu).contains("Pothana2000")) {
+ QFont f("Pothana2000");
+ const ShapeTable shape_table [] = {
+ { { 0xc15, 0xc4d, 0x0 },
+ { 0xbb, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc37, 0x0 },
+ { 0x4b, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc37, 0xc4d, 0x0 },
+ { 0xe0, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc37, 0xc4d, 0xc23, 0x0 },
+ { 0x4b, 0x91, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc30, 0x0 },
+ { 0x5a, 0xb2, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc30, 0xc4d, 0x0 },
+ { 0xbb, 0xb2, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc30, 0xc4d, 0xc15, 0x0 },
+ { 0x5a, 0xb2, 0x83, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc30, 0xc3f, 0x0 },
+ { 0xe2, 0xb2, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc15, 0xc48, 0x0 },
+ { 0xe6, 0xb3, 0x83, 0x0 } },
+ { { 0xc15, 0xc4d, 0xc30, 0xc48, 0x0 },
+ { 0xe6, 0xb3, 0x9f, 0x0 } },
+ { { 0xc15, 0xc46, 0xc56, 0x0 },
+ { 0xe6, 0xb3, 0x0 } },
+ { {0}, {0} }
+
+ };
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Pothana2000", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+
+void tst_QTextScriptEngine::kannada()
+{
+#if defined(Q_WS_X11)
+ {
+ if (QFontDatabase().families(QFontDatabase::Kannada).contains("Sampige")) {
+ QFont f("Sampige");
+ const ShapeTable shape_table [] = {
+ { { 0x0ca8, 0x0ccd, 0x0ca8, 0x0 },
+ { 0x0049, 0x00ba, 0x0 } },
+ { { 0x0ca8, 0x0ccd, 0x0ca1, 0x0 },
+ { 0x0049, 0x00b3, 0x0 } },
+ { { 0x0caf, 0x0cc2, 0x0 },
+ { 0x004f, 0x005d, 0x0 } },
+ { { 0x0ce0, 0x0 },
+ { 0x006a, 0x0 } },
+ { { 0x0ce6, 0x0ce7, 0x0ce8, 0x0 },
+ { 0x006b, 0x006c, 0x006d, 0x0 } },
+ { { 0x0cb5, 0x0ccb, 0x0 },
+ { 0x015f, 0x0067, 0x0 } },
+ { { 0x0cb0, 0x0ccd, 0x0cae, 0x0 },
+ { 0x004e, 0x0082, 0x0 } },
+ { { 0x0cb0, 0x0ccd, 0x0c95, 0x0 },
+ { 0x0036, 0x0082, 0x0 } },
+ { { 0x0c95, 0x0ccd, 0x0cb0, 0x0 },
+ { 0x0036, 0x00c1, 0x0 } },
+ { { 0x0cb0, 0x0ccd, 0x200d, 0x0c95, 0x0 },
+ { 0x0050, 0x00a7, 0x0 } },
+
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Sampige", SkipAll);
+ }
+ }
+ {
+ if (QFontDatabase().families(QFontDatabase::Kannada).contains("Tunga")) {
+ QFont f("Tunga");
+ const ShapeTable shape_table [] = {
+ { { 0x0cb7, 0x0cc6, 0x0 },
+ { 0x00b0, 0x006c, 0x0 } },
+ { { 0x0cb7, 0x0ccd, 0x0 },
+ { 0x0163, 0x0 } },
+ { { 0xc95, 0xcbf, 0xcd5, 0x0 },
+ { 0x114, 0x73, 0x0 } },
+ { { 0xc95, 0xcc6, 0xcd5, 0x0 },
+ { 0x90, 0x6c, 0x73, 0x0 } },
+ { { 0xc95, 0xcc6, 0xcd6, 0x0 },
+ { 0x90, 0x6c, 0x74, 0x0 } },
+ { { 0xc95, 0xcc6, 0xcc2, 0x0 },
+ { 0x90, 0x6c, 0x69, 0x0 } },
+ { { 0xc95, 0xcca, 0xcd5, 0x0 },
+ { 0x90, 0x6c, 0x69, 0x73, 0x0 } },
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Tunga", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+
+
+void tst_QTextScriptEngine::malayalam()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Malayalam).contains("AkrutiMal2")) {
+ QFont f("AkrutiMal2");
+ const ShapeTable shape_table [] = {
+ { { 0x0d15, 0x0d46, 0x0 },
+ { 0x005e, 0x0034, 0x0 } },
+ { { 0x0d15, 0x0d47, 0x0 },
+ { 0x005f, 0x0034, 0x0 } },
+ { { 0x0d15, 0x0d4b, 0x0 },
+ { 0x005f, 0x0034, 0x0058, 0x0 } },
+ { { 0x0d15, 0x0d48, 0x0 },
+ { 0x0060, 0x0034, 0x0 } },
+ { { 0x0d15, 0x0d4a, 0x0 },
+ { 0x005e, 0x0034, 0x0058, 0x0 } },
+ { { 0x0d30, 0x0d4d, 0x0d15, 0x0 },
+ { 0x009e, 0x0034, 0x0 } },
+ { { 0x0d15, 0x0d4d, 0x0d35, 0x0 },
+ { 0x0034, 0x007a, 0x0 } },
+ { { 0x0d15, 0x0d4d, 0x0d2f, 0x0 },
+ { 0x0034, 0x00a2, 0x0 } },
+ { { 0x0d1f, 0x0d4d, 0x0d1f, 0x0 },
+ { 0x0069, 0x0 } },
+ { { 0x0d26, 0x0d4d, 0x0d26, 0x0 },
+ { 0x0074, 0x0 } },
+ { { 0x0d30, 0x0d4d, 0x0 },
+ { 0x009e, 0x0 } },
+ { { 0x0d30, 0x0d4d, 0x200c, 0x0 },
+ { 0x009e, 0x0 } },
+ { { 0x0d30, 0x0d4d, 0x200d, 0x0 },
+ { 0x009e, 0x0 } },
+ { { 0xd15, 0xd46, 0xd3e, 0x0 },
+ { 0x5e, 0x34, 0x58, 0x0 } },
+ { { 0xd15, 0xd47, 0xd3e, 0x0 },
+ { 0x5f, 0x34, 0x58, 0x0 } },
+ { { 0xd15, 0xd46, 0xd57, 0x0 },
+ { 0x5e, 0x34, 0x65, 0x0 } },
+ { { 0xd15, 0xd57, 0x0 },
+ { 0x34, 0x65, 0x0 } },
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find AkrutiMal2", SkipAll);
+ }
+ }
+ {
+ if (QFontDatabase().families(QFontDatabase::Malayalam).contains("Rachana")) {
+ QFont f("Rachana");
+ const ShapeTable shape_table [] = {
+ { { 0xd37, 0xd4d, 0xd1f, 0xd4d, 0xd30, 0xd40, 0x0 },
+ { 0x385, 0xa3, 0x0 } },
+ { { 0xd2f, 0xd4d, 0xd15, 0xd4d, 0xd15, 0xd41, 0x0 },
+ { 0x2ff, 0x0 } },
+ { { 0xd33, 0xd4d, 0xd33, 0x0 },
+ { 0x3f8, 0x0 } },
+ { { 0xd2f, 0xd4d, 0xd15, 0xd4d, 0xd15, 0xd41, 0x0 },
+ { 0x2ff, 0x0 } },
+ { { 0xd30, 0xd4d, 0x200d, 0xd35, 0xd4d, 0xd35, 0x0 },
+ { 0xf3, 0x350, 0x0 } },
+
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Rachana", SkipAll);
+ }
+ }
+
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+void tst_QTextScriptEngine::sinhala()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Sinhala).contains("Malithi Web")) {
+ QFont f("Malithi Web");
+ const ShapeTable shape_table [] = {
+ { { 0xd9a, 0xdd9, 0xdcf, 0x0 },
+ { 0x4a, 0x61, 0x42, 0x0 } },
+ { { 0xd9a, 0xdd9, 0xddf, 0x0 },
+ { 0x4a, 0x61, 0x50, 0x0 } },
+ { { 0xd9a, 0xdd9, 0xdca, 0x0 },
+ { 0x4a, 0x62, 0x0 } },
+ { { 0xd9a, 0xddc, 0xdca, 0x0 },
+ { 0x4a, 0x61, 0x42, 0x41, 0x0 } },
+ { { 0xd9a, 0xdda, 0x0 },
+ { 0x4a, 0x62, 0x0 } },
+ { { 0xd9a, 0xddd, 0x0 },
+ { 0x4a, 0x61, 0x42, 0x41, 0x0 } },
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Malithi Web", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+
+void tst_QTextScriptEngine::khmer()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Khmer).contains("Khmer OS")) {
+ QFont f("Khmer OS");
+ const ShapeTable shape_table [] = {
+ { { 0x179a, 0x17cd, 0x0 },
+ { 0x24c, 0x27f, 0x0 } },
+ { { 0x179f, 0x17c5, 0x0 },
+ { 0x273, 0x203, 0x0 } },
+ { { 0x1790, 0x17d2, 0x1784, 0x17c3, 0x0 },
+ { 0x275, 0x242, 0x182, 0x0 } },
+ { { 0x179a, 0x0 },
+ { 0x24c, 0x0 } },
+ { { 0x1781, 0x17d2, 0x1798, 0x17c2, 0x0 },
+ { 0x274, 0x233, 0x197, 0x0 } },
+ { { 0x1798, 0x17b6, 0x0 },
+ { 0x1cb, 0x0 } },
+ { { 0x179a, 0x17b8, 0x0 },
+ { 0x24c, 0x26a, 0x0 } },
+ { { 0x1787, 0x17b6, 0x0 },
+ { 0x1ba, 0x0 } },
+ { { 0x1798, 0x17d2, 0x1796, 0x17bb, 0x0 },
+ { 0x24a, 0x195, 0x26d, 0x0 } },
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Khmer OS", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+void tst_QTextScriptEngine::linearB()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Any).contains("Penuturesu")) {
+ QFont f("Penuturesu");
+ const ShapeTable shape_table [] = {
+ { { 0xd800, 0xdc01, 0xd800, 0xdc02, 0xd800, 0xdc03, 0 },
+ { 0x5, 0x6, 0x7, 0 } },
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find Penuturesu", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+#if defined(Q_WS_X11)
+static bool decomposedShaping( const QFont &f, const QChar &ch)
+{
+ QString str = QString().append(ch);
+ QTextLayout layout(str, f);
+ QTextEngine *e = layout.d;
+ e->itemize();
+ e->shape(0);
+
+ QTextLayout decomposed(str.normalized(QString::NormalizationForm_D), f);
+ QTextEngine *de = decomposed.d;
+ de->itemize();
+ de->shape(0);
+
+ if( e->layoutData->items[0].num_glyphs != de->layoutData->items[0].num_glyphs )
+ goto error;
+
+ for (int i = 0; i < e->layoutData->items[0].num_glyphs; ++i) {
+ if ((e->layoutData->glyphLayout.glyphs[i] & 0xffffff) != (de->layoutData->glyphLayout.glyphs[i] & 0xffffff))
+ goto error;
+ }
+ return true;
+ error:
+ qDebug("%s: decomposedShaping of char %4x failed, nglyphs=%d, decomposed nglyphs %d",
+ f.family().toLatin1().constData(),
+ ch.unicode(),
+ e->layoutData->items[0].num_glyphs,
+ de->layoutData->items[0].num_glyphs);
+
+ str = "";
+ int i = 0;
+ while (i < e->layoutData->items[0].num_glyphs) {
+ str += QString("%1 ").arg(e->layoutData->glyphLayout.glyphs[i], 4, 16);
+ ++i;
+ }
+ qDebug(" composed glyph result = %s", str.toLatin1().constData());
+ str = "";
+ i = 0;
+ while (i < de->layoutData->items[0].num_glyphs) {
+ str += QString("%1 ").arg(de->layoutData->glyphLayout.glyphs[i], 4, 16);
+ ++i;
+ }
+ qDebug(" decomposed glyph result = %s", str.toLatin1().constData());
+ return false;
+}
+#endif
+
+
+void tst_QTextScriptEngine::greek()
+{
+#if defined(Q_WS_X11)
+ if (!haveTestFonts) {
+ QSKIP("Test fonts are not available", SkipAll);
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Any).contains("DejaVu Sans")) {
+ QFont f("DejaVu Sans");
+ for (int uc = 0x1f00; uc <= 0x1fff; ++uc) {
+ QString str;
+ str.append(uc);
+ if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) {
+ //qDebug() << "skipping" << hex << uc;
+ continue;
+ }
+ if (uc == 0x1fc1 || uc == 0x1fed)
+ continue;
+ QVERIFY( decomposedShaping(f, QChar(uc)) );
+ }
+ } else {
+ QSKIP("couldn't find DejaVu Sans", SkipAll);
+ }
+ }
+
+ {
+ if (QFontDatabase().families(QFontDatabase::Any).contains("SBL Greek")) {
+ QFont f("SBL Greek");
+ for (int uc = 0x1f00; uc <= 0x1fff; ++uc) {
+ QString str;
+ str.append(uc);
+ if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) {
+ //qDebug() << "skipping" << hex << uc;
+ continue;
+ }
+ if (uc == 0x1fc1 || uc == 0x1fed)
+ continue;
+ QVERIFY( decomposedShaping(f, QChar(uc) ) );
+
+ }
+
+ const ShapeTable shape_table [] = {
+ { { 0x3b1, 0x300, 0x313, 0x0 },
+ { 0xb8, 0x3d3, 0x3c7, 0x0 } },
+ { { 0x3b1, 0x313, 0x300, 0x0 },
+ { 0xd4, 0x0 } },
+
+ { {0}, {0} }
+ };
+
+
+ const ShapeTable *s = shape_table;
+ while (s->unicode[0]) {
+ QVERIFY( shaping(f, s) );
+ ++s;
+ }
+ } else {
+ QSKIP("couldn't find SBL_grk", SkipAll);
+ }
+ }
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+void tst_QTextScriptEngine::controlInSyllable_qtbug14204()
+{
+#if defined(Q_WS_X11)
+ QString s;
+ s.append(QChar(0x0915));
+ s.append(QChar(0x094d));
+ s.append(QChar(0x200d));
+ s.append(QChar(0x0915));
+
+ QTextLayout layout(s);
+ QTextEngine *e = layout.d;
+ e->itemize();
+ e->shape(0);
+
+ QVERIFY(e->layoutData->items[0].num_glyphs == 2);
+ QVERIFY(e->layoutData->glyphLayout.advances_x[1] != 0);
+#else
+ QSKIP("X11 specific test", SkipAll);
+#endif
+}
+
+void tst_QTextScriptEngine::combiningMarks_qtbug15675()
+{
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ QString s;
+ s.append(QChar(0x0061));
+ s.append(QChar(0x0062));
+ s.append(QChar(0x0300));
+ s.append(QChar(0x0063));
+
+ QFont font("Monaco");
+ QTextLayout layout(s, font);
+ QTextEngine *e = layout.d;
+ e->itemize();
+ e->shape(0);
+
+ QVERIFY(e->layoutData->items[0].num_glyphs == 4);
+ QVERIFY(e->layoutData->glyphLayout.advances_y[2] > 0);
+#elif defined(Q_WS_X11)
+ QFontDatabase db;
+
+ if (!db.families().contains("DejaVu Sans Mono")) {
+ QSKIP("Required font (DejaVu Sans Mono) doesn't exist, skip test.", SkipAll);
+ return;
+ }
+
+ QString s;
+ s.append(QChar(0x0062));
+ s.append(QChar(0x0332));
+ s.append(QChar(0x0063));
+
+ QTextLayout layout(s, QFont("DejaVu Sans Mono"));
+ QTextEngine *e = layout.d;
+ e->itemize();
+ e->shape(0);
+
+ QVERIFY(e->layoutData->items[0].num_glyphs == 3);
+ QVERIFY(e->layoutData->glyphLayout.advances_x[1] == 0);
+#else
+ QSKIP("X11/Mac specific test", SkipAll);
+#endif
+}
+
+void tst_QTextScriptEngine::mirroredChars_data()
+{
+ QTest::addColumn<int>("hintingPreference");
+
+ QTest::newRow("Default hinting") << int(QFont::PreferDefaultHinting);
+ QTest::newRow("No hinting") << int(QFont::PreferNoHinting);
+ QTest::newRow("Vertical hinting") << int(QFont::PreferVerticalHinting);
+ QTest::newRow("Full hinting") << int(QFont::PreferFullHinting);
+}
+
+void tst_QTextScriptEngine::mirroredChars()
+{
+#if defined(Q_WS_MAC)
+ QSKIP("Not supported on Mac", SkipAll);
+#endif
+ QFETCH(int, hintingPreference);
+
+ QFont font;
+ font.setHintingPreference(QFont::HintingPreference(hintingPreference));
+
+ QString s;
+ s.append(QLatin1Char('('));
+ s.append(QLatin1Char(')'));
+
+ HB_Glyph leftParenthesis;
+ HB_Glyph rightParenthesis;
+ {
+ QTextLayout layout(s);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QTextEngine *e = layout.engine();
+ e->itemize();
+ e->shape(0);
+ QCOMPARE(e->layoutData->items[0].num_glyphs, ushort(2));
+
+ const QGlyphLayout &glyphLayout = e->layoutData->glyphLayout;
+ leftParenthesis = glyphLayout.glyphs[0];
+ rightParenthesis = glyphLayout.glyphs[1];
+ }
+
+ {
+ QTextLayout layout(s);
+ layout.setFlags(Qt::TextForceRightToLeft);
+
+ QTextEngine *e = layout.engine();
+ e->itemize();
+ e->shape(0);
+ QCOMPARE(e->layoutData->items[0].num_glyphs, ushort(2));
+
+ const QGlyphLayout &glyphLayout = e->layoutData->glyphLayout;
+ QCOMPARE(glyphLayout.glyphs[0], rightParenthesis);
+ QCOMPARE(glyphLayout.glyphs[1], leftParenthesis);
+ }
+}
+
+QTEST_MAIN(tst_QTextScriptEngine)
+#include "tst_qtextscriptengine.moc"
diff --git a/tests/auto/gui/text/qtexttable/.gitignore b/tests/auto/gui/text/qtexttable/.gitignore
new file mode 100644
index 0000000000..876aa75c0a
--- /dev/null
+++ b/tests/auto/gui/text/qtexttable/.gitignore
@@ -0,0 +1 @@
+tst_qtexttable
diff --git a/tests/auto/gui/text/qtexttable/qtexttable.pro b/tests/auto/gui/text/qtexttable/qtexttable.pro
new file mode 100644
index 0000000000..611b706fc4
--- /dev/null
+++ b/tests/auto/gui/text/qtexttable/qtexttable.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtexttable.cpp
+
+
+
diff --git a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp
new file mode 100644
index 0000000000..83343811d8
--- /dev/null
+++ b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp
@@ -0,0 +1,1004 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qtextdocument.h>
+#include <qtextdocumentfragment.h>
+#include <qtexttable.h>
+#include <qdebug.h>
+#include <qtextcursor.h>
+#include <qtextdocument.h>
+#include <qtextedit.h>
+
+//TESTED_FILES=
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+QT_FORWARD_DECLARE_CLASS(QTextDocument)
+
+class tst_QTextTable : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTextTable();
+
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void cursorPositioning();
+ void variousTableModifications();
+ void tableShrinking();
+ void spans();
+ void variousModifications2();
+ void tableManager_undo();
+ void tableManager_removeCell();
+ void rowAt();
+ void rowAtWithSpans();
+ void multiBlockCells();
+ void insertRows();
+ void deleteInTable();
+ void mergeCells();
+ void mergeAndInsert();
+ void splitCells();
+ void blocksForTableShouldHaveEmptyFormat();
+ void removeTableByRemoveRows();
+ void removeTableByRemoveColumns();
+ void setCellFormat();
+ void removeRows1();
+ void removeRows2();
+ void removeRows3();
+ void removeRows4();
+ void removeRows5();
+ void removeColumns1();
+ void removeColumns2();
+ void removeColumns3();
+ void removeColumns4();
+ void removeColumns5();
+ void removeColumnsInTableWithMergedRows();
+ void QTBUG11282_insertBeforeMergedEnding_data();
+ void QTBUG11282_insertBeforeMergedEnding();
+
+private:
+ QTextTable *create2x2Table();
+ QTextTable *create4x4Table();
+
+ QTextTable *createTable(int rows, int cols);
+
+ QTextDocument *doc;
+ QTextCursor cursor;
+};
+
+tst_QTextTable::tst_QTextTable()
+{}
+
+void tst_QTextTable::init()
+{
+ doc = new QTextDocument;
+ cursor = QTextCursor(doc);
+}
+
+void tst_QTextTable::cleanup()
+{
+ cursor = QTextCursor();
+ delete doc;
+ doc = 0;
+}
+
+void tst_QTextTable::cursorPositioning()
+{
+ // ensure the cursor is placed at the beginning of the first cell upon
+ // table creation
+ QTextTable *table = cursor.insertTable(2, 2);
+
+ QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
+ QVERIFY(table->cellAt(0, 0).firstPosition() == table->firstPosition());
+}
+
+void tst_QTextTable::variousTableModifications()
+{
+ QTextTableFormat tableFmt;
+
+ QTextTable *tab = cursor.insertTable(2, 2, tableFmt);
+ QVERIFY(doc->toPlainText().length() == 5);
+ QVERIFY(tab == cursor.currentTable());
+ QVERIFY(tab->columns() == 2);
+ QVERIFY(tab->rows() == 2);
+
+ QVERIFY(cursor.position() == 1);
+ QTextCharFormat fmt = cursor.charFormat();
+ QVERIFY(fmt.objectIndex() == -1);
+ QTextTableCell cell = tab->cellAt(cursor);
+ QVERIFY(cell.isValid());
+ QVERIFY(cell.row() == 0);
+ QVERIFY(cell.column() == 0);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.position() == 2);
+ fmt = cursor.charFormat();
+ QVERIFY(fmt.objectIndex() == -1);
+ cell = tab->cellAt(cursor);
+ QVERIFY(cell.isValid());
+ QVERIFY(cell.row() == 0);
+ QVERIFY(cell.column() == 1);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.position() == 3);
+ fmt = cursor.charFormat();
+ QVERIFY(fmt.objectIndex() == -1);
+ cell = tab->cellAt(cursor);
+ QVERIFY(cell.isValid());
+ QVERIFY(cell.row() == 1);
+ QVERIFY(cell.column() == 0);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.position() == 4);
+ fmt = cursor.charFormat();
+ QVERIFY(fmt.objectIndex() == -1);
+ cell = tab->cellAt(cursor);
+ QVERIFY(cell.isValid());
+ QVERIFY(cell.row() == 1);
+ QVERIFY(cell.column() == 1);
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.position() == 5);
+ fmt = cursor.charFormat();
+ QVERIFY(fmt.objectIndex() == -1);
+ cell = tab->cellAt(cursor);
+ QVERIFY(!cell.isValid());
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.position() == 5);
+
+ // check we can't delete the cells with the cursor
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.position() == 1);
+ cursor.deleteChar();
+ QVERIFY(doc->toPlainText().length() == 5);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QVERIFY(cursor.position() == 2);
+ cursor.deleteChar();
+ QVERIFY(doc->toPlainText().length() == 5);
+ cursor.deletePreviousChar();
+ QVERIFY(cursor.position() == 2);
+ QVERIFY(doc->toPlainText().length() == 5);
+
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 2);
+
+ table->insertRows(2, 1);
+ QVERIFY(table->rows() == 3);
+ QVERIFY(table->columns() == 2);
+ QVERIFY(doc->toPlainText().length() == 7);
+ table->insertColumns(2, 2);
+ QVERIFY(table->rows() == 3);
+ QVERIFY(table->columns() == 4);
+ QVERIFY(doc->toPlainText().length() == 13);
+
+ table->resize(4, 5);
+ QVERIFY(table->rows() == 4);
+ QVERIFY(table->columns() == 5);
+ QVERIFY(doc->toPlainText().length() == 21);
+}
+
+void tst_QTextTable::tableShrinking()
+{
+ QTextTableFormat tableFmt;
+
+ cursor.insertTable(3, 4, tableFmt);
+ QVERIFY(doc->toPlainText().length() == 13);
+
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table->rows() == 3);
+ QVERIFY(table->columns() == 4);
+
+ table->removeRows(1, 1);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 4);
+ QVERIFY(doc->toPlainText().length() == 9);
+ table->removeColumns(1, 2);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 2);
+ QVERIFY(doc->toPlainText().length() == 5);
+
+ table->resize(1, 1);
+ QVERIFY(table->rows() == 1);
+ QVERIFY(table->columns() == 1);
+ QVERIFY(doc->toPlainText().length() == 2);
+}
+
+void tst_QTextTable::spans()
+{
+ QTextTableFormat tableFmt;
+
+ cursor.insertTable(2, 2, tableFmt);
+
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table->cellAt(0, 0) != table->cellAt(0, 1));
+ table->mergeCells(0, 0, 1, 2);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 2);
+ QVERIFY(table->cellAt(0, 0) == table->cellAt(0, 1));
+ table->mergeCells(0, 0, 2, 2);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 2);
+}
+
+void tst_QTextTable::variousModifications2()
+{
+ QTextTableFormat tableFmt;
+
+ cursor.insertTable(2, 5, tableFmt);
+ QVERIFY(doc->toPlainText().length() == 11);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(cursor.position() == 1);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 5);
+
+ table->insertColumns(0, 1);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 6);
+ table->insertColumns(6, 1);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 7);
+
+ table->insertRows(0, 1);
+ QVERIFY(table->rows() == 3);
+ QVERIFY(table->columns() == 7);
+ table->insertRows(3, 1);
+ QVERIFY(table->rows() == 4);
+ QVERIFY(table->columns() == 7);
+
+ table->removeRows(0, 1);
+ QVERIFY(table->rows() == 3);
+ QVERIFY(table->columns() == 7);
+ table->removeRows(2, 1);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 7);
+
+ table->removeColumns(0, 1);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 6);
+ table->removeColumns(5, 1);
+ QVERIFY(table->rows() == 2);
+ QVERIFY(table->columns() == 5);
+
+ tableFmt = table->format();
+ table->insertColumns(2, 1);
+ table->setFormat(tableFmt);
+ table->insertColumns(2, 1);
+ QVERIFY(table->columns() == 7);
+}
+
+void tst_QTextTable::tableManager_undo()
+{
+ QTextTableFormat fmt;
+ fmt.setBorder(10);
+ QTextTable *table = cursor.insertTable(2, 2, fmt);
+ QVERIFY(table);
+
+ QVERIFY(table->format().border() == 10);
+
+ fmt.setBorder(20);
+ table->setFormat(fmt);
+
+ QVERIFY(table->format().border() == 20);
+
+ doc->undo();
+
+ QVERIFY(table->format().border() == 10);
+}
+
+void tst_QTextTable::tableManager_removeCell()
+{
+ // essentially a test for TableManager::removeCell, in particular to remove empty items from the rowlist.
+ // If it fails it'll triger assertions inside TableManager. Yeah, not pretty, should VERIFY here ;(
+ cursor.insertTable(2, 2, QTextTableFormat());
+ doc->undo();
+ // ###
+ QVERIFY(true);
+}
+
+void tst_QTextTable::rowAt()
+{
+ // test TablePrivate::rowAt
+ QTextTable *table = cursor.insertTable(4, 2);
+
+ QCOMPARE(table->rows(), 4);
+ QCOMPARE(table->columns(), 2);
+
+ QTextCursor cell00Cursor = table->cellAt(0, 0).firstCursorPosition();
+ QTextCursor cell10Cursor = table->cellAt(1, 0).firstCursorPosition();
+ QTextCursor cell20Cursor = table->cellAt(2, 0).firstCursorPosition();
+ QTextCursor cell21Cursor = table->cellAt(2, 1).firstCursorPosition();
+ QTextCursor cell30Cursor = table->cellAt(3, 0).firstCursorPosition();
+ QVERIFY(table->cellAt(cell00Cursor).firstCursorPosition() == cell00Cursor);
+ QVERIFY(table->cellAt(cell10Cursor).firstCursorPosition() == cell10Cursor);
+ QVERIFY(table->cellAt(cell20Cursor).firstCursorPosition() == cell20Cursor);
+ QVERIFY(table->cellAt(cell30Cursor).firstCursorPosition() == cell30Cursor);
+
+ table->mergeCells(1, 0, 2, 1);
+
+ QCOMPARE(table->rows(), 4);
+ QCOMPARE(table->columns(), 2);
+
+ QVERIFY(cell00Cursor == table->cellAt(0, 0).firstCursorPosition());
+ QVERIFY(cell10Cursor == table->cellAt(1, 0).firstCursorPosition());
+ QVERIFY(cell10Cursor == table->cellAt(2, 0).firstCursorPosition());
+ QVERIFY(cell21Cursor == table->cellAt(2, 1).firstCursorPosition());
+ QVERIFY(cell30Cursor == table->cellAt(3, 0).firstCursorPosition());
+
+ table->mergeCells(1, 0, 2, 2);
+
+ QCOMPARE(table->rows(), 4);
+ QCOMPARE(table->columns(), 2);
+
+ QVERIFY(cell00Cursor == table->cellAt(0, 0).firstCursorPosition());
+ QVERIFY(cell00Cursor == table->cellAt(0, 0).firstCursorPosition());
+ QVERIFY(cell10Cursor == table->cellAt(1, 0).firstCursorPosition());
+ QVERIFY(cell10Cursor == table->cellAt(1, 1).firstCursorPosition());
+ QVERIFY(cell10Cursor == table->cellAt(2, 0).firstCursorPosition());
+ QVERIFY(cell10Cursor == table->cellAt(2, 1).firstCursorPosition());
+ QVERIFY(cell30Cursor == table->cellAt(3, 0).firstCursorPosition());
+}
+
+void tst_QTextTable::rowAtWithSpans()
+{
+ QTextTable *table = cursor.insertTable(2, 2);
+
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+
+ table->mergeCells(0, 0, 2, 1);
+ QVERIFY(table->cellAt(0, 0).rowSpan() == 2);
+
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+
+ table->mergeCells(0, 0, 2, 2);
+ QVERIFY(table->cellAt(0, 0).columnSpan() == 2);
+
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+}
+
+void tst_QTextTable::multiBlockCells()
+{
+ // little testcase for multi-block cells
+ QTextTable *table = cursor.insertTable(2, 2);
+
+ QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
+
+ cursor.insertText("Hello");
+ cursor.insertBlock(QTextBlockFormat());
+ cursor.insertText("World");
+
+ cursor.movePosition(QTextCursor::Left);
+ QVERIFY(table->cellAt(0, 0) == table->cellAt(cursor));
+}
+
+void tst_QTextTable::insertRows()
+{
+ // little testcase for multi-block cells
+ QTextTable *table = cursor.insertTable(2, 2);
+
+ QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
+
+ table->insertRows(0, 1);
+ QVERIFY(table->rows() == 3);
+
+ table->insertRows(1, 1);
+ QVERIFY(table->rows() == 4);
+
+ table->insertRows(-1, 1);
+ QVERIFY(table->rows() == 5);
+
+ table->insertRows(5, 2);
+ QVERIFY(table->rows() == 7);
+
+}
+
+void tst_QTextTable::deleteInTable()
+{
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
+
+ cursor = table->cellAt(1, 1).firstCursorPosition();
+ cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::KeepAnchor);
+
+ QCOMPARE(table->cellAt(cursor.position()).row(), 1);
+ QCOMPARE(table->cellAt(cursor.position()).column(), 0);
+
+ cursor.removeSelectedText();
+
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->rows(), 2);
+
+ // verify table is still all in shape. Only the text inside should get deleted
+ for (int row = 0; row < table->rows(); ++row)
+ for (int col = 0; col < table->columns(); ++col) {
+ const QTextTableCell cell = table->cellAt(row, col);
+ QVERIFY(cell.isValid());
+ QCOMPARE(cell.rowSpan(), 1);
+ QCOMPARE(cell.columnSpan(), 1);
+ }
+}
+
+QTextTable *tst_QTextTable::create2x2Table()
+{
+ cleanup();
+ init();
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
+ return table;
+}
+
+QTextTable *tst_QTextTable::create4x4Table()
+{
+ cleanup();
+ init();
+ QTextTable *table = cursor.insertTable(4, 4);
+ table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
+ return table;
+}
+
+QTextTable *tst_QTextTable::createTable(int rows, int cols)
+{
+ cleanup();
+ init();
+ QTextTable *table = cursor.insertTable(rows, cols);
+ return table;
+}
+
+void tst_QTextTable::mergeCells()
+{
+ QTextTable *table = create4x4Table();
+
+ table->mergeCells(1, 1, 1, 2);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+
+ table->mergeCells(1, 1, 2, 2);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
+
+ table = create4x4Table();
+
+ table->mergeCells(1, 1, 2, 1);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+
+ table->mergeCells(1, 1, 2, 2);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
+
+ table = create4x4Table();
+
+ table->mergeCells(1, 1, 2, 2);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
+
+ // should do nothing
+ table->mergeCells(1, 1, 1, 1);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
+
+ table = create2x2Table();
+
+ table->mergeCells(0, 1, 2, 1);
+ table->mergeCells(0, 0, 2, 2);
+ QVERIFY(table->cellAt(0, 0) == table->cellAt(0, 1));
+ QVERIFY(table->cellAt(0, 0) == table->cellAt(1, 0));
+ QVERIFY(table->cellAt(0, 0) == table->cellAt(1, 1));
+
+ QTextBlock block = table->cellAt(0, 0).firstCursorPosition().block();
+
+ QVERIFY(block.text() == "Blah Foo");
+ QVERIFY(block.next().text() == "Hah");
+ QVERIFY(block.next().next().text() == "Bar");
+
+ table = create4x4Table();
+
+ QTextCursor cursor = table->cellAt(3, 3).firstCursorPosition();
+ QTextTable *t2 = cursor.insertTable(2, 2);
+ t2->cellAt(0, 0).firstCursorPosition().insertText("Test");
+
+ table->mergeCells(2, 2, 2, 2);
+ cursor = table->cellAt(2, 2).firstCursorPosition();
+
+ QTextFrame *frame = cursor.currentFrame();
+
+ QTextFrame::iterator it = frame->begin();
+
+ // find the embedded table
+ while (it != frame->end() && !it.currentFrame())
+ ++it;
+
+ table = qobject_cast<QTextTable *>(it.currentFrame());
+
+ QVERIFY(table);
+
+ if (table) {
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+
+ QVERIFY(cursor.block().text() == "Test");
+ }
+
+ table = create2x2Table();
+
+ table->mergeCells(0, 1, 2, 1);
+
+ QVERIFY(table->cellAt(0, 0) != table->cellAt(0, 1));
+ QVERIFY(table->cellAt(0, 1) == table->cellAt(1, 1));
+
+ // should do nothing
+ table->mergeCells(0, 0, 1, 2);
+
+ QVERIFY(table->cellAt(0, 0) != table->cellAt(0, 1));
+ QVERIFY(table->cellAt(0, 1) == table->cellAt(1, 1));
+}
+
+void tst_QTextTable::mergeAndInsert()
+{
+ QTextTable *table = cursor.insertTable(4,3);
+ table->mergeCells(0,1,3,2);
+ table->mergeCells(3,0,1,3);
+ //Don't crash !
+ table->insertColumns(1,2);
+ QCOMPARE(table->columns(), 5);
+}
+
+void tst_QTextTable::splitCells()
+{
+ QTextTable *table = create4x4Table();
+ table->mergeCells(1, 1, 2, 2);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
+
+ table->splitCell(1, 1, 1, 2);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
+
+ table->splitCell(1, 1, 1, 1);
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
+
+
+ table = create4x4Table();
+ table->mergeCells(1, 1, 2, 2);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
+
+ table->splitCell(1, 1, 2, 1);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
+
+ table->splitCell(1, 1, 1, 1);
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
+
+
+ table = create4x4Table();
+ table->mergeCells(1, 1, 2, 2);
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
+
+ table->splitCell(1, 1, 1, 1);
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(1, 2));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 1));
+ QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
+
+ table = createTable(2, 5);
+ table->mergeCells(0, 0, 2, 1);
+ table->mergeCells(0, 1, 2, 1);
+ QVERIFY(table->cellAt(0, 0) == table->cellAt(1, 0));
+ QVERIFY(table->cellAt(0, 1) == table->cellAt(1, 1));
+ table->splitCell(0, 0, 1, 1);
+ QVERIFY(table->cellAt(0, 0) != table->cellAt(1, 0));
+ QVERIFY(table->cellAt(0, 1) == table->cellAt(1, 1));
+
+ table = createTable(2, 5);
+ table->mergeCells(0, 4, 2, 1);
+ QVERIFY(table->cellAt(0, 4) == table->cellAt(1, 4));
+
+ table->splitCell(0, 4, 1, 1);
+ QVERIFY(table->cellAt(0, 4) != table->cellAt(1, 4));
+}
+
+void tst_QTextTable::blocksForTableShouldHaveEmptyFormat()
+{
+ QTextBlockFormat fmt;
+ fmt.setProperty(QTextFormat::UserProperty, true);
+ cursor.insertBlock(fmt);
+ QVERIFY(cursor.blockFormat().hasProperty(QTextFormat::UserProperty));
+
+ QTextTable *table = cursor.insertTable(1, 1);
+ QVERIFY(!table->cellAt(0, 0).firstCursorPosition().blockFormat().hasProperty(QTextFormat::UserProperty));
+
+ int userPropCount = 0;
+ for (QTextBlock block = doc->begin();
+ block.isValid(); block = block.next()) {
+ if (block.blockFormat().hasProperty(QTextFormat::UserProperty))
+ userPropCount++;
+ }
+ QCOMPARE(userPropCount, 1);
+}
+
+void tst_QTextTable::removeTableByRemoveRows()
+{
+ QPointer<QTextTable> table1 = QTextCursor(cursor).insertTable(4, 4);
+ QPointer<QTextTable> table2 = QTextCursor(cursor).insertTable(4, 4);
+ QPointer<QTextTable> table3 = QTextCursor(cursor).insertTable(4, 4);
+
+ QVERIFY(table1);
+ QVERIFY(table2);
+ QVERIFY(table3);
+
+ table2->removeRows(1, 1);
+
+ QVERIFY(table1);
+ QVERIFY(table2);
+ QVERIFY(table3);
+
+ table2->removeRows(0, table2->rows());
+
+ QVERIFY(table1);
+ QVERIFY(!table2);
+ QVERIFY(table3);
+}
+
+void tst_QTextTable::removeTableByRemoveColumns()
+{
+ QPointer<QTextTable> table1 = QTextCursor(cursor).insertTable(4, 4);
+ QPointer<QTextTable> table2 = QTextCursor(cursor).insertTable(4, 4);
+ QPointer<QTextTable> table3 = QTextCursor(cursor).insertTable(4, 4);
+
+ QVERIFY(table1);
+ QVERIFY(table2);
+ QVERIFY(table3);
+
+ table2->removeColumns(1, 1);
+
+ QVERIFY(table1);
+ QVERIFY(table2);
+ QVERIFY(table3);
+
+ table2->removeColumns(0, table2->columns());
+
+ QVERIFY(table1);
+ QVERIFY(!table2);
+ QVERIFY(table3);
+}
+
+void tst_QTextTable::setCellFormat()
+{
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextCharFormat fmt;
+ fmt.setObjectIndex(23);
+ fmt.setBackground(Qt::blue);
+ fmt.setTableCellColumnSpan(25);
+ fmt.setTableCellRowSpan(42);
+ cell.setFormat(fmt);
+ QVERIFY(cell.format().background().color() == QColor(Qt::blue));
+ QCOMPARE(cell.format().tableCellColumnSpan(), 1);
+ QCOMPARE(cell.format().tableCellRowSpan(), 1);
+}
+
+void tst_QTextTable::removeRows1()
+{
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+ table->removeRows(0, 1);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Third"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Fourth"));
+}
+
+void tst_QTextTable::removeRows2()
+{
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+ table->removeRows(1, 1);
+ QCOMPARE(table->rows(), 1);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second"));
+}
+
+void tst_QTextTable::removeRows3()
+{
+ QTextTable *table = cursor.insertTable(3, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+ table->cellAt(2, 0).firstCursorPosition().insertText("Fifth");
+ table->cellAt(2, 1).firstCursorPosition().insertText("Sixth");
+ table->removeRows(1, 1);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Fifth"));
+ QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Sixth"));
+}
+
+void tst_QTextTable::removeRows4()
+{
+ QTextTable *table = cursor.insertTable(4, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+ table->cellAt(2, 0).firstCursorPosition().insertText("Fifth");
+ table->cellAt(2, 1).firstCursorPosition().insertText("Sixth");
+ table->cellAt(3, 0).firstCursorPosition().insertText("Seventh");
+ table->cellAt(3, 1).firstCursorPosition().insertText("Eighth");
+ table->removeRows(1, 2);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Seventh"));
+ QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Eighth"));
+}
+
+void tst_QTextTable::removeRows5()
+{
+ QTextTable *table = cursor.insertTable(2,2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+ table->insertRows(1,1);
+ table->mergeCells(1,0,1,2);
+ table->removeRows(1,1);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Third"));
+ QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Fourth"));
+}
+
+void tst_QTextTable::removeColumns1()
+{
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+ table->removeColumns(0, 1);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Second"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Fourth"));
+}
+
+void tst_QTextTable::removeColumns2()
+{
+ QTextTable *table = cursor.insertTable(2, 2);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
+ table->removeColumns(1, 1);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 1);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Third"));
+}
+
+void tst_QTextTable::removeColumns3()
+{
+ QTextTable *table = cursor.insertTable(2, 3);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(0, 2).firstCursorPosition().insertText("Third");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Fourth");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Fifth");
+ table->cellAt(1, 2).firstCursorPosition().insertText("Sixth");
+ table->removeColumns(1, 1);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Third"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Fourth"));
+ QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Sixth"));
+}
+
+void tst_QTextTable::removeColumns4()
+{
+ QTextTable *table = cursor.insertTable(2, 4);
+ table->cellAt(0, 0).firstCursorPosition().insertText("First");
+ table->cellAt(0, 1).firstCursorPosition().insertText("Second");
+ table->cellAt(0, 2).firstCursorPosition().insertText("Third");
+ table->cellAt(0, 3).firstCursorPosition().insertText("Fourth");
+ table->cellAt(1, 0).firstCursorPosition().insertText("Fifth");
+ table->cellAt(1, 1).firstCursorPosition().insertText("Sixth");
+ table->cellAt(1, 2).firstCursorPosition().insertText("Seventh");
+ table->cellAt(1, 3).firstCursorPosition().insertText("Eighth");
+ table->removeColumns(1, 2);
+ QCOMPARE(table->rows(), 2);
+ QCOMPARE(table->columns(), 2);
+ QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
+ QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Fourth"));
+ QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Fifth"));
+ QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Eighth"));
+}
+
+void tst_QTextTable::removeColumns5()
+{
+ QTextTable *table = cursor.insertTable(4, 4);
+ QTextCursor tc (doc);
+ tc.setPosition(table->cellAt(2,0).firstPosition());
+ tc.setPosition(table->cellAt(3,1).firstPosition(), QTextCursor::KeepAnchor);
+ table->mergeCells(tc);
+ QCOMPARE(table->rows(), 4);
+ QCOMPARE(table->columns(), 4);
+ QCOMPARE(table->cellAt(0, 0).firstPosition(), 1);
+ QCOMPARE(table->cellAt(0, 1).firstPosition(), 2);
+ QCOMPARE(table->cellAt(0, 2).firstPosition(), 3);
+ QCOMPARE(table->cellAt(0, 3).firstPosition(), 4);
+ QCOMPARE(table->cellAt(1, 0).firstPosition(), 5);
+ QCOMPARE(table->cellAt(1, 1).firstPosition(), 6);
+ QCOMPARE(table->cellAt(1, 2).firstPosition(), 7);
+ QCOMPARE(table->cellAt(1, 3).firstPosition(), 8);
+ QCOMPARE(table->cellAt(2, 0).firstPosition(), 9);
+ QCOMPARE(table->cellAt(2, 0).rowSpan(), 2);
+ QCOMPARE(table->cellAt(2, 0).columnSpan(), 2);
+ QCOMPARE(table->cellAt(2, 1).firstPosition(), 9);
+ QCOMPARE(table->cellAt(2, 2).firstPosition(), 10);
+ QCOMPARE(table->cellAt(2, 3).firstPosition(), 11);
+ QCOMPARE(table->cellAt(3, 0).firstPosition(), 9);
+ QCOMPARE(table->cellAt(3, 1).firstPosition(), 9);
+ QCOMPARE(table->cellAt(3, 2).firstPosition(), 12);
+ QCOMPARE(table->cellAt(3, 3).firstPosition(), 13);
+
+ table->removeColumns(1, 1);
+ QCOMPARE(table->rows(), 4);
+ QCOMPARE(table->columns(), 3);
+ QCOMPARE(table->cellAt(0, 0).firstPosition(), 1);
+ QCOMPARE(table->cellAt(0, 1).firstPosition(), 2);
+ QCOMPARE(table->cellAt(0, 2).firstPosition(), 3);
+ QCOMPARE(table->cellAt(1, 0).firstPosition(), 4);
+ QCOMPARE(table->cellAt(1, 1).firstPosition(), 5);
+ QCOMPARE(table->cellAt(1, 2).firstPosition(), 6);
+ QCOMPARE(table->cellAt(2, 0).firstPosition(), 7);
+ QCOMPARE(table->cellAt(2, 0).rowSpan(), 2);
+ QCOMPARE(table->cellAt(2, 0).columnSpan(), 1);
+ QCOMPARE(table->cellAt(2, 1).firstPosition(), 8);
+ QCOMPARE(table->cellAt(2, 2).firstPosition(), 9);
+ QCOMPARE(table->cellAt(3, 0).firstPosition(), 7);
+ QCOMPARE(table->cellAt(3, 1).firstPosition(), 10);
+ QCOMPARE(table->cellAt(3, 2).firstPosition(), 11);
+}
+
+void tst_QTextTable::removeColumnsInTableWithMergedRows()
+{
+ QTextTable *table = cursor.insertTable(3, 4);
+ table->mergeCells(0, 0, 1, 4);
+ QCOMPARE(table->rows(), 3);
+ QCOMPARE(table->columns(), 4);
+
+ table->removeColumns(0, table->columns() - 1);
+
+ QCOMPARE(table->rows(), 3);
+ QCOMPARE(table->columns(), 1);
+}
+
+void tst_QTextTable::QTBUG11282_insertBeforeMergedEnding_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<QList<int> >("merge");
+ QTest::addColumn<QList<int> >("insert");
+
+ QTest::newRow("2x3, merge two, insert one") << 2 << 3 << (QList<int>() << 1 << 2 << 2)
+ << (QList<int>() << 1 << 1) ;
+ QTest::newRow("3x4, merge three, insert one") << 3 << 4 << (QList<int>() << 1 << 3 << 3)
+ << (QList<int>() << 1 << 1) ;
+ QTest::newRow("4x3, merge two, insert two") << 4 << 3 << (QList<int>() << 1 << 4 << 2)
+ << (QList<int>() << 1 << 2) ;
+ QTest::newRow("4x4, merge middle two, insert one") << 4 << 4 << (QList<int>() << 1 << 4 << 2)
+ << (QList<int>() << 1 << 1) ;
+}
+
+void tst_QTextTable::QTBUG11282_insertBeforeMergedEnding()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(QList<int>, merge);
+ QFETCH(QList<int>, insert);
+ QTextTable *table = cursor.insertTable(rows, columns);
+ QTextEdit *textEdit = new QTextEdit;
+ textEdit->setDocument(doc);
+ textEdit->show();
+ QTest::qWaitForWindowShown(textEdit);
+ table->mergeCells(0,merge.at(0), merge.at(1), merge.at(2));
+ //Don't crash !
+ table->insertColumns(insert.at(0), insert.at(1));
+ //Check that the final size is what we expected
+ QCOMPARE(table->rows(), rows);
+ QCOMPARE(table->columns(), columns + insert.at(1));
+ delete textEdit;
+}
+
+QTEST_MAIN(tst_QTextTable)
+#include "tst_qtexttable.moc"
diff --git a/tests/auto/gui/text/qzip/.gitignore b/tests/auto/gui/text/qzip/.gitignore
new file mode 100644
index 0000000000..2d7dfbe70c
--- /dev/null
+++ b/tests/auto/gui/text/qzip/.gitignore
@@ -0,0 +1 @@
+tst_qzip
diff --git a/tests/auto/gui/text/qzip/qzip.pro b/tests/auto/gui/text/qzip/qzip.pro
new file mode 100644
index 0000000000..7631a3e93a
--- /dev/null
+++ b/tests/auto/gui/text/qzip/qzip.pro
@@ -0,0 +1,12 @@
+load(qttest_p4)
+QT += gui-private
+SOURCES += tst_qzip.cpp
+
+wince*|symbian: {
+ addFiles.files = testdata
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+ !symbian:DEFINES += SRCDIR=\\\".\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
diff --git a/tests/auto/gui/text/qzip/testdata/symlink.zip b/tests/auto/gui/text/qzip/testdata/symlink.zip
new file mode 100644
index 0000000000..027f96477a
--- /dev/null
+++ b/tests/auto/gui/text/qzip/testdata/symlink.zip
Binary files differ
diff --git a/tests/auto/gui/text/qzip/testdata/test.zip b/tests/auto/gui/text/qzip/testdata/test.zip
new file mode 100644
index 0000000000..a57ba4e2a9
--- /dev/null
+++ b/tests/auto/gui/text/qzip/testdata/test.zip
Binary files differ
diff --git a/tests/auto/gui/text/qzip/tst_qzip.cpp b/tests/auto/gui/text/qzip/tst_qzip.cpp
new file mode 100644
index 0000000000..0955ac069f
--- /dev/null
+++ b/tests/auto/gui/text/qzip/tst_qzip.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <private/qzipwriter_p.h>
+#include <private/qzipreader_p.h>
+
+#ifdef Q_OS_SYMBIAN
+#define SRCDIR "."
+#endif
+
+class tst_QZip : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void basicUnpack();
+ void symlinks();
+ void readTest();
+ void createArchive();
+};
+
+void tst_QZip::init()
+{
+}
+
+void tst_QZip::cleanup()
+{
+}
+
+void tst_QZip::basicUnpack()
+{
+ QZipReader zip(QString(SRCDIR) + "/testdata/test.zip", QIODevice::ReadOnly);
+ QList<QZipReader::FileInfo> files = zip.fileInfoList();
+ QCOMPARE(files.count(), 2);
+
+ QZipReader::FileInfo fi = files.at(0);
+ QVERIFY(fi.isValid());
+ QCOMPARE(fi.filePath, QString("test/"));
+ QCOMPARE(uint(fi.isDir), (uint) 1);
+ QCOMPARE(uint(fi.isFile), (uint) 0);
+ QCOMPARE(uint(fi.isSymLink), (uint) 0);
+
+ QCOMPARE(fi.permissions,QFile::Permissions( QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner
+ | QFile::ReadUser | QFile::WriteUser | QFile::ExeUser ));
+
+ QCOMPARE(fi.lastModified, QDateTime::fromString("2005.11.11 13:08:02", "yyyy.MM.dd HH:mm:ss"));
+
+ fi = files.at(1);
+ QVERIFY(fi.isValid());
+ QCOMPARE(fi.filePath, QString("test/test.txt"));
+ QCOMPARE(uint(fi.isDir), (uint) 0);
+ QCOMPARE(uint(fi.isFile), (uint) 1);
+ QCOMPARE(uint(fi.isSymLink), (uint) 0);
+
+ QVERIFY(fi.permissions == QFile::Permissions( QFile::ReadOwner | QFile::WriteOwner
+ | QFile::ReadUser | QFile::WriteUser ));
+
+ QCOMPARE(fi.lastModified, QDateTime::fromString("2005.11.11 13:08:02", "yyyy.MM.dd HH:mm:ss"));
+
+ QCOMPARE(zip.fileData("test/test.txt"), QByteArray("content\n"));
+
+ fi = files.at(-1);
+ QVERIFY(!fi.isValid());
+}
+
+void tst_QZip::symlinks()
+{
+ QZipReader zip(QString(SRCDIR) + "/testdata/symlink.zip", QIODevice::ReadOnly);
+ QList<QZipReader::FileInfo> files = zip.fileInfoList();
+ QCOMPARE(files.count(), 2);
+
+ QZipReader::FileInfo fi = files.at(0);
+ QVERIFY(fi.isValid());
+ QCOMPARE(fi.filePath, QString("symlink"));
+ QVERIFY(!fi.isDir);
+ QVERIFY(!fi.isFile);
+ QVERIFY(fi.isSymLink);
+
+ QCOMPARE(zip.fileData("symlink"), QByteArray("destination"));
+
+ fi = files.at(1);
+ QVERIFY(fi.isValid());
+ QCOMPARE(fi.filePath, QString("destination"));
+ QVERIFY(!fi.isDir);
+ QVERIFY(fi.isFile);
+ QVERIFY(!fi.isSymLink);
+}
+
+void tst_QZip::readTest()
+{
+ QZipReader zip("foobar.zip", QIODevice::ReadOnly); // non existing file.
+ QList<QZipReader::FileInfo> files = zip.fileInfoList();
+ QCOMPARE(files.count(), 0);
+ QByteArray b = zip.fileData("foobar");
+ QCOMPARE(b.size(), 0);
+}
+
+void tst_QZip::createArchive()
+{
+ QBuffer buffer;
+ QZipWriter zip(&buffer);
+ QByteArray fileContents("simple file contents\nline2\n");
+ zip.addFile("My Filename", fileContents);
+ zip.close();
+ QByteArray zipFile = buffer.buffer();
+
+ // QFile f("createArchiveTest.zip"); f.open(QIODevice::WriteOnly); f.write(zipFile); f.close();
+
+ QBuffer buffer2(&zipFile);
+ QZipReader zip2(&buffer2);
+ QList<QZipReader::FileInfo> files = zip2.fileInfoList();
+ QCOMPARE(files.count(), 1);
+ QZipReader::FileInfo file = files.at(0);
+ QCOMPARE(file.filePath, QString("My Filename"));
+ QCOMPARE(uint(file.isDir), (uint) 0);
+ QCOMPARE(uint(file.isFile), (uint) 1);
+ QCOMPARE(uint(file.isSymLink), (uint) 0);
+ QCOMPARE(file.permissions, QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser) );
+ QCOMPARE(file.size, (long long) 27);
+ QCOMPARE(zip2.fileData("My Filename"), fileContents);
+}
+
+QTEST_MAIN(tst_QZip)
+#include "tst_qzip.moc"
diff --git a/tests/auto/gui/text/text.pro b/tests/auto/gui/text/text.pro
new file mode 100644
index 0000000000..001a967ad6
--- /dev/null
+++ b/tests/auto/gui/text/text.pro
@@ -0,0 +1,32 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qabstracttextdocumentlayout \
+ qcssparser \
+ qfont \
+ qfontdatabase \
+ qfontmetrics \
+ qglyphrun \
+ qrawfont \
+ qstatictext \
+ qsyntaxhighlighter \
+ qtextblock \
+ qtextcursor \
+ qtextdocument \
+ qtextdocumentfragment \
+ qtextdocumentlayout \
+ qtextformat \
+ qtextlayout \
+ qtextlist \
+ qtextobject \
+ qtextpiecetable \
+ qtextscriptengine \
+ qtexttable \
+
+contains(QT_CONFIG, OdfWriter):SUBDIRS += qzip qtextodfwriter
+
+win32:SUBDIRS -= qtextpiecetable
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qcssparser \
+ qtextlayout \
+ qtextpiecetable \
diff --git a/tests/auto/gui/util/qdesktopservices/.gitignore b/tests/auto/gui/util/qdesktopservices/.gitignore
new file mode 100644
index 0000000000..c7ce852ccd
--- /dev/null
+++ b/tests/auto/gui/util/qdesktopservices/.gitignore
@@ -0,0 +1 @@
+tst_qdesktopservices
diff --git a/tests/auto/gui/util/qdesktopservices/qdesktopservices.pro b/tests/auto/gui/util/qdesktopservices/qdesktopservices.pro
new file mode 100644
index 0000000000..0e51ed0459
--- /dev/null
+++ b/tests/auto/gui/util/qdesktopservices/qdesktopservices.pro
@@ -0,0 +1,30 @@
+CONFIG += qttest_p4
+QT += widgets
+
+SOURCES += tst_qdesktopservices.cpp
+TARGET = tst_qdesktopservices
+symbian: {
+ dummy.files = text\\testfile.txt
+ dummy.path = .
+
+ text.files = text\\*
+ text.path = \\data\\others
+
+ image.files = image\\*
+ image.path = \\data\\images
+
+ audio.files = audio\\*
+ audio.path = \\data\\sounds
+
+ video.files = video\\*
+ video.path = \\data\\videos
+
+ install.files = install\\*
+ install.path = \\data\\installs
+
+ DEPLOYMENT += image audio video install
+
+ # These are only needed for manual tests
+ #DEPLOYMENT += dummy text
+ }
+
diff --git a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp
new file mode 100644
index 0000000000..8bea0a245b
--- /dev/null
+++ b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QStandardItemModel>
+#include <qdebug.h>
+#include <qdesktopservices.h>
+
+//#define RUN_MANUAL_TESTS
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_qdesktopservices : public QObject {
+ Q_OBJECT
+
+public:
+ tst_qdesktopservices();
+ virtual ~tst_qdesktopservices();
+
+private slots:
+ void init();
+ void cleanup();
+ void openUrl();
+#ifdef Q_OS_SYMBIAN
+ // These test are manual ones, you need to check from device that
+ // correct system application is started with correct content
+ // When you want to run these test, uncomment //#define RUN_MANUAL_TESTS
+ void openHttpUrl_data();
+ void openHttpUrl();
+ void openMailtoUrl_data();
+ void openMailtoUrl();
+ void openFileUrl_data();
+ void openFileUrl();
+ void openMultipleFileUrls();
+#endif
+ void handlers();
+ void storageLocation_data();
+ void storageLocation();
+
+ void storageLocationDoesNotEndWithSlash_data();
+ void storageLocationDoesNotEndWithSlash();
+
+protected:
+};
+
+tst_qdesktopservices::tst_qdesktopservices()
+{
+ QCoreApplication::setOrganizationName("Nokia");
+ QCoreApplication::setApplicationName("tst_qdesktopservices");
+}
+
+tst_qdesktopservices::~tst_qdesktopservices()
+{
+}
+
+void tst_qdesktopservices::init()
+{
+}
+
+void tst_qdesktopservices::cleanup()
+{
+}
+
+void tst_qdesktopservices::openUrl()
+{
+ // At the bare minimum check that they return false for invalid url's
+ QCOMPARE(QDesktopServices::openUrl(QUrl()), false);
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ // this test is only valid on windows on other systems it might mean open a new document in the application handling .file
+ QCOMPARE(QDesktopServices::openUrl(QUrl("file://invalid.file")), false);
+#endif
+}
+
+#ifdef Q_OS_SYMBIAN
+void tst_qdesktopservices::openHttpUrl_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<bool>("result");
+ QTest::newRow("BasicWithHttp") << QUrl("http://www.google.fi") << true;
+ QTest::newRow("BasicWithoutHttp") << QUrl("www.nokia.fi") << true;
+ QTest::newRow("BasicWithUserAndPw") << QUrl("http://s60prereleases:oslofjord@pepper.troll.no/s60prereleases/patches/") << true;
+ QTest::newRow("URL with space") << QUrl("http://www.manataka.org/Contents Page.html") << true;
+
+}
+
+void tst_qdesktopservices::openHttpUrl()
+{
+#ifndef RUN_MANUAL_TESTS
+ QSKIP("Test disabled -- only for manual purposes", SkipAll);
+#endif
+
+ QFETCH(QUrl, url);
+ QFETCH(bool, result);
+ QCOMPARE(QDesktopServices::openUrl(url), result);
+ QTest::qWait(30000);
+}
+
+void tst_qdesktopservices::openMailtoUrl_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<bool>("result");
+
+ // http://en.wikipedia.org/wiki/E-mail_address
+ // RFC Valid e-mail addresses
+ QTest::newRow("Wiki valid email 1") << QUrl("mailto:abc@example.com") << true;
+ QTest::newRow("Wiki valid email 2") << QUrl("mailto:Abc@example.com") << true;
+ QTest::newRow("Wiki valid email 3") << QUrl("mailto:aBC@example.com") << true;
+ QTest::newRow("Wiki valid email 4") << QUrl("mailto:abc.123@example.com") << true;
+ QTest::newRow("Wiki valid email 5") << QUrl("mailto:1234567890@example.com") << true;
+ QTest::newRow("Wiki valid email 6") << QUrl("mailto:_______@example.com") << true;
+ QTest::newRow("Wiki valid email 7") << QUrl("mailto:abc+mailbox/department=shipping@example.com") << true;
+ // S60 email client considers the next URL invalid, even ity should be valid
+ QTest::newRow("Wiki valid email 8") << QUrl("mailto:!#$%&'*+-/=?^_`.{|}~@example.com") << true; // all of these characters are allowed
+ QTest::newRow("Wiki valid email 9") << QUrl("mailto:\"abc@def\"@example.com") << true; // anything goes inside quotation marks
+ QTest::newRow("Wiki valid email 10") << QUrl("mailto:\"Fred \\\"quota\\\" Bloggs\"@example.com") << true; // however, quotes need escaping
+
+ // RFC invalid e-mail addresses
+ // These return true even though they are invalid, but check that user is notified about invalid URL in mail application
+ QTest::newRow("Wiki invalid email 1") << QUrl("mailto:Abc.example.com") << true; // character @ is missing
+ QTest::newRow("Wiki invalid email 2") << QUrl("mailto:Abc.@example.com") << true; // character dot(.) is last in local part
+ QTest::newRow("Wiki invalid email 3") << QUrl("mailto:Abc..123@example.com") << true; // character dot(.) is double
+ QTest::newRow("Wiki invalid email 4") << QUrl("mailto:A@b@c@example.com") << true; // only one @ is allowed outside quotations marks
+ QTest::newRow("Wiki invalid email 5") << QUrl("mailto:()[]\\;:,<>@example.com") << true; // none of the characters before the @ is allowed outside quotation marks
+
+ QTest::newRow("Basic") << QUrl("mailto:test@nokia.com") << true;
+ QTest::newRow("BasicSeveralAddr") << QUrl("mailto:test@nokia.com,test2@nokia.com,test3@nokia.com") << true;
+ QTest::newRow("BasicAndSubject") << QUrl("mailto:test@nokia.com?subject=hello nokia") << true;
+ QTest::newRow("BasicAndTo") << QUrl("mailto:test@nokia.com?to=test2@nokia.com") << true;
+
+ QTest::newRow("BasicAndCc") << QUrl("mailto:test@nokia.com?cc=mycc@address.com") << true;
+ QTest::newRow("BasicAndBcc") << QUrl("mailto:test@nokia.com?bcc=mybcc@address.com") << true;
+ QTest::newRow("BasicAndBody") << QUrl("mailto:test@nokia.com?body=Test email message body") << true;
+
+ // RFC examples, these are actually invalid because there is not host defined
+ // Check that user is notified about invalid URL in mail application
+ QTest::newRow("RFC2368 Example 1") << QUrl::fromEncoded("mailto:addr1%2C%20addr2") << true;
+ QTest::newRow("RFC2368 Example 2") << QUrl::fromEncoded("mailto:?to=addr1%2C%20addr2") << true;
+ QTest::newRow("RFC2368 Example 3") << QUrl("mailto:addr1?to=addr2") << true;
+
+ QTest::newRow("RFC2368 Example 4") << QUrl("mailto:joe@example.com?cc=bob@example.com&body=hello") << true;
+ QTest::newRow("RFC2368 Example 5") << QUrl("mailto:?to=joe@example.com&cc=bob@example.com&body=hello") << true;
+ QTest::newRow("RFC2368 Example 6") << QUrl("mailto:foobar@example.com?In-Reply-To=%3c3469A91.D10AF4C@example.com") << true; // OpaqueData
+ QTest::newRow("RFC2368 Example 7") << QUrl::fromEncoded("mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index") << true;
+ QTest::newRow("RFC2368 Example 8") << QUrl::fromEncoded("mailto:infobot@example.com?body=send%20current-issue") << true;
+ QTest::newRow("RFC2368 Example 9") << QUrl("mailto:infobot@example.com?subject=current-issue") << true;
+ QTest::newRow("RFC2368 Example 10") << QUrl("mailto:chris@example.com") << true;
+
+ //QTest::newRow("RFC2368 Example 11 - illegal chars") << QUrl("mailto:joe@example.com?cc=bob@example.com?body=hello") << false;
+ QTest::newRow("RFC2368 Example 12") << QUrl::fromEncoded("mailto:gorby%25kremvax@example.com") << true; // encoded reserved chars '%'
+ QTest::newRow("RFC2368 Example 13") << QUrl::fromEncoded("mailto:unlikely%3Faddress@example.com?blat=foop") << true; // encoded reserved chars `?'
+}
+
+void tst_qdesktopservices::openMailtoUrl()
+{
+#ifndef RUN_MANUAL_TESTS
+ QSKIP("Test disabled -- only for manual purposes", SkipAll);
+#endif
+
+ QFETCH(QUrl, url);
+ QFETCH(bool, result);
+ QCOMPARE(QDesktopServices::openUrl(url), result);
+ QTest::qWait(5000);
+}
+
+void tst_qdesktopservices::openFileUrl_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<bool>("result");
+
+ // Text files
+ QTest::newRow("DOS text file") << QUrl("file:///c:/data/others/dosfile.txt") << true;
+ QTest::newRow("No EOF text file") << QUrl("file:///c:/data/others/noendofline.txt") << true;
+ QTest::newRow("text file") << QUrl("file:///c:/data/others/testfile.txt") << true;
+ QTest::newRow("text file with space") << QUrl("file:///c:/data/others/test file.txt") << true;
+
+ // Images
+ QTest::newRow("BMP image") << QUrl("file:///c:/data/images/image.bmp") << true;
+ QTest::newRow("GIF image") << QUrl("file:///c:/data/images/image.gif") << true;
+ QTest::newRow("JPG image") << QUrl("file:///c:/data/images/image.jpg") << true;
+ QTest::newRow("PNG image") << QUrl("file:///c:/data/images/image.png") << true;
+
+ // Audio
+ QTest::newRow("MP4 audio") << QUrl("file:///c:/data/sounds/aac-only.mp4") << true;
+ QTest::newRow("3GP audio") << QUrl("file:///c:/data/sounds/audio_3gpp.3gp") << true;
+
+ // Video
+ QTest::newRow("MP4 video") << QUrl("file:///c:/data/videos/vid-mpeg4-22k.mp4") << true;
+
+ // Installs
+ QTest::newRow("SISX") << QUrl("file:///c:/data/installs/ErrRd.sisx") << true;
+
+ // Errors
+ QTest::newRow("File does not exist") << QUrl("file:///c:/thisfileneverexists.txt") << false;
+}
+
+void tst_qdesktopservices::openFileUrl()
+{
+#ifndef RUN_MANUAL_TESTS
+ QSKIP("Test disabled -- only for manual purposes", SkipAll);
+#endif
+
+ QFETCH(QUrl, url);
+ QFETCH(bool, result);
+ QCOMPARE(QDesktopServices::openUrl(url), result);
+ QTest::qWait(5000);
+}
+
+void tst_qdesktopservices::openMultipleFileUrls()
+{
+#ifndef RUN_MANUAL_TESTS
+ QSKIP("Test disabled -- only for manual purposes", SkipAll);
+#endif
+
+ QCOMPARE(QDesktopServices::openUrl(QUrl("file:///c:/data/images/image.bmp")), true);
+ QCOMPARE(QDesktopServices::openUrl(QUrl("file:///c:/data/images/image.png")), true);
+ QCOMPARE(QDesktopServices::openUrl(QUrl("file:///c:/data/others/noendofline.txt")), true);
+ QCOMPARE(QDesktopServices::openUrl(QUrl("file:///c:/data/installs/ErrRd.sisx")), true);
+}
+#endif
+
+
+class MyUrlHandler : public QObject
+{
+ Q_OBJECT
+public:
+ QUrl lastHandledUrl;
+
+public slots:
+ inline void handle(const QUrl &url) {
+ lastHandledUrl = url;
+ }
+};
+
+void tst_qdesktopservices::handlers()
+{
+ MyUrlHandler fooHandler;
+ MyUrlHandler barHandler;
+
+ QDesktopServices::setUrlHandler(QString("foo"), &fooHandler, "handle");
+ QDesktopServices::setUrlHandler(QString("bar"), &barHandler, "handle");
+
+ QUrl fooUrl("foo://blub/meh");
+ QUrl barUrl("bar://hmm/hmmmm");
+
+ QVERIFY(QDesktopServices::openUrl(fooUrl));
+ QVERIFY(QDesktopServices::openUrl(barUrl));
+
+ QCOMPARE(fooHandler.lastHandledUrl.toString(), fooUrl.toString());
+ QCOMPARE(barHandler.lastHandledUrl.toString(), barUrl.toString());
+}
+
+Q_DECLARE_METATYPE(QDesktopServices::StandardLocation)
+void tst_qdesktopservices::storageLocation_data()
+{
+ QTest::addColumn<QDesktopServices::StandardLocation>("location");
+ QTest::newRow("DesktopLocation") << QDesktopServices::DesktopLocation;
+ QTest::newRow("DocumentsLocation") << QDesktopServices::DocumentsLocation;
+ QTest::newRow("FontsLocation") << QDesktopServices::FontsLocation;
+ QTest::newRow("ApplicationsLocation") << QDesktopServices::ApplicationsLocation;
+ QTest::newRow("MusicLocation") << QDesktopServices::MusicLocation;
+ QTest::newRow("MoviesLocation") << QDesktopServices::MoviesLocation;
+ QTest::newRow("PicturesLocation") << QDesktopServices::PicturesLocation;
+ QTest::newRow("TempLocation") << QDesktopServices::TempLocation;
+ QTest::newRow("HomeLocation") << QDesktopServices::HomeLocation;
+ QTest::newRow("DataLocation") << QDesktopServices::DataLocation;
+}
+
+void tst_qdesktopservices::storageLocation()
+{
+ QFETCH(QDesktopServices::StandardLocation, location);
+#ifdef Q_OS_SYMBIAN
+ QString storageLocation = QDesktopServices::storageLocation(location);
+ QString displayName = QDesktopServices::displayName(location);
+ //qDebug( "displayName: %s", displayName );
+
+ storageLocation = storageLocation.toLower();
+ displayName = displayName.toLower();
+
+ QString drive = QDir::currentPath().left(2).toLower();
+ if( drive == "z:" )
+ drive = "c:";
+
+ switch(location) {
+ case QDesktopServices::DesktopLocation:
+ QCOMPARE( storageLocation, drive + QString("/data") );
+ break;
+ case QDesktopServices::DocumentsLocation:
+ QCOMPARE( storageLocation, drive + QString("/data") );
+ break;
+ case QDesktopServices::FontsLocation:
+ // Currently point always to ROM
+ QCOMPARE( storageLocation, QString("z:/resource/fonts") );
+ break;
+ case QDesktopServices::ApplicationsLocation:
+#ifdef Q_CC_NOKIAX86
+ QCOMPARE( storageLocation, QString("z:/sys/bin") );
+#else
+ QCOMPARE( storageLocation, drive + QString("/sys/bin") );
+#endif
+ break;
+ case QDesktopServices::MusicLocation:
+ QCOMPARE( storageLocation, drive + QString("/data/sounds") );
+ break;
+ case QDesktopServices::MoviesLocation:
+ QCOMPARE( storageLocation, drive + QString("/data/videos") );
+ break;
+ case QDesktopServices::PicturesLocation:
+ QCOMPARE( storageLocation, drive + QString("/data/images") );
+ break;
+ case QDesktopServices::TempLocation:
+ QCOMPARE( storageLocation, QDir::tempPath().toLower());
+ break;
+ case QDesktopServices::HomeLocation:
+ QCOMPARE( storageLocation, QDir::homePath().toLower());
+ break;
+ case QDesktopServices::DataLocation:
+ // Just check the folder not the drive
+ QCOMPARE( storageLocation.mid(2), QDir::currentPath().mid(2).toLower());
+ break;
+ default:
+ QCOMPARE( storageLocation, QString() );
+ break;
+ }
+
+#else
+ QDesktopServices::storageLocation(location);
+ QDesktopServices::displayName(location);
+#endif
+}
+
+
+void tst_qdesktopservices::storageLocationDoesNotEndWithSlash_data()
+{
+ storageLocation_data();
+}
+
+void tst_qdesktopservices::storageLocationDoesNotEndWithSlash()
+{
+ // Currently all desktop locations return their storage location
+ // with "Unix-style" paths (i.e. they use a slash, not backslash).
+ QFETCH(QDesktopServices::StandardLocation, location);
+ QString loc = QDesktopServices::storageLocation(location);
+ if (loc.size() > 1) // workaround for unlikely case of locations that return '/'
+ QCOMPARE(loc.endsWith(QLatin1Char('/')), false);
+}
+
+
+QTEST_MAIN(tst_qdesktopservices)
+#include "tst_qdesktopservices.moc"
diff --git a/tests/auto/gui/util/util.pro b/tests/auto/gui/util/util.pro
new file mode 100644
index 0000000000..91313ab85e
--- /dev/null
+++ b/tests/auto/gui/util/util.pro
@@ -0,0 +1,4 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qdesktopservices \
+