From a90f50942e5304e6bf1c8a3e32f1f65c7a38f60b Mon Sep 17 00:00:00 2001 From: Jo Asplin Date: Wed, 31 Aug 2011 17:11:06 +0200 Subject: 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 Reviewed-by: Jo Asplin --- tests/auto/corelib.pro | 1 - tests/auto/gui.pro | 60 +- tests/auto/gui/gui.pro | 9 + tests/auto/gui/image/image.pro | 18 + tests/auto/gui/image/qicoimageformat/.gitignore | 1 + .../qicoimageformat/icons/invalid/35floppy.ico | Bin 0 -> 1078 bytes .../image/qicoimageformat/icons/valid/35FLOPPY.ICO | Bin 0 -> 1078 bytes .../qicoimageformat/icons/valid/AddPerfMon.ico | Bin 0 -> 1078 bytes .../gui/image/qicoimageformat/icons/valid/App.ico | Bin 0 -> 318 bytes .../icons/valid/Obj_N2_Internal_Mem.ico | Bin 0 -> 25214 bytes .../gui/image/qicoimageformat/icons/valid/Qt.ico | Bin 0 -> 31371 bytes .../qicoimageformat/icons/valid/Status_Play.ico | Bin 0 -> 2862 bytes .../image/qicoimageformat/icons/valid/TIMER01.ICO | Bin 0 -> 1078 bytes .../image/qicoimageformat/icons/valid/WORLD.ico | Bin 0 -> 3310 bytes .../image/qicoimageformat/icons/valid/WORLDH.ico | Bin 0 -> 3310 bytes .../qicoimageformat/icons/valid/abcardWindow.ico | Bin 0 -> 22486 bytes .../icons/valid/semitransparent.ico | Bin 0 -> 25214 bytes .../icons/valid/trolltechlogo_tiny.ico | Bin 0 -> 3006 bytes .../gui/image/qicoimageformat/qicoimageformat.pro | 28 + .../image/qicoimageformat/tst_qicoimageformat.cpp | 338 ++ tests/auto/gui/image/qicon/.gitignore | 1 + tests/auto/gui/image/qicon/heart.svg | 55 + tests/auto/gui/image/qicon/heart.svgz | Bin 0 -> 1506 bytes .../testtheme/16x16/actions/appointment-new.png | Bin 0 -> 897 bytes .../testtheme/22x22/actions/appointment-new.png | Bin 0 -> 1411 bytes .../testtheme/32x32/actions/appointment-new.png | Bin 0 -> 2399 bytes .../gui/image/qicon/icons/testtheme/index.theme | 492 ++ .../icons/testtheme/scalable/actions/svg-only.svg | 425 ++ .../themeparent/16x16/actions/address-book-new.png | Bin 0 -> 796 bytes .../themeparent/16x16/actions/appointment-new.png | Bin 0 -> 897 bytes .../themeparent/22x22/actions/address-book-new.png | Bin 0 -> 924 bytes .../themeparent/22x22/actions/appointment-new.png | Bin 0 -> 1411 bytes .../themeparent/32x32/actions/address-book-new.png | Bin 0 -> 1897 bytes .../themeparent/32x32/actions/appointment-new.png | Bin 0 -> 2399 bytes .../gui/image/qicon/icons/themeparent/index.theme | 492 ++ .../scalable/actions/address-book-new.svg | 389 ++ .../scalable/actions/appointment-new.svg | 425 ++ tests/auto/gui/image/qicon/image.png | Bin 0 -> 14743 bytes tests/auto/gui/image/qicon/qicon.pro | 30 + tests/auto/gui/image/qicon/rect.png | Bin 0 -> 175 bytes tests/auto/gui/image/qicon/rect.svg | 76 + tests/auto/gui/image/qicon/trash.svg | 58 + tests/auto/gui/image/qicon/tst_qicon.cpp | 781 ++++ tests/auto/gui/image/qicon/tst_qicon.qrc | 20 + tests/auto/gui/image/qimage/.gitignore | 1 + tests/auto/gui/image/qimage/images/image.bmp | Bin 0 -> 306 bytes tests/auto/gui/image/qimage/images/image.gif | Bin 0 -> 1089 bytes tests/auto/gui/image/qimage/images/image.ico | Bin 0 -> 10134 bytes tests/auto/gui/image/qimage/images/image.jpg | Bin 0 -> 696 bytes tests/auto/gui/image/qimage/images/image.pbm | 8 + tests/auto/gui/image/qimage/images/image.pgm | 10 + tests/auto/gui/image/qimage/images/image.png | Bin 0 -> 549 bytes tests/auto/gui/image/qimage/images/image.ppm | 7 + tests/auto/gui/image/qimage/images/image.tif | Bin 0 -> 2242 bytes tests/auto/gui/image/qimage/images/image.xbm | 5 + tests/auto/gui/image/qimage/images/image.xpm | 261 ++ tests/auto/gui/image/qimage/qimage.pro | 23 + tests/auto/gui/image/qimage/tst_qimage.cpp | 2014 +++++++++ tests/auto/gui/image/qimageiohandler/.gitignore | 1 + .../gui/image/qimageiohandler/qimageiohandler.pro | 9 + .../image/qimageiohandler/tst_qimageiohandler.cpp | 96 + tests/auto/gui/image/qimagereader/.gitignore | 2 + .../gui/image/qimagereader/baseline/35floppy.png | Bin 0 -> 329 bytes .../gui/image/qimagereader/baseline/connect.png | Bin 0 -> 12943 bytes .../image/qimagereader/baseline/kde_favicon.png | Bin 0 -> 514 bytes .../qimagereader/baseline/semitransparent.png | Bin 0 -> 545 bytes tests/auto/gui/image/qimagereader/images/16bpp.bmp | Bin 0 -> 153654 bytes .../gui/image/qimagereader/images/4bpp-rle.bmp | Bin 0 -> 23662 bytes .../gui/image/qimagereader/images/YCbCr_cmyk.jpg | Bin 0 -> 3699 bytes .../gui/image/qimagereader/images/YCbCr_cmyk.png | Bin 0 -> 230 bytes .../gui/image/qimagereader/images/YCbCr_rgb.jpg | Bin 0 -> 2045 bytes tests/auto/gui/image/qimagereader/images/away.png | Bin 0 -> 753 bytes tests/auto/gui/image/qimagereader/images/ball.mng | Bin 0 -> 34394 bytes tests/auto/gui/image/qimagereader/images/bat1.gif | Bin 0 -> 953 bytes tests/auto/gui/image/qimagereader/images/bat2.gif | Bin 0 -> 980 bytes .../auto/gui/image/qimagereader/images/beavis.jpg | Bin 0 -> 20688 bytes tests/auto/gui/image/qimagereader/images/black.png | Bin 0 -> 697 bytes tests/auto/gui/image/qimagereader/images/black.xpm | 65 + .../gui/image/qimagereader/images/colorful.bmp | Bin 0 -> 65002 bytes .../image/qimagereader/images/corrupt-colors.xpm | 26 + .../gui/image/qimagereader/images/corrupt-data.tif | Bin 0 -> 8590 bytes .../qimagereader/images/corrupt-pixel-count.xpm | 11 + .../image/qimagereader/images/corrupt-pixels.xpm | 7 + .../auto/gui/image/qimagereader/images/corrupt.bmp | Bin 0 -> 116 bytes .../auto/gui/image/qimagereader/images/corrupt.gif | Bin 0 -> 2608 bytes .../auto/gui/image/qimagereader/images/corrupt.jpg | Bin 0 -> 18 bytes .../auto/gui/image/qimagereader/images/corrupt.mng | Bin 0 -> 183 bytes .../auto/gui/image/qimagereader/images/corrupt.png | Bin 0 -> 95 bytes .../auto/gui/image/qimagereader/images/corrupt.svg | 32 + .../gui/image/qimagereader/images/corrupt.svgz | Bin 0 -> 407 bytes .../auto/gui/image/qimagereader/images/corrupt.xbm | 5 + .../qimagereader/images/crash-signed-char.bmp | Bin 0 -> 45748 bytes tests/auto/gui/image/qimagereader/images/earth.gif | Bin 0 -> 51712 bytes .../gui/image/qimagereader/images/endless-anim.gif | Bin 0 -> 819 bytes tests/auto/gui/image/qimagereader/images/fire.mng | Bin 0 -> 44430 bytes tests/auto/gui/image/qimagereader/images/font.bmp | Bin 0 -> 1026 bytes .../gui/image/qimagereader/images/four-frames.gif | Bin 0 -> 427 bytes tests/auto/gui/image/qimagereader/images/gnus.xbm | 622 +++ .../image/qimagereader/images/grayscale-ref.tif | Bin 0 -> 256182 bytes .../gui/image/qimagereader/images/grayscale.tif | Bin 0 -> 64162 bytes tests/auto/gui/image/qimagereader/images/image.pbm | 8 + tests/auto/gui/image/qimagereader/images/image.pgm | 10 + tests/auto/gui/image/qimagereader/images/image.png | Bin 0 -> 549 bytes tests/auto/gui/image/qimagereader/images/image.ppm | 7 + .../gui/image/qimagereader/images/image_100dpi.tif | Bin 0 -> 2242 bytes .../gui/image/qimagereader/images/kollada-noext | Bin 0 -> 13907 bytes .../auto/gui/image/qimagereader/images/kollada.png | Bin 0 -> 13907 bytes .../auto/gui/image/qimagereader/images/marble.xpm | 470 ++ .../gui/image/qimagereader/images/namedcolors.xpm | 18 + .../image/qimagereader/images/negativeheight.bmp | Bin 0 -> 24630 bytes .../gui/image/qimagereader/images/noclearcode.bmp | Bin 0 -> 326 bytes .../gui/image/qimagereader/images/noclearcode.gif | Bin 0 -> 130 bytes .../image/qimagereader/images/nontransparent.xpm | 788 ++++ .../gui/image/qimagereader/images/qt-gif-anim.gif | Bin 0 -> 1661 bytes .../image/qimagereader/images/qt-gif-noanim.gif | Bin 0 -> 1642 bytes tests/auto/gui/image/qimagereader/images/qt.gif | Bin 0 -> 26504 bytes tests/auto/gui/image/qimagereader/images/qt1.gif | Bin 0 -> 7216 bytes tests/auto/gui/image/qimagereader/images/qt2.gif | Bin 0 -> 5559 bytes tests/auto/gui/image/qimagereader/images/qt3.gif | Bin 0 -> 4702 bytes tests/auto/gui/image/qimagereader/images/qt4.gif | Bin 0 -> 4310 bytes tests/auto/gui/image/qimagereader/images/qt5.gif | Bin 0 -> 4234 bytes tests/auto/gui/image/qimagereader/images/qt6.gif | Bin 0 -> 4732 bytes tests/auto/gui/image/qimagereader/images/qt7.gif | Bin 0 -> 5265 bytes tests/auto/gui/image/qimagereader/images/qt8.gif | Bin 0 -> 6144 bytes .../qimagereader/images/qtbug13653-no_eoi.jpg | Bin 0 -> 8250 bytes tests/auto/gui/image/qimagereader/images/rect.svg | 462 ++ tests/auto/gui/image/qimagereader/images/rect.svgz | Bin 0 -> 5082 bytes .../images/rgba_adobedeflate_littleendian.tif | Bin 0 -> 4784 bytes .../qimagereader/images/rgba_lzw_littleendian.tif | Bin 0 -> 26690 bytes .../images/rgba_nocompression_bigendian.tif | Bin 0 -> 160384 bytes .../images/rgba_nocompression_littleendian.tif | Bin 0 -> 160388 bytes .../images/rgba_packbits_littleendian.tif | Bin 0 -> 161370 bytes .../images/rgba_zipdeflate_littleendian.tif | Bin 0 -> 14728 bytes .../auto/gui/image/qimagereader/images/runners.ppm | Bin 0 -> 960016 bytes .../auto/gui/image/qimagereader/images/teapot.ppm | 31 + tests/auto/gui/image/qimagereader/images/test.ppm | 2 + tests/auto/gui/image/qimagereader/images/test.xpm | 260 ++ .../gui/image/qimagereader/images/test32bfv4.bmp | Bin 0 -> 232874 bytes .../gui/image/qimagereader/images/test32v5.bmp | Bin 0 -> 174858 bytes .../tiff_oriented/indexed_orientation_1.tiff | Bin 0 -> 7740 bytes .../tiff_oriented/indexed_orientation_2.tiff | Bin 0 -> 9570 bytes .../tiff_oriented/indexed_orientation_3.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_4.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_5.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_6.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_7.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_8.tiff | Bin 0 -> 11392 bytes .../images/tiff_oriented/mono_orientation_1.tiff | Bin 0 -> 2382 bytes .../images/tiff_oriented/mono_orientation_2.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_3.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_4.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_5.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_6.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_7.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_8.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/original_indexed.tiff | Bin 0 -> 5922 bytes .../images/tiff_oriented/original_mono.tiff | Bin 0 -> 786 bytes .../images/tiff_oriented/original_rgb.tiff | Bin 0 -> 12608 bytes .../images/tiff_oriented/rgb_orientation_1.tiff | Bin 0 -> 15560 bytes .../images/tiff_oriented/rgb_orientation_2.tiff | Bin 0 -> 17972 bytes .../images/tiff_oriented/rgb_orientation_3.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_4.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_5.tiff | Bin 0 -> 17648 bytes .../images/tiff_oriented/rgb_orientation_6.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_7.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_8.tiff | Bin 0 -> 17324 bytes .../gui/image/qimagereader/images/transparent.xpm | 788 ++++ .../gui/image/qimagereader/images/trolltech.gif | Bin 0 -> 42629 bytes tests/auto/gui/image/qimagereader/images/tst7.bmp | Bin 0 -> 582 bytes tests/auto/gui/image/qimagereader/images/tst7.png | Bin 0 -> 167 bytes tests/auto/gui/image/qimagereader/images/txts.png | Bin 0 -> 5413 bytes tests/auto/gui/image/qimagereader/qimagereader.pro | 36 + tests/auto/gui/image/qimagereader/qimagereader.qrc | 71 + .../gui/image/qimagereader/tst_qimagereader.cpp | 2026 +++++++++ tests/auto/gui/image/qimagewriter/.gitignore | 1 + .../gui/image/qimagewriter/images/YCbCr_cmyk.jpg | Bin 0 -> 3699 bytes .../gui/image/qimagewriter/images/YCbCr_rgb.jpg | Bin 0 -> 2045 bytes .../auto/gui/image/qimagewriter/images/beavis.jpg | Bin 0 -> 20688 bytes .../gui/image/qimagewriter/images/colorful.bmp | Bin 0 -> 65002 bytes tests/auto/gui/image/qimagewriter/images/earth.gif | Bin 0 -> 51712 bytes tests/auto/gui/image/qimagewriter/images/font.bmp | Bin 0 -> 1026 bytes tests/auto/gui/image/qimagewriter/images/gnus.xbm | 622 +++ .../auto/gui/image/qimagewriter/images/kollada.png | Bin 0 -> 13907 bytes .../auto/gui/image/qimagewriter/images/marble.xpm | 329 ++ .../auto/gui/image/qimagewriter/images/ship63.pbm | Bin 0 -> 111 bytes .../auto/gui/image/qimagewriter/images/teapot.ppm | 31 + .../auto/gui/image/qimagewriter/images/teapot.tiff | Bin 0 -> 262274 bytes .../gui/image/qimagewriter/images/trolltech.gif | Bin 0 -> 42629 bytes tests/auto/gui/image/qimagewriter/qimagewriter.pro | 25 + .../gui/image/qimagewriter/tst_qimagewriter.cpp | 628 +++ tests/auto/gui/image/qmovie/.gitignore | 1 + .../gui/image/qmovie/animations/comicsecard.gif | Bin 0 -> 12112 bytes tests/auto/gui/image/qmovie/animations/corrupt.gif | Bin 0 -> 847 bytes tests/auto/gui/image/qmovie/animations/dutch.mng | Bin 0 -> 18534 bytes .../auto/gui/image/qmovie/animations/trolltech.gif | Bin 0 -> 70228 bytes tests/auto/gui/image/qmovie/qmovie.pro | 28 + tests/auto/gui/image/qmovie/resources.qrc | 5 + tests/auto/gui/image/qmovie/tst_qmovie.cpp | 225 + tests/auto/gui/image/qpicture/.gitignore | 1 + tests/auto/gui/image/qpicture/qpicture.pro | 6 + tests/auto/gui/image/qpicture/tst_qpicture.cpp | 289 ++ tests/auto/gui/image/qpixmap/.gitignore | 1 + .../qpixmap/convertFromImage/task31722_0/img1.png | Bin 0 -> 26622 bytes .../qpixmap/convertFromImage/task31722_0/img2.png | Bin 0 -> 149 bytes .../qpixmap/convertFromImage/task31722_1/img1.png | Bin 0 -> 26532 bytes .../qpixmap/convertFromImage/task31722_1/img2.png | Bin 0 -> 160 bytes .../qpixmap/convertFromToHICON/icon_32bpp.ico | Bin 0 -> 285478 bytes .../convertFromToHICON/icon_32bpp_16x16.png | Bin 0 -> 754 bytes .../convertFromToHICON/icon_32bpp_256x256.png | Bin 0 -> 16269 bytes .../convertFromToHICON/icon_32bpp_32x32.png | Bin 0 -> 1745 bytes .../convertFromToHICON/icon_32bpp_48x48.png | Bin 0 -> 2618 bytes .../image/qpixmap/convertFromToHICON/icon_8bpp.ico | Bin 0 -> 7406 bytes .../qpixmap/convertFromToHICON/icon_8bpp_16x16.png | Bin 0 -> 1454 bytes .../qpixmap/convertFromToHICON/icon_8bpp_32x32.png | Bin 0 -> 1721 bytes .../qpixmap/convertFromToHICON/icon_8bpp_48x48.png | Bin 0 -> 1967 bytes tests/auto/gui/image/qpixmap/images/designer.png | Bin 0 -> 4282 bytes .../qpixmap/images/dx_-10_dy_-10_50_50_100_100.png | Bin 0 -> 4385 bytes .../image/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png | Bin 0 -> 4104 bytes .../qpixmap/images/dx_-10_dy_0_50_50_100_100.png | Bin 0 -> 4243 bytes .../image/qpixmap/images/dx_-10_dy_0_x_y_w_h.png | Bin 0 -> 4116 bytes .../qpixmap/images/dx_-128_dy_-128_x_y_w_h.png | Bin 0 -> 4282 bytes .../image/qpixmap/images/dx_-128_dy_0_x_y_w_h.png | Bin 0 -> 4282 bytes .../qpixmap/images/dx_0_dy_-10_50_50_100_100.png | Bin 0 -> 4367 bytes .../image/qpixmap/images/dx_0_dy_-10_x_y_w_h.png | Bin 0 -> 4157 bytes .../image/qpixmap/images/dx_0_dy_-128_x_y_w_h.png | Bin 0 -> 4282 bytes .../qpixmap/images/dx_0_dy_0_50_50_100_100.png | Bin 0 -> 4282 bytes .../gui/image/qpixmap/images/dx_0_dy_0_null.png | Bin 0 -> 4282 bytes .../gui/image/qpixmap/images/dx_0_dy_0_x_y_w_h.png | Bin 0 -> 4282 bytes .../qpixmap/images/dx_0_dy_10_50_50_100_100.png | Bin 0 -> 4271 bytes .../image/qpixmap/images/dx_0_dy_10_x_y_w_h.png | Bin 0 -> 4188 bytes .../image/qpixmap/images/dx_0_dy_128_x_y_w_h.png | Bin 0 -> 4282 bytes .../gui/image/qpixmap/images/dx_0_dy_1_null.png | Bin 0 -> 4282 bytes .../qpixmap/images/dx_10_dy_0_50_50_100_100.png | Bin 0 -> 4248 bytes .../image/qpixmap/images/dx_10_dy_0_x_y_w_h.png | Bin 0 -> 4196 bytes .../qpixmap/images/dx_10_dy_10_50_50_100_100.png | Bin 0 -> 4243 bytes .../image/qpixmap/images/dx_10_dy_10_x_y_w_h.png | Bin 0 -> 4220 bytes .../image/qpixmap/images/dx_128_dy_0_x_y_w_h.png | Bin 0 -> 4282 bytes .../qpixmap/images/dx_128_dy_128_64_64_128_128.png | Bin 0 -> 4282 bytes .../image/qpixmap/images/dx_128_dy_128_x_y_w_h.png | Bin 0 -> 4282 bytes .../gui/image/qpixmap/images/dx_1_dy_0_null.png | Bin 0 -> 4282 bytes .../image/qpixmap/loadFromData/designer_argb32.png | Bin 0 -> 4189 bytes .../loadFromData/designer_indexed8_no_alpha.gif | Bin 0 -> 3317 bytes .../loadFromData/designer_indexed8_no_alpha.png | Bin 0 -> 2431 bytes .../designer_indexed8_no_alpha_animated.gif | Bin 0 -> 4075 bytes .../loadFromData/designer_indexed8_with_alpha.gif | Bin 0 -> 2086 bytes .../loadFromData/designer_indexed8_with_alpha.png | Bin 0 -> 1405 bytes .../designer_indexed8_with_alpha_animated.gif | Bin 0 -> 4138 bytes .../image/qpixmap/loadFromData/designer_rgb32.jpg | Bin 0 -> 11810 bytes .../image/qpixmap/loadFromData/designer_rgb32.png | Bin 0 -> 4282 bytes tests/auto/gui/image/qpixmap/qpixmap.pro | 33 + tests/auto/gui/image/qpixmap/qpixmap.qrc | 29 + tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 1787 ++++++++ tests/auto/gui/image/qpixmapcache/.gitignore | 1 + tests/auto/gui/image/qpixmapcache/qpixmapcache.pro | 6 + .../gui/image/qpixmapcache/tst_qpixmapcache.cpp | 521 +++ tests/auto/gui/image/qpixmapfilter/noise.png | Bin 0 -> 7517 bytes .../auto/gui/image/qpixmapfilter/qpixmapfilter.pro | 13 + .../gui/image/qpixmapfilter/tst_qpixmapfilter.cpp | 450 ++ .../gui/image/qvolatileimage/qvolatileimage.pro | 10 + .../image/qvolatileimage/tst_qvolatileimage.cpp | 403 ++ tests/auto/gui/kernel/kernel.pro | 17 + tests/auto/gui/kernel/qclipboard/.gitignore | 5 + tests/auto/gui/kernel/qclipboard/copier/copier.pro | 10 + tests/auto/gui/kernel/qclipboard/copier/main.cpp | 54 + tests/auto/gui/kernel/qclipboard/paster/main.cpp | 54 + tests/auto/gui/kernel/qclipboard/paster/paster.pro | 11 + tests/auto/gui/kernel/qclipboard/qclipboard.pro | 4 + tests/auto/gui/kernel/qclipboard/test/test.pro | 32 + .../auto/gui/kernel/qclipboard/tst_qclipboard.cpp | 422 ++ tests/auto/gui/kernel/qdrag/.gitignore | 1 + tests/auto/gui/kernel/qdrag/qdrag.pro | 9 + tests/auto/gui/kernel/qdrag/tst_qdrag.cpp | 94 + tests/auto/gui/kernel/qevent/.gitignore | 1 + tests/auto/gui/kernel/qevent/qevent.pro | 4 + tests/auto/gui/kernel/qevent/tst_qevent.cpp | 92 + .../gui/kernel/qfileopenevent/qfileopenevent.pro | 3 + .../qfileopeneventexternal.cpp | 72 + .../qfileopeneventexternal.pro | 10 + tests/auto/gui/kernel/qfileopenevent/test/test.pro | 7 + .../qfileopenevent/test/tst_qfileopenevent.cpp | 362 ++ tests/auto/gui/kernel/qguivariant/.gitignore | 1 + tests/auto/gui/kernel/qguivariant/qguivariant.pro | 5 + .../gui/kernel/qguivariant/tst_qguivariant.cpp | 72 + tests/auto/gui/kernel/qkeysequence/.gitignore | 1 + tests/auto/gui/kernel/qkeysequence/keys_de.qm | Bin 0 -> 721 bytes tests/auto/gui/kernel/qkeysequence/keys_de.ts | 61 + .../auto/gui/kernel/qkeysequence/qkeysequence.pro | 8 + .../auto/gui/kernel/qkeysequence/qkeysequence.qrc | 6 + tests/auto/gui/kernel/qkeysequence/qt_de.qm | Bin 0 -> 186240 bytes .../gui/kernel/qkeysequence/tst_qkeysequence.cpp | 636 +++ tests/auto/gui/kernel/qmouseevent/.gitignore | 1 + tests/auto/gui/kernel/qmouseevent/qmouseevent.pro | 3 + .../gui/kernel/qmouseevent/tst_qmouseevent.cpp | 231 + tests/auto/gui/kernel/qmouseevent_modal/.gitignore | 1 + .../kernel/qmouseevent_modal/qmouseevent_modal.pro | 6 + .../qmouseevent_modal/tst_qmouseevent_modal.cpp | 231 + tests/auto/gui/kernel/qpalette/.gitignore | 1 + tests/auto/gui/kernel/qpalette/qpalette.pro | 6 + tests/auto/gui/kernel/qpalette/tst_qpalette.cpp | 132 + tests/auto/gui/kernel/qshortcut/.gitignore | 1 + tests/auto/gui/kernel/qshortcut/qshortcut.pro | 11 + tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp | 1272 ++++++ tests/auto/gui/kernel/qtouchevent/qtouchevent.pro | 3 + .../gui/kernel/qtouchevent/tst_qtouchevent.cpp | 1398 ++++++ tests/auto/gui/math3d/math3d.pro | 6 + tests/auto/gui/math3d/qmatrixnxn/qmatrixnxn.pro | 2 + .../auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp | 3385 ++++++++++++++ tests/auto/gui/math3d/qquaternion/qquaternion.pro | 2 + .../gui/math3d/qquaternion/tst_qquaternion.cpp | 888 ++++ tests/auto/gui/math3d/qvectornd/qvectornd.pro | 2 + tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp | 2142 +++++++++ tests/auto/gui/painting/painting.pro | 21 + tests/auto/gui/painting/qbrush/.gitignore | 1 + tests/auto/gui/painting/qbrush/qbrush.pro | 3 + tests/auto/gui/painting/qbrush/tst_qbrush.cpp | 423 ++ tests/auto/gui/painting/qcolor/.gitignore | 1 + tests/auto/gui/painting/qcolor/qcolor.pro | 5 + tests/auto/gui/painting/qcolor/tst_qcolor.cpp | 1538 +++++++ tests/auto/gui/painting/qpaintengine/.gitignore | 1 + .../gui/painting/qpaintengine/qpaintengine.pro | 9 + .../gui/painting/qpaintengine/tst_qpaintengine.cpp | 99 + tests/auto/gui/painting/qpainter/.gitignore | 2 + .../qpainter/drawEllipse/10x10SizeAt0x0.png | Bin 0 -> 243 bytes .../qpainter/drawEllipse/10x10SizeAt100x100.png | Bin 0 -> 245 bytes .../qpainter/drawEllipse/10x10SizeAt200x200.png | Bin 0 -> 195 bytes .../qpainter/drawEllipse/13x100SizeAt0x0.png | Bin 0 -> 461 bytes .../qpainter/drawEllipse/13x100SizeAt100x100.png | Bin 0 -> 470 bytes .../qpainter/drawEllipse/13x100SizeAt200x200.png | Bin 0 -> 195 bytes .../qpainter/drawEllipse/200x200SizeAt0x0.png | Bin 0 -> 1294 bytes .../qpainter/drawEllipse/200x200SizeAt100x100.png | Bin 0 -> 619 bytes .../qpainter/drawEllipse/200x200SizeAt200x200.png | Bin 0 -> 195 bytes .../painting/qpainter/drawLine_rop_bitmap/dst.xbm | 6 + .../drawLine_rop_bitmap/res/res_AndNotROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_AndROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_ClearROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_CopyROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_NandROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_NopROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_NorROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_NotAndROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_NotCopyROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_NotOrROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_NotROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_NotXorROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_OrNotROP.xbm | 6 + .../qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_SetROP.xbm | 6 + .../drawLine_rop_bitmap/res/res_XorROP.xbm | 6 + .../gui/painting/qpainter/drawPixmap_rop/dst1.png | Bin 0 -> 184 bytes .../gui/painting/qpainter/drawPixmap_rop/dst2.png | Bin 0 -> 184 bytes .../gui/painting/qpainter/drawPixmap_rop/dst3.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP0.png | Bin 0 -> 214 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP1.png | Bin 0 -> 247 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP2.png | Bin 0 -> 258 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP3.png | Bin 0 -> 253 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP4.png | Bin 0 -> 237 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP5.png | Bin 0 -> 260 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP6.png | Bin 0 -> 258 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP7.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_AndROP0.png | Bin 0 -> 173 bytes .../qpainter/drawPixmap_rop/res/res_AndROP1.png | Bin 0 -> 203 bytes .../qpainter/drawPixmap_rop/res/res_AndROP2.png | Bin 0 -> 217 bytes .../qpainter/drawPixmap_rop/res/res_AndROP3.png | Bin 0 -> 207 bytes .../qpainter/drawPixmap_rop/res/res_AndROP4.png | Bin 0 -> 196 bytes .../qpainter/drawPixmap_rop/res/res_AndROP5.png | Bin 0 -> 213 bytes .../qpainter/drawPixmap_rop/res/res_AndROP6.png | Bin 0 -> 218 bytes .../qpainter/drawPixmap_rop/res/res_AndROP7.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP0.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP1.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP2.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP3.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP4.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP5.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP6.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP7.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP0.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP1.png | Bin 0 -> 176 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP2.png | Bin 0 -> 175 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP3.png | Bin 0 -> 177 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP4.png | Bin 0 -> 176 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP5.png | Bin 0 -> 176 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP6.png | Bin 0 -> 176 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP7.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_NandROP0.png | Bin 0 -> 217 bytes .../qpainter/drawPixmap_rop/res/res_NandROP1.png | Bin 0 -> 242 bytes .../qpainter/drawPixmap_rop/res/res_NandROP2.png | Bin 0 -> 249 bytes .../qpainter/drawPixmap_rop/res/res_NandROP3.png | Bin 0 -> 244 bytes .../qpainter/drawPixmap_rop/res/res_NandROP4.png | Bin 0 -> 234 bytes .../qpainter/drawPixmap_rop/res/res_NandROP5.png | Bin 0 -> 254 bytes .../qpainter/drawPixmap_rop/res/res_NandROP6.png | Bin 0 -> 251 bytes .../qpainter/drawPixmap_rop/res/res_NandROP7.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NopROP0.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NopROP1.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NopROP2.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NopROP3.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NopROP4.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NopROP5.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NopROP6.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NopROP7.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NorROP0.png | Bin 0 -> 211 bytes .../qpainter/drawPixmap_rop/res/res_NorROP1.png | Bin 0 -> 208 bytes .../qpainter/drawPixmap_rop/res/res_NorROP2.png | Bin 0 -> 215 bytes .../qpainter/drawPixmap_rop/res/res_NorROP3.png | Bin 0 -> 187 bytes .../qpainter/drawPixmap_rop/res/res_NorROP4.png | Bin 0 -> 213 bytes .../qpainter/drawPixmap_rop/res/res_NorROP5.png | Bin 0 -> 204 bytes .../qpainter/drawPixmap_rop/res/res_NorROP6.png | Bin 0 -> 198 bytes .../qpainter/drawPixmap_rop/res/res_NorROP7.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP0.png | Bin 0 -> 177 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP1.png | Bin 0 -> 198 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP2.png | Bin 0 -> 195 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP3.png | Bin 0 -> 185 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP4.png | Bin 0 -> 188 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP5.png | Bin 0 -> 198 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP6.png | Bin 0 -> 185 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP7.png | Bin 0 -> 155 bytes .../drawPixmap_rop/res/res_NotCopyROP0.png | Bin 0 -> 168 bytes .../drawPixmap_rop/res/res_NotCopyROP1.png | Bin 0 -> 167 bytes .../drawPixmap_rop/res/res_NotCopyROP2.png | Bin 0 -> 167 bytes .../drawPixmap_rop/res/res_NotCopyROP3.png | Bin 0 -> 167 bytes .../drawPixmap_rop/res/res_NotCopyROP4.png | Bin 0 -> 167 bytes .../drawPixmap_rop/res/res_NotCopyROP5.png | Bin 0 -> 167 bytes .../drawPixmap_rop/res/res_NotCopyROP6.png | Bin 0 -> 167 bytes .../drawPixmap_rop/res/res_NotCopyROP7.png | Bin 0 -> 155 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP0.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP1.png | Bin 0 -> 224 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP2.png | Bin 0 -> 229 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP3.png | Bin 0 -> 224 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP4.png | Bin 0 -> 198 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP5.png | Bin 0 -> 229 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP6.png | Bin 0 -> 227 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP7.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_NotROP0.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NotROP1.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NotROP2.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NotROP3.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NotROP4.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NotROP5.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NotROP6.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NotROP7.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP0.png | Bin 0 -> 239 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP1.png | Bin 0 -> 237 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP2.png | Bin 0 -> 243 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP3.png | Bin 0 -> 226 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP4.png | Bin 0 -> 235 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP5.png | Bin 0 -> 230 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP6.png | Bin 0 -> 232 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP7.png | Bin 0 -> 184 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP0.png | Bin 0 -> 217 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP1.png | Bin 0 -> 213 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP2.png | Bin 0 -> 222 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP3.png | Bin 0 -> 194 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP4.png | Bin 0 -> 219 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP5.png | Bin 0 -> 215 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP6.png | Bin 0 -> 212 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP7.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_OrROP0.png | Bin 0 -> 186 bytes .../qpainter/drawPixmap_rop/res/res_OrROP1.png | Bin 0 -> 212 bytes .../qpainter/drawPixmap_rop/res/res_OrROP2.png | Bin 0 -> 216 bytes .../qpainter/drawPixmap_rop/res/res_OrROP3.png | Bin 0 -> 194 bytes .../qpainter/drawPixmap_rop/res/res_OrROP4.png | Bin 0 -> 207 bytes .../qpainter/drawPixmap_rop/res/res_OrROP5.png | Bin 0 -> 214 bytes .../qpainter/drawPixmap_rop/res/res_OrROP6.png | Bin 0 -> 208 bytes .../qpainter/drawPixmap_rop/res/res_OrROP7.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_SetROP0.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_SetROP1.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_SetROP2.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_SetROP3.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_SetROP4.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_SetROP5.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_SetROP6.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_SetROP7.png | Bin 0 -> 169 bytes .../qpainter/drawPixmap_rop/res/res_XorROP0.png | Bin 0 -> 228 bytes .../qpainter/drawPixmap_rop/res/res_XorROP1.png | Bin 0 -> 255 bytes .../qpainter/drawPixmap_rop/res/res_XorROP2.png | Bin 0 -> 260 bytes .../qpainter/drawPixmap_rop/res/res_XorROP3.png | Bin 0 -> 251 bytes .../qpainter/drawPixmap_rop/res/res_XorROP4.png | Bin 0 -> 251 bytes .../qpainter/drawPixmap_rop/res/res_XorROP5.png | Bin 0 -> 261 bytes .../qpainter/drawPixmap_rop/res/res_XorROP6.png | Bin 0 -> 264 bytes .../qpainter/drawPixmap_rop/res/res_XorROP7.png | Bin 0 -> 228 bytes .../gui/painting/qpainter/drawPixmap_rop/src1.xbm | 12 + .../painting/qpainter/drawPixmap_rop/src2-mask.xbm | 16 + .../gui/painting/qpainter/drawPixmap_rop/src2.xbm | 16 + .../gui/painting/qpainter/drawPixmap_rop/src3.xbm | 12 + .../qpainter/drawPixmap_rop_bitmap/dst.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_AndNotROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_AndROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_ClearROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_CopyROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_NandROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_NopROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_NorROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_NotAndROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_NotOrROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_NotROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_NotXorROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_OrNotROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_OrROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_SetROP.xbm | 6 + .../drawPixmap_rop_bitmap/res/res_XorROP.xbm | 6 + .../qpainter/drawPixmap_rop_bitmap/src1-mask.xbm | 6 + .../qpainter/drawPixmap_rop_bitmap/src1.xbm | 6 + .../qpainter/drawPixmap_rop_bitmap/src2.xbm | 5 + tests/auto/gui/painting/qpainter/qpainter.pro | 20 + tests/auto/gui/painting/qpainter/task217400.png | Bin 0 -> 526 bytes tests/auto/gui/painting/qpainter/tst_qpainter.cpp | 4697 ++++++++++++++++++++ .../qpainter/utils/createImages/createImages.pro | 11 + .../painting/qpainter/utils/createImages/main.cpp | 194 + tests/auto/gui/painting/qpainterpath/.gitignore | 2 + .../gui/painting/qpainterpath/qpainterpath.pro | 5 + .../gui/painting/qpainterpath/tst_qpainterpath.cpp | 1332 ++++++ .../gui/painting/qpainterpathstroker/.gitignore | 1 + .../qpainterpathstroker/qpainterpathstroker.pro | 5 + .../tst_qpainterpathstroker.cpp | 75 + tests/auto/gui/painting/qpathclipper/.gitignore | 1 + tests/auto/gui/painting/qpathclipper/pathcompare.h | 126 + tests/auto/gui/painting/qpathclipper/paths.cpp | 734 +++ tests/auto/gui/painting/qpathclipper/paths.h | 95 + .../gui/painting/qpathclipper/qpathclipper.pro | 11 + .../gui/painting/qpathclipper/tst_qpathclipper.cpp | 1334 ++++++ tests/auto/gui/painting/qpen/.gitignore | 1 + tests/auto/gui/painting/qpen/qpen.pro | 5 + tests/auto/gui/painting/qpen/tst_qpen.cpp | 226 + tests/auto/gui/painting/qpolygon/.gitignore | 1 + tests/auto/gui/painting/qpolygon/qpolygon.pro | 7 + tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp | 105 + tests/auto/gui/painting/qprinter/.gitignore | 4 + tests/auto/gui/painting/qprinter/qprinter.pro | 5 + tests/auto/gui/painting/qprinter/tst_qprinter.cpp | 1044 +++++ tests/auto/gui/painting/qprinterinfo/.gitignore | 1 + .../gui/painting/qprinterinfo/qprinterinfo.pro | 7 + .../gui/painting/qprinterinfo/tst_qprinterinfo.cpp | 401 ++ tests/auto/gui/painting/qregion/.gitignore | 1 + tests/auto/gui/painting/qregion/qregion.pro | 8 + tests/auto/gui/painting/qregion/tst_qregion.cpp | 1012 +++++ tests/auto/gui/painting/qtransform/.gitignore | 1 + tests/auto/gui/painting/qtransform/qtransform.pro | 7 + .../gui/painting/qtransform/tst_qtransform.cpp | 807 ++++ tests/auto/gui/painting/qwmatrix/.gitignore | 1 + tests/auto/gui/painting/qwmatrix/qwmatrix.pro | 6 + tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp | 436 ++ .../text/qabstracttextdocumentlayout/.gitignore | 1 + .../qabstracttextdocumentlayout.pro | 9 + .../tst_qabstracttextdocumentlayout.cpp | 159 + tests/auto/gui/text/qcssparser/.gitignore | 1 + tests/auto/gui/text/qcssparser/qcssparser.pro | 17 + .../qcssparser/testdata/scanner/comments/input | 1 + .../qcssparser/testdata/scanner/comments/output | 4 + .../qcssparser/testdata/scanner/comments2/input | 1 + .../qcssparser/testdata/scanner/comments2/output | 12 + .../qcssparser/testdata/scanner/comments3/input | 1 + .../qcssparser/testdata/scanner/comments3/output | 4 + .../qcssparser/testdata/scanner/comments4/input | 1 + .../qcssparser/testdata/scanner/comments4/output | 3 + .../qcssparser/testdata/scanner/quotedstring/input | 1 + .../testdata/scanner/quotedstring/output | 5 + .../text/qcssparser/testdata/scanner/simple/input | 1 + .../text/qcssparser/testdata/scanner/simple/output | 9 + .../text/qcssparser/testdata/scanner/unicode/input | 1 + .../qcssparser/testdata/scanner/unicode/output | 3 + tests/auto/gui/text/qcssparser/tst_qcssparser.cpp | 1718 +++++++ tests/auto/gui/text/qfont/.gitignore | 1 + tests/auto/gui/text/qfont/qfont.pro | 5 + tests/auto/gui/text/qfont/tst_qfont.cpp | 629 +++ tests/auto/gui/text/qfontdatabase/.gitignore | 1 + tests/auto/gui/text/qfontdatabase/FreeMono.ttf | Bin 0 -> 267400 bytes .../auto/gui/text/qfontdatabase/qfontdatabase.pro | 10 + .../gui/text/qfontdatabase/tst_qfontdatabase.cpp | 294 ++ tests/auto/gui/text/qfontmetrics/.gitignore | 1 + tests/auto/gui/text/qfontmetrics/qfontmetrics.pro | 4 + tests/auto/gui/text/qfontmetrics/testfont.qrc | 5 + .../gui/text/qfontmetrics/tst_qfontmetrics.cpp | 323 ++ tests/auto/gui/text/qfontmetrics/ucs4font.ttf | Bin 0 -> 3076 bytes tests/auto/gui/text/qglyphrun/qglyphrun.pro | 11 + tests/auto/gui/text/qglyphrun/test.ttf | Bin 0 -> 3712 bytes tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp | 679 +++ tests/auto/gui/text/qrawfont/qrawfont.pro | 14 + tests/auto/gui/text/qrawfont/testfont.ttf | Bin 0 -> 63212 bytes .../gui/text/qrawfont/testfont_bold_italic.ttf | Bin 0 -> 49760 bytes tests/auto/gui/text/qrawfont/tst_qrawfont.cpp | 897 ++++ tests/auto/gui/text/qstatictext/qstatictext.pro | 5 + .../auto/gui/text/qstatictext/tst_qstatictext.cpp | 870 ++++ tests/auto/gui/text/qsyntaxhighlighter/.gitignore | 1 + .../text/qsyntaxhighlighter/qsyntaxhighlighter.pro | 4 + .../qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp | 549 +++ tests/auto/gui/text/qtextblock/.gitignore | 1 + tests/auto/gui/text/qtextblock/qtextblock.pro | 9 + tests/auto/gui/text/qtextblock/tst_qtextblock.cpp | 197 + tests/auto/gui/text/qtextcursor/.gitignore | 1 + tests/auto/gui/text/qtextcursor/qtextcursor.pro | 5 + .../auto/gui/text/qtextcursor/tst_qtextcursor.cpp | 1862 ++++++++ tests/auto/gui/text/qtextdocument/.gitignore | 1 + tests/auto/gui/text/qtextdocument/common.h | 93 + .../auto/gui/text/qtextdocument/qtextdocument.pro | 6 + .../gui/text/qtextdocument/tst_qtextdocument.cpp | 2788 ++++++++++++ .../auto/gui/text/qtextdocumentfragment/.gitignore | 1 + .../qtextdocumentfragment.pro | 8 + .../tst_qtextdocumentfragment.cpp | 4030 +++++++++++++++++ tests/auto/gui/text/qtextdocumentlayout/.gitignore | 1 + .../qtextdocumentlayout/qtextdocumentlayout.pro | 5 + .../tst_qtextdocumentlayout.cpp | 276 ++ tests/auto/gui/text/qtextformat/.gitignore | 1 + tests/auto/gui/text/qtextformat/qtextformat.pro | 9 + .../auto/gui/text/qtextformat/tst_qtextformat.cpp | 374 ++ tests/auto/gui/text/qtextlayout/.gitignore | 1 + tests/auto/gui/text/qtextlayout/qtextlayout.pro | 12 + .../auto/gui/text/qtextlayout/tst_qtextlayout.cpp | 1506 +++++++ tests/auto/gui/text/qtextlist/.gitignore | 1 + tests/auto/gui/text/qtextlist/qtextlist.pro | 9 + tests/auto/gui/text/qtextlist/tst_qtextlist.cpp | 453 ++ tests/auto/gui/text/qtextobject/.gitignore | 1 + tests/auto/gui/text/qtextobject/qtextobject.pro | 9 + .../auto/gui/text/qtextobject/tst_qtextobject.cpp | 128 + tests/auto/gui/text/qtextodfwriter/.gitignore | 1 + .../gui/text/qtextodfwriter/qtextodfwriter.pro | 6 + .../gui/text/qtextodfwriter/tst_qtextodfwriter.cpp | 426 ++ tests/auto/gui/text/qtextpiecetable/.gitignore | 1 + .../gui/text/qtextpiecetable/qtextpiecetable.pro | 9 + .../text/qtextpiecetable/tst_qtextpiecetable.cpp | 1155 +++++ tests/auto/gui/text/qtextscriptengine/.gitignore | 1 + .../text/qtextscriptengine/generate/generate.pro | 14 + .../gui/text/qtextscriptengine/generate/main.cpp | 129 + .../text/qtextscriptengine/qtextscriptengine.pro | 7 + .../qtextscriptengine/tst_qtextscriptengine.cpp | 1304 ++++++ tests/auto/gui/text/qtexttable/.gitignore | 1 + tests/auto/gui/text/qtexttable/qtexttable.pro | 6 + tests/auto/gui/text/qtexttable/tst_qtexttable.cpp | 1004 +++++ tests/auto/gui/text/qzip/.gitignore | 1 + tests/auto/gui/text/qzip/qzip.pro | 12 + tests/auto/gui/text/qzip/testdata/symlink.zip | Bin 0 -> 289 bytes tests/auto/gui/text/qzip/testdata/test.zip | Bin 0 -> 286 bytes tests/auto/gui/text/qzip/tst_qzip.cpp | 167 + tests/auto/gui/text/text.pro | 32 + tests/auto/gui/util/qdesktopservices/.gitignore | 1 + .../gui/util/qdesktopservices/qdesktopservices.pro | 30 + .../util/qdesktopservices/tst_qdesktopservices.cpp | 388 ++ tests/auto/gui/util/util.pro | 4 + tests/auto/other.pro | 10 - tests/auto/qabstracttextdocumentlayout/.gitignore | 1 - .../qabstracttextdocumentlayout.pro | 9 - .../tst_qabstracttextdocumentlayout.cpp | 159 - tests/auto/qbrush/.gitignore | 1 - tests/auto/qbrush/qbrush.pro | 3 - tests/auto/qbrush/tst_qbrush.cpp | 423 -- tests/auto/qclipboard/.gitignore | 5 - tests/auto/qclipboard/copier/copier.pro | 10 - tests/auto/qclipboard/copier/main.cpp | 54 - tests/auto/qclipboard/paster/main.cpp | 54 - tests/auto/qclipboard/paster/paster.pro | 11 - tests/auto/qclipboard/qclipboard.pro | 4 - tests/auto/qclipboard/test/test.pro | 32 - tests/auto/qclipboard/tst_qclipboard.cpp | 422 -- tests/auto/qcolor/.gitignore | 1 - tests/auto/qcolor/qcolor.pro | 5 - tests/auto/qcolor/tst_qcolor.cpp | 1538 ------- tests/auto/qcssparser/.gitignore | 1 - tests/auto/qcssparser/qcssparser.pro | 17 - .../qcssparser/testdata/scanner/comments/input | 1 - .../qcssparser/testdata/scanner/comments/output | 4 - .../qcssparser/testdata/scanner/comments2/input | 1 - .../qcssparser/testdata/scanner/comments2/output | 12 - .../qcssparser/testdata/scanner/comments3/input | 1 - .../qcssparser/testdata/scanner/comments3/output | 4 - .../qcssparser/testdata/scanner/comments4/input | 1 - .../qcssparser/testdata/scanner/comments4/output | 3 - .../qcssparser/testdata/scanner/quotedstring/input | 1 - .../testdata/scanner/quotedstring/output | 5 - .../auto/qcssparser/testdata/scanner/simple/input | 1 - .../auto/qcssparser/testdata/scanner/simple/output | 9 - .../auto/qcssparser/testdata/scanner/unicode/input | 1 - .../qcssparser/testdata/scanner/unicode/output | 3 - tests/auto/qcssparser/tst_qcssparser.cpp | 1718 ------- tests/auto/qdesktopservices/.gitignore | 1 - tests/auto/qdesktopservices/qdesktopservices.pro | 30 - .../auto/qdesktopservices/tst_qdesktopservices.cpp | 388 -- tests/auto/qdrag/.gitignore | 1 - tests/auto/qdrag/qdrag.pro | 9 - tests/auto/qdrag/tst_qdrag.cpp | 94 - tests/auto/qevent/.gitignore | 1 - tests/auto/qevent/qevent.pro | 4 - tests/auto/qevent/tst_qevent.cpp | 92 - tests/auto/qfileopenevent/qfileopenevent.pro | 3 - .../qfileopeneventexternal.cpp | 72 - .../qfileopeneventexternal.pro | 10 - tests/auto/qfileopenevent/test/test.pro | 7 - .../qfileopenevent/test/tst_qfileopenevent.cpp | 362 -- tests/auto/qfont/.gitignore | 1 - tests/auto/qfont/qfont.pro | 5 - tests/auto/qfont/tst_qfont.cpp | 629 --- tests/auto/qfontdatabase/.gitignore | 1 - tests/auto/qfontdatabase/FreeMono.ttf | Bin 267400 -> 0 bytes tests/auto/qfontdatabase/qfontdatabase.pro | 10 - tests/auto/qfontdatabase/tst_qfontdatabase.cpp | 294 -- tests/auto/qfontmetrics/.gitignore | 1 - tests/auto/qfontmetrics/qfontmetrics.pro | 4 - tests/auto/qfontmetrics/testfont.qrc | 5 - tests/auto/qfontmetrics/tst_qfontmetrics.cpp | 323 -- tests/auto/qfontmetrics/ucs4font.ttf | Bin 3076 -> 0 bytes tests/auto/qgl/qgl.qrc | 2 +- tests/auto/qglyphrun/qglyphrun.pro | 11 - tests/auto/qglyphrun/test.ttf | Bin 3712 -> 0 bytes tests/auto/qglyphrun/tst_qglyphrun.cpp | 679 --- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 2 +- tests/auto/qguivariant/.gitignore | 1 - tests/auto/qguivariant/qguivariant.pro | 5 - tests/auto/qguivariant/tst_qguivariant.cpp | 72 - tests/auto/qicoimageformat/.gitignore | 1 - .../qicoimageformat/icons/invalid/35floppy.ico | Bin 1078 -> 0 bytes .../auto/qicoimageformat/icons/valid/35FLOPPY.ICO | Bin 1078 -> 0 bytes .../qicoimageformat/icons/valid/AddPerfMon.ico | Bin 1078 -> 0 bytes tests/auto/qicoimageformat/icons/valid/App.ico | Bin 318 -> 0 bytes .../icons/valid/Obj_N2_Internal_Mem.ico | Bin 25214 -> 0 bytes tests/auto/qicoimageformat/icons/valid/Qt.ico | Bin 31371 -> 0 bytes .../qicoimageformat/icons/valid/Status_Play.ico | Bin 2862 -> 0 bytes tests/auto/qicoimageformat/icons/valid/TIMER01.ICO | Bin 1078 -> 0 bytes tests/auto/qicoimageformat/icons/valid/WORLD.ico | Bin 3310 -> 0 bytes tests/auto/qicoimageformat/icons/valid/WORLDH.ico | Bin 3310 -> 0 bytes .../qicoimageformat/icons/valid/abcardWindow.ico | Bin 22486 -> 0 bytes .../icons/valid/semitransparent.ico | Bin 25214 -> 0 bytes .../icons/valid/trolltechlogo_tiny.ico | Bin 3006 -> 0 bytes tests/auto/qicoimageformat/qicoimageformat.pro | 28 - tests/auto/qicoimageformat/tst_qicoimageformat.cpp | 338 -- tests/auto/qicon/.gitignore | 1 - tests/auto/qicon/heart.svg | 55 - tests/auto/qicon/heart.svgz | Bin 1506 -> 0 bytes .../testtheme/16x16/actions/appointment-new.png | Bin 897 -> 0 bytes .../testtheme/22x22/actions/appointment-new.png | Bin 1411 -> 0 bytes .../testtheme/32x32/actions/appointment-new.png | Bin 2399 -> 0 bytes tests/auto/qicon/icons/testtheme/index.theme | 492 -- .../icons/testtheme/scalable/actions/svg-only.svg | 425 -- .../themeparent/16x16/actions/address-book-new.png | Bin 796 -> 0 bytes .../themeparent/16x16/actions/appointment-new.png | Bin 897 -> 0 bytes .../themeparent/22x22/actions/address-book-new.png | Bin 924 -> 0 bytes .../themeparent/22x22/actions/appointment-new.png | Bin 1411 -> 0 bytes .../themeparent/32x32/actions/address-book-new.png | Bin 1897 -> 0 bytes .../themeparent/32x32/actions/appointment-new.png | Bin 2399 -> 0 bytes tests/auto/qicon/icons/themeparent/index.theme | 492 -- .../scalable/actions/address-book-new.svg | 389 -- .../scalable/actions/appointment-new.svg | 425 -- tests/auto/qicon/image.png | Bin 14743 -> 0 bytes tests/auto/qicon/qicon.pro | 30 - tests/auto/qicon/rect.png | Bin 175 -> 0 bytes tests/auto/qicon/rect.svg | 76 - tests/auto/qicon/trash.svg | 58 - tests/auto/qicon/tst_qicon.cpp | 781 ---- tests/auto/qicon/tst_qicon.qrc | 20 - tests/auto/qimage/.gitignore | 1 - tests/auto/qimage/images/image.bmp | Bin 306 -> 0 bytes tests/auto/qimage/images/image.gif | Bin 1089 -> 0 bytes tests/auto/qimage/images/image.ico | Bin 10134 -> 0 bytes tests/auto/qimage/images/image.jpg | Bin 696 -> 0 bytes tests/auto/qimage/images/image.pbm | 8 - tests/auto/qimage/images/image.pgm | 10 - tests/auto/qimage/images/image.png | Bin 549 -> 0 bytes tests/auto/qimage/images/image.ppm | 7 - tests/auto/qimage/images/image.tif | Bin 2242 -> 0 bytes tests/auto/qimage/images/image.xbm | 5 - tests/auto/qimage/images/image.xpm | 261 -- tests/auto/qimage/qimage.pro | 23 - tests/auto/qimage/tst_qimage.cpp | 2014 --------- tests/auto/qimageiohandler/.gitignore | 1 - tests/auto/qimageiohandler/qimageiohandler.pro | 9 - tests/auto/qimageiohandler/tst_qimageiohandler.cpp | 96 - tests/auto/qimagereader/.gitignore | 2 - tests/auto/qimagereader/baseline/35floppy.png | Bin 329 -> 0 bytes tests/auto/qimagereader/baseline/connect.png | Bin 12943 -> 0 bytes tests/auto/qimagereader/baseline/kde_favicon.png | Bin 514 -> 0 bytes .../auto/qimagereader/baseline/semitransparent.png | Bin 545 -> 0 bytes tests/auto/qimagereader/images/16bpp.bmp | Bin 153654 -> 0 bytes tests/auto/qimagereader/images/4bpp-rle.bmp | Bin 23662 -> 0 bytes tests/auto/qimagereader/images/YCbCr_cmyk.jpg | Bin 3699 -> 0 bytes tests/auto/qimagereader/images/YCbCr_cmyk.png | Bin 230 -> 0 bytes tests/auto/qimagereader/images/YCbCr_rgb.jpg | Bin 2045 -> 0 bytes tests/auto/qimagereader/images/away.png | Bin 753 -> 0 bytes tests/auto/qimagereader/images/ball.mng | Bin 34394 -> 0 bytes tests/auto/qimagereader/images/bat1.gif | Bin 953 -> 0 bytes tests/auto/qimagereader/images/bat2.gif | Bin 980 -> 0 bytes tests/auto/qimagereader/images/beavis.jpg | Bin 20688 -> 0 bytes tests/auto/qimagereader/images/black.png | Bin 697 -> 0 bytes tests/auto/qimagereader/images/black.xpm | 65 - tests/auto/qimagereader/images/colorful.bmp | Bin 65002 -> 0 bytes tests/auto/qimagereader/images/corrupt-colors.xpm | 26 - tests/auto/qimagereader/images/corrupt-data.tif | Bin 8590 -> 0 bytes .../qimagereader/images/corrupt-pixel-count.xpm | 11 - tests/auto/qimagereader/images/corrupt-pixels.xpm | 7 - tests/auto/qimagereader/images/corrupt.bmp | Bin 116 -> 0 bytes tests/auto/qimagereader/images/corrupt.gif | Bin 2608 -> 0 bytes tests/auto/qimagereader/images/corrupt.jpg | Bin 18 -> 0 bytes tests/auto/qimagereader/images/corrupt.mng | Bin 183 -> 0 bytes tests/auto/qimagereader/images/corrupt.png | Bin 95 -> 0 bytes tests/auto/qimagereader/images/corrupt.svg | 32 - tests/auto/qimagereader/images/corrupt.svgz | Bin 407 -> 0 bytes tests/auto/qimagereader/images/corrupt.xbm | 5 - .../auto/qimagereader/images/crash-signed-char.bmp | Bin 45748 -> 0 bytes tests/auto/qimagereader/images/earth.gif | Bin 51712 -> 0 bytes tests/auto/qimagereader/images/endless-anim.gif | Bin 819 -> 0 bytes tests/auto/qimagereader/images/fire.mng | Bin 44430 -> 0 bytes tests/auto/qimagereader/images/font.bmp | Bin 1026 -> 0 bytes tests/auto/qimagereader/images/four-frames.gif | Bin 427 -> 0 bytes tests/auto/qimagereader/images/gnus.xbm | 622 --- tests/auto/qimagereader/images/grayscale-ref.tif | Bin 256182 -> 0 bytes tests/auto/qimagereader/images/grayscale.tif | Bin 64162 -> 0 bytes tests/auto/qimagereader/images/image.pbm | 8 - tests/auto/qimagereader/images/image.pgm | 10 - tests/auto/qimagereader/images/image.png | Bin 549 -> 0 bytes tests/auto/qimagereader/images/image.ppm | 7 - tests/auto/qimagereader/images/image_100dpi.tif | Bin 2242 -> 0 bytes tests/auto/qimagereader/images/kollada-noext | Bin 13907 -> 0 bytes tests/auto/qimagereader/images/kollada.png | Bin 13907 -> 0 bytes tests/auto/qimagereader/images/marble.xpm | 470 -- tests/auto/qimagereader/images/namedcolors.xpm | 18 - tests/auto/qimagereader/images/negativeheight.bmp | Bin 24630 -> 0 bytes tests/auto/qimagereader/images/noclearcode.bmp | Bin 326 -> 0 bytes tests/auto/qimagereader/images/noclearcode.gif | Bin 130 -> 0 bytes tests/auto/qimagereader/images/nontransparent.xpm | 788 ---- tests/auto/qimagereader/images/qt-gif-anim.gif | Bin 1661 -> 0 bytes tests/auto/qimagereader/images/qt-gif-noanim.gif | Bin 1642 -> 0 bytes tests/auto/qimagereader/images/qt.gif | Bin 26504 -> 0 bytes tests/auto/qimagereader/images/qt1.gif | Bin 7216 -> 0 bytes tests/auto/qimagereader/images/qt2.gif | Bin 5559 -> 0 bytes tests/auto/qimagereader/images/qt3.gif | Bin 4702 -> 0 bytes tests/auto/qimagereader/images/qt4.gif | Bin 4310 -> 0 bytes tests/auto/qimagereader/images/qt5.gif | Bin 4234 -> 0 bytes tests/auto/qimagereader/images/qt6.gif | Bin 4732 -> 0 bytes tests/auto/qimagereader/images/qt7.gif | Bin 5265 -> 0 bytes tests/auto/qimagereader/images/qt8.gif | Bin 6144 -> 0 bytes .../auto/qimagereader/images/qtbug13653-no_eoi.jpg | Bin 8250 -> 0 bytes tests/auto/qimagereader/images/rect.svg | 462 -- tests/auto/qimagereader/images/rect.svgz | Bin 5082 -> 0 bytes .../images/rgba_adobedeflate_littleendian.tif | Bin 4784 -> 0 bytes .../qimagereader/images/rgba_lzw_littleendian.tif | Bin 26690 -> 0 bytes .../images/rgba_nocompression_bigendian.tif | Bin 160384 -> 0 bytes .../images/rgba_nocompression_littleendian.tif | Bin 160388 -> 0 bytes .../images/rgba_packbits_littleendian.tif | Bin 161370 -> 0 bytes .../images/rgba_zipdeflate_littleendian.tif | Bin 14728 -> 0 bytes tests/auto/qimagereader/images/runners.ppm | Bin 960016 -> 0 bytes tests/auto/qimagereader/images/teapot.ppm | 31 - tests/auto/qimagereader/images/test.ppm | 2 - tests/auto/qimagereader/images/test.xpm | 260 -- tests/auto/qimagereader/images/test32bfv4.bmp | Bin 232874 -> 0 bytes tests/auto/qimagereader/images/test32v5.bmp | Bin 174858 -> 0 bytes .../tiff_oriented/indexed_orientation_1.tiff | Bin 7740 -> 0 bytes .../tiff_oriented/indexed_orientation_2.tiff | Bin 9570 -> 0 bytes .../tiff_oriented/indexed_orientation_3.tiff | Bin 11392 -> 0 bytes .../tiff_oriented/indexed_orientation_4.tiff | Bin 11392 -> 0 bytes .../tiff_oriented/indexed_orientation_5.tiff | Bin 11392 -> 0 bytes .../tiff_oriented/indexed_orientation_6.tiff | Bin 11392 -> 0 bytes .../tiff_oriented/indexed_orientation_7.tiff | Bin 11392 -> 0 bytes .../tiff_oriented/indexed_orientation_8.tiff | Bin 11392 -> 0 bytes .../images/tiff_oriented/mono_orientation_1.tiff | Bin 2382 -> 0 bytes .../images/tiff_oriented/mono_orientation_2.tiff | Bin 1608 -> 0 bytes .../images/tiff_oriented/mono_orientation_3.tiff | Bin 1608 -> 0 bytes .../images/tiff_oriented/mono_orientation_4.tiff | Bin 1608 -> 0 bytes .../images/tiff_oriented/mono_orientation_5.tiff | Bin 1608 -> 0 bytes .../images/tiff_oriented/mono_orientation_6.tiff | Bin 1608 -> 0 bytes .../images/tiff_oriented/mono_orientation_7.tiff | Bin 1608 -> 0 bytes .../images/tiff_oriented/mono_orientation_8.tiff | Bin 1608 -> 0 bytes .../images/tiff_oriented/original_indexed.tiff | Bin 5922 -> 0 bytes .../images/tiff_oriented/original_mono.tiff | Bin 786 -> 0 bytes .../images/tiff_oriented/original_rgb.tiff | Bin 12608 -> 0 bytes .../images/tiff_oriented/rgb_orientation_1.tiff | Bin 15560 -> 0 bytes .../images/tiff_oriented/rgb_orientation_2.tiff | Bin 17972 -> 0 bytes .../images/tiff_oriented/rgb_orientation_3.tiff | Bin 17324 -> 0 bytes .../images/tiff_oriented/rgb_orientation_4.tiff | Bin 17324 -> 0 bytes .../images/tiff_oriented/rgb_orientation_5.tiff | Bin 17648 -> 0 bytes .../images/tiff_oriented/rgb_orientation_6.tiff | Bin 17324 -> 0 bytes .../images/tiff_oriented/rgb_orientation_7.tiff | Bin 17324 -> 0 bytes .../images/tiff_oriented/rgb_orientation_8.tiff | Bin 17324 -> 0 bytes tests/auto/qimagereader/images/transparent.xpm | 788 ---- tests/auto/qimagereader/images/trolltech.gif | Bin 42629 -> 0 bytes tests/auto/qimagereader/images/tst7.bmp | Bin 582 -> 0 bytes tests/auto/qimagereader/images/tst7.png | Bin 167 -> 0 bytes tests/auto/qimagereader/images/txts.png | Bin 5413 -> 0 bytes tests/auto/qimagereader/qimagereader.pro | 36 - tests/auto/qimagereader/qimagereader.qrc | 71 - tests/auto/qimagereader/tst_qimagereader.cpp | 2026 --------- tests/auto/qimagewriter/.gitignore | 1 - tests/auto/qimagewriter/images/YCbCr_cmyk.jpg | Bin 3699 -> 0 bytes tests/auto/qimagewriter/images/YCbCr_rgb.jpg | Bin 2045 -> 0 bytes tests/auto/qimagewriter/images/beavis.jpg | Bin 20688 -> 0 bytes tests/auto/qimagewriter/images/colorful.bmp | Bin 65002 -> 0 bytes tests/auto/qimagewriter/images/earth.gif | Bin 51712 -> 0 bytes tests/auto/qimagewriter/images/font.bmp | Bin 1026 -> 0 bytes tests/auto/qimagewriter/images/gnus.xbm | 622 --- tests/auto/qimagewriter/images/kollada.png | Bin 13907 -> 0 bytes tests/auto/qimagewriter/images/marble.xpm | 329 -- tests/auto/qimagewriter/images/ship63.pbm | Bin 111 -> 0 bytes tests/auto/qimagewriter/images/teapot.ppm | 31 - tests/auto/qimagewriter/images/teapot.tiff | Bin 262274 -> 0 bytes tests/auto/qimagewriter/images/trolltech.gif | Bin 42629 -> 0 bytes tests/auto/qimagewriter/qimagewriter.pro | 25 - tests/auto/qimagewriter/tst_qimagewriter.cpp | 628 --- tests/auto/qkeysequence/.gitignore | 1 - tests/auto/qkeysequence/keys_de.qm | Bin 721 -> 0 bytes tests/auto/qkeysequence/keys_de.ts | 61 - tests/auto/qkeysequence/qkeysequence.pro | 8 - tests/auto/qkeysequence/qkeysequence.qrc | 6 - tests/auto/qkeysequence/qt_de.qm | Bin 186240 -> 0 bytes tests/auto/qkeysequence/tst_qkeysequence.cpp | 636 --- tests/auto/qmatrixnxn/qmatrixnxn.pro | 2 - tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp | 3385 -------------- tests/auto/qmouseevent/.gitignore | 1 - tests/auto/qmouseevent/qmouseevent.pro | 3 - tests/auto/qmouseevent/tst_qmouseevent.cpp | 231 - tests/auto/qmouseevent_modal/.gitignore | 1 - tests/auto/qmouseevent_modal/qmouseevent_modal.pro | 6 - .../qmouseevent_modal/tst_qmouseevent_modal.cpp | 231 - tests/auto/qmovie/.gitignore | 1 - tests/auto/qmovie/animations/comicsecard.gif | Bin 12112 -> 0 bytes tests/auto/qmovie/animations/corrupt.gif | Bin 847 -> 0 bytes tests/auto/qmovie/animations/dutch.mng | Bin 18534 -> 0 bytes tests/auto/qmovie/animations/trolltech.gif | Bin 70228 -> 0 bytes tests/auto/qmovie/qmovie.pro | 28 - tests/auto/qmovie/resources.qrc | 5 - tests/auto/qmovie/tst_qmovie.cpp | 225 - tests/auto/qpaintengine/.gitignore | 1 - tests/auto/qpaintengine/qpaintengine.pro | 9 - tests/auto/qpaintengine/tst_qpaintengine.cpp | 99 - tests/auto/qpainter/.gitignore | 2 - tests/auto/qpainter/drawEllipse/10x10SizeAt0x0.png | Bin 243 -> 0 bytes .../qpainter/drawEllipse/10x10SizeAt100x100.png | Bin 245 -> 0 bytes .../qpainter/drawEllipse/10x10SizeAt200x200.png | Bin 195 -> 0 bytes .../auto/qpainter/drawEllipse/13x100SizeAt0x0.png | Bin 461 -> 0 bytes .../qpainter/drawEllipse/13x100SizeAt100x100.png | Bin 470 -> 0 bytes .../qpainter/drawEllipse/13x100SizeAt200x200.png | Bin 195 -> 0 bytes .../auto/qpainter/drawEllipse/200x200SizeAt0x0.png | Bin 1294 -> 0 bytes .../qpainter/drawEllipse/200x200SizeAt100x100.png | Bin 619 -> 0 bytes .../qpainter/drawEllipse/200x200SizeAt200x200.png | Bin 195 -> 0 bytes tests/auto/qpainter/drawLine_rop_bitmap/dst.xbm | 6 - .../drawLine_rop_bitmap/res/res_AndNotROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_AndROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_ClearROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_CopyROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_NandROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_NopROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_NorROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_NotAndROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_NotCopyROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_NotOrROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_NotROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_NotXorROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_OrNotROP.xbm | 6 - .../qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_SetROP.xbm | 6 - .../drawLine_rop_bitmap/res/res_XorROP.xbm | 6 - tests/auto/qpainter/drawPixmap_rop/dst1.png | Bin 184 -> 0 bytes tests/auto/qpainter/drawPixmap_rop/dst2.png | Bin 184 -> 0 bytes tests/auto/qpainter/drawPixmap_rop/dst3.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP0.png | Bin 214 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP1.png | Bin 247 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP2.png | Bin 258 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP3.png | Bin 253 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP4.png | Bin 237 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP5.png | Bin 260 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP6.png | Bin 258 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndNotROP7.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndROP0.png | Bin 173 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndROP1.png | Bin 203 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndROP2.png | Bin 217 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndROP3.png | Bin 207 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndROP4.png | Bin 196 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndROP5.png | Bin 213 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndROP6.png | Bin 218 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_AndROP7.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP0.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP1.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP2.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP3.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP4.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP5.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP6.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_ClearROP7.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP0.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP1.png | Bin 176 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP2.png | Bin 175 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP3.png | Bin 177 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP4.png | Bin 176 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP5.png | Bin 176 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP6.png | Bin 176 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_CopyROP7.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NandROP0.png | Bin 217 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NandROP1.png | Bin 242 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NandROP2.png | Bin 249 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NandROP3.png | Bin 244 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NandROP4.png | Bin 234 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NandROP5.png | Bin 254 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NandROP6.png | Bin 251 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NandROP7.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NopROP0.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NopROP1.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NopROP2.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NopROP3.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NopROP4.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NopROP5.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NopROP6.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NopROP7.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NorROP0.png | Bin 211 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NorROP1.png | Bin 208 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NorROP2.png | Bin 215 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NorROP3.png | Bin 187 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NorROP4.png | Bin 213 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NorROP5.png | Bin 204 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NorROP6.png | Bin 198 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NorROP7.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP0.png | Bin 177 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP1.png | Bin 198 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP2.png | Bin 195 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP3.png | Bin 185 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP4.png | Bin 188 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP5.png | Bin 198 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP6.png | Bin 185 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotAndROP7.png | Bin 155 -> 0 bytes .../drawPixmap_rop/res/res_NotCopyROP0.png | Bin 168 -> 0 bytes .../drawPixmap_rop/res/res_NotCopyROP1.png | Bin 167 -> 0 bytes .../drawPixmap_rop/res/res_NotCopyROP2.png | Bin 167 -> 0 bytes .../drawPixmap_rop/res/res_NotCopyROP3.png | Bin 167 -> 0 bytes .../drawPixmap_rop/res/res_NotCopyROP4.png | Bin 167 -> 0 bytes .../drawPixmap_rop/res/res_NotCopyROP5.png | Bin 167 -> 0 bytes .../drawPixmap_rop/res/res_NotCopyROP6.png | Bin 167 -> 0 bytes .../drawPixmap_rop/res/res_NotCopyROP7.png | Bin 155 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP0.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP1.png | Bin 224 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP2.png | Bin 229 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP3.png | Bin 224 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP4.png | Bin 198 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP5.png | Bin 229 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP6.png | Bin 227 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotOrROP7.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotROP0.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotROP1.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotROP2.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotROP3.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotROP4.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotROP5.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotROP6.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotROP7.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP0.png | Bin 239 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP1.png | Bin 237 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP2.png | Bin 243 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP3.png | Bin 226 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP4.png | Bin 235 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP5.png | Bin 230 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP6.png | Bin 232 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_NotXorROP7.png | Bin 184 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP0.png | Bin 217 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP1.png | Bin 213 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP2.png | Bin 222 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP3.png | Bin 194 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP4.png | Bin 219 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP5.png | Bin 215 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP6.png | Bin 212 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrNotROP7.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrROP0.png | Bin 186 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrROP1.png | Bin 212 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrROP2.png | Bin 216 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrROP3.png | Bin 194 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrROP4.png | Bin 207 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrROP5.png | Bin 214 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrROP6.png | Bin 208 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_OrROP7.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_SetROP0.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_SetROP1.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_SetROP2.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_SetROP3.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_SetROP4.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_SetROP5.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_SetROP6.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_SetROP7.png | Bin 169 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_XorROP0.png | Bin 228 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_XorROP1.png | Bin 255 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_XorROP2.png | Bin 260 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_XorROP3.png | Bin 251 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_XorROP4.png | Bin 251 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_XorROP5.png | Bin 261 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_XorROP6.png | Bin 264 -> 0 bytes .../qpainter/drawPixmap_rop/res/res_XorROP7.png | Bin 228 -> 0 bytes tests/auto/qpainter/drawPixmap_rop/src1.xbm | 12 - tests/auto/qpainter/drawPixmap_rop/src2-mask.xbm | 16 - tests/auto/qpainter/drawPixmap_rop/src2.xbm | 16 - tests/auto/qpainter/drawPixmap_rop/src3.xbm | 12 - tests/auto/qpainter/drawPixmap_rop_bitmap/dst.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_AndNotROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_AndROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_ClearROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_CopyROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_NandROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_NopROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_NorROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_NotAndROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_NotOrROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_NotROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_NotXorROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_OrNotROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_OrROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_SetROP.xbm | 6 - .../drawPixmap_rop_bitmap/res/res_XorROP.xbm | 6 - .../qpainter/drawPixmap_rop_bitmap/src1-mask.xbm | 6 - tests/auto/qpainter/drawPixmap_rop_bitmap/src1.xbm | 6 - tests/auto/qpainter/drawPixmap_rop_bitmap/src2.xbm | 5 - tests/auto/qpainter/qpainter.pro | 20 - tests/auto/qpainter/task217400.png | Bin 526 -> 0 bytes tests/auto/qpainter/tst_qpainter.cpp | 4697 -------------------- .../qpainter/utils/createImages/createImages.pro | 11 - tests/auto/qpainter/utils/createImages/main.cpp | 194 - tests/auto/qpainterpath/.gitignore | 2 - tests/auto/qpainterpath/qpainterpath.pro | 5 - tests/auto/qpainterpath/tst_qpainterpath.cpp | 1332 ------ tests/auto/qpainterpathstroker/.gitignore | 1 - .../qpainterpathstroker/qpainterpathstroker.pro | 5 - .../tst_qpainterpathstroker.cpp | 75 - tests/auto/qpalette/.gitignore | 1 - tests/auto/qpalette/qpalette.pro | 6 - tests/auto/qpalette/tst_qpalette.cpp | 132 - tests/auto/qpathclipper/.gitignore | 1 - tests/auto/qpathclipper/pathcompare.h | 126 - tests/auto/qpathclipper/paths.cpp | 734 --- tests/auto/qpathclipper/paths.h | 95 - tests/auto/qpathclipper/qpathclipper.pro | 11 - tests/auto/qpathclipper/tst_qpathclipper.cpp | 1334 ------ tests/auto/qpen/.gitignore | 1 - tests/auto/qpen/qpen.pro | 5 - tests/auto/qpen/tst_qpen.cpp | 226 - tests/auto/qpicture/.gitignore | 1 - tests/auto/qpicture/qpicture.pro | 6 - tests/auto/qpicture/tst_qpicture.cpp | 289 -- tests/auto/qpixmap/.gitignore | 1 - .../qpixmap/convertFromImage/task31722_0/img1.png | Bin 26622 -> 0 bytes .../qpixmap/convertFromImage/task31722_0/img2.png | Bin 149 -> 0 bytes .../qpixmap/convertFromImage/task31722_1/img1.png | Bin 26532 -> 0 bytes .../qpixmap/convertFromImage/task31722_1/img2.png | Bin 160 -> 0 bytes .../auto/qpixmap/convertFromToHICON/icon_32bpp.ico | Bin 285478 -> 0 bytes .../convertFromToHICON/icon_32bpp_16x16.png | Bin 754 -> 0 bytes .../convertFromToHICON/icon_32bpp_256x256.png | Bin 16269 -> 0 bytes .../convertFromToHICON/icon_32bpp_32x32.png | Bin 1745 -> 0 bytes .../convertFromToHICON/icon_32bpp_48x48.png | Bin 2618 -> 0 bytes .../auto/qpixmap/convertFromToHICON/icon_8bpp.ico | Bin 7406 -> 0 bytes .../qpixmap/convertFromToHICON/icon_8bpp_16x16.png | Bin 1454 -> 0 bytes .../qpixmap/convertFromToHICON/icon_8bpp_32x32.png | Bin 1721 -> 0 bytes .../qpixmap/convertFromToHICON/icon_8bpp_48x48.png | Bin 1967 -> 0 bytes tests/auto/qpixmap/images/designer.png | Bin 4282 -> 0 bytes .../qpixmap/images/dx_-10_dy_-10_50_50_100_100.png | Bin 4385 -> 0 bytes .../auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png | Bin 4104 -> 0 bytes .../qpixmap/images/dx_-10_dy_0_50_50_100_100.png | Bin 4243 -> 0 bytes tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.png | Bin 4116 -> 0 bytes .../qpixmap/images/dx_-128_dy_-128_x_y_w_h.png | Bin 4282 -> 0 bytes tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.png | Bin 4282 -> 0 bytes .../qpixmap/images/dx_0_dy_-10_50_50_100_100.png | Bin 4367 -> 0 bytes tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.png | Bin 4157 -> 0 bytes tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.png | Bin 4282 -> 0 bytes .../qpixmap/images/dx_0_dy_0_50_50_100_100.png | Bin 4282 -> 0 bytes tests/auto/qpixmap/images/dx_0_dy_0_null.png | Bin 4282 -> 0 bytes tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.png | Bin 4282 -> 0 bytes .../qpixmap/images/dx_0_dy_10_50_50_100_100.png | Bin 4271 -> 0 bytes tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.png | Bin 4188 -> 0 bytes tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.png | Bin 4282 -> 0 bytes tests/auto/qpixmap/images/dx_0_dy_1_null.png | Bin 4282 -> 0 bytes .../qpixmap/images/dx_10_dy_0_50_50_100_100.png | Bin 4248 -> 0 bytes tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.png | Bin 4196 -> 0 bytes .../qpixmap/images/dx_10_dy_10_50_50_100_100.png | Bin 4243 -> 0 bytes tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.png | Bin 4220 -> 0 bytes tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.png | Bin 4282 -> 0 bytes .../qpixmap/images/dx_128_dy_128_64_64_128_128.png | Bin 4282 -> 0 bytes .../auto/qpixmap/images/dx_128_dy_128_x_y_w_h.png | Bin 4282 -> 0 bytes tests/auto/qpixmap/images/dx_1_dy_0_null.png | Bin 4282 -> 0 bytes .../auto/qpixmap/loadFromData/designer_argb32.png | Bin 4189 -> 0 bytes .../loadFromData/designer_indexed8_no_alpha.gif | Bin 3317 -> 0 bytes .../loadFromData/designer_indexed8_no_alpha.png | Bin 2431 -> 0 bytes .../designer_indexed8_no_alpha_animated.gif | Bin 4075 -> 0 bytes .../loadFromData/designer_indexed8_with_alpha.gif | Bin 2086 -> 0 bytes .../loadFromData/designer_indexed8_with_alpha.png | Bin 1405 -> 0 bytes .../designer_indexed8_with_alpha_animated.gif | Bin 4138 -> 0 bytes tests/auto/qpixmap/loadFromData/designer_rgb32.jpg | Bin 11810 -> 0 bytes tests/auto/qpixmap/loadFromData/designer_rgb32.png | Bin 4282 -> 0 bytes tests/auto/qpixmap/qpixmap.pro | 33 - tests/auto/qpixmap/qpixmap.qrc | 29 - tests/auto/qpixmap/tst_qpixmap.cpp | 1787 -------- tests/auto/qpixmapcache/.gitignore | 1 - tests/auto/qpixmapcache/qpixmapcache.pro | 6 - tests/auto/qpixmapcache/tst_qpixmapcache.cpp | 521 --- tests/auto/qpixmapfilter/noise.png | Bin 7517 -> 0 bytes tests/auto/qpixmapfilter/qpixmapfilter.pro | 13 - tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp | 450 -- tests/auto/qpolygon/.gitignore | 1 - tests/auto/qpolygon/qpolygon.pro | 7 - tests/auto/qpolygon/tst_qpolygon.cpp | 105 - tests/auto/qprinter/.gitignore | 4 - tests/auto/qprinter/qprinter.pro | 5 - tests/auto/qprinter/tst_qprinter.cpp | 1044 ----- tests/auto/qprinterinfo/.gitignore | 1 - tests/auto/qprinterinfo/qprinterinfo.pro | 7 - tests/auto/qprinterinfo/tst_qprinterinfo.cpp | 401 -- tests/auto/qquaternion/qquaternion.pro | 2 - tests/auto/qquaternion/tst_qquaternion.cpp | 888 ---- tests/auto/qrawfont/qrawfont.pro | 14 - tests/auto/qrawfont/testfont.ttf | Bin 63212 -> 0 bytes tests/auto/qrawfont/testfont_bold_italic.ttf | Bin 49760 -> 0 bytes tests/auto/qrawfont/tst_qrawfont.cpp | 897 ---- tests/auto/qregion/.gitignore | 1 - tests/auto/qregion/qregion.pro | 8 - tests/auto/qregion/tst_qregion.cpp | 1012 ----- tests/auto/qshortcut/.gitignore | 1 - tests/auto/qshortcut/qshortcut.pro | 11 - tests/auto/qshortcut/tst_qshortcut.cpp | 1272 ------ tests/auto/qstatictext/qstatictext.pro | 5 - tests/auto/qstatictext/tst_qstatictext.cpp | 870 ---- tests/auto/qsyntaxhighlighter/.gitignore | 1 - .../auto/qsyntaxhighlighter/qsyntaxhighlighter.pro | 4 - .../qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp | 549 --- tests/auto/qtextblock/.gitignore | 1 - tests/auto/qtextblock/qtextblock.pro | 9 - tests/auto/qtextblock/tst_qtextblock.cpp | 197 - tests/auto/qtextcursor/.gitignore | 1 - tests/auto/qtextcursor/qtextcursor.pro | 5 - tests/auto/qtextcursor/tst_qtextcursor.cpp | 1862 -------- tests/auto/qtextdocument/.gitignore | 1 - tests/auto/qtextdocument/common.h | 93 - tests/auto/qtextdocument/qtextdocument.pro | 6 - tests/auto/qtextdocument/tst_qtextdocument.cpp | 2788 ------------ tests/auto/qtextdocumentfragment/.gitignore | 1 - .../qtextdocumentfragment.pro | 8 - .../tst_qtextdocumentfragment.cpp | 4030 ----------------- tests/auto/qtextdocumentlayout/.gitignore | 1 - .../qtextdocumentlayout/qtextdocumentlayout.pro | 5 - .../tst_qtextdocumentlayout.cpp | 276 -- tests/auto/qtextformat/.gitignore | 1 - tests/auto/qtextformat/qtextformat.pro | 9 - tests/auto/qtextformat/tst_qtextformat.cpp | 374 -- tests/auto/qtextlayout/.gitignore | 1 - tests/auto/qtextlayout/qtextlayout.pro | 12 - tests/auto/qtextlayout/tst_qtextlayout.cpp | 1506 ------- tests/auto/qtextlist/.gitignore | 1 - tests/auto/qtextlist/qtextlist.pro | 9 - tests/auto/qtextlist/tst_qtextlist.cpp | 453 -- tests/auto/qtextobject/.gitignore | 1 - tests/auto/qtextobject/qtextobject.pro | 9 - tests/auto/qtextobject/tst_qtextobject.cpp | 128 - tests/auto/qtextodfwriter/.gitignore | 1 - tests/auto/qtextodfwriter/qtextodfwriter.pro | 5 - tests/auto/qtextodfwriter/tst_qtextodfwriter.cpp | 426 -- tests/auto/qtextpiecetable/.gitignore | 1 - tests/auto/qtextpiecetable/qtextpiecetable.pro | 9 - tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp | 1155 ----- tests/auto/qtextscriptengine/.gitignore | 1 - tests/auto/qtextscriptengine/generate/generate.pro | 14 - tests/auto/qtextscriptengine/generate/main.cpp | 129 - tests/auto/qtextscriptengine/qtextscriptengine.pro | 7 - .../qtextscriptengine/tst_qtextscriptengine.cpp | 1304 ------ tests/auto/qtexttable/.gitignore | 1 - tests/auto/qtexttable/qtexttable.pro | 6 - tests/auto/qtexttable/tst_qtexttable.cpp | 1004 ----- tests/auto/qtouchevent/qtouchevent.pro | 3 - tests/auto/qtouchevent/tst_qtouchevent.cpp | 1398 ------ tests/auto/qtransform/.gitignore | 1 - tests/auto/qtransform/qtransform.pro | 7 - tests/auto/qtransform/tst_qtransform.cpp | 807 ---- tests/auto/qvectornd/qvectornd.pro | 2 - tests/auto/qvectornd/tst_qvectornd.cpp | 2142 --------- tests/auto/qvolatileimage/qvolatileimage.pro | 10 - tests/auto/qvolatileimage/tst_qvolatileimage.cpp | 403 -- tests/auto/qwmatrix/.gitignore | 1 - tests/auto/qwmatrix/qwmatrix.pro | 6 - tests/auto/qwmatrix/tst_qwmatrix.cpp | 436 -- tests/auto/qzip/.gitignore | 1 - tests/auto/qzip/qzip.pro | 11 - tests/auto/qzip/testdata/symlink.zip | Bin 289 -> 0 bytes tests/auto/qzip/testdata/test.zip | Bin 286 -> 0 bytes tests/auto/qzip/tst_qzip.cpp | 167 - 1268 files changed, 66897 insertions(+), 66857 deletions(-) create mode 100644 tests/auto/gui/gui.pro create mode 100644 tests/auto/gui/image/image.pro create mode 100644 tests/auto/gui/image/qicoimageformat/.gitignore create mode 100644 tests/auto/gui/image/qicoimageformat/icons/invalid/35floppy.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/35FLOPPY.ICO create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/AddPerfMon.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/App.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/Qt.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/Status_Play.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/TIMER01.ICO create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/WORLD.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/WORLDH.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/abcardWindow.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/semitransparent.ico create mode 100644 tests/auto/gui/image/qicoimageformat/icons/valid/trolltechlogo_tiny.ico create mode 100644 tests/auto/gui/image/qicoimageformat/qicoimageformat.pro create mode 100644 tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp create mode 100644 tests/auto/gui/image/qicon/.gitignore create mode 100644 tests/auto/gui/image/qicon/heart.svg create mode 100644 tests/auto/gui/image/qicon/heart.svgz create mode 100644 tests/auto/gui/image/qicon/icons/testtheme/16x16/actions/appointment-new.png create mode 100644 tests/auto/gui/image/qicon/icons/testtheme/22x22/actions/appointment-new.png create mode 100644 tests/auto/gui/image/qicon/icons/testtheme/32x32/actions/appointment-new.png create mode 100644 tests/auto/gui/image/qicon/icons/testtheme/index.theme create mode 100644 tests/auto/gui/image/qicon/icons/testtheme/scalable/actions/svg-only.svg create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/address-book-new.png create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/appointment-new.png create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/address-book-new.png create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/appointment-new.png create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/address-book-new.png create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/appointment-new.png create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/index.theme create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/address-book-new.svg create mode 100644 tests/auto/gui/image/qicon/icons/themeparent/scalable/actions/appointment-new.svg create mode 100644 tests/auto/gui/image/qicon/image.png create mode 100644 tests/auto/gui/image/qicon/qicon.pro create mode 100644 tests/auto/gui/image/qicon/rect.png create mode 100644 tests/auto/gui/image/qicon/rect.svg create mode 100644 tests/auto/gui/image/qicon/trash.svg create mode 100644 tests/auto/gui/image/qicon/tst_qicon.cpp create mode 100644 tests/auto/gui/image/qicon/tst_qicon.qrc create mode 100644 tests/auto/gui/image/qimage/.gitignore create mode 100644 tests/auto/gui/image/qimage/images/image.bmp create mode 100644 tests/auto/gui/image/qimage/images/image.gif create mode 100644 tests/auto/gui/image/qimage/images/image.ico create mode 100644 tests/auto/gui/image/qimage/images/image.jpg create mode 100644 tests/auto/gui/image/qimage/images/image.pbm create mode 100644 tests/auto/gui/image/qimage/images/image.pgm create mode 100644 tests/auto/gui/image/qimage/images/image.png create mode 100644 tests/auto/gui/image/qimage/images/image.ppm create mode 100644 tests/auto/gui/image/qimage/images/image.tif create mode 100644 tests/auto/gui/image/qimage/images/image.xbm create mode 100644 tests/auto/gui/image/qimage/images/image.xpm create mode 100644 tests/auto/gui/image/qimage/qimage.pro create mode 100644 tests/auto/gui/image/qimage/tst_qimage.cpp create mode 100644 tests/auto/gui/image/qimageiohandler/.gitignore create mode 100644 tests/auto/gui/image/qimageiohandler/qimageiohandler.pro create mode 100644 tests/auto/gui/image/qimageiohandler/tst_qimageiohandler.cpp create mode 100644 tests/auto/gui/image/qimagereader/.gitignore create mode 100644 tests/auto/gui/image/qimagereader/baseline/35floppy.png create mode 100644 tests/auto/gui/image/qimagereader/baseline/connect.png create mode 100644 tests/auto/gui/image/qimagereader/baseline/kde_favicon.png create mode 100644 tests/auto/gui/image/qimagereader/baseline/semitransparent.png create mode 100644 tests/auto/gui/image/qimagereader/images/16bpp.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/4bpp-rle.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.jpg create mode 100644 tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.png create mode 100644 tests/auto/gui/image/qimagereader/images/YCbCr_rgb.jpg create mode 100644 tests/auto/gui/image/qimagereader/images/away.png create mode 100644 tests/auto/gui/image/qimagereader/images/ball.mng create mode 100644 tests/auto/gui/image/qimagereader/images/bat1.gif create mode 100644 tests/auto/gui/image/qimagereader/images/bat2.gif create mode 100644 tests/auto/gui/image/qimagereader/images/beavis.jpg create mode 100644 tests/auto/gui/image/qimagereader/images/black.png create mode 100644 tests/auto/gui/image/qimagereader/images/black.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/colorful.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt-colors.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt-data.tif create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt-pixel-count.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt-pixels.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt.gif create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt.jpg create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt.mng create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt.png create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt.svg create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt.svgz create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt.xbm create mode 100644 tests/auto/gui/image/qimagereader/images/crash-signed-char.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/earth.gif create mode 100644 tests/auto/gui/image/qimagereader/images/endless-anim.gif create mode 100644 tests/auto/gui/image/qimagereader/images/fire.mng create mode 100644 tests/auto/gui/image/qimagereader/images/font.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/four-frames.gif create mode 100644 tests/auto/gui/image/qimagereader/images/gnus.xbm create mode 100644 tests/auto/gui/image/qimagereader/images/grayscale-ref.tif create mode 100644 tests/auto/gui/image/qimagereader/images/grayscale.tif create mode 100644 tests/auto/gui/image/qimagereader/images/image.pbm create mode 100644 tests/auto/gui/image/qimagereader/images/image.pgm create mode 100644 tests/auto/gui/image/qimagereader/images/image.png create mode 100644 tests/auto/gui/image/qimagereader/images/image.ppm create mode 100644 tests/auto/gui/image/qimagereader/images/image_100dpi.tif create mode 100644 tests/auto/gui/image/qimagereader/images/kollada-noext create mode 100644 tests/auto/gui/image/qimagereader/images/kollada.png create mode 100644 tests/auto/gui/image/qimagereader/images/marble.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/namedcolors.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/negativeheight.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/noclearcode.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/noclearcode.gif create mode 100644 tests/auto/gui/image/qimagereader/images/nontransparent.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/qt-gif-anim.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt-gif-noanim.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt1.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt2.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt3.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt4.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt5.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt6.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt7.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qt8.gif create mode 100644 tests/auto/gui/image/qimagereader/images/qtbug13653-no_eoi.jpg create mode 100644 tests/auto/gui/image/qimagereader/images/rect.svg create mode 100644 tests/auto/gui/image/qimagereader/images/rect.svgz create mode 100644 tests/auto/gui/image/qimagereader/images/rgba_adobedeflate_littleendian.tif create mode 100644 tests/auto/gui/image/qimagereader/images/rgba_lzw_littleendian.tif create mode 100644 tests/auto/gui/image/qimagereader/images/rgba_nocompression_bigendian.tif create mode 100644 tests/auto/gui/image/qimagereader/images/rgba_nocompression_littleendian.tif create mode 100644 tests/auto/gui/image/qimagereader/images/rgba_packbits_littleendian.tif create mode 100644 tests/auto/gui/image/qimagereader/images/rgba_zipdeflate_littleendian.tif create mode 100644 tests/auto/gui/image/qimagereader/images/runners.ppm create mode 100644 tests/auto/gui/image/qimagereader/images/teapot.ppm create mode 100644 tests/auto/gui/image/qimagereader/images/test.ppm create mode 100644 tests/auto/gui/image/qimagereader/images/test.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/test32bfv4.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/test32v5.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_1.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_2.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_3.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_4.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_5.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_6.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_7.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/mono_orientation_8.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/original_indexed.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/original_mono.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/original_rgb.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff create mode 100644 tests/auto/gui/image/qimagereader/images/transparent.xpm create mode 100644 tests/auto/gui/image/qimagereader/images/trolltech.gif create mode 100644 tests/auto/gui/image/qimagereader/images/tst7.bmp create mode 100644 tests/auto/gui/image/qimagereader/images/tst7.png create mode 100755 tests/auto/gui/image/qimagereader/images/txts.png create mode 100644 tests/auto/gui/image/qimagereader/qimagereader.pro create mode 100644 tests/auto/gui/image/qimagereader/qimagereader.qrc create mode 100644 tests/auto/gui/image/qimagereader/tst_qimagereader.cpp create mode 100644 tests/auto/gui/image/qimagewriter/.gitignore create mode 100644 tests/auto/gui/image/qimagewriter/images/YCbCr_cmyk.jpg create mode 100644 tests/auto/gui/image/qimagewriter/images/YCbCr_rgb.jpg create mode 100644 tests/auto/gui/image/qimagewriter/images/beavis.jpg create mode 100644 tests/auto/gui/image/qimagewriter/images/colorful.bmp create mode 100644 tests/auto/gui/image/qimagewriter/images/earth.gif create mode 100644 tests/auto/gui/image/qimagewriter/images/font.bmp create mode 100644 tests/auto/gui/image/qimagewriter/images/gnus.xbm create mode 100644 tests/auto/gui/image/qimagewriter/images/kollada.png create mode 100644 tests/auto/gui/image/qimagewriter/images/marble.xpm create mode 100644 tests/auto/gui/image/qimagewriter/images/ship63.pbm create mode 100644 tests/auto/gui/image/qimagewriter/images/teapot.ppm create mode 100644 tests/auto/gui/image/qimagewriter/images/teapot.tiff create mode 100644 tests/auto/gui/image/qimagewriter/images/trolltech.gif create mode 100644 tests/auto/gui/image/qimagewriter/qimagewriter.pro create mode 100644 tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp create mode 100644 tests/auto/gui/image/qmovie/.gitignore create mode 100644 tests/auto/gui/image/qmovie/animations/comicsecard.gif create mode 100644 tests/auto/gui/image/qmovie/animations/corrupt.gif create mode 100644 tests/auto/gui/image/qmovie/animations/dutch.mng create mode 100644 tests/auto/gui/image/qmovie/animations/trolltech.gif create mode 100644 tests/auto/gui/image/qmovie/qmovie.pro create mode 100644 tests/auto/gui/image/qmovie/resources.qrc create mode 100644 tests/auto/gui/image/qmovie/tst_qmovie.cpp create mode 100644 tests/auto/gui/image/qpicture/.gitignore create mode 100644 tests/auto/gui/image/qpicture/qpicture.pro create mode 100644 tests/auto/gui/image/qpicture/tst_qpicture.cpp create mode 100644 tests/auto/gui/image/qpixmap/.gitignore create mode 100644 tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img1.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img2.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img1.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img2.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp.ico create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_16x16.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_256x256.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_32x32.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_48x48.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp.ico create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_16x16.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_32x32.png create mode 100644 tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_48x48.png create mode 100644 tests/auto/gui/image/qpixmap/images/designer.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_50_50_100_100.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_-128_dy_0_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_50_50_100_100.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_-128_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_0_50_50_100_100.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_0_null.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_0_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_10_50_50_100_100.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_10_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_128_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_0_dy_1_null.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_10_dy_0_50_50_100_100.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_10_dy_0_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_10_dy_10_50_50_100_100.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_10_dy_10_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_128_dy_0_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_128_dy_128_64_64_128_128.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_128_dy_128_x_y_w_h.png create mode 100644 tests/auto/gui/image/qpixmap/images/dx_1_dy_0_null.png create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_argb32.png create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.gif create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.png create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.gif create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.png create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.jpg create mode 100644 tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.png create mode 100644 tests/auto/gui/image/qpixmap/qpixmap.pro create mode 100644 tests/auto/gui/image/qpixmap/qpixmap.qrc create mode 100644 tests/auto/gui/image/qpixmap/tst_qpixmap.cpp create mode 100644 tests/auto/gui/image/qpixmapcache/.gitignore create mode 100644 tests/auto/gui/image/qpixmapcache/qpixmapcache.pro create mode 100644 tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp create mode 100644 tests/auto/gui/image/qpixmapfilter/noise.png create mode 100644 tests/auto/gui/image/qpixmapfilter/qpixmapfilter.pro create mode 100644 tests/auto/gui/image/qpixmapfilter/tst_qpixmapfilter.cpp create mode 100644 tests/auto/gui/image/qvolatileimage/qvolatileimage.pro create mode 100644 tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp create mode 100644 tests/auto/gui/kernel/kernel.pro create mode 100644 tests/auto/gui/kernel/qclipboard/.gitignore create mode 100644 tests/auto/gui/kernel/qclipboard/copier/copier.pro create mode 100644 tests/auto/gui/kernel/qclipboard/copier/main.cpp create mode 100644 tests/auto/gui/kernel/qclipboard/paster/main.cpp create mode 100644 tests/auto/gui/kernel/qclipboard/paster/paster.pro create mode 100644 tests/auto/gui/kernel/qclipboard/qclipboard.pro create mode 100644 tests/auto/gui/kernel/qclipboard/test/test.pro create mode 100644 tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp create mode 100644 tests/auto/gui/kernel/qdrag/.gitignore create mode 100644 tests/auto/gui/kernel/qdrag/qdrag.pro create mode 100644 tests/auto/gui/kernel/qdrag/tst_qdrag.cpp create mode 100644 tests/auto/gui/kernel/qevent/.gitignore create mode 100644 tests/auto/gui/kernel/qevent/qevent.pro create mode 100644 tests/auto/gui/kernel/qevent/tst_qevent.cpp create mode 100644 tests/auto/gui/kernel/qfileopenevent/qfileopenevent.pro create mode 100644 tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp create mode 100644 tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro create mode 100644 tests/auto/gui/kernel/qfileopenevent/test/test.pro create mode 100644 tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp create mode 100644 tests/auto/gui/kernel/qguivariant/.gitignore create mode 100644 tests/auto/gui/kernel/qguivariant/qguivariant.pro create mode 100644 tests/auto/gui/kernel/qguivariant/tst_qguivariant.cpp create mode 100644 tests/auto/gui/kernel/qkeysequence/.gitignore create mode 100644 tests/auto/gui/kernel/qkeysequence/keys_de.qm create mode 100644 tests/auto/gui/kernel/qkeysequence/keys_de.ts create mode 100644 tests/auto/gui/kernel/qkeysequence/qkeysequence.pro create mode 100644 tests/auto/gui/kernel/qkeysequence/qkeysequence.qrc create mode 100644 tests/auto/gui/kernel/qkeysequence/qt_de.qm create mode 100644 tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp create mode 100644 tests/auto/gui/kernel/qmouseevent/.gitignore create mode 100644 tests/auto/gui/kernel/qmouseevent/qmouseevent.pro create mode 100644 tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp create mode 100644 tests/auto/gui/kernel/qmouseevent_modal/.gitignore create mode 100644 tests/auto/gui/kernel/qmouseevent_modal/qmouseevent_modal.pro create mode 100644 tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp create mode 100644 tests/auto/gui/kernel/qpalette/.gitignore create mode 100644 tests/auto/gui/kernel/qpalette/qpalette.pro create mode 100644 tests/auto/gui/kernel/qpalette/tst_qpalette.cpp create mode 100644 tests/auto/gui/kernel/qshortcut/.gitignore create mode 100644 tests/auto/gui/kernel/qshortcut/qshortcut.pro create mode 100644 tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp create mode 100644 tests/auto/gui/kernel/qtouchevent/qtouchevent.pro create mode 100644 tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp create mode 100644 tests/auto/gui/math3d/math3d.pro create mode 100644 tests/auto/gui/math3d/qmatrixnxn/qmatrixnxn.pro create mode 100644 tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp create mode 100644 tests/auto/gui/math3d/qquaternion/qquaternion.pro create mode 100644 tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp create mode 100644 tests/auto/gui/math3d/qvectornd/qvectornd.pro create mode 100644 tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp create mode 100644 tests/auto/gui/painting/painting.pro create mode 100644 tests/auto/gui/painting/qbrush/.gitignore create mode 100644 tests/auto/gui/painting/qbrush/qbrush.pro create mode 100644 tests/auto/gui/painting/qbrush/tst_qbrush.cpp create mode 100644 tests/auto/gui/painting/qcolor/.gitignore create mode 100644 tests/auto/gui/painting/qcolor/qcolor.pro create mode 100644 tests/auto/gui/painting/qcolor/tst_qcolor.cpp create mode 100644 tests/auto/gui/painting/qpaintengine/.gitignore create mode 100644 tests/auto/gui/painting/qpaintengine/qpaintengine.pro create mode 100644 tests/auto/gui/painting/qpaintengine/tst_qpaintengine.cpp create mode 100644 tests/auto/gui/painting/qpainter/.gitignore create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.png create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.png create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.png create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.png create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.png create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.png create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.png create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.png create mode 100644 tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.png create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/dst.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.png create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/src1.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/src2-mask.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/src2.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop/src3.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/dst.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1.xbm create mode 100644 tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src2.xbm create mode 100644 tests/auto/gui/painting/qpainter/qpainter.pro create mode 100644 tests/auto/gui/painting/qpainter/task217400.png create mode 100644 tests/auto/gui/painting/qpainter/tst_qpainter.cpp create mode 100644 tests/auto/gui/painting/qpainter/utils/createImages/createImages.pro create mode 100644 tests/auto/gui/painting/qpainter/utils/createImages/main.cpp create mode 100644 tests/auto/gui/painting/qpainterpath/.gitignore create mode 100644 tests/auto/gui/painting/qpainterpath/qpainterpath.pro create mode 100644 tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp create mode 100644 tests/auto/gui/painting/qpainterpathstroker/.gitignore create mode 100644 tests/auto/gui/painting/qpainterpathstroker/qpainterpathstroker.pro create mode 100644 tests/auto/gui/painting/qpainterpathstroker/tst_qpainterpathstroker.cpp create mode 100644 tests/auto/gui/painting/qpathclipper/.gitignore create mode 100644 tests/auto/gui/painting/qpathclipper/pathcompare.h create mode 100644 tests/auto/gui/painting/qpathclipper/paths.cpp create mode 100644 tests/auto/gui/painting/qpathclipper/paths.h create mode 100644 tests/auto/gui/painting/qpathclipper/qpathclipper.pro create mode 100644 tests/auto/gui/painting/qpathclipper/tst_qpathclipper.cpp create mode 100644 tests/auto/gui/painting/qpen/.gitignore create mode 100644 tests/auto/gui/painting/qpen/qpen.pro create mode 100644 tests/auto/gui/painting/qpen/tst_qpen.cpp create mode 100644 tests/auto/gui/painting/qpolygon/.gitignore create mode 100644 tests/auto/gui/painting/qpolygon/qpolygon.pro create mode 100644 tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp create mode 100644 tests/auto/gui/painting/qprinter/.gitignore create mode 100644 tests/auto/gui/painting/qprinter/qprinter.pro create mode 100644 tests/auto/gui/painting/qprinter/tst_qprinter.cpp create mode 100644 tests/auto/gui/painting/qprinterinfo/.gitignore create mode 100644 tests/auto/gui/painting/qprinterinfo/qprinterinfo.pro create mode 100644 tests/auto/gui/painting/qprinterinfo/tst_qprinterinfo.cpp create mode 100644 tests/auto/gui/painting/qregion/.gitignore create mode 100644 tests/auto/gui/painting/qregion/qregion.pro create mode 100644 tests/auto/gui/painting/qregion/tst_qregion.cpp create mode 100644 tests/auto/gui/painting/qtransform/.gitignore create mode 100644 tests/auto/gui/painting/qtransform/qtransform.pro create mode 100644 tests/auto/gui/painting/qtransform/tst_qtransform.cpp create mode 100644 tests/auto/gui/painting/qwmatrix/.gitignore create mode 100644 tests/auto/gui/painting/qwmatrix/qwmatrix.pro create mode 100644 tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp create mode 100644 tests/auto/gui/text/qabstracttextdocumentlayout/.gitignore create mode 100644 tests/auto/gui/text/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro create mode 100644 tests/auto/gui/text/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp create mode 100644 tests/auto/gui/text/qcssparser/.gitignore create mode 100644 tests/auto/gui/text/qcssparser/qcssparser.pro create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/comments/input create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/comments/output create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/comments2/input create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/comments2/output create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/comments3/input create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/comments3/output create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/comments4/input create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/comments4/output create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/input create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/quotedstring/output create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/simple/input create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/simple/output create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/unicode/input create mode 100644 tests/auto/gui/text/qcssparser/testdata/scanner/unicode/output create mode 100644 tests/auto/gui/text/qcssparser/tst_qcssparser.cpp create mode 100644 tests/auto/gui/text/qfont/.gitignore create mode 100644 tests/auto/gui/text/qfont/qfont.pro create mode 100644 tests/auto/gui/text/qfont/tst_qfont.cpp create mode 100644 tests/auto/gui/text/qfontdatabase/.gitignore create mode 100644 tests/auto/gui/text/qfontdatabase/FreeMono.ttf create mode 100644 tests/auto/gui/text/qfontdatabase/qfontdatabase.pro create mode 100644 tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp create mode 100644 tests/auto/gui/text/qfontmetrics/.gitignore create mode 100644 tests/auto/gui/text/qfontmetrics/qfontmetrics.pro create mode 100644 tests/auto/gui/text/qfontmetrics/testfont.qrc create mode 100644 tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp create mode 100644 tests/auto/gui/text/qfontmetrics/ucs4font.ttf create mode 100644 tests/auto/gui/text/qglyphrun/qglyphrun.pro create mode 100644 tests/auto/gui/text/qglyphrun/test.ttf create mode 100644 tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp create mode 100644 tests/auto/gui/text/qrawfont/qrawfont.pro create mode 100644 tests/auto/gui/text/qrawfont/testfont.ttf create mode 100644 tests/auto/gui/text/qrawfont/testfont_bold_italic.ttf create mode 100644 tests/auto/gui/text/qrawfont/tst_qrawfont.cpp create mode 100644 tests/auto/gui/text/qstatictext/qstatictext.pro create mode 100644 tests/auto/gui/text/qstatictext/tst_qstatictext.cpp create mode 100644 tests/auto/gui/text/qsyntaxhighlighter/.gitignore create mode 100644 tests/auto/gui/text/qsyntaxhighlighter/qsyntaxhighlighter.pro create mode 100644 tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp create mode 100644 tests/auto/gui/text/qtextblock/.gitignore create mode 100644 tests/auto/gui/text/qtextblock/qtextblock.pro create mode 100644 tests/auto/gui/text/qtextblock/tst_qtextblock.cpp create mode 100644 tests/auto/gui/text/qtextcursor/.gitignore create mode 100644 tests/auto/gui/text/qtextcursor/qtextcursor.pro create mode 100644 tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp create mode 100644 tests/auto/gui/text/qtextdocument/.gitignore create mode 100644 tests/auto/gui/text/qtextdocument/common.h create mode 100644 tests/auto/gui/text/qtextdocument/qtextdocument.pro create mode 100644 tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp create mode 100644 tests/auto/gui/text/qtextdocumentfragment/.gitignore create mode 100644 tests/auto/gui/text/qtextdocumentfragment/qtextdocumentfragment.pro create mode 100644 tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp create mode 100644 tests/auto/gui/text/qtextdocumentlayout/.gitignore create mode 100644 tests/auto/gui/text/qtextdocumentlayout/qtextdocumentlayout.pro create mode 100644 tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp create mode 100644 tests/auto/gui/text/qtextformat/.gitignore create mode 100644 tests/auto/gui/text/qtextformat/qtextformat.pro create mode 100644 tests/auto/gui/text/qtextformat/tst_qtextformat.cpp create mode 100644 tests/auto/gui/text/qtextlayout/.gitignore create mode 100644 tests/auto/gui/text/qtextlayout/qtextlayout.pro create mode 100644 tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp create mode 100644 tests/auto/gui/text/qtextlist/.gitignore create mode 100644 tests/auto/gui/text/qtextlist/qtextlist.pro create mode 100644 tests/auto/gui/text/qtextlist/tst_qtextlist.cpp create mode 100644 tests/auto/gui/text/qtextobject/.gitignore create mode 100644 tests/auto/gui/text/qtextobject/qtextobject.pro create mode 100644 tests/auto/gui/text/qtextobject/tst_qtextobject.cpp create mode 100644 tests/auto/gui/text/qtextodfwriter/.gitignore create mode 100644 tests/auto/gui/text/qtextodfwriter/qtextodfwriter.pro create mode 100644 tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp create mode 100644 tests/auto/gui/text/qtextpiecetable/.gitignore create mode 100644 tests/auto/gui/text/qtextpiecetable/qtextpiecetable.pro create mode 100644 tests/auto/gui/text/qtextpiecetable/tst_qtextpiecetable.cpp create mode 100644 tests/auto/gui/text/qtextscriptengine/.gitignore create mode 100644 tests/auto/gui/text/qtextscriptengine/generate/generate.pro create mode 100644 tests/auto/gui/text/qtextscriptengine/generate/main.cpp create mode 100644 tests/auto/gui/text/qtextscriptengine/qtextscriptengine.pro create mode 100644 tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp create mode 100644 tests/auto/gui/text/qtexttable/.gitignore create mode 100644 tests/auto/gui/text/qtexttable/qtexttable.pro create mode 100644 tests/auto/gui/text/qtexttable/tst_qtexttable.cpp create mode 100644 tests/auto/gui/text/qzip/.gitignore create mode 100644 tests/auto/gui/text/qzip/qzip.pro create mode 100644 tests/auto/gui/text/qzip/testdata/symlink.zip create mode 100644 tests/auto/gui/text/qzip/testdata/test.zip create mode 100644 tests/auto/gui/text/qzip/tst_qzip.cpp create mode 100644 tests/auto/gui/text/text.pro create mode 100644 tests/auto/gui/util/qdesktopservices/.gitignore create mode 100644 tests/auto/gui/util/qdesktopservices/qdesktopservices.pro create mode 100644 tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp create mode 100644 tests/auto/gui/util/util.pro delete mode 100644 tests/auto/qabstracttextdocumentlayout/.gitignore delete mode 100644 tests/auto/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro delete mode 100644 tests/auto/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp delete mode 100644 tests/auto/qbrush/.gitignore delete mode 100644 tests/auto/qbrush/qbrush.pro delete mode 100644 tests/auto/qbrush/tst_qbrush.cpp delete mode 100644 tests/auto/qclipboard/.gitignore delete mode 100644 tests/auto/qclipboard/copier/copier.pro delete mode 100644 tests/auto/qclipboard/copier/main.cpp delete mode 100644 tests/auto/qclipboard/paster/main.cpp delete mode 100644 tests/auto/qclipboard/paster/paster.pro delete mode 100644 tests/auto/qclipboard/qclipboard.pro delete mode 100644 tests/auto/qclipboard/test/test.pro delete mode 100644 tests/auto/qclipboard/tst_qclipboard.cpp delete mode 100644 tests/auto/qcolor/.gitignore delete mode 100644 tests/auto/qcolor/qcolor.pro delete mode 100644 tests/auto/qcolor/tst_qcolor.cpp delete mode 100644 tests/auto/qcssparser/.gitignore delete mode 100644 tests/auto/qcssparser/qcssparser.pro delete mode 100644 tests/auto/qcssparser/testdata/scanner/comments/input delete mode 100644 tests/auto/qcssparser/testdata/scanner/comments/output delete mode 100644 tests/auto/qcssparser/testdata/scanner/comments2/input delete mode 100644 tests/auto/qcssparser/testdata/scanner/comments2/output delete mode 100644 tests/auto/qcssparser/testdata/scanner/comments3/input delete mode 100644 tests/auto/qcssparser/testdata/scanner/comments3/output delete mode 100644 tests/auto/qcssparser/testdata/scanner/comments4/input delete mode 100644 tests/auto/qcssparser/testdata/scanner/comments4/output delete mode 100644 tests/auto/qcssparser/testdata/scanner/quotedstring/input delete mode 100644 tests/auto/qcssparser/testdata/scanner/quotedstring/output delete mode 100644 tests/auto/qcssparser/testdata/scanner/simple/input delete mode 100644 tests/auto/qcssparser/testdata/scanner/simple/output delete mode 100644 tests/auto/qcssparser/testdata/scanner/unicode/input delete mode 100644 tests/auto/qcssparser/testdata/scanner/unicode/output delete mode 100644 tests/auto/qcssparser/tst_qcssparser.cpp delete mode 100644 tests/auto/qdesktopservices/.gitignore delete mode 100644 tests/auto/qdesktopservices/qdesktopservices.pro delete mode 100644 tests/auto/qdesktopservices/tst_qdesktopservices.cpp delete mode 100644 tests/auto/qdrag/.gitignore delete mode 100644 tests/auto/qdrag/qdrag.pro delete mode 100644 tests/auto/qdrag/tst_qdrag.cpp delete mode 100644 tests/auto/qevent/.gitignore delete mode 100644 tests/auto/qevent/qevent.pro delete mode 100644 tests/auto/qevent/tst_qevent.cpp delete mode 100644 tests/auto/qfileopenevent/qfileopenevent.pro delete mode 100644 tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp delete mode 100644 tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro delete mode 100644 tests/auto/qfileopenevent/test/test.pro delete mode 100644 tests/auto/qfileopenevent/test/tst_qfileopenevent.cpp delete mode 100644 tests/auto/qfont/.gitignore delete mode 100644 tests/auto/qfont/qfont.pro delete mode 100644 tests/auto/qfont/tst_qfont.cpp delete mode 100644 tests/auto/qfontdatabase/.gitignore delete mode 100644 tests/auto/qfontdatabase/FreeMono.ttf delete mode 100644 tests/auto/qfontdatabase/qfontdatabase.pro delete mode 100644 tests/auto/qfontdatabase/tst_qfontdatabase.cpp delete mode 100644 tests/auto/qfontmetrics/.gitignore delete mode 100644 tests/auto/qfontmetrics/qfontmetrics.pro delete mode 100644 tests/auto/qfontmetrics/testfont.qrc delete mode 100644 tests/auto/qfontmetrics/tst_qfontmetrics.cpp delete mode 100644 tests/auto/qfontmetrics/ucs4font.ttf delete mode 100644 tests/auto/qglyphrun/qglyphrun.pro delete mode 100644 tests/auto/qglyphrun/test.ttf delete mode 100644 tests/auto/qglyphrun/tst_qglyphrun.cpp delete mode 100644 tests/auto/qguivariant/.gitignore delete mode 100644 tests/auto/qguivariant/qguivariant.pro delete mode 100644 tests/auto/qguivariant/tst_qguivariant.cpp delete mode 100644 tests/auto/qicoimageformat/.gitignore delete mode 100644 tests/auto/qicoimageformat/icons/invalid/35floppy.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/35FLOPPY.ICO delete mode 100644 tests/auto/qicoimageformat/icons/valid/AddPerfMon.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/App.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/Qt.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/Status_Play.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/TIMER01.ICO delete mode 100644 tests/auto/qicoimageformat/icons/valid/WORLD.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/WORLDH.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/abcardWindow.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/semitransparent.ico delete mode 100644 tests/auto/qicoimageformat/icons/valid/trolltechlogo_tiny.ico delete mode 100644 tests/auto/qicoimageformat/qicoimageformat.pro delete mode 100644 tests/auto/qicoimageformat/tst_qicoimageformat.cpp delete mode 100644 tests/auto/qicon/.gitignore delete mode 100644 tests/auto/qicon/heart.svg delete mode 100644 tests/auto/qicon/heart.svgz delete mode 100644 tests/auto/qicon/icons/testtheme/16x16/actions/appointment-new.png delete mode 100644 tests/auto/qicon/icons/testtheme/22x22/actions/appointment-new.png delete mode 100644 tests/auto/qicon/icons/testtheme/32x32/actions/appointment-new.png delete mode 100644 tests/auto/qicon/icons/testtheme/index.theme delete mode 100644 tests/auto/qicon/icons/testtheme/scalable/actions/svg-only.svg delete mode 100644 tests/auto/qicon/icons/themeparent/16x16/actions/address-book-new.png delete mode 100644 tests/auto/qicon/icons/themeparent/16x16/actions/appointment-new.png delete mode 100644 tests/auto/qicon/icons/themeparent/22x22/actions/address-book-new.png delete mode 100644 tests/auto/qicon/icons/themeparent/22x22/actions/appointment-new.png delete mode 100644 tests/auto/qicon/icons/themeparent/32x32/actions/address-book-new.png delete mode 100644 tests/auto/qicon/icons/themeparent/32x32/actions/appointment-new.png delete mode 100644 tests/auto/qicon/icons/themeparent/index.theme delete mode 100644 tests/auto/qicon/icons/themeparent/scalable/actions/address-book-new.svg delete mode 100644 tests/auto/qicon/icons/themeparent/scalable/actions/appointment-new.svg delete mode 100644 tests/auto/qicon/image.png delete mode 100644 tests/auto/qicon/qicon.pro delete mode 100644 tests/auto/qicon/rect.png delete mode 100644 tests/auto/qicon/rect.svg delete mode 100644 tests/auto/qicon/trash.svg delete mode 100644 tests/auto/qicon/tst_qicon.cpp delete mode 100644 tests/auto/qicon/tst_qicon.qrc delete mode 100644 tests/auto/qimage/.gitignore delete mode 100644 tests/auto/qimage/images/image.bmp delete mode 100644 tests/auto/qimage/images/image.gif delete mode 100644 tests/auto/qimage/images/image.ico delete mode 100644 tests/auto/qimage/images/image.jpg delete mode 100644 tests/auto/qimage/images/image.pbm delete mode 100644 tests/auto/qimage/images/image.pgm delete mode 100644 tests/auto/qimage/images/image.png delete mode 100644 tests/auto/qimage/images/image.ppm delete mode 100644 tests/auto/qimage/images/image.tif delete mode 100644 tests/auto/qimage/images/image.xbm delete mode 100644 tests/auto/qimage/images/image.xpm delete mode 100644 tests/auto/qimage/qimage.pro delete mode 100644 tests/auto/qimage/tst_qimage.cpp delete mode 100644 tests/auto/qimageiohandler/.gitignore delete mode 100644 tests/auto/qimageiohandler/qimageiohandler.pro delete mode 100644 tests/auto/qimageiohandler/tst_qimageiohandler.cpp delete mode 100644 tests/auto/qimagereader/.gitignore delete mode 100644 tests/auto/qimagereader/baseline/35floppy.png delete mode 100644 tests/auto/qimagereader/baseline/connect.png delete mode 100644 tests/auto/qimagereader/baseline/kde_favicon.png delete mode 100644 tests/auto/qimagereader/baseline/semitransparent.png delete mode 100644 tests/auto/qimagereader/images/16bpp.bmp delete mode 100644 tests/auto/qimagereader/images/4bpp-rle.bmp delete mode 100644 tests/auto/qimagereader/images/YCbCr_cmyk.jpg delete mode 100644 tests/auto/qimagereader/images/YCbCr_cmyk.png delete mode 100644 tests/auto/qimagereader/images/YCbCr_rgb.jpg delete mode 100644 tests/auto/qimagereader/images/away.png delete mode 100644 tests/auto/qimagereader/images/ball.mng delete mode 100644 tests/auto/qimagereader/images/bat1.gif delete mode 100644 tests/auto/qimagereader/images/bat2.gif delete mode 100644 tests/auto/qimagereader/images/beavis.jpg delete mode 100644 tests/auto/qimagereader/images/black.png delete mode 100644 tests/auto/qimagereader/images/black.xpm delete mode 100644 tests/auto/qimagereader/images/colorful.bmp delete mode 100644 tests/auto/qimagereader/images/corrupt-colors.xpm delete mode 100644 tests/auto/qimagereader/images/corrupt-data.tif delete mode 100644 tests/auto/qimagereader/images/corrupt-pixel-count.xpm delete mode 100644 tests/auto/qimagereader/images/corrupt-pixels.xpm delete mode 100644 tests/auto/qimagereader/images/corrupt.bmp delete mode 100644 tests/auto/qimagereader/images/corrupt.gif delete mode 100644 tests/auto/qimagereader/images/corrupt.jpg delete mode 100644 tests/auto/qimagereader/images/corrupt.mng delete mode 100644 tests/auto/qimagereader/images/corrupt.png delete mode 100644 tests/auto/qimagereader/images/corrupt.svg delete mode 100644 tests/auto/qimagereader/images/corrupt.svgz delete mode 100644 tests/auto/qimagereader/images/corrupt.xbm delete mode 100644 tests/auto/qimagereader/images/crash-signed-char.bmp delete mode 100644 tests/auto/qimagereader/images/earth.gif delete mode 100644 tests/auto/qimagereader/images/endless-anim.gif delete mode 100644 tests/auto/qimagereader/images/fire.mng delete mode 100644 tests/auto/qimagereader/images/font.bmp delete mode 100644 tests/auto/qimagereader/images/four-frames.gif delete mode 100644 tests/auto/qimagereader/images/gnus.xbm delete mode 100644 tests/auto/qimagereader/images/grayscale-ref.tif delete mode 100644 tests/auto/qimagereader/images/grayscale.tif delete mode 100644 tests/auto/qimagereader/images/image.pbm delete mode 100644 tests/auto/qimagereader/images/image.pgm delete mode 100644 tests/auto/qimagereader/images/image.png delete mode 100644 tests/auto/qimagereader/images/image.ppm delete mode 100644 tests/auto/qimagereader/images/image_100dpi.tif delete mode 100644 tests/auto/qimagereader/images/kollada-noext delete mode 100644 tests/auto/qimagereader/images/kollada.png delete mode 100644 tests/auto/qimagereader/images/marble.xpm delete mode 100644 tests/auto/qimagereader/images/namedcolors.xpm delete mode 100644 tests/auto/qimagereader/images/negativeheight.bmp delete mode 100644 tests/auto/qimagereader/images/noclearcode.bmp delete mode 100644 tests/auto/qimagereader/images/noclearcode.gif delete mode 100644 tests/auto/qimagereader/images/nontransparent.xpm delete mode 100644 tests/auto/qimagereader/images/qt-gif-anim.gif delete mode 100644 tests/auto/qimagereader/images/qt-gif-noanim.gif delete mode 100644 tests/auto/qimagereader/images/qt.gif delete mode 100644 tests/auto/qimagereader/images/qt1.gif delete mode 100644 tests/auto/qimagereader/images/qt2.gif delete mode 100644 tests/auto/qimagereader/images/qt3.gif delete mode 100644 tests/auto/qimagereader/images/qt4.gif delete mode 100644 tests/auto/qimagereader/images/qt5.gif delete mode 100644 tests/auto/qimagereader/images/qt6.gif delete mode 100644 tests/auto/qimagereader/images/qt7.gif delete mode 100644 tests/auto/qimagereader/images/qt8.gif delete mode 100644 tests/auto/qimagereader/images/qtbug13653-no_eoi.jpg delete mode 100644 tests/auto/qimagereader/images/rect.svg delete mode 100644 tests/auto/qimagereader/images/rect.svgz delete mode 100644 tests/auto/qimagereader/images/rgba_adobedeflate_littleendian.tif delete mode 100644 tests/auto/qimagereader/images/rgba_lzw_littleendian.tif delete mode 100644 tests/auto/qimagereader/images/rgba_nocompression_bigendian.tif delete mode 100644 tests/auto/qimagereader/images/rgba_nocompression_littleendian.tif delete mode 100644 tests/auto/qimagereader/images/rgba_packbits_littleendian.tif delete mode 100644 tests/auto/qimagereader/images/rgba_zipdeflate_littleendian.tif delete mode 100644 tests/auto/qimagereader/images/runners.ppm delete mode 100644 tests/auto/qimagereader/images/teapot.ppm delete mode 100644 tests/auto/qimagereader/images/test.ppm delete mode 100644 tests/auto/qimagereader/images/test.xpm delete mode 100644 tests/auto/qimagereader/images/test32bfv4.bmp delete mode 100644 tests/auto/qimagereader/images/test32v5.bmp delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff delete mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff delete mode 100644 tests/auto/qimagereader/images/transparent.xpm delete mode 100644 tests/auto/qimagereader/images/trolltech.gif delete mode 100644 tests/auto/qimagereader/images/tst7.bmp delete mode 100644 tests/auto/qimagereader/images/tst7.png delete mode 100755 tests/auto/qimagereader/images/txts.png delete mode 100644 tests/auto/qimagereader/qimagereader.pro delete mode 100644 tests/auto/qimagereader/qimagereader.qrc delete mode 100644 tests/auto/qimagereader/tst_qimagereader.cpp delete mode 100644 tests/auto/qimagewriter/.gitignore delete mode 100644 tests/auto/qimagewriter/images/YCbCr_cmyk.jpg delete mode 100644 tests/auto/qimagewriter/images/YCbCr_rgb.jpg delete mode 100644 tests/auto/qimagewriter/images/beavis.jpg delete mode 100644 tests/auto/qimagewriter/images/colorful.bmp delete mode 100644 tests/auto/qimagewriter/images/earth.gif delete mode 100644 tests/auto/qimagewriter/images/font.bmp delete mode 100644 tests/auto/qimagewriter/images/gnus.xbm delete mode 100644 tests/auto/qimagewriter/images/kollada.png delete mode 100644 tests/auto/qimagewriter/images/marble.xpm delete mode 100644 tests/auto/qimagewriter/images/ship63.pbm delete mode 100644 tests/auto/qimagewriter/images/teapot.ppm delete mode 100644 tests/auto/qimagewriter/images/teapot.tiff delete mode 100644 tests/auto/qimagewriter/images/trolltech.gif delete mode 100644 tests/auto/qimagewriter/qimagewriter.pro delete mode 100644 tests/auto/qimagewriter/tst_qimagewriter.cpp delete mode 100644 tests/auto/qkeysequence/.gitignore delete mode 100644 tests/auto/qkeysequence/keys_de.qm delete mode 100644 tests/auto/qkeysequence/keys_de.ts delete mode 100644 tests/auto/qkeysequence/qkeysequence.pro delete mode 100644 tests/auto/qkeysequence/qkeysequence.qrc delete mode 100644 tests/auto/qkeysequence/qt_de.qm delete mode 100644 tests/auto/qkeysequence/tst_qkeysequence.cpp delete mode 100644 tests/auto/qmatrixnxn/qmatrixnxn.pro delete mode 100644 tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp delete mode 100644 tests/auto/qmouseevent/.gitignore delete mode 100644 tests/auto/qmouseevent/qmouseevent.pro delete mode 100644 tests/auto/qmouseevent/tst_qmouseevent.cpp delete mode 100644 tests/auto/qmouseevent_modal/.gitignore delete mode 100644 tests/auto/qmouseevent_modal/qmouseevent_modal.pro delete mode 100644 tests/auto/qmouseevent_modal/tst_qmouseevent_modal.cpp delete mode 100644 tests/auto/qmovie/.gitignore delete mode 100644 tests/auto/qmovie/animations/comicsecard.gif delete mode 100644 tests/auto/qmovie/animations/corrupt.gif delete mode 100644 tests/auto/qmovie/animations/dutch.mng delete mode 100644 tests/auto/qmovie/animations/trolltech.gif delete mode 100644 tests/auto/qmovie/qmovie.pro delete mode 100644 tests/auto/qmovie/resources.qrc delete mode 100644 tests/auto/qmovie/tst_qmovie.cpp delete mode 100644 tests/auto/qpaintengine/.gitignore delete mode 100644 tests/auto/qpaintengine/qpaintengine.pro delete mode 100644 tests/auto/qpaintengine/tst_qpaintengine.cpp delete mode 100644 tests/auto/qpainter/.gitignore delete mode 100644 tests/auto/qpainter/drawEllipse/10x10SizeAt0x0.png delete mode 100644 tests/auto/qpainter/drawEllipse/10x10SizeAt100x100.png delete mode 100644 tests/auto/qpainter/drawEllipse/10x10SizeAt200x200.png delete mode 100644 tests/auto/qpainter/drawEllipse/13x100SizeAt0x0.png delete mode 100644 tests/auto/qpainter/drawEllipse/13x100SizeAt100x100.png delete mode 100644 tests/auto/qpainter/drawEllipse/13x100SizeAt200x200.png delete mode 100644 tests/auto/qpainter/drawEllipse/200x200SizeAt0x0.png delete mode 100644 tests/auto/qpainter/drawEllipse/200x200SizeAt100x100.png delete mode 100644 tests/auto/qpainter/drawEllipse/200x200SizeAt200x200.png delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/dst.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm delete mode 100644 tests/auto/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop/dst1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/dst2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/dst3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_AndROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NandROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NandROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NandROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NandROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NandROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NandROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NandROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NandROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NopROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NopROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NopROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NopROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NopROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NopROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NopROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NopROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NorROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NorROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NorROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NorROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NorROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NorROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NorROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NorROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_OrROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_SetROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_SetROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_SetROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_SetROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_SetROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_SetROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_SetROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_SetROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_XorROP0.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_XorROP1.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_XorROP2.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_XorROP3.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_XorROP4.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_XorROP5.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_XorROP6.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/res/res_XorROP7.png delete mode 100644 tests/auto/qpainter/drawPixmap_rop/src1.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop/src2-mask.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop/src2.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop/src3.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/dst.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/src1.xbm delete mode 100644 tests/auto/qpainter/drawPixmap_rop_bitmap/src2.xbm delete mode 100644 tests/auto/qpainter/qpainter.pro delete mode 100644 tests/auto/qpainter/task217400.png delete mode 100644 tests/auto/qpainter/tst_qpainter.cpp delete mode 100644 tests/auto/qpainter/utils/createImages/createImages.pro delete mode 100644 tests/auto/qpainter/utils/createImages/main.cpp delete mode 100644 tests/auto/qpainterpath/.gitignore delete mode 100644 tests/auto/qpainterpath/qpainterpath.pro delete mode 100644 tests/auto/qpainterpath/tst_qpainterpath.cpp delete mode 100644 tests/auto/qpainterpathstroker/.gitignore delete mode 100644 tests/auto/qpainterpathstroker/qpainterpathstroker.pro delete mode 100644 tests/auto/qpainterpathstroker/tst_qpainterpathstroker.cpp delete mode 100644 tests/auto/qpalette/.gitignore delete mode 100644 tests/auto/qpalette/qpalette.pro delete mode 100644 tests/auto/qpalette/tst_qpalette.cpp delete mode 100644 tests/auto/qpathclipper/.gitignore delete mode 100644 tests/auto/qpathclipper/pathcompare.h delete mode 100644 tests/auto/qpathclipper/paths.cpp delete mode 100644 tests/auto/qpathclipper/paths.h delete mode 100644 tests/auto/qpathclipper/qpathclipper.pro delete mode 100644 tests/auto/qpathclipper/tst_qpathclipper.cpp delete mode 100644 tests/auto/qpen/.gitignore delete mode 100644 tests/auto/qpen/qpen.pro delete mode 100644 tests/auto/qpen/tst_qpen.cpp delete mode 100644 tests/auto/qpicture/.gitignore delete mode 100644 tests/auto/qpicture/qpicture.pro delete mode 100644 tests/auto/qpicture/tst_qpicture.cpp delete mode 100644 tests/auto/qpixmap/.gitignore delete mode 100644 tests/auto/qpixmap/convertFromImage/task31722_0/img1.png delete mode 100644 tests/auto/qpixmap/convertFromImage/task31722_0/img2.png delete mode 100644 tests/auto/qpixmap/convertFromImage/task31722_1/img1.png delete mode 100644 tests/auto/qpixmap/convertFromImage/task31722_1/img2.png delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_32bpp.ico delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_32bpp_16x16.png delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_32bpp_256x256.png delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_32bpp_32x32.png delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_32bpp_48x48.png delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_8bpp.ico delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_8bpp_16x16.png delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_8bpp_32x32.png delete mode 100644 tests/auto/qpixmap/convertFromToHICON/icon_8bpp_48x48.png delete mode 100644 tests/auto/qpixmap/images/designer.png delete mode 100644 tests/auto/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png delete mode 100644 tests/auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_-10_dy_0_50_50_100_100.png delete mode 100644 tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_-10_50_50_100_100.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_0_50_50_100_100.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_0_null.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_10_50_50_100_100.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_0_dy_1_null.png delete mode 100644 tests/auto/qpixmap/images/dx_10_dy_0_50_50_100_100.png delete mode 100644 tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_10_dy_10_50_50_100_100.png delete mode 100644 tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_128_dy_128_64_64_128_128.png delete mode 100644 tests/auto/qpixmap/images/dx_128_dy_128_x_y_w_h.png delete mode 100644 tests/auto/qpixmap/images/dx_1_dy_0_null.png delete mode 100644 tests/auto/qpixmap/loadFromData/designer_argb32.png delete mode 100644 tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha.gif delete mode 100644 tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha.png delete mode 100644 tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif delete mode 100644 tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha.gif delete mode 100644 tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha.png delete mode 100644 tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif delete mode 100644 tests/auto/qpixmap/loadFromData/designer_rgb32.jpg delete mode 100644 tests/auto/qpixmap/loadFromData/designer_rgb32.png delete mode 100644 tests/auto/qpixmap/qpixmap.pro delete mode 100644 tests/auto/qpixmap/qpixmap.qrc delete mode 100644 tests/auto/qpixmap/tst_qpixmap.cpp delete mode 100644 tests/auto/qpixmapcache/.gitignore delete mode 100644 tests/auto/qpixmapcache/qpixmapcache.pro delete mode 100644 tests/auto/qpixmapcache/tst_qpixmapcache.cpp delete mode 100644 tests/auto/qpixmapfilter/noise.png delete mode 100644 tests/auto/qpixmapfilter/qpixmapfilter.pro delete mode 100644 tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp delete mode 100644 tests/auto/qpolygon/.gitignore delete mode 100644 tests/auto/qpolygon/qpolygon.pro delete mode 100644 tests/auto/qpolygon/tst_qpolygon.cpp delete mode 100644 tests/auto/qprinter/.gitignore delete mode 100644 tests/auto/qprinter/qprinter.pro delete mode 100644 tests/auto/qprinter/tst_qprinter.cpp delete mode 100644 tests/auto/qprinterinfo/.gitignore delete mode 100644 tests/auto/qprinterinfo/qprinterinfo.pro delete mode 100644 tests/auto/qprinterinfo/tst_qprinterinfo.cpp delete mode 100644 tests/auto/qquaternion/qquaternion.pro delete mode 100644 tests/auto/qquaternion/tst_qquaternion.cpp delete mode 100644 tests/auto/qrawfont/qrawfont.pro delete mode 100644 tests/auto/qrawfont/testfont.ttf delete mode 100644 tests/auto/qrawfont/testfont_bold_italic.ttf delete mode 100644 tests/auto/qrawfont/tst_qrawfont.cpp delete mode 100644 tests/auto/qregion/.gitignore delete mode 100644 tests/auto/qregion/qregion.pro delete mode 100644 tests/auto/qregion/tst_qregion.cpp delete mode 100644 tests/auto/qshortcut/.gitignore delete mode 100644 tests/auto/qshortcut/qshortcut.pro delete mode 100644 tests/auto/qshortcut/tst_qshortcut.cpp delete mode 100644 tests/auto/qstatictext/qstatictext.pro delete mode 100644 tests/auto/qstatictext/tst_qstatictext.cpp delete mode 100644 tests/auto/qsyntaxhighlighter/.gitignore delete mode 100644 tests/auto/qsyntaxhighlighter/qsyntaxhighlighter.pro delete mode 100644 tests/auto/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp delete mode 100644 tests/auto/qtextblock/.gitignore delete mode 100644 tests/auto/qtextblock/qtextblock.pro delete mode 100644 tests/auto/qtextblock/tst_qtextblock.cpp delete mode 100644 tests/auto/qtextcursor/.gitignore delete mode 100644 tests/auto/qtextcursor/qtextcursor.pro delete mode 100644 tests/auto/qtextcursor/tst_qtextcursor.cpp delete mode 100644 tests/auto/qtextdocument/.gitignore delete mode 100644 tests/auto/qtextdocument/common.h delete mode 100644 tests/auto/qtextdocument/qtextdocument.pro delete mode 100644 tests/auto/qtextdocument/tst_qtextdocument.cpp delete mode 100644 tests/auto/qtextdocumentfragment/.gitignore delete mode 100644 tests/auto/qtextdocumentfragment/qtextdocumentfragment.pro delete mode 100644 tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp delete mode 100644 tests/auto/qtextdocumentlayout/.gitignore delete mode 100644 tests/auto/qtextdocumentlayout/qtextdocumentlayout.pro delete mode 100644 tests/auto/qtextdocumentlayout/tst_qtextdocumentlayout.cpp delete mode 100644 tests/auto/qtextformat/.gitignore delete mode 100644 tests/auto/qtextformat/qtextformat.pro delete mode 100644 tests/auto/qtextformat/tst_qtextformat.cpp delete mode 100644 tests/auto/qtextlayout/.gitignore delete mode 100644 tests/auto/qtextlayout/qtextlayout.pro delete mode 100644 tests/auto/qtextlayout/tst_qtextlayout.cpp delete mode 100644 tests/auto/qtextlist/.gitignore delete mode 100644 tests/auto/qtextlist/qtextlist.pro delete mode 100644 tests/auto/qtextlist/tst_qtextlist.cpp delete mode 100644 tests/auto/qtextobject/.gitignore delete mode 100644 tests/auto/qtextobject/qtextobject.pro delete mode 100644 tests/auto/qtextobject/tst_qtextobject.cpp delete mode 100644 tests/auto/qtextodfwriter/.gitignore delete mode 100644 tests/auto/qtextodfwriter/qtextodfwriter.pro delete mode 100644 tests/auto/qtextodfwriter/tst_qtextodfwriter.cpp delete mode 100644 tests/auto/qtextpiecetable/.gitignore delete mode 100644 tests/auto/qtextpiecetable/qtextpiecetable.pro delete mode 100644 tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp delete mode 100644 tests/auto/qtextscriptengine/.gitignore delete mode 100644 tests/auto/qtextscriptengine/generate/generate.pro delete mode 100644 tests/auto/qtextscriptengine/generate/main.cpp delete mode 100644 tests/auto/qtextscriptengine/qtextscriptengine.pro delete mode 100644 tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp delete mode 100644 tests/auto/qtexttable/.gitignore delete mode 100644 tests/auto/qtexttable/qtexttable.pro delete mode 100644 tests/auto/qtexttable/tst_qtexttable.cpp delete mode 100644 tests/auto/qtouchevent/qtouchevent.pro delete mode 100644 tests/auto/qtouchevent/tst_qtouchevent.cpp delete mode 100644 tests/auto/qtransform/.gitignore delete mode 100644 tests/auto/qtransform/qtransform.pro delete mode 100644 tests/auto/qtransform/tst_qtransform.cpp delete mode 100644 tests/auto/qvectornd/qvectornd.pro delete mode 100644 tests/auto/qvectornd/tst_qvectornd.cpp delete mode 100644 tests/auto/qvolatileimage/qvolatileimage.pro delete mode 100644 tests/auto/qvolatileimage/tst_qvolatileimage.cpp delete mode 100644 tests/auto/qwmatrix/.gitignore delete mode 100644 tests/auto/qwmatrix/qwmatrix.pro delete mode 100644 tests/auto/qwmatrix/tst_qwmatrix.cpp delete mode 100644 tests/auto/qzip/.gitignore delete mode 100644 tests/auto/qzip/qzip.pro delete mode 100644 tests/auto/qzip/testdata/symlink.zip delete mode 100644 tests/auto/qzip/testdata/test.zip delete mode 100644 tests/auto/qzip/tst_qzip.cpp (limited to 'tests/auto') diff --git a/tests/auto/corelib.pro b/tests/auto/corelib.pro index c64ed21b98..da2089b66b 100644 --- a/tests/auto/corelib.pro +++ b/tests/auto/corelib.pro @@ -17,7 +17,6 @@ SUBDIRS=\ qdatetime \ qeasingcurve \ qelapsedtimer \ - qevent \ qexplicitlyshareddatapointer \ qfreelist \ qhash \ diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 20194f9b7b..7525c6d5ce 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -5,6 +5,7 @@ # TEMPLATE=subdirs SUBDIRS=\ + gui \ gestures \ languagechange \ modeltest \ @@ -16,17 +17,13 @@ SUBDIRS=\ qabstractscrollarea \ qabstractslider \ qabstractspinbox \ - qabstracttextdocumentlayout \ qaction \ qactiongroup \ qapplication \ qboxlayout \ - qbrush \ qbuttongroup \ qcalendarwidget \ qcheckbox \ - qclipboard \ - qcolor \ qcolordialog \ qcolumnview \ qcommandlinkbutton \ @@ -34,7 +31,6 @@ SUBDIRS=\ qcomplextext \ qdatawidgetmapper \ qdatetimeedit \ - qdesktopservices \ qdesktopwidget \ qdial \ qdialog \ @@ -43,21 +39,15 @@ SUBDIRS=\ qdockwidget \ qdoublespinbox \ qdoublevalidator \ - qdrag \ qerrormessage \ qfiledialog \ qfiledialog2 \ qfileiconprovider \ - qfileopenevent \ qfilesystemmodel \ qfocusframe \ - qfont \ qfontcombobox \ - qfontdatabase \ qfontdialog \ - qfontmetrics \ qformlayout \ - qglyphrun \ qgraphicsanchorlayout \ qgraphicsanchorlayout1 \ qgraphicseffect \ @@ -79,14 +69,8 @@ SUBDIRS=\ qgraphicswidget \ qgridlayout \ qgroupbox \ - qguivariant \ qheaderview \ - qicoimageformat \ - qicon \ qidentityproxymodel \ - qimageiohandler \ - qimagereader \ - qimagewriter \ qinputcontext \ qinputdialog \ qintvalidator \ @@ -94,7 +78,6 @@ SUBDIRS=\ qitemeditorfactory \ qitemselectionmodel \ qitemview \ - qkeysequence \ qlabel \ qlcdnumber \ qlineedit \ @@ -105,42 +88,23 @@ SUBDIRS=\ #qlocalsocket \ # FIXME: uses qtscript (QTBUG-19242) qmacstyle \ qmainwindow \ - qmatrixnxn \ qmdisubwindow \ qmessagebox \ qmetaobject \ qmimedata \ - qmouseevent_modal \ - qmovie \ - qvolatileimage \ qnetworkaccessmanager_and_qprogressdialog \ qopengl \ - qpaintengine \ - qpainterpath \ - qpainterpathstroker \ - qpalette \ - qpathclipper \ - qpen \ - qpicture \ - qpixmapcache \ - qpixmapfilter \ qplaintextedit \ qpointer \ - qpolygon \ - qprinterinfo \ qprogressbar \ qprogressdialog \ qpushbutton \ - qquaternion \ qradiobutton \ - qrawfont \ qregexpvalidator \ - qregion \ qscrollarea \ qscrollbar \ qscroller \ qsharedpointer_and_qwidget \ - qshortcut \ qsidebar \ qsignalmapper \ qsizegrip \ @@ -153,35 +117,20 @@ SUBDIRS=\ qstandarditem \ qstandarditemmodel \ qstatemachine \ - qstatictext \ qstatusbar \ qstringlistmodel \ qstyle \ qstyleoption \ qstylesheetstyle \ - qsyntaxhighlighter \ qsystemtrayicon \ qtabbar \ qtableview \ qtablewidget \ qtcpsocket \ - qtextblock \ - qtextcursor \ - qtextdocumentfragment \ - qtextdocumentlayout \ - qtextformat \ - qtextlayout \ - qtextlist \ - qtextobject \ - qtextpiecetable \ - qtextscriptengine \ - qtexttable \ qtipc \ qtoolbar \ qtoolbox \ qtooltip \ - qtouchevent \ - qtransform \ qtransformedscreen \ qtranslator \ qtreeview \ @@ -189,12 +138,10 @@ SUBDIRS=\ qtreewidgetitemiterator \ qundogroup \ qundostack \ - qvectornd \ qwidget_window \ qwidgetaction \ qwindowsurface \ qwizard \ - qwmatrix \ qwsembedwidget \ qwsinputmethod \ qwswindowsystem \ @@ -212,15 +159,10 @@ win32:SUBDIRS -= qtextpiecetable qlistwidget \ qmainwindow \ qnetworkreply \ - qpathclipper \ - qpixmapcache \ qsidebar \ qstylesheetstyle \ - qtextlayout \ - qtextpiecetable \ qtipc \ qtoolbar \ - qstatictext \ symbian:SUBDIRS -= \ qsystemtrayicon \ 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/invalid/35floppy.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/35FLOPPY.ICO 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/AddPerfMon.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/App.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/Qt.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/Status_Play.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/TIMER01.ICO 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/WORLD.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/WORLDH.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/abcardWindow.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/semitransparent.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qicoimageformat/icons/valid/trolltechlogo_tiny.ico 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 +#include +#include + +#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(fmt.data()), "ico" ); +} + +void tst_QIcoImageFormat::canRead_data() +{ + QTest::addColumn("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("index"); + QTest::addColumn("width"); + QTest::addColumn("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 @@ + + + + + +Heart Left-Highlight +This is a normal valentines day heart. + + +holiday +valentines + +valentine +hash(0x8a091c0) +hash(0x8a0916c) +signs_and_symbols +hash(0x8a091f0) +day + + + + +Jon Phillips + + + + +Jon Phillips + + + + +Jon Phillips + + + +image/svg+xml + + +en + + + + + + + + + + + + + + + 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/heart.svgz 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/testtheme/16x16/actions/appointment-new.png 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/testtheme/22x22/actions/appointment-new.png 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/testtheme/32x32/actions/appointment-new.png 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + New Appointment + + + appointment + new + meeting + rvsp + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/address-book-new.png 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/themeparent/16x16/actions/appointment-new.png 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/address-book-new.png 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/themeparent/22x22/actions/appointment-new.png 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/address-book-new.png 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/icons/themeparent/32x32/actions/appointment-new.png 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Addess Book - New + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + address + contact + book + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + New Appointment + + + appointment + new + meeting + rvsp + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/image.png 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 Binary files /dev/null and b/tests/auto/gui/image/qicon/rect.png 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 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + 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 @@ + + + + + +Keep Tidy Inside + + + + +symbol +bin +signs_and_symbols +clean +rubish +trash +inside +garbage +sign + + + + +Martin Owens + + + + +Martin Owens + + + + +Martin Owens + + + +image/svg+xml + + +en + + + + + + + + + + + + + + + + + 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 +#include +#include + +#if defined(Q_OS_SYMBIAN) +#define SRCDIR "." +#endif +#include + +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("source"); + QTest::addColumn("argument"); + QTest::addColumn("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("argument"); + QTest::addColumn("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 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 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 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 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 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("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 @@ + + +image.png +rect.png +./icons/testtheme/16x16/actions/appointment-new.png +./icons/testtheme/22x22/actions/appointment-new.png +./icons/testtheme/32x32/actions/appointment-new.png +./icons/testtheme/index.theme +./icons/testtheme/scalable/actions/svg-only.svg +./icons/themeparent/16x16/actions/address-book-new.png +./icons/themeparent/16x16/actions/appointment-new.png +./icons/themeparent/22x22/actions/address-book-new.png +./icons/themeparent/22x22/actions/appointment-new.png +./icons/themeparent/32x32/actions/address-book-new.png +./icons/themeparent/32x32/actions/appointment-new.png +./icons/themeparent/index.theme +./icons/themeparent/scalable/actions/address-book-new.svg +./icons/themeparent/scalable/actions/appointment-new.svg + + 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 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/image.bmp 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 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/image.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/image.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/image.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/image.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/image.tif 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 + +#include +#include +#include +#include +#include + +#include +#include + + +//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("testFormat"); + QTest::addColumn("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 formats = QImageReader::supportedImageFormats(); + // qDebug("Image input formats : %s", formats.join(" | ").latin1()); + + bool formatSupported = false; + for (QList::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("red"); + QTest::addColumn("green"); + QTest::addColumn("blue"); + QTest::addColumn("alpha"); + QTest::addColumn("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("inFormat"); + QTest::addColumn("inPixel"); + QTest::addColumn("resFormat"); + QTest::addColumn("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("x"); + QTest::addColumn("y"); + QTest::addColumn("alpha1"); + QTest::addColumn("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("format"); + QTest::addColumn("degrees"); + + QVector 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("format"); + QTest::addColumn("value"); + QTest::addColumn("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 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("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("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 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 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("format"); + QTest::addColumn("color"); + QTest::addColumn("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 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("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 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 + +#include +#include +#include +#include + +//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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/baseline/35floppy.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/baseline/connect.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/baseline/kde_favicon.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/baseline/semitransparent.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/16bpp.bmp 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/4bpp-rle.bmp 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/YCbCr_cmyk.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/YCbCr_rgb.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/away.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/ball.mng 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/bat1.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/bat2.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/beavis.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/black.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/colorful.bmp 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/corrupt-data.tif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/corrupt.bmp 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/corrupt.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/corrupt.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/corrupt.mng 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/corrupt.png 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 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/rect.svgz 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/rgba_adobedeflate_littleendian.tif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/rgba_lzw_littleendian.tif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/rgba_nocompression_bigendian.tif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/rgba_nocompression_littleendian.tif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/rgba_packbits_littleendian.tif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/rgba_zipdeflate_littleendian.tif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/runners.ppm 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!j@#k@$h>"dµf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&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: X/K%���������&4$+2F=;HPEJL&\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlR¶xT­sTµd)ŠO$w; m6 +g3 +a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d!Y0�����������W+]. s=‡M$dPŸlR\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀoTM¥oRdPvE"V+K%A 99���†F¤['qUMtVM99H:9H:9H:9H:9H:9H:9H:9H:9H:9H99H99H99H99H99H99H:9H;:H>;HB=HPDJ\JKmSMwXN|ZN°y[ᦆ֘uº{W¹yU¿€]Á„b­tU£nR—hQˆaO{ZNvWNtVMvXNwXNyYNzYN{ZN|ZN}[N}[N~[N~[N~[N~[N~[N~[N~[N}[N}[N{ZNzYNxXN…L$f3 +���I$L&P(U*\. €J#\O›jQ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀžkR‰aOo9 L&C!:4���f3 +X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?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$���G#K%Q(W+zG#nTM˜iQ\À\À\À\À\À\À\À\À\À\À\À\ÀdOLrUMuWNwXNyYN{ZN}[N{ZNwXNsVM \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àˆ`OcPnA"M&@ 8F#���m6 +›W&rVMvWNyYNzYN|ZN}[N}[N>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%���F#B!Y,L&U*~I#„^O†`O\À\À\À\ÀcNLrUMzYN\O„^Oˆ`OŠbPŒcPdPeP’fP“fP“fQ“fQ”fQ‘ePcP‰aP~[N�\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À’fPsVM^/ C!7 ������ŽQ%tVMwXNzYN|ZN}[N\N\O€\O]O]O‚]O‚]OA=HB=HB=HB>HC>HC>ID?IE?IF@IG@IIAIKBIŒcPdP’eP–gQšiQŸlR£nR¤\'´d)¿i*Æm+Îs/Ïs/Êo+Én+Ål*¾i*ºg)³c(ª_(ªqS¦oR¡mRkQ™iQ•gQ“fP‘ePŽdPcPŒbP‹bPŠbPŠaP‰aP‰aO‰aOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O„^Oƒ^O‚]O\O}[N›Q��D"?D"K%_/ kRL’fPODJSFJ†_OŠbPŽcP‘eP“fQ–gQ™iQœjQžkR lR¡mR£nR¤nR¥oR¥oR¥oR¤nR¢mRŸlRšiQ‘eP…_O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀB+‘ePI#L&90���y< šPxXN{ZN}[N\N€\O]O‚]Oƒ^Oƒ^O„^O„_O…_O…_O†_O†`O‡`O‡`Oˆ`O‰aOŠaP‹bPŒbPcPŽdP‘eP“fP•gQ˜hQšiQžkR¢mR¡Z'«_(¶e)½h)Âk*Çn,Çn,Æm*Æl*Áj*ºf)¶e)²c(«_(¦]'§pR¤nR¡mRžkR›jQ™iQ–gQ”gQ“fP‘ePdPdPŽdPŽcPcPŒcPŒbP‹bP‹bP‹bPŠbPŠaP‰aP‰aO‰aOˆ`O‡`O†_O…_Oƒ^O]Oª_(@ ���B!I$B!N'w=‘eP`LKbNLeOLkR mR£nR¥oR§pSªqS¬rS®sS¯tS°tS°tS±uS±uS°tS¯tS­sSªrS§pS¢mRšjQŒbPjQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‹bPpTME"5���������‡M$tVM{ZN}[N\O]O‚^Oƒ^O„_O…_O†_O†`O‡`Oˆ`Oˆ`O‰aO‰aPŠaPŠbP‹bPŒbPcPŽcPdPdP’eP“fP•gQ—hQ™iQ›jQkR lR¢mR¡Z'¬`(µd)ºg)ÇgÀj*Àj*¾i*¿i*»g)µd)²c(¯a(ª_(¤\'§pR¥oR¢nR mRžkRœjQšiQ˜iQ—hQ•gQ”gQ“fP’eP‘eP‘ePdPdPdPŽcPŽcPcPcPŒcPŒbP‹bP‹bPŠbPŠaP‰aOˆ`O†_O„^O\NœQ����@ <G#_LKŽcPlSMnTMpUMsVM°tS²uT³vTµwT¶wT¶xT¶xT¶wTµwT´vT²uT¯tS¬sSªqS§pS¤oR¢nRžkR˜hQ‹bPeOL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN\NJ%0������1ŽJvWN}[N\O]Oƒ^O…_O†_O†`O‡`Oˆ`O‰aO‰aPŠaPŠbP‹bPŒbPŒbPcPŽcPŽdPdPdP‘eP’eP”fQ•gQ–gQ˜hQ™iQ›jQkQŸlR¡mRžY&¦]'­`(³c(·e)Àc¸\¸\¹\º]»]¶^®a(¬`(©^'£['¢['¥oR£nR¡mR lRžkRœkQ›jQšiQ˜iQ—hQ–gQ•gQ”gQ”fQ“fP’eP’eP‘eP‘ePdPdPdPdPŽdPŽcPcPcPŒbP‹bPŠaPˆaO†`O]O˜O������G#7F#uWMƒ^OwXNxXNzYN{ZN|ZN¹yT¸yT·xT´wT±uT­sS¨pS¡mRœjQ•gQdPŒbP‰aP‰aPŒbPŽcP‘ePcP|ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[JKŠbP^/ 1 01|> wXN}[N]Oƒ^O…_O‡`O‡`OˆaO‰aPŠaP‹bP‹bPŒbPŒcPcPŽcPŽcPdPdPdP‘eP’eP“fP”fQ•gQ–gQ—hQ˜hQ™iQ›jQœkQžkRŸlR mRžY&¦]'­`(±b(·[ÇgÉiÉhÅfÂdÃe¿c«Uª_(§]'£[' Z'¤nR£nR¡mR mRŸlRžkRkQœjQšjQšiQ™iQ˜hQ—hQ–gQ•gQ•gQ”fQ”fQ“fP“fP’eP’eP‘eP‘ePePdPdPdPŽcPcPŒbPŠbPˆ`Oƒ^O‰D �����4M&dPnSM|[N|[O|[OzZOxXNªrS¢nR˜hQŽcPƒ^OvXNiQL^KKRFJMCJJAIKBISFJ\JKnSMxYN†_O€\OaMK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀB!qUMŠaPC!/00a0 uWN}[N‚]O…_O†`Oˆ`O‰aPŠaP‹bPŒbPŒcPcPŽcPŽcPdPdPdP‘eP‘eP’eP“fP“fQ”fQ•gQ–gQ—hQ˜hQ™iQ™iQ›jQœjQkRžlRŸlRœX&¢['¨^'¬`(´ZÂdÄfÈiÆgÂd¿c¿c¼a¸_©T¥\'£[' Z'ŸY&£nR¢mR¡mR lRŸlRžkRkQœjQ›jQšjQšiQ™iQ˜hQ—hQ—hQ–hQ–gQ•gQ•gQ”gQ”fQ”fQ“fQ“fP’fP’eP‘eP‘ePdPdPŽcPŒbP‰aOƒ^Ox< �������:ŠaP]Oj8sVMmSMfOL^KKUGJIAIQEJ?IeZY638*  B\À\À\À\À\À,  4 .G1!\TU¡ƒrsVM{ZN`MK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[JKyYNŒbP/0������ˆN$]O…_Oˆ`O‹bPŒbPcPŽcPdPdPdP‘eP‘eP’eP’fP“fP“fQ”fQ”gQ•gQ–gQ–gQ—hQ—hQ˜hQ™iQ™iQšiQ›jQœjQœkQkRžkRŸlRœO¡Z'¥\'©^'­V¼a¾bÁeÆi!Ãf¾b»a¹`·_³]²\µZ¢[' Z'ŸY&œQ¡mR¡mR mR lRŸlRŸlRžkRkRkQœkQœjQ›jQ›jQšjQšiQšiQ™iQ™iQ˜iQ˜hQ˜hQ—hQ—hQ—hQ–hQ–gQ–gQ•gQ•gQ”fQ’fPdPcPšW&������������dPŠaPrUM + B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6 + ���X,uWM‚]O‡`OŠbPcPŽdPdPdP‘eP’eP’fP“fP“fQ”fQ”gQ•gQ•gQ–gQ–gQ—hQ—hQ˜hQ˜iQ™iQ™iQšiQ›jQ›jQœjQœkQkQžkRžlRŸlR¢Z'¤\'§]'·_¹`¼a½bÁeÅi"Áe¼aº`·_¶_²]²\±\«Y¡Z' Z'¡Z'¡mR¡mR mR lR lRŸlRŸlRžlRžkRžkRkRkQœkQœjQœjQ›jQ›jQ›jQšjQšiQšiQšiQ™iQ™iQ™iQ˜iQ˜hQ˜hQ—hQ–gQ•gQ“fQdP†_Oq8 ���������–gQˆ`OuWM”T%\À\À\À\À\À\À\À\À\À\À B B!!T,c5ƒF‚T3È›~Æ“qƒ^OfOL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK_LKsVM‡`OcP������ ’S%]OŠbPcPdP‘eP’eP“fP“fQ”fQ”gQ•gQ•gQ–gQ–gQ—hQ—hQ—hQ˜hQ˜iQ™iQ™iQšiQšiQ›jQ›jQœjQœjQkQkRžkRžlRŸlRŸlR¥\'¦]'¨^'­Vº`»a½bÁfÄi"Àe»a¹`·_¶_³]±\±\¤R¢Z'¢Z'£['¡mR¡mR¡mR¡mR mR lR lRŸlRŸlRŸlRžlRžkRžkRkRkRkQkQœjQœjQœjQœjQœjQ›jQ›jQ›jQ›jQšjQšiQ™iQ™iQ˜hQ–gQ‘eP§Sq8 ������‰aO•gQ‡`OtVMœX&\À\À\À\À\À\À\À\À\À\À B B B l@!{A…L$›Y'½†a“fPˆaO]KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀODJ[JKaMKqUM\OcPƒ^O������vE"‚]OŠaPdP‘eP“fP”fQ•gQ•gQ–gQ–hQ—hQ—hQ˜hQ˜hQ˜iQ™iQ™iQ™iQšiQšjQ›jQ›jQœjQœjQœkQkQkRžkRžkRŸlRŸlRŸlR lR©^'©^'ª_(®W»a¼a¾cÂg Äi"¿e»a¹`·_¶_³^±\±\¤R£['£['§]'¢mR¢mR¡mR¡mR¡mR¡mR mR lR lR lR lRŸlRŸlRŸlRŸlRžlRžlRžkRžkRžkRžkRkRkRkRkRkQkQkQœjQœjQšiQ˜hQ’ePšW&M&���oTMšiQ‘eP…_OtVMmSMdOL\À\À\À\À\À\À\À\À\À B B B ‘J Z'ª_(œkQ™iQ‡`OSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJ\JKcNLlRMzYN‡`O’ePzZN��� �\Nˆ`OdP“fQ•gQ–gQ—hQ˜hQ˜hQ™iQ™iQ™iQšiQšiQšiQ›jQ›jQ›jQœjQœjQœjQœkQkQkRžkRžkRžlRŸlRŸlRŸlR lR lR mR®a(­`(¬`(¶[½a½b¿dÃh!Äi"¿d»a¹`¸_¶_µ^²]³]¦S¤\'§]'«_(¢nR¢mR¢mR¢mR¢mR¢mR¢mR¡mR¡mR¡mR¡mR¡mR mR mR mR mR lR lR lR lR lR lR lR lR lRŸlRŸlR lRŸlRžkRœkQ™iQePt: ������kQ˜hQcP€]OtVMlSMa2 \À\À\À\À\À\À\À\À\À B B +$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�oTM•gQ™iQkQŸlRŸlR lR mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR£nR£nR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nRÆl*Ãl+¾j+¹g)¸f)¶e)µd)¶e)¶e)·e)·e)¸f)¾i*Ìs0Ðs.¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦pR§pR§pR§pR§pR§pS§pS¨pS¨qS©qS©qS©qS¨pS©qS§pS¤nRŸlR‘I˜hQ§pR¥oR¡mRšiQ’ePŠaP€\OsVMpTMnTMlRM–X)\À\À\À\À\À\À\À B%C)D$;J/[8"LBITGJYIKWHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK_LKcNLgPLjQLlRMpUMzYNƒ^O‹bP‘eP˜hQkQŸlR”fQ- —hQ›jQŸlR¢mR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦oR¦oR¦oR¦pR¦pR§pRàpßy-Ûw-Ûw-Þy.â{-ãu§pS§pS§pS§pS§pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨qS©qS©qS©qS©qS©qS©qS©qSªqSªrS«rS«rS¬rS¬rS¬rS¬rS¬sS«rSªqS¦oRšiQ™iQ©qSªqS§pR¡mRœjQ•gQcP„_O{ZNtVMpUMoTMmSMjQL_9 \À\À\À\À\À B "C(D#*A$[<)dI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JKaMKeOLhPLkRLmSMoTMuWM}[N…_O‹bP’eP˜hQžkR¢mR£nRžkR!-EkR¡mR¤nR¥oR¦pR§pR§pS§pS§pS§pS§pS§pS§pS§pR§pS§pS§pS§pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨qS¨qS¨qS©qS©qS©qS©qS©qS©qS©qS©qS©qS©qS©qSªqSªqSªqSªqSªrS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬sS­sS®sS®sS¯tS¯tS¯tS¯tS°tS°uS°tS®sS«rS£nR¦oR®sS­sS«rS§pR¢mRœjQ–gQdPˆaO\OyYNuWMqUMoTMnSMkRLo8 \À\À\À\À\À B'D+E$(1 J/jH1NCJUGJYIKUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK]KKbNLfOLiQLkRMmSMoTMqUMxXN\N†_OŒbP’fP˜hQkQ¡mR¥oR§pS¦pR˜hQ¢mR¥oR¨pSªqS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rSªrSªrSªrS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬rS¬rS¬rS¬rS¬sS¬sS­sS­sS­sS­sS­sS­sS®sS®sS®sS®sS®tS¯tS°tS°uS±uS±uT±uT²uT²uT²uT´vTµwT´vT³vT²uT¯tS¢mR¯tS±uT±uS®tS«rS§pR¢mRkQ—hQ‘ePŠaPƒ^O\N{ZNvXNqUMpTMnSMlRMP%\À\À\À\À B#C*E$.E- .!G$Y:%d<"SFJYIKZIKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀPDJZIK_LKdNLgPLjQLlRMnSMpTMqUMuWMyYN€\O†`OcP’fP—hQœjQ¡mR¥oR¨qS«rS«rSªrS mR�«rS­sS¯tS°tS°tS°tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS®tS®sS®sS®sS®sS®sS®sS®sS®sS®sS®tS®tS®tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS°tS°tS°tS±uS±uS±uT²uT²vT³vT³vT´vT´vT´wTµwTµwTµwT·xT·xT¸xT¸yT¸yU·xU¥\'©qS³vTµwTµwT´vT±uT®tTªrS¦oR¡mRkQ˜hQ’eP‹bP‡`Oƒ^O€\O|ZNxXNtVMpTMoTMmSMjQLh7\À\À\À B(D"-E*1F, 4#K)pL5PEJWHK[JKXHK:9H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀUGJ\JKaMLeOLhPLkRLmSMoTMpUMrVMvWNyYN|ZN]O‡`OŒcP‘eP—hQ›jQ lR¤nR§pSªqS­sS¯tS°uS¯tS­sS mR^/ ²vT³vT´vT´wTµwT´wT´vT³vT´vT´vT´vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT´vT´vT´vT´vT´wTµwTµwTµwTµwT¶wT¶wT¶xT·xT·xT·xT¸xT¸xT¸xT¹yTºyT»zU¼zU½{U½{V½|V•gQ¬rSµwT¸xT¹yU¹yU¹zV·yVµxV±vU­tT©qS¥oS mRœjQ—hQ’ePcPŠbP‡`O„_O]O}[NyYNuWMpUMoTMmSMkRL}H#\À\À &D -E(1F/!2#8 W7"iA&UGJ[JK\JKREJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀMCIXIK^KKcNLfOLiQLkRMmSMoTMqUMsVMwXNzYN}[N€\Oƒ^O‡`OŒbP‘eP–gQšjQžkR¢mR¥oR©qS¬rS¯tS±uS³vT´vTµwT´wT²uT­sS lR«_(¹yT¹yTºyTºyTºyTºyTºyT¹yT¹yT¸yT¸xT¸xT¸xT¸xT¸xT¸xT¸yT¸yT¸yT¸yT¹yT¹yT¹yT¹yT¹yT¹yT¹yTºyTºyTºyTºyTºzT»zT¼zU¼{U½{U¾{U¾|U¿|UÀ}VÁ~VÂWÀY™iQ«rSµwT¹yT¼zU½|V¿}XÁ€ZÂ]Á]¾€]»~[¶zY±wW¬tU¨qS¤nSŸlR›jQ–gQ“fPePŽcP‹bPˆ`O…_O‚]O~\NzZNvXNqUMoTMnSMlRMiQLg=!\À +!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?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 |> ���������������’eP¦oR¨qS¦oR¡mRšjQ‘eP„^OhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ\KKaMLeOLhPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_Oˆ`OŠbPcPdP‘eP“fQ•gQ—hQ™iQ›jRkRŸmS¢nT¤qV¨sX¬w[±{_¶€c½†hÄŒnË’tÒ™zØŸ€Þ¥…㩉ç­ê¯Žê¯Žê®ç«Šä§†ß£Ûž|Õ˜vГpËŽkljfÃ…bÀ‚_½\»}Yº{X¸zW¸yV·xU·xU·xT¶xT¶xT¶xU¶xU·xU·xU·yV·yV·zW¸zX¸{Y¹|Y¹|Z¹}[¹}[¹}\¹}\¸}\·}\¶|\µ{[³zZ²yZ°wY®vX¬tWªsV¨rU¦pT¤oS£nS¡mRŸlRžkRœjQšiQ˜hQ–gQ”fQ’ePdPŽcP‹bPˆ`O…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQLfOLJ(V.]KKePNkUQcNLQEJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‚]O¡mR©qS¬rS°tS³vTµwT·xUº{WĆbÒ“qךxÊo +���������������K«rS´vT¶wT´vT²uT®sSªqS¤nRkQ•gQˆ`OuWNY,\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^KKbNLfOLhQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N]O„^O†_O‰aO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRkRŸmS¢oT¥qV¨tX­w[±|_·d½†iÄŒnË“tÒ™zØŸ€Þ¥…㩉笌鮎ꮎ魌檉㧅ߢ€Ú{Õ—uÏ’pËjƈfÂ…b¿^½\»|Y¹{X¸zV·yV·xU·xU¶xT¶xT¶xT¶xU¶xU¶xU¶xU·yV·yV·yW¸zW¸{X¸{Y¸|Z¹|Z¹|[¹}[¸}\¸}\·|\¶|[µ{[³zZ±xY°wX®vX¬tWªsV¨rU¦pT¥oS£nS¡mRŸlRžkRœjQšjQ˜iQ—hQ”gQ’fPdPŽcP‹bP‰aO†_Oƒ^O€\O|ZNxXNtVMoTMnSMlRMjQLgPLzG#\JKcOMoXUgPMZIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À’fP”gQ•gQ—hQ™iQkQ lR¤nR§pRªqS¬sS¯tS������:"r<zYN­sS¹yT¾|UÁ~WÆ„^ËŠeË‹gƈe¾‚aµz[­tV¦pS¢mRkQ–gQŠbPzYNkRL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀRFJZJK`LKcNLfPLiQLkRMmSMoTMqUMrVMvWNyYN|ZN\N]O„^O‡`O‰aO‹bPcPdP’eP”fQ–gQ—hQ™iQ›jRlR mS¢oU¥qV©tY­x\²|`¸d¾‡iÅoË“uÒ™{ÙŸ€Þ¥…㩉笌é®é®è¬‹å©ˆâ¦„Þ¡ÙœzÔ—tÏ‘oÊŒjƈe„a¿^½~[»|Y¹{X¸zV·yV·xU¶xU¶xT¶xT¶xT¶xT¶xU¶xU¶xU¶xV·yV·yW·zW·zX¸{Y¸{Y¸|Z¸|Z¸|[¸|[·|[·|[¶{[´z[³yZ±xY°wX®vW¬tWªsV¨rU¦pT¥oS£nS¡mRŸlRžkRœkRšjQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aP†`Oƒ^O€]O}[NyYNuWNqUMnSMlSMkRLhPLcNLbNLpYVlUP`LK>;H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À›jQ‡`O{ZN©^'¨^'­`(·e)½h)Ãk*Êo+±b(£nRºyTÃ~UÇXÒdãŸwò°‰ñ°‹è©…ÝŸ}Ô˜vÈm¾„eµ}_®x[°y\®x[«tW§qT¡mRœjQ–gQ‹bP}[NlRM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\JKaMKdNLgPLjQLlRMnSMpTMqUMsVMvXNzYN|[N\O‚]O…_O‡`O‰aPŒbPŽcPdP’eP”fQ–gQ˜hQšiQœjRžlS mS£oU¦rW©uY®x\³|`¸d¾‡jÅoÌ“uÒš{Ù €Þ¥…㩉欋è­è­Œç«Šå©‡á¥ƒÝ ~Ø›yÓ–tΑoÊŒjňe„a¿^¼~[º|Y¹{W¸zV·yV·xU¶xU¶xT¶xT¶xT¶xT¶xU¶xU¶xU¶xU¶xV·yV·yW·zX·zX¸{Y¸{Z¸{Z·|Z·|[·|[¶{[µ{[´zZ³yZ±xY¯wX®uW¬tVªsV¨rU¦pT¥oS£nS¡mR lRžkRœkR›jQ™iQ—hQ•gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O~[NzYNvWNrUMnSMmSMkRLiQLeOLoXUu]XdOLKBI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À:9H\N–hQ¸}\¯uU­sT¯tT¯tS¨qS¤nR£nR¢nRŸlR›jQšiQ˜hQ—hQ–gQ”fQ’eP‘eP—hQœkR mS¥pUªtX«uY¨sW¦qU mS›jQ•gQƒB’S%jQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀLBIXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMtVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽcPeP’fP”fQ–gQ˜hQšiRœkRžlS nT£pU¦rWªuY®y]³}`¹‚e¿ˆjÅŽpÌ”vÓš{Ù Þ¤…⨉櫋笌笋櫊䨆ंܟ~ךxÒ•sÎnÉŒiŇeÁ„a¾€^¼~[º|Y¹{W¸yV·yV·xU¶xU¶xT¶wT¶wT¶wT¶xT¶xU¶xU¶xU¶xV¶yV¶yW·zW·zX·zY·{Y·{Z·{Z·{Z¶{Z¶{ZµzZ³yZ²yY±xY¯vX­uW¬tVªsU¨rU¦pT¥oS£nS¡mR lRžlRkR›jQ™iQ—hQ•gQ“fQ‘ePdPcPŠaP‡`O…_O‚]O\N{ZNwXNsVMnSMmSMkRMiQLfOL_LKhQMUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À (6BFP>=DKHMqjk€trwf`~kc„ndŠqesete¯Ž{w`¡v[\N†_OcP“fP˜iQœjRŸlS£oT¦qV¥qV£oTžlR™iQº^‡`OQ%hPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJZIK_LKcNLfOLiQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N€]Oƒ^O…_Oˆ`OŠaPŒcPŽdP‘eP“fP”gQ–hQ˜iQšjRœkRžlS¡nT£pU¦rWªuZ®y]³}a¹‚e¿ˆkÆŽpÌ”vÓš{ÙŸ€Þ¤…⨈媊櫋櫊婈⦅ߣ۞}ÖšxÑ•rÍmÈ‹ićdÁƒa¾€]¼~[º|Y¹zW¸yV·yU¶xU¶xU¶wT¶wT¶wT¶wT¶wT¶xU¶xU¶xU¶xU¶xV¶yV¶yW¶zX·zX·zY¶zY¶{Y¶{Z¶{ZµzZ´zZ³yY²xY°wX¯vX­uW«tVªsU¨rU¦pT¥oS£nS¡mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ‘ePdPcP‹bPˆ`O…_O‚]O\O|ZNxXNtVMoTMmSMlRMjQLgPLbML[JK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À%5 (6$/79CEEKjgkrc_›…{‘uf±{Ÿw_ºq]Oˆ`OŽcP”fQ˜hQ›jRžlR¡nT¢oT¡nTkR˜hQŽdP¦]'ŽQ%\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀUGJ[JK`MKdNLgPLiQLkRMmSMoTMqUMrUMuWNxXN{ZN~[N]Oƒ^O†_Oˆ`OŠbPcPdP£['µd)•gQ—hQ˜iQšjRœkRžlS¡nT£pU§rWªvZ¯y]´~aºƒfÀˆkÆŽpÌ”vÓš{ØŸ€Ý¤„ᧇ䩉媊媉䨇᥄ޡ€Ú|Õ˜wДrÌmÈŠhĆdÀƒ`¾€]»}[º|Y¸zW·yV·xU¶xU¶xU¶wTµwTµwTµwTµwTµwUµwUµxUµxUµxV¶xV¶yW¶yW¶yX¶zX¶zY¶zYµzYµzY´zY´yY²yY±xY°wX®vW­uW«tVªsU¨qU¦pT¥oS£nS¢mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ’ePdPcP‹bPˆaO†_Oƒ^O€\O|[NxYNtWMpUMmSMlRMjQLgPLcNLA;=\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À#*6+.8;:AHEJmgjd\]‡pe«}œxc w^»pƒ^OŠaP‘eP–gQšiQžlR mS¢nT mS›jR•gQ»h*œX&ˆM$\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀC+WHJ]KKaMLdOLgPLjQLlRMnSMoTMqUMrVMvWNyYN|ZN\N]O„^O†_OˆaO‹bPcPžY&«_(³c(•gQ—hQ™iQšjRœkRŸlS¡nT¤pV§sX«vZ¯z^´~bºƒfÀ‰kÆŽpÌ”vÒš{ØŸ€Ý£„ই㩉䩉䩈⧆ःܠØœ{Ô—vÏ“qËŽlljgÆcÀ‚`½]»}Z¹{Y¸zW·yV¶xU¶xU¶wUµwTµwTµwTµwTµwTµwTµwUµwUµxUµxVµxVµxVµyWµyWµyXµyXµyYµzY´yY´yY³yY²xY±wX°wX®vW­uV«tVªrU¨qU¦pT¥oS£nS¢mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ’ePdPŽcP‹bP‰aO†_Oƒ^O€\O}[NyYNuWNqUMmSMlRMjQLhPLdNL\1\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À+.775;ICFphhŠztŠre¯}Ÿya¢vZ]OŠaP‘eP–gQšiQkRŸlS¡nTžlS™iQÌq.¯b*“S%zG#\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀMCJXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMsVMvWNyYN|ZN\N‚]O„^O†`O‰aO‹bP—U&¥\'¯a(»g)Ìr/—hQ™iQ›jRkRŸmS¡nT¤pV§sX«v[¯z^´~bºƒfÀ‰kÆŽpÌ”vÒ™{מÜ£ƒà¦†â¨ˆã¨ˆã¨‡á¦…Þ£‚ÛŸ~×›yÓ–uÎ’pÊkƉgÂ…c¿‚_½]»}Z¹{X¸zW·yV¶xU¶xUµwTµwTµwTµwTµwTµwTµwTµwUµwUµwUµxUµxVµxVµxWµyWµyWµyXµyX´yX´yY³yY³xX²xX°wX¯vW®uW¬tV«sV©rU¨qT¦pT¥oS£nS¡mR mRžlRkR›jQšiQ˜hQ–gQ”fQ’ePdPŽcPŒbP‰aO†`Oƒ^O€]O}[NzYNvWNrUMmSMlRMjQLhQLeOL_LK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À,)/ZTVXON„uq‡od®}Ÿyb»s]OŠaPeP•gQšiQkRžlRŸlSœkR–hQ»g*¤\(ŽQ%`LK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À B B_LKcNLfOLiQLkRLmSMoTMpTMrUMtVMwXNzYN}[N\O‚]O„_O‡`O‰aOQ%ŸY&©^'±b(¾i*Õ{8—hQ™iQ›jRkRŸmS¡nT¤qV§sX«v[°z^µ~bºƒfÀ‰kÆŽpÌ”vÒ™{מÛ¢ƒß¥…ᧇ⧇ᦆऄݢڞ}ÖšxÒ•tÍ‘oÉŒjňfÂ…b¿_¼\º}Z¹{X·zW·yV¶xU¶xUµwTµwTµwTµwTµwTµwTµwTµwT´wU´wU´wU´xVµxVµxVµxW´xW´yW´yX´yX³xX³xX²xX±wX°wW¯vW­uW¬tV«sU©rU§qT¦pT¤oS£nS¡mR mRžlRkR›jQšiQ˜hQ–gQ”gQ’fPdPŽcPŒbP‰aP‡`O„^O]O~[N{ZNvXNrVMnSMlRMjRLhQLeOLaML+O+O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀHFLXQRTJH~pm‚la¬Ž}Ÿzc»t¤tT‰aPdP•gQšiQœjRžlRžlS›jRÖ|:´e*˜V&ˆN$\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À B B`LKdNLgPLiQLkRMmSMoTMpUMrUMtVMwXNzYN}[N€\O‚]O…_O‡`O‰aPšW&£['«_(´d)Âl,݃@Òt.™iQ›jRkRŸmS¡oU¤qV¨sX«w[°z^µbºƒgÀ‰kÆŽpÌ”uÑ™zÖ~Ú¡‚Þ¤„ॆআॅޣ‚Ü Ø{Õ™wÑ”sÌnÈŒjňfÁ„b¾_¼~\º|Z¸{X·yW¶yV¶xUµwUµwTµwTµwTµwT´wT´wT´wT´wT´wU´wU´wU´wU´wV´xV´xV´xW´xW³xW³xW³xX²xX±wX°wW¯vW®uW­uV¬tVªsU©rU§qT¦pT¤oS£nS¡mR lRžlRkR›jQšiQ˜hQ–hQ”gQ’fPdPŽcPŒbPŠaP‡`O„^O]O~[N{ZNwXNsVMoTMlRMjRLiQLfOLbML+O+O‚+O‚+O‚\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À6./fZXeVRHAIZIKiQLuWM¤tU‰aOdP–gQšjQkRžlRkR˜iQÄn/¬b,‘R%rC"\À\À\À\À\À\À\À\À\À\À\À\À"Fx"Fx!Fx!Fx B B BdNLgPLjQLlRMmSMoTMqUMrUMtWMwXNzZN}[N€\O‚^O…_O‡`O“S%X&¥\'®a(·g+Ês2Ó{9Àj*™iQ›jRkSŸmS¢oU¤qV¨sX«w[°z^µbº„gÀ‰kÆŽpË“uИyÕœ}٠ܢƒÞ¤„ߤ„Þ£ƒÝ¡ÚŸ~×›zÓ—vÏ“rËmÇ‹ićeÀƒa¾€^»~\¹|Z¸zX·yW¶xVµxUµwUµwTµwT´wT´wT´wT´wT´wT´wT´wT´wU´wU´wU´wU´wV³wV³xV³xW³xW²wW²wW±wW±wW°vW¯vW®uV¬tV«sUªsU¨rT§qT¦pT¤oS£nS¡mR lRžlRkR›jQšiQ˜hQ–gQ”gQ’fPePŽcPŒbPŠaP‡`O„_O]O~\N{ZNxXNsVMoTMlRMjRLiQLfPLbNL +O‚+O‚+P‚+P‚+P‚\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@89dWT@IIAI\JKlRMyYN„^OcP”gQ™iQkRžlRžkR™iRÍt3±d-’S%I#\À\À\À:^‘:^‘:^‘:^‘:^:^:^:^:^"Fx"Fx B B B BeOLhPLjRLlSMnSMpTMqUMrVMuWMxXN{ZN~[N€]Oƒ^O…_O“S%›W&¢['©^(¹k2½i+Ó{:•gQ—hQ™iQ›jRkSŸmT¢oU¤qV¨tY¬w[°{_µbºƒf¿ˆkÄoÊ’tÏ–xÓš|×~Ù €Û¡Û¡Û €Ùž~×›{Ô˜wДsÌoÉŒkʼngÂ…c¿‚`¼]º}[¸{Y·zX¶yVµxVµwU´wU´wT´wT´vT´vT´vT´vT³vT³vT³vT³vT³vU³vU³vU³wU²wU²wV²wV²wV±wV±vV°vV°vV¯uV®uV­tV¬tUªsU©rU¨qT§pT¥pS¤oS¢nS¡mR lRžlRkR›jQ™iQ˜hQ–gQ”gQ’fPePŽdPŒbPŠaPˆ`O…_O‚]O\N|ZNxYNtWMpTMlRMjRLiQLgPLcNL_LK+P‚+P‚+P‚,P‚,P‚,P‚,P‚,P‚Nr¤\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À]QNl\VG@IMCI_LKoTM|ZN†`OdP–gQšjQkRžlRœkR—hQºh*¤^,ŒP%X3:_‘:_‘:_‘:_‘:_‘:_‘:_‘:_‘:^‘:^‘:^‘:^‘"Fx B B B BfOLiQLkRLmSMnTMpTMqUMrVMuWNxYN{ZN~[N€]Oƒ^OŽP%—U&X&£['¬`)½n4Ãn/Àj*•gQ—hQ™iQ›jRkSŸmT¢oU¤qW¨tY«w[°z^´~b¹ƒf¿ˆjÄŒoÉ‘sΕwÒ™{Õœ}ØžÙŸ€ÚŸ€Ùž~ל|ÕšyÒ—vÏ“rËnÇ‹jĈfÁ„c¾`¼]¹}[¸{Y·zW¶xVµxU´wU´wT´wT´vT´vT³vT³vT³vT³vT³vT³vT³vT³vT²vU²vU²vU²vU²vU±vV±vV±vV°vV°vV¯uV®uV­uV¬tU«sUªrU©rT¨qT¦pT¥oS£oS¢nS¡mRŸlRžkRœkR›jQ™iQ˜hQ–gQ”gQ“fPePŽdPŒbPŠaPˆ`O…_O‚]O\N|ZNyYNuWMpUMlRMjQLiQLgPLdNL_LK,P‚,P‚,P‚,P‚,P‚Nr¤Nr¤Nr¤Nr¤Nr¥Nr¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaSOD>IJAIQEJbNLrUM~[NˆaO‘eP—hQœjQžkRŸlR›jRÌs0²e,“T&ƒK$;_‘;_‘;_‘;_‘;_‘;_‘;_‘:_‘:_‘:_‘:_‘:_‘:_‘ B B B BgPLiQLkRLmSMoTMpTMqUMsVMuWNxYN{ZN~[N]O‡M$“S%™V&ŸY&¥\'±e-¹j/Ñz:”fQ•gQ—hQ™iR›jRkSŸmT¢oU¤qW¨tY«w[¯z^´~b¹ƒf¾‡jÃŒnÈrÍ”vјyÔ›|Ö~מ~Øž~×}Õ›{Ó˜xЕtÍ’qÊŽmÆŠiÇeÀ„b½_»~\¹|Z·{Y¶yWµxVµxU´wU´wT´vT³vT³vT³vT³vT³vT³vT³vT³vT²vT²vT²vT²vU²vU²vU±vU±vU±vU°vV°vV¯uV®uV®uV­tU¬sU«sUªrU¨qT§qT¦pS¥oS£nS¢nR¡mRŸlRžkRœkR›jQ™iQ˜hQ–gQ”gQ’fPePŽdPŒbPŠaPˆ`O…_O‚]O\O|ZNyYNuWMqUMlSMjQLhQLfPLdNL_LK,P‚,P‚Nr¤Nr¤Nr¤Nr¤Nr¥Nr¥Nr¥Ns¥Ns¥Ns¥Ns¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀdUOG@IMCITFJeOLtWM€]O‹bP“fP™iQkRŸlRkR™iQ¾j,©c/P%[JK;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘ B B B BgPLiQLkRMmSMoTMpTMqUMsVMvWNyYN{ZN~[N|H#ŽQ%•T%›W& Z'¦]'ºm5¸f*Ív5”fQ•gQ—hQ™iR›jRkSŸmT¡oU¤qW§sY«v[¯z^³~b¸‚e½‡i‹nÇqË“uÏ–xÒ™zÔ›|Öœ}Öœ|Õ›{Ô™yÑ–vÏ“sÌoÈlʼnh†e¿ƒa¼€_º~\¸|Z·zX¶yWµxV´wU´wU³vT³vT³vT³vT³vT³vT³vT²vT²vT²vT²vT²vT²vT±vT±vU±vU±vU°uU°uU°uU¯uU®uU®tU­tU¬tU«sUªrU©rT¨qT§pT¥pS¤oS£nS¢mR mRŸlRžkRœjR›jQ™iQ—hQ–gQ”fQ’fPePŽcPŒbPŠaPˆ`O…_O‚^O\O|ZNyYNuWNqUMmSMjQLhQLfPLdNL`LKNr¤Nr¤Nr¥Nr¥Nr¥Ns¥Ns¥Ns¥Ns¥Os¥Os¥Os¥Os¥Os¥Os¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À2#TB3REJVGJ`LKpTM}[N‰aO’ePšiQžkR lRžlR˜hQ·e)¢^.P%^8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMrUMsVMxF#‡M$ŽQ%’S%–U&šW&žY&¢['ªa+¿s;¹g+dP‘eP“fQ”gQ–hQ˜iQšjRœkSžlS nU£pV¦rX©uZ¬x]°{_´~b¸‚e¼…iÀ‰kÃŒnÆŽpÈrÊ‘sË’sË‘rÊqÉoÇmÅ‹kÈhÀ…e¾ƒb¼€`º~^¸|[¶{ZµyX´xW³wV²vU²vU²vT±uT±uT±uT±uT±uT±uT±uT±uT°uT°uT°tT°tT¯tT¯tT¯tT¯tT®tT®tT­sT­sT¬sT¬sT«rTªrT©rT©qT¨qS§pS¦pS¥oS£nS¢nR¡mR lRŸlRkRœjQ›jQ™iQ˜hQ–gQ•gQ“fP‘ePdPcP‹bP‰aO‡`O„^O‚]O\N|ZNxXNuWMqUMmSMhPLgPLeOLcNL`LKZIK,Pƒ,Pƒ,QƒOs¦Os¦Ot¦Ot¦Ot¦Ot¦Pt¦Pt¦Pt¦Pt¦Pt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀvšÍvšÍv›Ív›Ív›Ív›Ív›Íw›Íw›Í=a“=a“=a“#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GymYPODJUGJXIKeOLtWM‚]OcP•gQœjQ lR mRkRÈp.´g0”T&ˆN$]8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMrUMv>„L$ŒP%‘R%•T%˜V&œX& Z'¤\'°f0¹m5Äq3dP‘eP“fQ”gQ–gQ˜hQ™jR›kSlS nT¢pV¥rX¨tZ«w\¯z_³}a·dº„g¾‡jÁŠlÄŒnÆŽpÇqÈqÈpÇŽoÆmÅ‹kÉiÁ‡g¿„d½‚aº_¸}]·|[µzY´yX³xW³wV²vU²vU±uT±uT±uT±uT±uT±uT°uS°uS°tS°tS°tS¯tS¯tT¯tT¯tT®tT®tT®sT­sT­sT¬sT¬sT«rTªrTªrT©qT¨qS§pS¦pS¥oS¤oS£nS¢mR¡mRŸlRžlRkRœjQšjQ™iQ—hQ–gQ”fQ’fP‘ePdPcP‹bP‰aO†`O„^O]O~\N{ZNxXNuWMqUMiQLgPLfOLeOLbNL_LKZIK,Qƒ,Qƒ,Qƒ,Qƒ,QƒOt¦Pt¦Pt¦Pt¦Pt¦Pt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àv›Ív›Ív›Ív›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Í=a“=a“=a“=a“=a“#Gz#Gz#Gz#Gz#Gz#Gz#GzgUOS=2RFJWHJ[JKlRMzYN†`OeP˜iQžkR mRŸlR™iQ¼h*°h4‘R%ˆN$^9 [JK#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMI#†L$‹O$Q%“S%—U&šW&X&¡Z'¦](·l5´f,Èt5dPeP’fP”fQ–gQ—hQ™iR›kRlSŸmT¢oV¤qW§tY«v[®y^±|aµc¸‚f¼…h¿ˆkÁŠlÃŒnÅnÅoÅnÅŒmÄ‹k‰iÁ‡g¿…e½ƒc»€`¹~^·|\¶{Z´yY³xW²wV²vU±vU±uT±uT±uT°uT°uT°tS°tS°tS°tS°tS¯tS¯tS¯tS¯tS®tS®tS®sS­sT­sT­sT¬sT¬rT«rTªrTªrS©qS¨qS§pS¦pS¦oS¥oS¤nS¢nR¡mR mRŸlRžkRkR›jQšiQ˜iQ—hQ•gQ”fQ’ePePdPcPŠbPˆ`O†_Oƒ^O]O~[N{ZNxXNtVMqUMhPLgPLfOLdNLbML_LKbE6,Qƒ,Qƒ,Qƒ,Qƒ-Qƒ-Qƒ-QƒPt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Q„-Q„-Q„\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@d–w›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Îw›Îw›Î=a”=a”=a”=a”=a”=a”=a“#Hz#Gz#Gz#Gz#Gz#Gz#GzmYPPDJUGJYIKbMLqUM\NŠbP”fQ›jQŸlR¡mRžlRËp,µe+ \+R%ˆN$b; ]8 [7 XHKO+N1L/L/L/K/K/ eb”>b”>b”>b”>b”>b”>b”>b”=b”=b”=b”=b”=b”=b”=b”=b”YEUGJYIK_LKnSM|ZNˆ`O’ePšiQŸlR¡mR mR™iQºg*´j4šW'‘R%ŽQ%h>!g=!f=!db”>b”>b”>b”>b”>b”>b”$Hz$Hz$Hz$Hz$Hz>b”>b”>b”>b”>b”gVOS=2RFJWHK[JKeOLsVM€]OŒbP•gQœjQ lR¡mRžlRÌr/¹g*²h2–U&“S%‘R%Q%ŽQ%ŒP%£['¨]'¬`(°b(´d)¸f)»g)¾i*Áj*I#¡Z'¡Z' Z' Z'¡Z'£['¤['¥\'¦]'ª_)±d,³d)Äq3‹bPcPdP‘eP’fQ”fQ–gQ—hQ™iR›kSlSŸmU¡oV¤qW¦sY©u[¬x]¯z^±|`´~b¶€d¸‚eºƒf»„f»„f¼„f»ƒe»‚dºb¹€a·~_¶}^µ{\´zZ³yY²wX±wW°vV°uU¯uU¯tT¯tT¯tT®tS®tS®tS®sS®sS®sS®sS®sS­sS­sS­sS­sS¬sS¬rS¬rS«rS«rSªrSªqS©qS©qS¨pS§pS¦pS¦oS¥oS¤oR£nR¢nR¡mR mRŸlRžkRkRœjQšjQ™iQ˜hQ–hQ•gQ“fQ’ePdPŽcPŒcPŠbPˆ`O†_O„^O]O\N|ZNyYNuWNrUMnSMjQLdNLcNLaMK_LK[JK`D6Pt¦Pt¦Pt§Pt§Pt§Pu§Pu§Pu§Pu§Qu§Qu§Qu§Qu§Qu§Qu§-Q„-Q„-Q„-R„-R„-R„-R„-R„-R„-R„-R„-R„.R„.R„Rv¨Rv¨Rv¨~¢Ô~¢Ô~¢Ô~¢Ô\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@e—@e—@e—@e—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—xœÏxœÏxœÏxÏxÏxÏxÏyÏyÏ>b•>b”>b”$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b”>b”>b”>b”>b”YDb”>b”>b”>b”Q@:R<2fL@WHJZJKaMKoTM|ZNˆ`O‘eP™iQŸlR¡mR¡mRœjRÇo-»i-´h0«`)§]'¨]'¬`(°b(´d)¸f)¼h)Àj*Ãk*Æm*Én+Ìp+Ïq+Òr,§]'§]'§]'¨^'ª_(«_(¬`(­`(¯b)²c)ºi.ˆ`OŠaPŒbPŽcPdP‘eP“fQ”gQ–hQ˜iRšjR›kSlTŸnU¢oV¤qW¦sY©uZ«w\­y]°{_²|`³}aµ~b¶b¶b¶b¶a¶~`µ}_µ|^´{]³z[²yZ±xY°wX¯vW¯uV®uU®tU®tT­tT­sT­sS­sS­sS­sS­sS­sS­sS­sS¬sS¬rS¬rS¬rS«rS«rS«rSªrSªqS©qS©qS¨qS¨pS§pS¦pS¦oS¥oR¤oR¤nR£nR¢mR¡mR lRŸlRžkRkRœjQšjQ™iQ˜hQ–hQ•gQ“fQ’ePdPdPcP‹bP‰aO‡`O…_O‚]O\O}[NzYNwXNtVMpTMlRMhPLcNLaMK_LK]KKbR]C5Pu§Pu§Pu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨-R„-R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae˜Ae˜Ae˜Ae˜yÏyÏyÏAf˜Af˜Af˜$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b•>b•>b”>b”WD3TFJXHK[JKfOLsVM€]O‹bP”gQœjQ lR¡mR mRœkRÅm,½i,ºj/²d+±c)²c(¶e)ºf)¾h*Áj*Ål*Én+Ëo+Îq+Ñr+Ós,Õt,ƒK$ª^(ª_(«_(¬`(®a(¯a)°b)³d*¶f+¾m1‡`O‰aP‹bPcPdPeP’fQ”fQ•gQ—hR™iR›kSlTŸmT¡oV£pW¥rX§tY©v[¬w\®y]¯z^±{_²|`³}`´}`´}`´}_´|^³{^³{\²z[±yZ°xY°wX¯vW®uV®tU­tU­tT­sT­sT­sS­sS¬sS¬sS¬sS¬rS¬rS¬rS¬rS¬rS«rS«rS«rS«rSªrSªqSªqS©qS©qS¨qS¨pS§pS¦pS¦oS¥oR¤oR¤nR£nR¢mR¡mR mRŸlRžlRkRœjQ›jQšiQ˜iQ—hQ–gQ”fQ“fP‘ePdPŽcPŒbPŠaPˆ`O†_O„^O]O\N|ZNyYNvWNsVMoTMkRLgPLbML`LK^KK\JK~aR[B5Pu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe—Ae—Ae—Ae—Ae—Ae—Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Af˜Af˜Af˜yÐAf˜Af˜Af˜Af˜Af˜Bf˜$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c•>c•>b•>b•O?:[E|aRZA5-QƒQu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„Rv¨Rv¨Rv©Rv©Rv©Rw©£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe˜Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Af˜Af˜Af˜Af˜Af˜yžÐyžÐyžÐzžÐzžÐzžÐBf˜Bf˜Bf˜Bf˜Bf˜$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c•>c•>c•>c•VC^C6W@5-Q„-Q„Qu§Qu§Qu§Qu§Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„Rv©Rw©Rw©Rw©¤Ö¤Ö¤Ö¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö¤Ö¤Ö¤Ö\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAf˜Af˜Af˜Af˜Af˜Af˜Af˜Af˜zžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐBf˜Bf˜Bf˜Bf˜$I{$I{$I{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz YE\C6T>4-Q„-Q„-Q„-R„Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„Rw©Sw©€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAf˜Af˜Bf˜Bf˜Bf˜zžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑBf˜Bf˜Bf˜$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$H{$H{$H{$H{?c•?c•?c•?c•$H{$H{$H{SB;R<2zbVUGJXIK[JK[JKuWN€\OŠaP’fP™iQŸlR¡mR£nS£nS¥pTà€9Þ9Õw2Öw0Öv/Öv.Ùx/Üz0Þz0á|1ã~2æ€3è5éƒ6ë…8ë…8ºm4¼o7¾q8Äu;Ãs9Ãs8ºj0‚]O„^O†_Oˆ`OŠaPŒbPcPdP‘eP’fQ”fQ•gQ—hR™iRšjSœkSlTŸnU¡oV¢pV¤qW¦rX§sY¨tY©uYªuZ«uZ«vZ«vY«uY«uX«uX«tW«tV«sVªsUªsUªrTªrTªrTªrSªqSªqSªqSªqSªqS©qS©qS©qS©qS©qS©qS©qS©qS¨qS¨pS¨pS§pS§pR§pR¦oR¦oR¥oR¥oR¤nR£nR£nR¢mR¡mR mR lRŸlRžkRkRœjQ›jQšiQ™iQ—hQ–gQ•gQ”fQ’eP‘ePdPcPŒbPŠaPˆ`O†_O„^O‚]O\O}[NzYNwXNtVMqUMnSMiQLeOL`LK]KKmP?kN?|aSZA5P<4-R„-R„-R„-R„-R„-R„Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×Ei›Ei›Ei›Ei›Ei›Ei›Ei›\À\À\À\À\À\À\À\À\À\À\À\ÀBf˜zžÐzžÐzžÐzžÐzžÐzžÐzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑBf™Bf™Bf™%I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{?c–?c–?c–?c–?c–?c•?c•?c•?c•$H{$H{$H{jXP^H=}dXUGJXHKZIKkRLwXN‚]O‹bP”fQšiQžkR mR£nS¥pT¨qU¨rUç…;ç†>ì‰?è†<å‚9ê†;î‰=ðŠ=ðŠ>ôŽAø‘Dü•Hÿ˜Kù’E¿r:Àt;Àt;Át<Ãt:½n4´f,]Oƒ^O…_O‡`O‰aO‹bPŒcPŽcPdP‘eP“fQ”gQ–hQ˜iR™jR›kSœlSžmTŸnU¡oV¢pV¤qW¥rW¦rX§sX¨tX©tX©tX©tX©tXªtWªsW©sV©sV©rU©rU©rT©qT©qT©qS©qS©qS©qS©qS©qS©qS©qS©qS¨qS¨qS¨pS¨pS¨pS¨pS§pS§pS§pR¦pR¦oR¦oR¥oR¥oR¤nR¤nR£nR¢nR¢mR¡mR mR lRŸlRžkRkRœjQ›jQšiQ™iQ˜hQ–hQ•gQ”fQ’fP‘ePdPŽcPŒcP‹bP‰aO‡`O…_Oƒ^O]O~[N{ZNyYNvWNsVMpTMlRMgPLcNL†gUƒeUlO?~bT{`SW@5-R„-R„-R„-R„-R„-R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R….R…Ei›Ei›Ei›€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›\À\À\À\À\À\À\À\À\À\ÀzžÑzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒBg™Bg™Bg™%I{%I{%I{%I{%I{%I{%I{@d–?d–?d–?d–?d–?d–?d–?d–?d–?c–?c–?c–?c–$I{$I{L=:WD`KA-R„-R„-R„.R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R….R….R….R…EiœEiœEiœEiœEiœEiœ¥×¥×¥×¥×¥×¥×¥×EiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœ\À\À\À\À\À\À\À\ÀzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒ{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| ÒCg™Cg™%I{%I{%I{@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–?d–?d–?d–?d–?d–?d–$I{$I{dUPYEXG@-R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©.R„.R„.R„.R„.R„.R„.R„.R„.R….R….R….R….R….R….S…EiœEiœEiœEjœEjœEjœEjœEjœ¥×¥×¥×EjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEiœEiœEiœ\À\À\À\À\À\À{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| ÒCg™@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–?d–$I{$I{RA;P<3zcXnVIuh™~pdNLpUMÁ”w¬zZ«vS‘eP–gQœjQžlR¡mR¤oS§pT­uV¯vW±xY¶|\¼€_ÆdƉgÈŠhÊŒiÌŽkÎlÿRñF¶k4²g1¯d-­b+ª_(¢Z'}[N€\O‚]O„^O†_Oˆ`O‰aP‹bPcPŽcPdP‘eQ’fQ”gQ•gQ—hR˜iR™jR›kSœkSlTžmT nT¡nU¡oU¢oU£pU¤pU¤pU¤pU¥pU¥pT¥pT¥pT¥pT¥pS¥pS¥oS¦oS¦oS¦oS¦oS¦oS¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¥oR¥oR¥oR¥oR¤oR¤nR¤nR£nR£nR¢nR¢mR¡mR¡mR lRŸlRŸlRžkRkRœkQœjQ›jQšiQ™iQ˜hQ—hQ•gQ”gQ“fP’ePePdPcPŒbPŠbP‰aO‡`O…_Oƒ^O]O~\N|[NzYNwXNtVMpUM—pY”oXzWBuUB…gVlP@jO@|bUx`TcMB3!.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©.R„.R„.R„.R„.R….R….R….R….R….S….S….S…EjœEjœEjœEjœEjœEjœEjœEjœEjœ¦Ø¦ØEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœ\À\À\À\ÀBg™{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| ÒCg™Cg™Cg™Cg™|¡Ó@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–%I{;0/SB;R=4fODpXL‘xkš€r˜vbº“zÀ”x«{[ÃldP•gQ™iQ›jQŸlR£nR¦pS¨qTªrT¬tU°wWµ{Z¸}\¸|\¸}\¹~]»]å}+Ý~6­d.ªa+¨_)§^(¤\'zYN|ZN~\N€]Oƒ^O„_O†_Oˆ`OŠaP‹bPcPŽdPdP‘eQ“fQ”gQ•gQ—hR˜iR™jRšjSœkSlSžlTŸmT mT nT¡nT¢nT¢oT£oT£oT£oT£oT¤oS¤oS¤oS¤oS¤oS¤oS¤oS¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¤oR¤oR¤nR¤nR¤nR£nR£nR£nR¢mR¢mR¡mR¡mR lR lRŸlRžlRžkRkQœjQ›jQšjQ™iQ™iQ˜hQ—hQ•gQ”gQ“fQ’ePePdPŽcPŒbPŠbP‰aO‡`O…_Oƒ^O]O\N}[NzZNxXNuWMrUM™rZ–pY|XCxVCsTBmQAkOA~cVzaU`I>\IARv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©.R….R….R….R….R….S….S….S….S…FjœFjœFjœFjœFjœFjœFjœFjœ‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦ØFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœ\À\ÀBg™{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ó| ÓCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™}¡Ó@e—@e—@e—@e—@e—@e—@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–%I{<1/J82^I@gQFqYN‘xl™€s—vc¢{d¿”yª{\«wUÄi‘eP•gQ˜hQkQ mR¢mR¤nR¥oS§pSªrT¬tU¬tU¬tU¬tU­tU®tUÒt.ƒL&¤](¢['¡Z'žY&xYN{ZN}[N\N]Oƒ^O…_O‡`OˆaOŠaPŒbPcPdPeP‘eQ“fQ”gQ•gQ—hR˜iR™iRšjR›kSœkSlSžlSŸmSŸmS mS nS¡nS¡nS¢nS¢nS¢nS¢nS£nS£nS£nR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR£nR£nR£nR£nR£nR¢nR¢mR¢mR¡mR¡mR¡mR lR lRŸlRžlRžkRkRœkQœjQ›jQšiQ™iQ˜iQ—hQ–hQ•gQ”fQ“fP’ePePdPŽcPŒbP‹bP‰aO‡`O†_O„^O‚]O\O}[N{ZNxYNvWNsVM›s[˜rZ~ZDnYŒkYqSBkPAiOA|cVbK?\G>NB?Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©.S….S….S….S….S….S…FjœFjœFjœFjœFjœFjœ‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦ØFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœCg™Cg™| Ò| Ò| Ò| Ò| Ò| Ó| Ó| Ó| Ó|¡Ó|¡ÓCg™Cg™Cg™Cg™Cg™Cg™Cg™CgšCgšCgšCgšCgš}¡ÓAe—Ae—Ae—@e—@e—@e—@e—@e—@e—@e—@e—@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–%I{@d–@d–<1/H72\I@ePGpYNxm˜€t–vc¡{e¾”zÁ“u‘p«wU¬uQ‘eP•gQ™iQšjQœjQžlR¡mR£nR¤nR¤oR¤oR¤oR¤oR¤oRÇgb;  Z'žY&›W&“S%vXNyYN{ZN~[N€\O‚]Oƒ^O…_O‡`O‰aOŠaPŒbPcPdPdP‘eQ“fQ”gQ•gQ–hQ˜iR™iRšjR›jR›kSœkSlSžlSžlSŸlSŸmS mS mS¡mS¡mS¡mR¡mR¢mR¢mR¢mR¢mR¢nR¢nR¢nR£nR£nR£nR£nR£nR¢nR¢nR¢mR¢mR¢mR¢mR¡mR¡mR¡mR mR lRŸlRŸlRžlRžkRkRkQœjQ›jQ›jQšiQ™iQ˜hQ—hQ–gQ•gQ”fQ“fP‘ePdPdPcPŒbP‹bP‰aO‡`O†_O„^O‚]O€\O}[N{ZNyYNvXNtVMu\„]E€[E’oZŽmZŠkYnRBjOB}cVdL@`I?XGARv¨Rv¨Rv¨Rv¨Rv©Rv©Rw©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwª.S….S….S….S…/S…FjœFjœFjœFjœ‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦ÙFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœ‚¦Ù‚¦ÙCg™Cg™| Ó| Ó|¡Ó|¡Ó|¡Ó|¡Ó|¡ÓCg™Cg™Cg™Cg™CgšCgšCgšCgšCgšCgšCgšCgšChšChšChšChšChš}¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—@e—@e—@e—@e—@e—@e—@e—@d—%I{%I{%I{%I{%I{@d–@d–<10F61o]Vye]„oeŽxmœ‚u”udŸ{e¥}d¨|aÀ’tÁpÃl¬uQdP’eP”fQ–gQ˜iQ›jQœjQœjQœjQœjQœkQœkQkQ_9 œX&™V&•T%rUMuWMwXNzYN|ZN~[N€\O‚]O„^O…_O‡`O‰aOŠbPŒbPcPŽdPdP‘eQ’fQ”fQ•gQ–hQ—hR˜iR™iRšjR›jRœkRœkRkRlRžlRžlRŸlRŸlRŸlR lR mR mR mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR mR lR lRŸlRŸlRŸlRžkRžkRkRkQœjQ›jQ›jQšiQ™iQ˜iQ—hQ–hQ•gQ”gQ“fQ’fP‘ePdPdPcPŒbPŠbP‰aO‡`O†_O„^O‚]O€\O~[N{ZNyYNwXNtVMrUM†^F‚]F”q\o[ŒlZqTD€fX}dWeMAbK@O=6NB@Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxª/S…/S…FjœFjœFjœƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœƒ§Ùƒ§Ùƒ§Ùƒ§ÙCg™Cg™Cg™}¡Ó}¡Ó}¡ÓCg™CgšCgšCgšCgšCgšCgšCgšChšChšChšChšChšChšChšChšChšChšDhšDhšDhš~¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—%I{%I{%I{%I{%I{%I{%I{%I{%I{@d—@d—E:9D61m\Vwe]lXOuaX„k_¨‹z±|¡|e¥|c§|`©z]ªyXÂnÃlÄŽkÄŽidP’eP“fP“fP“fP’fP“fP“fP“fP[7 —U&”T%P%pTMsVMuWMxXNzYN|ZN~[N€\O‚]O„^O†_O‡`O‰aOŠbPŒbPcPŽdPdP‘eP’eQ“fQ”gQ•gQ–hQ—hQ˜iR™iRšjR›jR›jRœkRœkRkRkRžkRžlRžlRŸlRŸlRŸlRŸlR lR lR lR lR lR lR lR lR lR lR lR lR lRŸlRŸlRŸlRŸlRžkRžkRkRkQœkQœjQ›jQ›jQšiQ™iQ˜iQ˜hQ—hQ–gQ•gQ”fQ“fP’eP‘ePdPŽdPcPŒbPŠbP‰aO‡`O…_O„^O‚]O€\O~[N|ZNyYNwXNuWMrUM‡`G„^G–r]|ZFxXFtVEgY~eY{cXbLA[H?REA.R„.R„Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSxªSxªSxªSxªTxªTxªTxªƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙFjFjFjFjFjFjFjFjFjFjFjƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙCg™Cgš}¡Ó}¡ÓCgšCgšCgšCgšChšChšChšChšChšChšChšChšChšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš~¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—%I|%I|%I|%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{@e—@e—B99B51k[Vud]iWPr_Wye] †yªŒ|²}¡|e¤|c¾’w¨{^¨z\©yZÁp«xW«wU«wU«wU«wUÃŽlÃŽlÂŽlÂŽlkD(’S%ŒP%nSMoTMqUMsVMvWNxXNzYN|ZN~[N€\O‚]O„^O†_O‡`O‰aOŠaP‹bPcPŽcPdPeP’eQ“fQ”fQ•gQ–gQ–hQ—hQ˜iQ™iR™iRšjR›jR›jRœjRœkRœkRkRkRkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRžlRžkRžkRžkRkRkQkQœkQœjQ›jQ›jQšjQšiQ™iQ˜iQ˜hQ—hQ–gQ•gQ”gQ“fQ’fP‘ePePdPŽcPcP‹bPŠaPˆaO‡`O…_Oƒ^O‚]O€\O~[N|ZNyYNwXNuWMrUMŸw_œv_˜t^~\GzYGvWF†j[fZ|dYybX\I@VGB5/2.R„.R„.R„.R„Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxªSxªTxªTxªTxªTxªFkFkFkFkƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§ÚFkFkFkFkFkFkFkFkƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Ú}¡Ó}¡Ó}¡Ô}¡ÔChšChšChšChšChšChšChšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš~£ÕAe˜Ae˜Ae˜Ae˜Ae˜%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{%I{%I{%I{%I{@e—@e—<68?31gYVpa\bRMjYTq`Z€j`¡‡z«}²‘}¶’|¸’{º’z»’x¼’w§z^¿‘t¿‘s¿‘s¿s¿r¿r¾r¾r°h2‹O$„L$mSMnSMnTMoTMtVMvWNxXNzYN|ZN~[N€\O‚]O„^O…_O‡`OˆaOŠaP‹bPŒcPŽcPdPdP‘eP’eQ“fQ”fQ•gQ–gQ–hQ—hQ˜hQ˜iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœkQœkQkQkRkRkRkRkRkRkRkRkRkQkQkQœkQœjQœjQœjQ›jQ›jQšjQšiQ™iQ™iQ˜hQ—hQ—hQ–gQ•gQ•gQ”fQ“fP’eP‘ePdPdPcPŒbP‹bP‰aPˆ`O†`O…_Oƒ^O]O€\O~[N|ZNyYNwXNtWM£z` y`w`šu_€]I|[HwXGˆl\ƒi[}eZycYr_WjZU;23.R„.R„.R„.R„.R….R….R…Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxªTxªTxªTxªTxª/S…/S…GkGkGkGkGkGkGkƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨ÚGkGkGkƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Ú}¢Ô}¢Ô}¢Ô}¢Ô~¢ÔDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš£ÕAf˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{Ae—Ae—Ae—?89H=:?YUY`QGfVLudXjeitlm{po|qp}rp~rpsqsq€tqŒr_=1+xJ)’o[~[F€\G‚^H„_I…`IkRLlRMnSMpTMrVMuWMwXNyYN{ZN}[N~\N€\O‚]Oƒ^O„_O†_O‡`Oˆ`O‰aPŠbP‹bPŒcPcPŽcPdPdPeP‘eP’eP’fP“fQ“fQ”fQ”gQ•gQ•gQ•gQ–gQ–gQ–gQ–hQ–hQ—hQ—hQ—hQ—hQ—hQ–hQ–hQ–gQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘eP‘ePdPdPŽdPŽcPcPŒbP‹bPŠaP‰aO‡`O†_O…_Oƒ^O‚]O€\O~\N}[N{ZNyYNwXNuWM“iOhOŽgO‹eOžze›yd—wd”tcrbtYKjTIaOG[KFj]Y^UU?;@.R….R….S….S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…GkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkž…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û…©Û…©Û£Õ£Õ£Õ£Õ£Õ£Õ£Õ£ÕDh›Dh›Dh›Dh›Di›Di›Di›Di›Di›¤Ö¤Ö¤Ö¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|Af˜Ae˜Ae˜%J|%J|%J|%I|%I|%I|%I|���#-#%.()1MEAQIEUMI]SL]TM=4.1+(=.#6,&5( 1%"ŒlYn[“p\•r]]Hƒ_I…`JœwažybkRLmSMpTMrUMtVMvWNxXNzYN|ZN}[N\N€]O‚]Oƒ^O…_O†_O‡`OˆaO‰aPŠaP‹bPŒbPcPŽcPŽdPdPdPeP‘eP‘eP’eP’fP“fP“fQ“fQ”fQ”fQ”fQ”gQ”gQ•gQ•gQ•gQ•gQ•gQ”gQ”fQ”fQ”fQ”fQ“fQ“fP“fP’eP’eP‘eP‘ePdPdPdPŽcPcPŒcPŒbP‹bPŠaP‰aO‡`O†_O…_Oƒ^O‚]O]O\O}[N|ZNzYNxXNvWN¬‚gªg¨€ghPŒfPŸ|fœzf˜xe”vdscsYLiTK_NHYKFh\Z]UV=;@.R….S….S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxª/S…/S…/S…/S…GlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û£Õ£Õ£Õ£Õ£Õ£Õ£Ö£ÖDi›Di›Di›Di›Di›Di›¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Ei›&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Af˜Af˜Af˜Af˜Af˜%J|%J|%J|%J|%J|%J|%I|%I|%I|, +,!.! "`E6†iYŒlZo\“q]•s^^J™va›wbycŸzd {e¤}foTMqUMsVMuWNwXNyYN{ZN|ZN~[N\O]O‚]Oƒ^O…_O†_O‡`Oˆ`O‰aOŠaP‹bPŒbPŒcPcPŽcPŽdPdPdPdPeP‘eP‘eP‘eP’eP’eP’eP’eP’fP’fP’fP“fP’fP’fP’fP’eP’eP’eP‘eP‘eP‘ePePdPdPdPŽdPŽcPcPŒcPŒbP‹bPŠaP‰aOˆ`O‡`O†_O…_Oƒ^O‚]O]O\O~[N|[N{ZNyYNwXN®ƒi¬ƒiª‚i¨i¦€hŒhR‰fQ†dQ‚bP•wfx]Oˆpdkbtd_m`]OEDG?A;:@.S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTx«Tx«Tx«Ty«/S†GlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ£Ö£Ö£Ö£Ö¤Ö¤Ö¤Ö¤Ö¤ÖEi›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×€¥×€¥×€¥×Bg™Bg™Bg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Af˜Af˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|��� +,YA5jPBpSD‹l[o]’q^–t`‚_Kšwbœycžze {f¡}g¤h¨i”lSrVMtWMvWNxXNyYN{ZN|[N~[N\O]O‚]Oƒ^O„_O…_O†`O‡`Oˆ`O‰aPŠaP‹bP‹bPŒbPcPcPŽcPŽcPdPdPdPdPdPdPdPdPePePePePePdPdPdPdPdPdPdPŽcPŽcPcPcPŒbP‹bP‹bPŠaP‰aOˆ`O‡`O†`O…_O„^Oƒ^O‚]O€]O\O~[N|[N{ZNyYNxXN°…j®„j¬„jªƒj¨‚j¦€jŒhSŠgS†eRƒcR|`QŒsf…oe}jcrd`k_]LCDC=@,,3(4F(4F.S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžChšChš¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|#5H71O;3V?4iOBoSDsVFo]{[I^Kƒ`L…bN‡dOŸ{f }g¢~h¥€j’kT•mU˜oVšqWrWwXNxXNzYN{ZN}[N~[N\O€]O‚]Oƒ^O„^O…_O…_O†`O‡`Oˆ`O‰aO‰aPŠaP‹bP‹bPŒbPŒbPŒcPcPcPcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPcPcPcPŒcPŒbP‹bP‹bP‹bPŠaP‰aP‰aOˆ`O‡`O†_O…_O„_O„^Oƒ^O]O€\O\N~[N|ZN{ZNyYN›oTšoT™oT—nT¬„lªƒl¨‚ljUŒiTŠhT†fT€cSvi‰rgnfyidqdah^^HBD?<@)+3OZkMYk(5F(5F(5F/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Ty«Uy«†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžDhšDhšDhšChš&K}&K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|A99N?;L:2T>4gNBlRD‡k\‹n^z[J~^LaN…cO‡dP‰fQŠgRŒhTjU’lV•nW˜pXšrXsY¶‹q¸qºŽr¼r½r¿s©z[©z[ªz[«{[¬{[¬{ZÅ“rÅ’qÅ’qÅ’pÅ’pÅ‘o­yV­xV¬xU¬wT¬wTŠaPŠbP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bPŠaPŠaPŠaP‰aP‰aOˆaOˆ`O‡`O‡`O†_O…_O„^Oƒ^O‚^O‚]O]O€\O~\N}[N|ZNzYNpTœpU›pUšpU˜oV—oV•nV“mV‘lVkVŒjVˆhVƒfU~cUuj†qh~mfugdkaad\^E@D98?$(2minffm^blV^lMYk(5F(5F/S…TxªTxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Uy«Uy«†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}ChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|Ae˜Ae˜;GY<68I=:I82Q=4XA6~fZ„j\‰m^p`|]L€`NƒcP†eQˆgS¡j£€l¦‚m©„n•oX˜qYšrZt[¶Œr¸sºs¼t½t¾‘t¨z]©{]ª{]«{\«{\¬{\¬{[Ä“sÄ“rÄ’rÄ’qÄ’pÄ‘p¬yWÄoÃnÃmÃlÂŽlÂŽkÁkˆaOˆaOˆaOˆaOˆaOˆaOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O…_O„_O„^Oƒ^O‚]O]O€]O\O~\N}[N|ZN¶‰l¶‰lµˆmœqV›qVšqV™pW˜pW–oW¬…nª…n§„n¤‚nŸ€n›~n€eW‘xlŠtk‚piykfodcf_`JDG@>C*,5$1MYktr~tstmolinadmX_lNZkMZkTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«ÝHlŸHlŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™&J}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Af˜Af˜Af˜Af˜;GY;GY;GY1'!D:9N?;N;3]I?zdY€h[†l^‹oasc“ue€bQ„dR‡fT l¢m¦ƒn©…o«‡p®ˆq±Šr³‹sžv] w]¹u»u¼‘u¾‘u¿’v¨{^©{^ª|^«|]«|]«{\¬{\¬{[¬{[¬zZ«zZ«yY«yX«xXÂoÂnÂnÁŽmÁŽm¨uT¨uS§tS§tS§tR¦sR¦sQ…_O…_O…_O„^O„^Oƒ^Oƒ^O‚^O‚]O]O€]O¢rS¡rS¡rS¸‰k·‰l·‰l¶‰m¶‰mµ‰m´‰n³‰n›qWšqX™qX®‡o­‡o«†p¨…p¤ƒp pœp—}o{cXv`Vp]U}nishfhaba\_DAF::B$)4�MYkMYkMYkŒtctq\QPPIKFDI;>H/8GMZkTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸImŸImŸImŸImŸImŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšChšChšChšChšChšChšChšChšCgšCgš&K}&K}&K}&K}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;GY;GY;GY;GY;,#I=:H82YF?^JA|e[‚j]ˆn`Œqcte”wg—yiš|k~l €n£‚o¤ƒp¦…q­‰s°Šs›u]žv^Ÿw^¡x_£y_¤z_¥z_¦{_¿“w¿“wÀ“vÁ“vÁ“v“u“u“tª{\ª{\ªz[ªzZªyZªyY©xXÁpÀo¨wW¨vV§vV§uU¦uU¦uT¥tT½Œl¼‹k¼‹k¼‹k»‹k»‹kºŠk¢sT¢rT¢rT¡rT¡rT¡rU rU rV·Šn¶ŠnµŠnµŠo´Šo³‰o²‰p±‰p™qY®ˆq¬‡qª†r§…r¤„r ‚rœ€q€gZ{dYvaXp^WiYU`TRVNOb]aEBH<+[NL^SQWNNKFJ?AI2:HTx«Ty«Ty«Ty«Uy«Uy«Uy«Uy«Uy«‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝImŸImŸImŸImŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšChš&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}CgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;HY;HY;HY;HY;GY3("D::B41RB=YG@wcZ}g\ƒk_‡nbŒrdug}aRdT„gV‡iX‰kY¢ƒq¤„r¥…s§†t‘p^’q^Ÿw` x`¢y`£z`¤za¥{a½“x¾“x¿“w¿“wÀ“wÀ“vÀ“vÀ“vÀ“uÀ’uÀ’tÀ‘sÀ‘sÀ‘r¿r¿q¿q¾p¾Žp¾Žo½Žo¥vW¼n¼Œn»Œn»Œn»ŒnºŒnº‹m¢tV¡sV¡sV¡sV sV sWŸsWŸsXžsXµŠpµŠp´ŠpœsY›sYšrZ˜r[–r\”q\‘p]¦†t£„tŸƒsœs€h\{e[vbYo^XhZV`USXPQNJMECJRS[47A+((MYkMYkMYkMZk(5F(5F(5FOHJT=+YML_SRZQQMGJABI2:H/T†Uy«Uy«Uy«Uy«Uy«Uy«‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸˆ¬Þˆ¬Þ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}CgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™&J|&J|Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;HY;HY;HY;HY>DM>DM;HY89<:+#9&B52I94ZHAxd[}g^k`†nc‹rey_R}bTeVƒgX…iYˆk[Šl\Œn]o^¥‡v§ˆvšvaœwažxa yb¢zb¤{b¤{a¼“x½“x¦|a§|a§|`§{`§{_§{_§{^§z^¾‘u¾‘t¾‘t¾s½s½r½r¥wZ¤wZ¤vY¤vY£vY£uX¢uX¢uX¢uX¹Œp¸Œp¸Œp·Œp·‹p¶‹p¶‹pµ‹qµ‹qtZ›t[šs\™s\˜s]–r]”r^’q^p^o^Šn^‡l^ƒj^h]{f\ub[n^YgZW_UTWPQOKOEEKST]JNY>=?JJIMYkMYk(5F(5F(5F(5F(5F)5G)5GK=4S<*XMLbWVYPPLGJ@AI/T†/T†Uy«Uy«Uy«‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞImŸImŸImŸIm ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞIm Im Im Im Im Im Im Im ˆ¬Þˆ¬Þˆ¬Þˆ¬Þ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Dh›Dh›Dh›Dh›DhšDhšDhšDhš'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜;HY;HY;HY;HY;HY;HYCIR>DMCIR;HYCIR.$0"8&?*G/V=+w[F{g^€kanXMs\Px_S{bU~dWfYƒhZ†j\ˆl]Šm^¢…v§ˆwªŠx­Œy¯y±Žz´zµz·‘z¹’z£{b£{b¤{b¥{b¥{a¥{a¥{`¥{`¥z_¥z_¥z^¼‘u¥y]¤y]¤x]¤x\£w\£w[¢w[¢v[¢v[¡v[¡v[¸r·r¶r¶ŒsµŒs´Œs´Œs²Œt±‹u°‹u˜t^–s_•s_“r_’r`q`p`¡…wž„v›‚v—€u“~twd]sb[l^ZeYW]TUUORLJOYYaRU^JOZ>>@!$)RXaMYk39B-3<-3<(5F)5G)5G)5G)5G)5GFDJK9*^K=YONg\\TLMIFJ:>I0T†0T†ImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞIm Im In In In In In In ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßIn In In In In ˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ß'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Di›Di›Dh›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}ChšChšChšChšChšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™&J}&J}&J}&J}&J|&J|&J|&J|&J|Bg™Bg™Bg™Bg™Bg™Bf™Bf™EM>EMCIR;HY;HYCIRCIR)6&8&@*H0I1!\B0}_JhTKjM8q[Pt]Sw`U{cW~eYg[ƒi\…k^‡m_Ÿ…v¢†w¥ˆx¨Šyª‹z­z¯Ž{±{²{³{´{žzdŸzd zc zc¡zc¸‘y¸‘y¸‘y¸‘x¸x¸x·w·w·w·wŸw_Ÿw_žw_µŽv´Žv³v²v²w±w°Œw¯Œw®Œw­‹w«‹xªŠx¨‰x¦‰x¥ˆx£‡x¡†xž…x›ƒw—v’~vŽ|t‰ys„vrh\YcXX[TUSNRIHOUXaNS^JFE>>A')+"%(4:C(5F(5F3:B3:B-3<-3<)5G)5G)5G)5G)5G)5GE:4O:*TKLbXWcZZPIKDCJIm Im Im Im ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßIn In In In In In Jn Jn Jn Jn Jn ˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn ‰­ß‰­ß‰­ß‰­ßˆ­ßˆ­ßˆ­ßˆ­ß'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšChšChšChšChšChšChšCgšCgšCgšCgš&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J|&J|&J|Cg™Cg™Cg™Bg™Bg™Bg™EMCIRCIRCIR888DGNCJRCIRBBB(0 8&<)G0M5"X@0z^K†bFŠkUlXPp[Rs^TvaVzcX}fZg\i]™u›‚v„wŸ†x¢‡y¥‰z§Šz©‹{ªŒ{•ve–ve—we˜we°|°|±{²{²{²{²{²{±z±z±Žz±Žz±Žz°Žy™vb˜vb—vb–ub•ub•uc”tc“tc’sbscrcqc¢‡y †y…y›„x˜‚x•w’w|uˆytƒvs~sqyooslmVQTOLR[\dQU`KHHAAD:<@68; &�Z`i-4<%');AJ4:C4:C4:C-4<)5G)5G)5G)5G)6G)6G@84H8-N?5YPQmccoghd`dIn In In In In In ˆ¬ßˆ¬ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßJn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~Ei›Ei›Ei›Ei›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšChšChšChš&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J}Cg™Cg™Cg™Cg™B9;>68;����Z`iZ`iMZk)5G4:C-4<4:C4:C-4<;BJ)5G)6G)6G)6G)6G)6GC6-L;.leg„{{ypqhbeVYcJn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­àJn¡Jn¡Jn¡Jn¡Jn¡Jn¡Jn¡‰­à‰­à‰­à‰­à‰­à'L~'L~'L~'L~'L~'L~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhš'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}Cg™Cg™Cg™<535=AG=?D?AD==1(B3)B2&F4'E4)gTGlXJs^OzcTzaPqfethgvjhbVTcWUdXVeYWfZXg[Yh\Zi]Zi][j^\€us€ususts~tt~tt}tt|st{stut~tt|sszrsyqrwpquoqsmpqloXTXTQWPOULLSSJEA<:=99757335./2113)+.'),)+.8:="(���3@Q���������������JMPV\eT[cNZlNZlZ`iZ`iZ`iZ`iSYbY`h4;C.4=)6GCPaCPaCPaCPaCPaEQbZOGa_emhkŠƒ„nfgeaeJn¡Jn¡Jn¡Jn¡Jn¡Jn¡Š®àŠ®àŠ®àŠ®àŠ®àJo¡Jo¡Jo¡Jo¡Jo¡Jo¡Jo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Š®àŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡ƒ§Úƒ§Úƒ§Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨ÚEjœEiœEiœEiœEiœ'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}Di›Di›Di›Di›Dh›Dh›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}$.>=I[=I[2)>0&A2'C3(I8-^OFbRHfUJjXMq^RwcVzfYfRDfQCdN@zdTqijrjksklrklrklrklqjmpjmpjmojmojmnimmimkhliflscYm`Xg\VbYT^VRE>;A<:>98:77645:873220/0,-/)+.*,/#%( &������15;5BS������������������KKKJMP]dlU[dNZlNZlZ`iTZcZaiZaiZ`iZ`iSZbŽ”LS[V]eDPbDPbDPbDPbDPbDPbWMF^^diei®”†…rkeaeJo¡Jo¡Jo¡Jo¡Š®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Š¯áŠ¯áŠ¯áŠ¯áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡ƒ¨Úƒ¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨ÛGk'L~'L~'L~'L~'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Di›Di›Di›Di›Di›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}%/> ,>=I[=I[ ,> ,>#)2(.7#)2(.7#)2#)2#)2#)2(.7(.7(.767@D>A214$+3#%("$'###""""""&&&888888cB*}\I@!%+%!5*$:/(;0)<1*>3+@4+>1(bUKN@6OA6L=3QB8M?4_RKaTLbUMcVNcVNcVObVOaVOaUO`UO_UO^UO^TO\SOYRNWPNUOMWPKYSOWRN;63953:76755333,/2'),%(+"%(!' ���"&,KXi04:������������������JMP]_b^emU[dNZlNZlT[cU[dU[dU[d[aj•ž•ž•žˆŽ—–¥W]fDPbDPbDPbDPbDPbDPb‘nSž…w—|m¨‚ƒqjKo¡Ko¡Ko¡Š®àŠ®àŠ®àŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áŠ¯áŠ¯áŠ¯áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨Û„¨Û„¨Û„¨Û„©Û„©Û„©Û„©ÛGkGkGkGkGkGk'L~'L~'L~'L~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Di›Di›'K}'K}'K}'K}HlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}*2? ->=I[=I[ ,> ,> ,>#)2#)2#)2(.7(.7#)2#)2(.7(.7(.7(.7/28:79G@A<89',4#%(#%(######""""""8888888887'vS:‹jW;)� + &3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!' ���15;6CT37=������������������������MMMKMP^ad_enY`hNZlNZlU\dV\eŠ‘™Š™Š™–Ÿ–Ÿ–ž•ž“œ—¦Œ’›ƒ¡DQbDQbDQbDQbDQbMUc¤ƒ‘ylŸ‡|€oiKo¡Š¯áŠ¯áŠ¯áŠ¯áŠ¯áŠ¯áŠ¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯áKo¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢‹¯â‹¯â‹¯â‹¯âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨Û„¨Û„¨Û„©Û„©Û„©Û„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©ÛGkžGkžGkžGkžGkžGkžGkžGkžGkž…©Û…©Ü…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}'K}'K}'K}'K}'K}HO\=J[=J[=J[ -> ,> ,>(.7#)2#)2(.7(.7(.7#)2(.7(.7(/7(/7)/8/28114H7,99@.05&,5$&)$$$######"""(((8888888888888884"nO9„gXˆjZE/ (�-" + %' %$#" ! !$ ���48>7CU:GX ���������������������������JJJLLLKMPagp_enNZlLPV˜Ÿ§Œ’›Œ’›Œ’›‹’š‹‘šŠ‘™‘— –Ÿ–Ÿ–Ÿ“œ“œ—¦„¢„¢DQbDQbDQbDQbNVc…uo‡rjѼ³º«§‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯áKp¢Kp¢Kp¢Kp¢Kp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢‹°â‹°â‹°â‹°âŒ°âŒ°âŒ°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢„¨Û„¨Û„¨Û„©Û„©Û„©Û„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGkžGkžGkžGlžGlžGlž…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}DhšDhšDhšIP\=J[=J[=J[=J[ -> ->(.7#)2#)2(.7(.7(.7#)2(.7(/7(/7)/8)/8)/803966:E?AC>A856,07%'*%')$$$######(((DDDBBB8888888880 cF1w]OcS{`QS;+57'   *  ��    ;?E7CU;HY=I[ ���������������������������������JJJMMMKMPacfbhq‘— ƒ¡ƒ¡‘— “œ“œ“œŒ“›Œ’›Œ’›‹‘š‘— ‘— —Ÿ™Ÿ¨”œ“œ“œ„‘¢„‘¢„‘¢„‘¢EQcHScNVd´¨§¿®¨Èµ®¯‘‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯â‹¯â‹¯â‹¯â‹¯â‹¯â‹°â‹°â‹°â‹°â‹°â‹°â‹°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Œ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Ü…©Ü…©ÜGlžGlž…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÝHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž‡«Ý‡«ÝDhšDhšDhšDhš=J[=J[=J[=J[=J[=J[ ->(/7#)2#)2(.7(.7(.7#*2(/7)/8)/8)/8)/8)08*0903:56:88@KBB=;@348*08&(+'(*%%%$$$(((EEE(((&&&���">-"bF3oXMs[Ow]Py^PqbpXMdH5R<,Q;, &%%#'-"'-&3DS_qP\nR_p>J\?K]AG@B::@66:-29'),)'%BBBFFFEEE)))))))))&&&��������������� ������������������������������������������@@@FFFACFZ\_[ajagp„¢„¢„¢ž¥­Ÿ¦®—¦–¥–ž•žŽ•Ž””œ“œ‘— —Ÿ›¡ªš ©™ ¨Ž•Ž”Ž”…‘£…‘£…‘£EQcGRcKTdPWd­¥§¿¯ª‹°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°ãŒ°ãŒ°ãŒ°ãŒ°ãLp£Lp£Lq£Lq£Lq£Lq£Lq£Lq£Lq£Œ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£…©Û…©Û…©Û…©Û…©Û…©Û…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHlžHlžHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«ÞŸ>J\>J\=J[=J[=J[=J[FLU39B#*2(/7)/7)/8$*3$*3$*3)/8)08*09*09*19',5(-5*.6.17338@<=G@BH@BXW]UUXLPWFHKDFHKKKHHH+++%%%%%%$$$###!!!!!!777777777777777777777AAAFFFACFACF\^aeltbhqDQbDQbDQbŸ¥®¡§°¡§°¡§°¡§°—¦–Ÿ”š£”š£“™¢’™¡’˜¡‘˜ ‘— ›¡ª›¡ªš ©•ž™Ÿ¨Ž”ERcERcERcERcHScLUdRXd|njŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°ãŒ°ãŒ°ãŒ°ãŒ°ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬ÞŽŸŽŸŽŸŽŸ>J\=J[=J[FLUFLU(/7(/7*08*08%+3$*3$+3$+3*09*09*19&,5&,5'-6).6*/7-18NPURRVXUVc]^f^_[X]\XYTUZLQYKMPFHJ)))(((&&&%%%%%%$$$$$$###!!!!!!!!!777777777BBBEEEACGADGFIL\ckZ`iTZcDQbDQbDQbagpbiqcircir¢©±¢¨±¡¨°¡§°•œ¤•›¤”›£”š£“™¢’™¡’˜¡œ¢«œ¢«›¡ªš¡©•žY`hY_hERcERcERcGSdJTdNVdTYeLp¢Lp¢Œ°ãŒ°ãŒ°ãŒ°ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£±ã±ã±ã±ä±ä±ä±ä±ä±ä±ä±ä±ä±ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²äMq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞŽŸŽŸŽŸŽŸŽŸŽŸŽŸFLUFLUFLU)/8+08+08&+3&+3%+4%+4%+4*19+1:&,5'-5'-6(.6FLTHMTINUKOVOQWSTXYWX`[^lbac]_f_\a_aY\aRX_,.1*,.*+-***((('''&&&%%%%%%$$$$$$$$$###!!!!!!!!!!!!!!!%%%%%%%%%%%%"""""""""KKKJJJFFFGIL]_b^dm\bkV]eDQbEQcEQcEQccirdjsdksektdjsdjscir£©²¢¨±¢¨±–œ¥•œ¤•›¤”›£”š£“™¢’™¡£¬œ¢«›¢ª[ajZ`iOU^ERcERcFRdFRdITdLUdPWeVZeLp£Lq£Lq£Lq£±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ä±ä±ä±ä±ä±ä²ä²ä²äMq£²ä²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äMr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«ÞHmŸHmŸHmŸ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞŽŸŽŸŽŸŽŸ‚Ž ‚Ž ‚Ž ‚Ž ”›£Š™ŠŽ•-18,18',3',4',4&,4%,4+1:,2:'-5DJSEKSEKTFLTFLUHMUINVKOWLPWQSYTUZWWZpjje^`offb\_h`]eaaCCG8;A27?-/2+-/.+)******)))((('''&&&&&&%%%%%%$$$$$$$$$$$$$$$$$$######???EEEEEEEEE((((((###&&&%%%HJMHJMHJMHJM_en]dlZ`i_enEQcEQcEQcEQcbhqektflufluflufluektektdksdjscjr£©²¢©±¢¨±–œ¥•œ¤•›¤”›£”š£“™¢£¬\ckQW`[ajZaiOU^FRdFRdFRdHSdKUdNVeRXeX\fLq£Mq£Mq£Mq£Mq£±ã±ã±ã±ã±ã±ä±ä±ä±ä±ä²ä²ä²ä²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äMr¤Mr¤Mr¤Mr¤Mr¤Ž²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åNr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬ÞHmŸHmŸHmŸHmŸImŸImŸImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ”›£Š‘™‹•‹•PT[KOVJOV(-4(-4'-5'-5JOXEKSEKSEKTFLTFLTGMUGMUHNVIOWKPWLQXMRYPTZTV[\]a_^asljd^azporjkE@CLEBIEFEDG29A28A17@135,.1+-0+,/./1..0'),)))++++++++++++***FFFFFFACFACFEEEACFACFŠŒJLOJLOKQZ_en]clY_hU[dEQcEQcEQcEQcEQcagp[aj\bk\bkgnvgnvgmvgmvfluflueltektdksdjscjrcir¢©±—¦–œ¥•œ¤•›¤TZcSYbRYaRXaQW`[bj[ajZ`iFSdFSdGSdJTdLVePXeTZfZ]fMq£Mq£Mq£Mq£Mq£Mq£Mq£²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äNr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Ž²åŽ²åŽ²åŽ²åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³å³å³å³å³å³å³å³åNr¤Nr¤Nr¤Nr¤Nr¤³å³å†ªÜ†ªÜ†ªÝHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ­ß‚Ž ‚Ž ‚Ž ‚Ž ‚ ‚ ‚ ‚ ‚ …Œ”’•šŒ•‘”›LPVLPWKPW‹—‹—‹˜•‹‘™FLTFLTFLUGMUGMUHMVHNVINWIOWKPXLQYMRYNSZTX`X[a[]b]^c__ccacib`JDGi__aYYPJLD@C=;AKEDTQR@?A>>A;/5>.4=-4 + + images/16bpp.bmp + images/4bpp-rle.bmp + images/YCbCr_cmyk.jpg + images/YCbCr_cmyk.png + images/YCbCr_rgb.jpg + images/away.png + images/ball.mng + images/bat1.gif + images/bat2.gif + images/beavis.jpg + images/black.png + images/black.xpm + images/colorful.bmp + images/corrupt-colors.xpm + images/corrupt-pixels.xpm + images/corrupt.bmp + images/corrupt.gif + images/corrupt.jpg + images/corrupt.mng + images/corrupt.png + images/corrupt.xbm + images/crash-signed-char.bmp + images/earth.gif + images/fire.mng + images/font.bmp + images/gnus.xbm + images/image.pbm + images/image.pgm + images/image.png + images/image.ppm + images/image_100dpi.tif + images/kollada.png + images/marble.xpm + images/namedcolors.xpm + images/negativeheight.bmp + images/noclearcode.bmp + images/noclearcode.gif + images/nontransparent.xpm + images/runners.ppm + images/teapot.ppm + images/test.ppm + images/test.xpm + images/test32bfv4.bmp + images/test32v5.bmp + images/tst7.bmp + images/tst7.png + images/transparent.xpm + images/trolltech.gif + images/qt.gif + images/qt1.gif + images/qt2.gif + images/qt3.gif + images/qt4.gif + images/qt5.gif + images/qt6.gif + images/qt7.gif + images/qt8.gif + images/endless-anim.gif + images/four-frames.gif + images/qt-gif-anim.gif + images/qt-gif-noanim.gif + images/rect.svg + images/rect.svgz + images/corrupt.svg + images/corrupt.svgz + images/qtbug13653-no_eoi.jpg + images/txts.png + + 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../../platformquirks.h" + +#if defined(Q_OS_SYMBIAN) +# define SRCDIR "." +#endif + +typedef QMap QStringMap; +typedef QList 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("fileName"); + QTest::addColumn("success"); + QTest::addColumn("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("fileName"); + QTest::addColumn("newSize"); + QTest::addColumn("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("fileName"); + QTest::addColumn("newRect"); + QTest::addColumn("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("fileName"); + QTest::addColumn("newRect"); + QTest::addColumn("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("fileName"); + QTest::addColumn("format"); + QTest::addColumn("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 formats = QImageReader::supportedImageFormats(); + QList sortedFormats = formats; + qSort(sortedFormats); + + // check that the list is sorted + QCOMPARE(formats, sortedFormats); + + QSet 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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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("fileName"); + QTest::addColumn("format"); + QTest::addColumn("size"); + QTest::addColumn("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("fileName"); + QTest::addColumn("shouldFail"); + QTest::addColumn("message"); + QTest::addColumn("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("fileName"); + QTest::addColumn("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 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("uncompressedFile"); + QTest::addColumn("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("expected"); + QTest::addColumn("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("fileName"); + QTest::addColumn("expectedDotsPerMeterX"); + QTest::addColumn("expectedDotsPerMeterY"); + QTest::addColumn("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("fileName"); + QTest::addColumn("expectedPhysicalDpiX"); + QTest::addColumn("expectedPhysicalDpiY"); + QTest::addColumn("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("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("name"); + QTest::addColumn("extension"); + QTest::addColumn("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 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("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("fileName"); + QTest::addColumn("key"); + QTest::addColumn("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("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 Binary files /dev/null and b/tests/auto/gui/image/qimagewriter/images/YCbCr_cmyk.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qimagewriter/images/YCbCr_rgb.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qimagewriter/images/beavis.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qimagewriter/images/colorful.bmp 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 Binary files /dev/null and b/tests/auto/gui/image/qimagewriter/images/earth.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qimagewriter/images/font.bmp 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 Binary files /dev/null and b/tests/auto/gui/image/qimagewriter/images/kollada.png 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 Binary files /dev/null and b/tests/auto/gui/image/qimagewriter/images/ship63.pbm 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!j@#k@$h>"dµf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&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: X/K%���������&4$+2F=;HPEJL&\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlR¶xT­sTµd)ŠO$w; m6 +g3 +a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d!Y0�����������W+]. s=‡M$dPŸlR\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀoTM¥oRdPvE"V+K%A 99���†F¤['qUMtVM99H:9H:9H:9H:9H:9H:9H:9H:9H:9H99H99H99H99H99H99H:9H;:H>;HB=HPDJ\JKmSMwXN|ZN°y[ᦆ֘uº{W¹yU¿€]Á„b­tU£nR—hQˆaO{ZNvWNtVMvXNwXNyYNzYN{ZN|ZN}[N}[N~[N~[N~[N~[N~[N~[N~[N}[N}[N{ZNzYNxXN…L$f3 +���I$L&P(U*\. €J#\O›jQ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀžkR‰aOo9 L&C!:4���f3 +X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?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$���G#K%Q(W+zG#nTM˜iQ\À\À\À\À\À\À\À\À\À\À\À\ÀdOLrUMuWNwXNyYN{ZN}[N{ZNwXNsVM \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àˆ`OcPnA"M&@ 8F#���m6 +›W&rVMvWNyYNzYN|ZN}[N}[N>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%���F#B!Y,L&U*~I#„^O†`O\À\À\À\ÀcNLrUMzYN\O„^Oˆ`OŠbPŒcPdPeP’fP“fP“fQ“fQ”fQ‘ePcP‰aP~[N�\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À’fPsVM^/ C!7 ������ŽQ%tVMwXNzYN|ZN}[N\N\O€\O]O]O‚]O‚]OA=HB=HB=HB>HC>HC>ID?IE?IF@IG@IIAIKBIŒcPdP’eP–gQšiQŸlR£nR¤\'´d)¿i*Æm+Îs/Ïs/Êo+Én+Ål*¾i*ºg)³c(ª_(ªqS¦oR¡mRkQ™iQ•gQ“fP‘ePŽdPcPŒbP‹bPŠbPŠaP‰aP‰aO‰aOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O„^Oƒ^O‚]O\O}[N›Q��D"?D"K%_/ kRL’fPODJSFJ†_OŠbPŽcP‘eP“fQ–gQ™iQœjQžkR lR¡mR£nR¤nR¥oR¥oR¥oR¤nR¢mRŸlRšiQ‘eP…_O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀB+‘ePI#L&90���y< šPxXN{ZN}[N\N€\O]O‚]Oƒ^Oƒ^O„^O„_O…_O…_O†_O†`O‡`O‡`Oˆ`O‰aOŠaP‹bPŒbPcPŽdP‘eP“fP•gQ˜hQšiQžkR¢mR¡Z'«_(¶e)½h)Âk*Çn,Çn,Æm*Æl*Áj*ºf)¶e)²c(«_(¦]'§pR¤nR¡mRžkR›jQ™iQ–gQ”gQ“fP‘ePdPdPŽdPŽcPcPŒcPŒbP‹bP‹bP‹bPŠbPŠaP‰aP‰aO‰aOˆ`O‡`O†_O…_Oƒ^O]Oª_(@ ���B!I$B!N'w=‘eP`LKbNLeOLkR mR£nR¥oR§pSªqS¬rS®sS¯tS°tS°tS±uS±uS°tS¯tS­sSªrS§pS¢mRšjQŒbPjQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‹bPpTME"5���������‡M$tVM{ZN}[N\O]O‚^Oƒ^O„_O…_O†_O†`O‡`Oˆ`Oˆ`O‰aO‰aPŠaPŠbP‹bPŒbPcPŽcPdPdP’eP“fP•gQ—hQ™iQ›jQkR lR¢mR¡Z'¬`(µd)ºg)ÇgÀj*Àj*¾i*¿i*»g)µd)²c(¯a(ª_(¤\'§pR¥oR¢nR mRžkRœjQšiQ˜iQ—hQ•gQ”gQ“fP’eP‘eP‘ePdPdPdPŽcPŽcPcPcPŒcPŒbP‹bP‹bPŠbPŠaP‰aOˆ`O†_O„^O\NœQ����@ <G#_LKŽcPlSMnTMpUMsVM°tS²uT³vTµwT¶wT¶xT¶xT¶wTµwT´vT²uT¯tS¬sSªqS§pS¤oR¢nRžkR˜hQ‹bPeOL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN\NJ%0������1ŽJvWN}[N\O]Oƒ^O…_O†_O†`O‡`Oˆ`O‰aO‰aPŠaPŠbP‹bPŒbPŒbPcPŽcPŽdPdPdP‘eP’eP”fQ•gQ–gQ˜hQ™iQ›jQkQŸlR¡mRžY&¦]'­`(³c(·e)Àc¸\¸\¹\º]»]¶^®a(¬`(©^'£['¢['¥oR£nR¡mR lRžkRœkQ›jQšiQ˜iQ—hQ–gQ•gQ”gQ”fQ“fP’eP’eP‘eP‘ePdPdPdPdPŽdPŽcPcPcPŒbP‹bPŠaPˆaO†`O]O˜O������G#7F#uWMƒ^OwXNxXNzYN{ZN|ZN¹yT¸yT·xT´wT±uT­sS¨pS¡mRœjQ•gQdPŒbP‰aP‰aPŒbPŽcP‘ePcP|ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[JKŠbP^/ 1 01|> wXN}[N]Oƒ^O…_O‡`O‡`OˆaO‰aPŠaP‹bP‹bPŒbPŒcPcPŽcPŽcPdPdPdP‘eP’eP“fP”fQ•gQ–gQ—hQ˜hQ™iQ›jQœkQžkRŸlR mRžY&¦]'­`(±b(·[ÇgÉiÉhÅfÂdÃe¿c«Uª_(§]'£[' Z'¤nR£nR¡mR mRŸlRžkRkQœjQšjQšiQ™iQ˜hQ—hQ–gQ•gQ•gQ”fQ”fQ“fP“fP’eP’eP‘eP‘ePePdPdPdPŽcPcPŒbPŠbPˆ`Oƒ^O‰D �����4M&dPnSM|[N|[O|[OzZOxXNªrS¢nR˜hQŽcPƒ^OvXNiQL^KKRFJMCJJAIKBISFJ\JKnSMxYN†_O€\OaMK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀB!qUMŠaPC!/00a0 uWN}[N‚]O…_O†`Oˆ`O‰aPŠaP‹bPŒbPŒcPcPŽcPŽcPdPdPdP‘eP‘eP’eP“fP“fQ”fQ•gQ–gQ—hQ˜hQ™iQ™iQ›jQœjQkRžlRŸlRœX&¢['¨^'¬`(´ZÂdÄfÈiÆgÂd¿c¿c¼a¸_©T¥\'£[' Z'ŸY&£nR¢mR¡mR lRŸlRžkRkQœjQ›jQšjQšiQ™iQ˜hQ—hQ—hQ–hQ–gQ•gQ•gQ”gQ”fQ”fQ“fQ“fP’fP’eP‘eP‘ePdPdPŽcPŒbP‰aOƒ^Ox< �������:ŠaP]Oj8sVMmSMfOL^KKUGJIAIQEJ?IeZY638*  B\À\À\À\À\À,  4 .G1!\TU¡ƒrsVM{ZN`MK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[JKyYNŒbP/0������ˆN$]O…_Oˆ`O‹bPŒbPcPŽcPdPdPdP‘eP‘eP’eP’fP“fP“fQ”fQ”gQ•gQ–gQ–gQ—hQ—hQ˜hQ™iQ™iQšiQ›jQœjQœkQkRžkRŸlRœO¡Z'¥\'©^'­V¼a¾bÁeÆi!Ãf¾b»a¹`·_³]²\µZ¢[' Z'ŸY&œQ¡mR¡mR mR lRŸlRŸlRžkRkRkQœkQœjQ›jQ›jQšjQšiQšiQ™iQ™iQ˜iQ˜hQ˜hQ—hQ—hQ—hQ–hQ–gQ–gQ•gQ•gQ”fQ’fPdPcPšW&������������dPŠaPrUM + B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6 + ���X,uWM‚]O‡`OŠbPcPŽdPdPdP‘eP’eP’fP“fP“fQ”fQ”gQ•gQ•gQ–gQ–gQ—hQ—hQ˜hQ˜iQ™iQ™iQšiQ›jQ›jQœjQœkQkQžkRžlRŸlR¢Z'¤\'§]'·_¹`¼a½bÁeÅi"Áe¼aº`·_¶_²]²\±\«Y¡Z' Z'¡Z'¡mR¡mR mR lR lRŸlRŸlRžlRžkRžkRkRkQœkQœjQœjQ›jQ›jQ›jQšjQšiQšiQšiQ™iQ™iQ™iQ˜iQ˜hQ˜hQ—hQ–gQ•gQ“fQdP†_Oq8 ���������–gQˆ`OuWM”T%\À\À\À\À\À\À\À\À\À\À B B!!T,c5ƒF‚T3È›~Æ“qƒ^OfOL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK_LKsVM‡`OcP������ ’S%]OŠbPcPdP‘eP’eP“fP“fQ”fQ”gQ•gQ•gQ–gQ–gQ—hQ—hQ—hQ˜hQ˜iQ™iQ™iQšiQšiQ›jQ›jQœjQœjQkQkRžkRžlRŸlRŸlR¥\'¦]'¨^'­Vº`»a½bÁfÄi"Àe»a¹`·_¶_³]±\±\¤R¢Z'¢Z'£['¡mR¡mR¡mR¡mR mR lR lRŸlRŸlRŸlRžlRžkRžkRkRkRkQkQœjQœjQœjQœjQœjQ›jQ›jQ›jQ›jQšjQšiQ™iQ™iQ˜hQ–gQ‘eP§Sq8 ������‰aO•gQ‡`OtVMœX&\À\À\À\À\À\À\À\À\À\À B B B l@!{A…L$›Y'½†a“fPˆaO]KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀODJ[JKaMKqUM\OcPƒ^O������vE"‚]OŠaPdP‘eP“fP”fQ•gQ•gQ–gQ–hQ—hQ—hQ˜hQ˜hQ˜iQ™iQ™iQ™iQšiQšjQ›jQ›jQœjQœjQœkQkQkRžkRžkRŸlRŸlRŸlR lR©^'©^'ª_(®W»a¼a¾cÂg Äi"¿e»a¹`·_¶_³^±\±\¤R£['£['§]'¢mR¢mR¡mR¡mR¡mR¡mR mR lR lR lR lRŸlRŸlRŸlRŸlRžlRžlRžkRžkRžkRžkRkRkRkRkRkQkQkQœjQœjQšiQ˜hQ’ePšW&M&���oTMšiQ‘eP…_OtVMmSMdOL\À\À\À\À\À\À\À\À\À B B B ‘J Z'ª_(œkQ™iQ‡`OSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJ\JKcNLlRMzYN‡`O’ePzZN��� �\Nˆ`OdP“fQ•gQ–gQ—hQ˜hQ˜hQ™iQ™iQ™iQšiQšiQšiQ›jQ›jQ›jQœjQœjQœjQœkQkQkRžkRžkRžlRŸlRŸlRŸlR lR lR mR®a(­`(¬`(¶[½a½b¿dÃh!Äi"¿d»a¹`¸_¶_µ^²]³]¦S¤\'§]'«_(¢nR¢mR¢mR¢mR¢mR¢mR¢mR¡mR¡mR¡mR¡mR¡mR mR mR mR mR lR lR lR lR lR lR lR lR lRŸlRŸlR lRŸlRžkRœkQ™iQePt: ������kQ˜hQcP€]OtVMlSMa2 \À\À\À\À\À\À\À\À\À B B +$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�oTM•gQ™iQkQŸlRŸlR lR mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR£nR£nR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nRÆl*Ãl+¾j+¹g)¸f)¶e)µd)¶e)¶e)·e)·e)¸f)¾i*Ìs0Ðs.¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦pR§pR§pR§pR§pR§pS§pS¨pS¨qS©qS©qS©qS¨pS©qS§pS¤nRŸlR‘I˜hQ§pR¥oR¡mRšiQ’ePŠaP€\OsVMpTMnTMlRM–X)\À\À\À\À\À\À\À B%C)D$;J/[8"LBITGJYIKWHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK_LKcNLgPLjQLlRMpUMzYNƒ^O‹bP‘eP˜hQkQŸlR”fQ- —hQ›jQŸlR¢mR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦oR¦oR¦oR¦pR¦pR§pRàpßy-Ûw-Ûw-Þy.â{-ãu§pS§pS§pS§pS§pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨qS©qS©qS©qS©qS©qS©qS©qSªqSªrS«rS«rS¬rS¬rS¬rS¬rS¬sS«rSªqS¦oRšiQ™iQ©qSªqS§pR¡mRœjQ•gQcP„_O{ZNtVMpUMoTMmSMjQL_9 \À\À\À\À\À B "C(D#*A$[<)dI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JKaMKeOLhPLkRLmSMoTMuWM}[N…_O‹bP’eP˜hQžkR¢mR£nRžkR!-EkR¡mR¤nR¥oR¦pR§pR§pS§pS§pS§pS§pS§pS§pS§pR§pS§pS§pS§pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨qS¨qS¨qS©qS©qS©qS©qS©qS©qS©qS©qS©qS©qS©qSªqSªqSªqSªqSªrS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬sS­sS®sS®sS¯tS¯tS¯tS¯tS°tS°uS°tS®sS«rS£nR¦oR®sS­sS«rS§pR¢mRœjQ–gQdPˆaO\OyYNuWMqUMoTMnSMkRLo8 \À\À\À\À\À B'D+E$(1 J/jH1NCJUGJYIKUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK]KKbNLfOLiQLkRMmSMoTMqUMxXN\N†_OŒbP’fP˜hQkQ¡mR¥oR§pS¦pR˜hQ¢mR¥oR¨pSªqS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rSªrSªrSªrS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬rS¬rS¬rS¬rS¬sS¬sS­sS­sS­sS­sS­sS­sS®sS®sS®sS®sS®tS¯tS°tS°uS±uS±uT±uT²uT²uT²uT´vTµwT´vT³vT²uT¯tS¢mR¯tS±uT±uS®tS«rS§pR¢mRkQ—hQ‘ePŠaPƒ^O\N{ZNvXNqUMpTMnSMlRMP%\À\À\À\À B#C*E$.E- .!G$Y:%d<"SFJYIKZIKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀPDJZIK_LKdNLgPLjQLlRMnSMpTMqUMuWMyYN€\O†`OcP’fP—hQœjQ¡mR¥oR¨qS«rS«rSªrS mR�«rS­sS¯tS°tS°tS°tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS®tS®sS®sS®sS®sS®sS®sS®sS®sS®sS®tS®tS®tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS°tS°tS°tS±uS±uS±uT²uT²vT³vT³vT´vT´vT´wTµwTµwTµwT·xT·xT¸xT¸yT¸yU·xU¥\'©qS³vTµwTµwT´vT±uT®tTªrS¦oR¡mRkQ˜hQ’eP‹bP‡`Oƒ^O€\O|ZNxXNtVMpTMoTMmSMjQLh7\À\À\À B(D"-E*1F, 4#K)pL5PEJWHK[JKXHK:9H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀUGJ\JKaMLeOLhPLkRLmSMoTMpUMrVMvWNyYN|ZN]O‡`OŒcP‘eP—hQ›jQ lR¤nR§pSªqS­sS¯tS°uS¯tS­sS mR^/ ²vT³vT´vT´wTµwT´wT´vT³vT´vT´vT´vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT´vT´vT´vT´vT´wTµwTµwTµwTµwT¶wT¶wT¶xT·xT·xT·xT¸xT¸xT¸xT¹yTºyT»zU¼zU½{U½{V½|V•gQ¬rSµwT¸xT¹yU¹yU¹zV·yVµxV±vU­tT©qS¥oS mRœjQ—hQ’ePcPŠbP‡`O„_O]O}[NyYNuWMpUMoTMmSMkRL}H#\À\À &D -E(1F/!2#8 W7"iA&UGJ[JK\JKREJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀMCIXIK^KKcNLfOLiQLkRMmSMoTMqUMsVMwXNzYN}[N€\Oƒ^O‡`OŒbP‘eP–gQšjQžkR¢mR¥oR©qS¬rS¯tS±uS³vT´vTµwT´wT²uT­sS lR«_(¹yT¹yTºyTºyTºyTºyTºyT¹yT¹yT¸yT¸xT¸xT¸xT¸xT¸xT¸xT¸yT¸yT¸yT¸yT¹yT¹yT¹yT¹yT¹yT¹yT¹yTºyTºyTºyTºyTºzT»zT¼zU¼{U½{U¾{U¾|U¿|UÀ}VÁ~VÂWÀY™iQ«rSµwT¹yT¼zU½|V¿}XÁ€ZÂ]Á]¾€]»~[¶zY±wW¬tU¨qS¤nSŸlR›jQ–gQ“fPePŽcP‹bPˆ`O…_O‚]O~\NzZNvXNqUMoTMnSMlRMiQLg=!\À +!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?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 |> ���������������’eP¦oR¨qS¦oR¡mRšjQ‘eP„^OhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ\KKaMLeOLhPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_Oˆ`OŠbPcPdP‘eP“fQ•gQ—hQ™iQ›jRkRŸmS¢nT¤qV¨sX¬w[±{_¶€c½†hÄŒnË’tÒ™zØŸ€Þ¥…㩉ç­ê¯Žê¯Žê®ç«Šä§†ß£Ûž|Õ˜vГpËŽkljfÃ…bÀ‚_½\»}Yº{X¸zW¸yV·xU·xU·xT¶xT¶xT¶xU¶xU·xU·xU·yV·yV·zW¸zX¸{Y¹|Y¹|Z¹}[¹}[¹}\¹}\¸}\·}\¶|\µ{[³zZ²yZ°wY®vX¬tWªsV¨rU¦pT¤oS£nS¡mRŸlRžkRœjQšiQ˜hQ–gQ”fQ’ePdPŽcP‹bPˆ`O…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQLfOLJ(V.]KKePNkUQcNLQEJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‚]O¡mR©qS¬rS°tS³vTµwT·xUº{WĆbÒ“qךxÊo +���������������K«rS´vT¶wT´vT²uT®sSªqS¤nRkQ•gQˆ`OuWNY,\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^KKbNLfOLhQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N]O„^O†_O‰aO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRkRŸmS¢oT¥qV¨tX­w[±|_·d½†iÄŒnË“tÒ™zØŸ€Þ¥…㩉笌鮎ꮎ魌檉㧅ߢ€Ú{Õ—uÏ’pËjƈfÂ…b¿^½\»|Y¹{X¸zV·yV·xU·xU¶xT¶xT¶xT¶xU¶xU¶xU¶xU·yV·yV·yW¸zW¸{X¸{Y¸|Z¹|Z¹|[¹}[¸}\¸}\·|\¶|[µ{[³zZ±xY°wX®vX¬tWªsV¨rU¦pT¥oS£nS¡mRŸlRžkRœjQšjQ˜iQ—hQ”gQ’fPdPŽcP‹bP‰aO†_Oƒ^O€\O|ZNxXNtVMoTMnSMlRMjQLgPLzG#\JKcOMoXUgPMZIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À’fP”gQ•gQ—hQ™iQkQ lR¤nR§pRªqS¬sS¯tS������:"r<zYN­sS¹yT¾|UÁ~WÆ„^ËŠeË‹gƈe¾‚aµz[­tV¦pS¢mRkQ–gQŠbPzYNkRL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀRFJZJK`LKcNLfPLiQLkRMmSMoTMqUMrVMvWNyYN|ZN\N]O„^O‡`O‰aO‹bPcPdP’eP”fQ–gQ—hQ™iQ›jRlR mS¢oU¥qV©tY­x\²|`¸d¾‡iÅoË“uÒ™{ÙŸ€Þ¥…㩉笌é®é®è¬‹å©ˆâ¦„Þ¡ÙœzÔ—tÏ‘oÊŒjƈe„a¿^½~[»|Y¹{X¸zV·yV·xU¶xU¶xT¶xT¶xT¶xT¶xU¶xU¶xU¶xV·yV·yW·zW·zX¸{Y¸{Y¸|Z¸|Z¸|[¸|[·|[·|[¶{[´z[³yZ±xY°wX®vW¬tWªsV¨rU¦pT¥oS£nS¡mRŸlRžkRœkRšjQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aP†`Oƒ^O€]O}[NyYNuWNqUMnSMlSMkRLhPLcNLbNLpYVlUP`LK>;H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À›jQ‡`O{ZN©^'¨^'­`(·e)½h)Ãk*Êo+±b(£nRºyTÃ~UÇXÒdãŸwò°‰ñ°‹è©…ÝŸ}Ô˜vÈm¾„eµ}_®x[°y\®x[«tW§qT¡mRœjQ–gQ‹bP}[NlRM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\JKaMKdNLgPLjQLlRMnSMpTMqUMsVMvXNzYN|[N\O‚]O…_O‡`O‰aPŒbPŽcPdP’eP”fQ–gQ˜hQšiQœjRžlS mS£oU¦rW©uY®x\³|`¸d¾‡jÅoÌ“uÒš{Ù €Þ¥…㩉欋è­è­Œç«Šå©‡á¥ƒÝ ~Ø›yÓ–tΑoÊŒjňe„a¿^¼~[º|Y¹{W¸zV·yV·xU¶xU¶xT¶xT¶xT¶xT¶xU¶xU¶xU¶xU¶xV·yV·yW·zX·zX¸{Y¸{Z¸{Z·|Z·|[·|[¶{[µ{[´zZ³yZ±xY¯wX®uW¬tVªsV¨rU¦pT¥oS£nS¡mR lRžkRœkR›jQ™iQ—hQ•gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O~[NzYNvWNrUMnSMmSMkRLiQLeOLoXUu]XdOLKBI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À:9H\N–hQ¸}\¯uU­sT¯tT¯tS¨qS¤nR£nR¢nRŸlR›jQšiQ˜hQ—hQ–gQ”fQ’eP‘eP—hQœkR mS¥pUªtX«uY¨sW¦qU mS›jQ•gQƒB’S%jQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀLBIXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMtVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽcPeP’fP”fQ–gQ˜hQšiRœkRžlS nT£pU¦rWªuY®y]³}`¹‚e¿ˆjÅŽpÌ”vÓš{Ù Þ¤…⨉櫋笌笋櫊䨆ंܟ~ךxÒ•sÎnÉŒiŇeÁ„a¾€^¼~[º|Y¹{W¸yV·yV·xU¶xU¶xT¶wT¶wT¶wT¶xT¶xU¶xU¶xU¶xV¶yV¶yW·zW·zX·zY·{Y·{Z·{Z·{Z¶{Z¶{ZµzZ³yZ²yY±xY¯vX­uW¬tVªsU¨rU¦pT¥oS£nS¡mR lRžlRkR›jQ™iQ—hQ•gQ“fQ‘ePdPcPŠaP‡`O…_O‚]O\N{ZNwXNsVMnSMmSMkRMiQLfOL_LKhQMUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À (6BFP>=DKHMqjk€trwf`~kc„ndŠqesete¯Ž{w`¡v[\N†_OcP“fP˜iQœjRŸlS£oT¦qV¥qV£oTžlR™iQº^‡`OQ%hPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJZIK_LKcNLfOLiQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N€]Oƒ^O…_Oˆ`OŠaPŒcPŽdP‘eP“fP”gQ–hQ˜iQšjRœkRžlS¡nT£pU¦rWªuZ®y]³}a¹‚e¿ˆkÆŽpÌ”vÓš{ÙŸ€Þ¤…⨈媊櫋櫊婈⦅ߣ۞}ÖšxÑ•rÍmÈ‹ićdÁƒa¾€]¼~[º|Y¹zW¸yV·yU¶xU¶xU¶wT¶wT¶wT¶wT¶wT¶xU¶xU¶xU¶xU¶xV¶yV¶yW¶zX·zX·zY¶zY¶{Y¶{Z¶{ZµzZ´zZ³yY²xY°wX¯vX­uW«tVªsU¨rU¦pT¥oS£nS¡mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ‘ePdPcP‹bPˆ`O…_O‚]O\O|ZNxXNtVMoTMmSMlRMjQLgPLbML[JK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À%5 (6$/79CEEKjgkrc_›…{‘uf±{Ÿw_ºq]Oˆ`OŽcP”fQ˜hQ›jRžlR¡nT¢oT¡nTkR˜hQŽdP¦]'ŽQ%\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀUGJ[JK`MKdNLgPLiQLkRMmSMoTMqUMrUMuWNxXN{ZN~[N]Oƒ^O†_Oˆ`OŠbPcPdP£['µd)•gQ—hQ˜iQšjRœkRžlS¡nT£pU§rWªvZ¯y]´~aºƒfÀˆkÆŽpÌ”vÓš{ØŸ€Ý¤„ᧇ䩉媊媉䨇᥄ޡ€Ú|Õ˜wДrÌmÈŠhĆdÀƒ`¾€]»}[º|Y¸zW·yV·xU¶xU¶xU¶wTµwTµwTµwTµwTµwUµwUµxUµxUµxV¶xV¶yW¶yW¶yX¶zX¶zY¶zYµzYµzY´zY´yY²yY±xY°wX®vW­uW«tVªsU¨qU¦pT¥oS£nS¢mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ’ePdPcP‹bPˆaO†_Oƒ^O€\O|[NxYNtWMpUMmSMlRMjQLgPLcNLA;=\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À#*6+.8;:AHEJmgjd\]‡pe«}œxc w^»pƒ^OŠaP‘eP–gQšiQžlR mS¢nT mS›jR•gQ»h*œX&ˆM$\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀC+WHJ]KKaMLdOLgPLjQLlRMnSMoTMqUMrVMvWNyYN|ZN\N]O„^O†_OˆaO‹bPcPžY&«_(³c(•gQ—hQ™iQšjRœkRŸlS¡nT¤pV§sX«vZ¯z^´~bºƒfÀ‰kÆŽpÌ”vÒš{ØŸ€Ý£„ই㩉䩉䩈⧆ःܠØœ{Ô—vÏ“qËŽlljgÆcÀ‚`½]»}Z¹{Y¸zW·yV¶xU¶xU¶wUµwTµwTµwTµwTµwTµwTµwUµwUµxUµxVµxVµxVµyWµyWµyXµyXµyYµzY´yY´yY³yY²xY±wX°wX®vW­uV«tVªrU¨qU¦pT¥oS£nS¢mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ’ePdPŽcP‹bP‰aO†_Oƒ^O€\O}[NyYNuWNqUMmSMlRMjQLhPLdNL\1\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À+.775;ICFphhŠztŠre¯}Ÿya¢vZ]OŠaP‘eP–gQšiQkRŸlS¡nTžlS™iQÌq.¯b*“S%zG#\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀMCJXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMsVMvWNyYN|ZN\N‚]O„^O†`O‰aO‹bP—U&¥\'¯a(»g)Ìr/—hQ™iQ›jRkRŸmS¡nT¤pV§sX«v[¯z^´~bºƒfÀ‰kÆŽpÌ”vÒ™{מÜ£ƒà¦†â¨ˆã¨ˆã¨‡á¦…Þ£‚ÛŸ~×›yÓ–uÎ’pÊkƉgÂ…c¿‚_½]»}Z¹{X¸zW·yV¶xU¶xUµwTµwTµwTµwTµwTµwTµwTµwUµwUµwUµxUµxVµxVµxWµyWµyWµyXµyX´yX´yY³yY³xX²xX°wX¯vW®uW¬tV«sV©rU¨qT¦pT¥oS£nS¡mR mRžlRkR›jQšiQ˜hQ–gQ”fQ’ePdPŽcPŒbP‰aO†`Oƒ^O€]O}[NzYNvWNrUMmSMlRMjQLhQLeOL_LK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À,)/ZTVXON„uq‡od®}Ÿyb»s]OŠaPeP•gQšiQkRžlRŸlSœkR–hQ»g*¤\(ŽQ%`LK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À B B_LKcNLfOLiQLkRLmSMoTMpTMrUMtVMwXNzYN}[N\O‚]O„_O‡`O‰aOQ%ŸY&©^'±b(¾i*Õ{8—hQ™iQ›jRkRŸmS¡nT¤qV§sX«v[°z^µ~bºƒfÀ‰kÆŽpÌ”vÒ™{מÛ¢ƒß¥…ᧇ⧇ᦆऄݢڞ}ÖšxÒ•tÍ‘oÉŒjňfÂ…b¿_¼\º}Z¹{X·zW·yV¶xU¶xUµwTµwTµwTµwTµwTµwTµwTµwT´wU´wU´wU´xVµxVµxVµxW´xW´yW´yX´yX³xX³xX²xX±wX°wW¯vW­uW¬tV«sU©rU§qT¦pT¤oS£nS¡mR mRžlRkR›jQšiQ˜hQ–gQ”gQ’fPdPŽcPŒbP‰aP‡`O„^O]O~[N{ZNvXNrVMnSMlRMjRLhQLeOLaML+O+O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀHFLXQRTJH~pm‚la¬Ž}Ÿzc»t¤tT‰aPdP•gQšiQœjRžlRžlS›jRÖ|:´e*˜V&ˆN$\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À B B`LKdNLgPLiQLkRMmSMoTMpUMrUMtVMwXNzYN}[N€\O‚]O…_O‡`O‰aPšW&£['«_(´d)Âl,݃@Òt.™iQ›jRkRŸmS¡oU¤qV¨sX«w[°z^µbºƒgÀ‰kÆŽpÌ”uÑ™zÖ~Ú¡‚Þ¤„ॆআॅޣ‚Ü Ø{Õ™wÑ”sÌnÈŒjňfÁ„b¾_¼~\º|Z¸{X·yW¶yV¶xUµwUµwTµwTµwTµwT´wT´wT´wT´wT´wU´wU´wU´wU´wV´xV´xV´xW´xW³xW³xW³xX²xX±wX°wW¯vW®uW­uV¬tVªsU©rU§qT¦pT¤oS£nS¡mR lRžlRkR›jQšiQ˜hQ–hQ”gQ’fPdPŽcPŒbPŠaP‡`O„^O]O~[N{ZNwXNsVMoTMlRMjRLiQLfOLbML+O+O‚+O‚+O‚\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À6./fZXeVRHAIZIKiQLuWM¤tU‰aOdP–gQšjQkRžlRkR˜iQÄn/¬b,‘R%rC"\À\À\À\À\À\À\À\À\À\À\À\À"Fx"Fx!Fx!Fx B B BdNLgPLjQLlRMmSMoTMqUMrUMtWMwXNzZN}[N€\O‚^O…_O‡`O“S%X&¥\'®a(·g+Ês2Ó{9Àj*™iQ›jRkSŸmS¢oU¤qV¨sX«w[°z^µbº„gÀ‰kÆŽpË“uИyÕœ}٠ܢƒÞ¤„ߤ„Þ£ƒÝ¡ÚŸ~×›zÓ—vÏ“rËmÇ‹ićeÀƒa¾€^»~\¹|Z¸zX·yW¶xVµxUµwUµwTµwT´wT´wT´wT´wT´wT´wT´wT´wU´wU´wU´wU´wV³wV³xV³xW³xW²wW²wW±wW±wW°vW¯vW®uV¬tV«sUªsU¨rT§qT¦pT¤oS£nS¡mR lRžlRkR›jQšiQ˜hQ–gQ”gQ’fPePŽcPŒbPŠaP‡`O„_O]O~\N{ZNxXNsVMoTMlRMjRLiQLfPLbNL +O‚+O‚+P‚+P‚+P‚\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@89dWT@IIAI\JKlRMyYN„^OcP”gQ™iQkRžlRžkR™iRÍt3±d-’S%I#\À\À\À:^‘:^‘:^‘:^‘:^:^:^:^:^"Fx"Fx B B B BeOLhPLjRLlSMnSMpTMqUMrVMuWMxXN{ZN~[N€]Oƒ^O…_O“S%›W&¢['©^(¹k2½i+Ó{:•gQ—hQ™iQ›jRkSŸmT¢oU¤qV¨tY¬w[°{_µbºƒf¿ˆkÄoÊ’tÏ–xÓš|×~Ù €Û¡Û¡Û €Ùž~×›{Ô˜wДsÌoÉŒkʼngÂ…c¿‚`¼]º}[¸{Y·zX¶yVµxVµwU´wU´wT´wT´vT´vT´vT´vT³vT³vT³vT³vT³vU³vU³vU³wU²wU²wV²wV²wV±wV±vV°vV°vV¯uV®uV­tV¬tUªsU©rU¨qT§pT¥pS¤oS¢nS¡mR lRžlRkR›jQ™iQ˜hQ–gQ”gQ’fPePŽdPŒbPŠaPˆ`O…_O‚]O\N|ZNxYNtWMpTMlRMjRLiQLgPLcNL_LK+P‚+P‚+P‚,P‚,P‚,P‚,P‚,P‚Nr¤\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À]QNl\VG@IMCI_LKoTM|ZN†`OdP–gQšjQkRžlRœkR—hQºh*¤^,ŒP%X3:_‘:_‘:_‘:_‘:_‘:_‘:_‘:_‘:^‘:^‘:^‘:^‘"Fx B B B BfOLiQLkRLmSMnTMpTMqUMrVMuWNxYN{ZN~[N€]Oƒ^OŽP%—U&X&£['¬`)½n4Ãn/Àj*•gQ—hQ™iQ›jRkSŸmT¢oU¤qW¨tY«w[°z^´~b¹ƒf¿ˆjÄŒoÉ‘sΕwÒ™{Õœ}ØžÙŸ€ÚŸ€Ùž~ל|ÕšyÒ—vÏ“rËnÇ‹jĈfÁ„c¾`¼]¹}[¸{Y·zW¶xVµxU´wU´wT´wT´vT´vT³vT³vT³vT³vT³vT³vT³vT³vT²vU²vU²vU²vU²vU±vV±vV±vV°vV°vV¯uV®uV­uV¬tU«sUªrU©rT¨qT¦pT¥oS£oS¢nS¡mRŸlRžkRœkR›jQ™iQ˜hQ–gQ”gQ“fPePŽdPŒbPŠaPˆ`O…_O‚]O\N|ZNyYNuWMpUMlRMjQLiQLgPLdNL_LK,P‚,P‚,P‚,P‚,P‚Nr¤Nr¤Nr¤Nr¤Nr¥Nr¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaSOD>IJAIQEJbNLrUM~[NˆaO‘eP—hQœjQžkRŸlR›jRÌs0²e,“T&ƒK$;_‘;_‘;_‘;_‘;_‘;_‘;_‘:_‘:_‘:_‘:_‘:_‘:_‘ B B B BgPLiQLkRLmSMoTMpTMqUMsVMuWNxYN{ZN~[N]O‡M$“S%™V&ŸY&¥\'±e-¹j/Ñz:”fQ•gQ—hQ™iR›jRkSŸmT¢oU¤qW¨tY«w[¯z^´~b¹ƒf¾‡jÃŒnÈrÍ”vјyÔ›|Ö~מ~Øž~×}Õ›{Ó˜xЕtÍ’qÊŽmÆŠiÇeÀ„b½_»~\¹|Z·{Y¶yWµxVµxU´wU´wT´vT³vT³vT³vT³vT³vT³vT³vT³vT²vT²vT²vT²vU²vU²vU±vU±vU±vU°vV°vV¯uV®uV®uV­tU¬sU«sUªrU¨qT§qT¦pS¥oS£nS¢nR¡mRŸlRžkRœkR›jQ™iQ˜hQ–gQ”gQ’fPePŽdPŒbPŠaPˆ`O…_O‚]O\O|ZNyYNuWMqUMlSMjQLhQLfPLdNL_LK,P‚,P‚Nr¤Nr¤Nr¤Nr¤Nr¥Nr¥Nr¥Ns¥Ns¥Ns¥Ns¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀdUOG@IMCITFJeOLtWM€]O‹bP“fP™iQkRŸlRkR™iQ¾j,©c/P%[JK;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘ B B B BgPLiQLkRMmSMoTMpTMqUMsVMvWNyYN{ZN~[N|H#ŽQ%•T%›W& Z'¦]'ºm5¸f*Ív5”fQ•gQ—hQ™iR›jRkSŸmT¡oU¤qW§sY«v[¯z^³~b¸‚e½‡i‹nÇqË“uÏ–xÒ™zÔ›|Öœ}Öœ|Õ›{Ô™yÑ–vÏ“sÌoÈlʼnh†e¿ƒa¼€_º~\¸|Z·zX¶yWµxV´wU´wU³vT³vT³vT³vT³vT³vT³vT²vT²vT²vT²vT²vT²vT±vT±vU±vU±vU°uU°uU°uU¯uU®uU®tU­tU¬tU«sUªrU©rT¨qT§pT¥pS¤oS£nS¢mR mRŸlRžkRœjR›jQ™iQ—hQ–gQ”fQ’fPePŽcPŒbPŠaPˆ`O…_O‚^O\O|ZNyYNuWNqUMmSMjQLhQLfPLdNL`LKNr¤Nr¤Nr¥Nr¥Nr¥Ns¥Ns¥Ns¥Ns¥Os¥Os¥Os¥Os¥Os¥Os¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À2#TB3REJVGJ`LKpTM}[N‰aO’ePšiQžkR lRžlR˜hQ·e)¢^.P%^8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMrUMsVMxF#‡M$ŽQ%’S%–U&šW&žY&¢['ªa+¿s;¹g+dP‘eP“fQ”gQ–hQ˜iQšjRœkSžlS nU£pV¦rX©uZ¬x]°{_´~b¸‚e¼…iÀ‰kÃŒnÆŽpÈrÊ‘sË’sË‘rÊqÉoÇmÅ‹kÈhÀ…e¾ƒb¼€`º~^¸|[¶{ZµyX´xW³wV²vU²vU²vT±uT±uT±uT±uT±uT±uT±uT±uT°uT°uT°tT°tT¯tT¯tT¯tT¯tT®tT®tT­sT­sT¬sT¬sT«rTªrT©rT©qT¨qS§pS¦pS¥oS£nS¢nR¡mR lRŸlRkRœjQ›jQ™iQ˜hQ–gQ•gQ“fP‘ePdPcP‹bP‰aO‡`O„^O‚]O\N|ZNxXNuWMqUMmSMhPLgPLeOLcNL`LKZIK,Pƒ,Pƒ,QƒOs¦Os¦Ot¦Ot¦Ot¦Ot¦Pt¦Pt¦Pt¦Pt¦Pt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀvšÍvšÍv›Ív›Ív›Ív›Ív›Íw›Íw›Í=a“=a“=a“#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GymYPODJUGJXIKeOLtWM‚]OcP•gQœjQ lR mRkRÈp.´g0”T&ˆN$]8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMrUMv>„L$ŒP%‘R%•T%˜V&œX& Z'¤\'°f0¹m5Äq3dP‘eP“fQ”gQ–gQ˜hQ™jR›kSlS nT¢pV¥rX¨tZ«w\¯z_³}a·dº„g¾‡jÁŠlÄŒnÆŽpÇqÈqÈpÇŽoÆmÅ‹kÉiÁ‡g¿„d½‚aº_¸}]·|[µzY´yX³xW³wV²vU²vU±uT±uT±uT±uT±uT±uT°uS°uS°tS°tS°tS¯tS¯tT¯tT¯tT®tT®tT®sT­sT­sT¬sT¬sT«rTªrTªrT©qT¨qS§pS¦pS¥oS¤oS£nS¢mR¡mRŸlRžlRkRœjQšjQ™iQ—hQ–gQ”fQ’fP‘ePdPcP‹bP‰aO†`O„^O]O~\N{ZNxXNuWMqUMiQLgPLfOLeOLbNL_LKZIK,Qƒ,Qƒ,Qƒ,Qƒ,QƒOt¦Pt¦Pt¦Pt¦Pt¦Pt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àv›Ív›Ív›Ív›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Í=a“=a“=a“=a“=a“#Gz#Gz#Gz#Gz#Gz#Gz#GzgUOS=2RFJWHJ[JKlRMzYN†`OeP˜iQžkR mRŸlR™iQ¼h*°h4‘R%ˆN$^9 [JK#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMI#†L$‹O$Q%“S%—U&šW&X&¡Z'¦](·l5´f,Èt5dPeP’fP”fQ–gQ—hQ™iR›kRlSŸmT¢oV¤qW§tY«v[®y^±|aµc¸‚f¼…h¿ˆkÁŠlÃŒnÅnÅoÅnÅŒmÄ‹k‰iÁ‡g¿…e½ƒc»€`¹~^·|\¶{Z´yY³xW²wV²vU±vU±uT±uT±uT°uT°uT°tS°tS°tS°tS°tS¯tS¯tS¯tS¯tS®tS®tS®sS­sT­sT­sT¬sT¬rT«rTªrTªrS©qS¨qS§pS¦pS¦oS¥oS¤nS¢nR¡mR mRŸlRžkRkR›jQšiQ˜iQ—hQ•gQ”fQ’ePePdPcPŠbPˆ`O†_Oƒ^O]O~[N{ZNxXNtVMqUMhPLgPLfOLdNLbML_LKbE6,Qƒ,Qƒ,Qƒ,Qƒ-Qƒ-Qƒ-QƒPt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Q„-Q„-Q„\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@d–w›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Îw›Îw›Î=a”=a”=a”=a”=a”=a”=a“#Hz#Gz#Gz#Gz#Gz#Gz#GzmYPPDJUGJYIKbMLqUM\NŠbP”fQ›jQŸlR¡mRžlRËp,µe+ \+R%ˆN$b; ]8 [7 XHKO+N1L/L/L/K/K/ eb”>b”>b”>b”>b”>b”>b”>b”=b”=b”=b”=b”=b”=b”=b”=b”YEUGJYIK_LKnSM|ZNˆ`O’ePšiQŸlR¡mR mR™iQºg*´j4šW'‘R%ŽQ%h>!g=!f=!db”>b”>b”>b”>b”>b”>b”$Hz$Hz$Hz$Hz$Hz>b”>b”>b”>b”>b”gVOS=2RFJWHK[JKeOLsVM€]OŒbP•gQœjQ lR¡mRžlRÌr/¹g*²h2–U&“S%‘R%Q%ŽQ%ŒP%£['¨]'¬`(°b(´d)¸f)»g)¾i*Áj*I#¡Z'¡Z' Z' Z'¡Z'£['¤['¥\'¦]'ª_)±d,³d)Äq3‹bPcPdP‘eP’fQ”fQ–gQ—hQ™iR›kSlSŸmU¡oV¤qW¦sY©u[¬x]¯z^±|`´~b¶€d¸‚eºƒf»„f»„f¼„f»ƒe»‚dºb¹€a·~_¶}^µ{\´zZ³yY²wX±wW°vV°uU¯uU¯tT¯tT¯tT®tS®tS®tS®sS®sS®sS®sS®sS­sS­sS­sS­sS¬sS¬rS¬rS«rS«rSªrSªqS©qS©qS¨pS§pS¦pS¦oS¥oS¤oR£nR¢nR¡mR mRŸlRžkRkRœjQšjQ™iQ˜hQ–hQ•gQ“fQ’ePdPŽcPŒcPŠbPˆ`O†_O„^O]O\N|ZNyYNuWNrUMnSMjQLdNLcNLaMK_LK[JK`D6Pt¦Pt¦Pt§Pt§Pt§Pu§Pu§Pu§Pu§Qu§Qu§Qu§Qu§Qu§Qu§-Q„-Q„-Q„-R„-R„-R„-R„-R„-R„-R„-R„-R„.R„.R„Rv¨Rv¨Rv¨~¢Ô~¢Ô~¢Ô~¢Ô\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@e—@e—@e—@e—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—xœÏxœÏxœÏxÏxÏxÏxÏyÏyÏ>b•>b”>b”$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b”>b”>b”>b”>b”YDb”>b”>b”>b”Q@:R<2fL@WHJZJKaMKoTM|ZNˆ`O‘eP™iQŸlR¡mR¡mRœjRÇo-»i-´h0«`)§]'¨]'¬`(°b(´d)¸f)¼h)Àj*Ãk*Æm*Én+Ìp+Ïq+Òr,§]'§]'§]'¨^'ª_(«_(¬`(­`(¯b)²c)ºi.ˆ`OŠaPŒbPŽcPdP‘eP“fQ”gQ–hQ˜iRšjR›kSlTŸnU¢oV¤qW¦sY©uZ«w\­y]°{_²|`³}aµ~b¶b¶b¶b¶a¶~`µ}_µ|^´{]³z[²yZ±xY°wX¯vW¯uV®uU®tU®tT­tT­sT­sS­sS­sS­sS­sS­sS­sS­sS¬sS¬rS¬rS¬rS«rS«rS«rSªrSªqS©qS©qS¨qS¨pS§pS¦pS¦oS¥oR¤oR¤nR£nR¢mR¡mR lRŸlRžkRkRœjQšjQ™iQ˜hQ–hQ•gQ“fQ’ePdPdPcP‹bP‰aO‡`O…_O‚]O\O}[NzYNwXNtVMpTMlRMhPLcNLaMK_LK]KKbR]C5Pu§Pu§Pu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨-R„-R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae˜Ae˜Ae˜Ae˜yÏyÏyÏAf˜Af˜Af˜$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b•>b•>b”>b”WD3TFJXHK[JKfOLsVM€]O‹bP”gQœjQ lR¡mR mRœkRÅm,½i,ºj/²d+±c)²c(¶e)ºf)¾h*Áj*Ål*Én+Ëo+Îq+Ñr+Ós,Õt,ƒK$ª^(ª_(«_(¬`(®a(¯a)°b)³d*¶f+¾m1‡`O‰aP‹bPcPdPeP’fQ”fQ•gQ—hR™iR›kSlTŸmT¡oV£pW¥rX§tY©v[¬w\®y]¯z^±{_²|`³}`´}`´}`´}_´|^³{^³{\²z[±yZ°xY°wX¯vW®uV®tU­tU­tT­sT­sT­sS­sS¬sS¬sS¬sS¬rS¬rS¬rS¬rS¬rS«rS«rS«rS«rSªrSªqSªqS©qS©qS¨qS¨pS§pS¦pS¦oS¥oR¤oR¤nR£nR¢mR¡mR mRŸlRžlRkRœjQ›jQšiQ˜iQ—hQ–gQ”fQ“fP‘ePdPŽcPŒbPŠaPˆ`O†_O„^O]O\N|ZNyYNvWNsVMoTMkRLgPLbML`LK^KK\JK~aR[B5Pu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe—Ae—Ae—Ae—Ae—Ae—Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Af˜Af˜Af˜yÐAf˜Af˜Af˜Af˜Af˜Bf˜$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c•>c•>b•>b•O?:[E|aRZA5-QƒQu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„Rv¨Rv¨Rv©Rv©Rv©Rw©£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe˜Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Af˜Af˜Af˜Af˜Af˜yžÐyžÐyžÐzžÐzžÐzžÐBf˜Bf˜Bf˜Bf˜Bf˜$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c•>c•>c•>c•VC^C6W@5-Q„-Q„Qu§Qu§Qu§Qu§Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„Rv©Rw©Rw©Rw©¤Ö¤Ö¤Ö¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö¤Ö¤Ö¤Ö\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAf˜Af˜Af˜Af˜Af˜Af˜Af˜Af˜zžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐBf˜Bf˜Bf˜Bf˜$I{$I{$I{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz YE\C6T>4-Q„-Q„-Q„-R„Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„Rw©Sw©€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAf˜Af˜Bf˜Bf˜Bf˜zžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑBf˜Bf˜Bf˜$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$H{$H{$H{$H{?c•?c•?c•?c•$H{$H{$H{SB;R<2zbVUGJXIK[JK[JKuWN€\OŠaP’fP™iQŸlR¡mR£nS£nS¥pTà€9Þ9Õw2Öw0Öv/Öv.Ùx/Üz0Þz0á|1ã~2æ€3è5éƒ6ë…8ë…8ºm4¼o7¾q8Äu;Ãs9Ãs8ºj0‚]O„^O†_Oˆ`OŠaPŒbPcPdP‘eP’fQ”fQ•gQ—hR™iRšjSœkSlTŸnU¡oV¢pV¤qW¦rX§sY¨tY©uYªuZ«uZ«vZ«vY«uY«uX«uX«tW«tV«sVªsUªsUªrTªrTªrTªrSªqSªqSªqSªqSªqS©qS©qS©qS©qS©qS©qS©qS©qS¨qS¨pS¨pS§pS§pR§pR¦oR¦oR¥oR¥oR¤nR£nR£nR¢mR¡mR mR lRŸlRžkRkRœjQ›jQšiQ™iQ—hQ–gQ•gQ”fQ’eP‘ePdPcPŒbPŠaPˆ`O†_O„^O‚]O\O}[NzYNwXNtVMqUMnSMiQLeOL`LK]KKmP?kN?|aSZA5P<4-R„-R„-R„-R„-R„-R„Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×Ei›Ei›Ei›Ei›Ei›Ei›Ei›\À\À\À\À\À\À\À\À\À\À\À\ÀBf˜zžÐzžÐzžÐzžÐzžÐzžÐzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑBf™Bf™Bf™%I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{?c–?c–?c–?c–?c–?c•?c•?c•?c•$H{$H{$H{jXP^H=}dXUGJXHKZIKkRLwXN‚]O‹bP”fQšiQžkR mR£nS¥pT¨qU¨rUç…;ç†>ì‰?è†<å‚9ê†;î‰=ðŠ=ðŠ>ôŽAø‘Dü•Hÿ˜Kù’E¿r:Àt;Àt;Át<Ãt:½n4´f,]Oƒ^O…_O‡`O‰aO‹bPŒcPŽcPdP‘eP“fQ”gQ–hQ˜iR™jR›kSœlSžmTŸnU¡oV¢pV¤qW¥rW¦rX§sX¨tX©tX©tX©tX©tXªtWªsW©sV©sV©rU©rU©rT©qT©qT©qS©qS©qS©qS©qS©qS©qS©qS©qS¨qS¨qS¨pS¨pS¨pS¨pS§pS§pS§pR¦pR¦oR¦oR¥oR¥oR¤nR¤nR£nR¢nR¢mR¡mR mR lRŸlRžkRkRœjQ›jQšiQ™iQ˜hQ–hQ•gQ”fQ’fP‘ePdPŽcPŒcP‹bP‰aO‡`O…_Oƒ^O]O~[N{ZNyYNvWNsVMpTMlRMgPLcNL†gUƒeUlO?~bT{`SW@5-R„-R„-R„-R„-R„-R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R….R…Ei›Ei›Ei›€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›\À\À\À\À\À\À\À\À\À\ÀzžÑzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒBg™Bg™Bg™%I{%I{%I{%I{%I{%I{%I{@d–?d–?d–?d–?d–?d–?d–?d–?d–?c–?c–?c–?c–$I{$I{L=:WD`KA-R„-R„-R„.R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R….R….R….R…EiœEiœEiœEiœEiœEiœ¥×¥×¥×¥×¥×¥×¥×EiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœ\À\À\À\À\À\À\À\ÀzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒ{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| ÒCg™Cg™%I{%I{%I{@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–?d–?d–?d–?d–?d–?d–$I{$I{dUPYEXG@-R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©.R„.R„.R„.R„.R„.R„.R„.R„.R….R….R….R….R….R….S…EiœEiœEiœEjœEjœEjœEjœEjœ¥×¥×¥×EjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEiœEiœEiœ\À\À\À\À\À\À{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| ÒCg™@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–?d–$I{$I{RA;P<3zcXnVIuh™~pdNLpUMÁ”w¬zZ«vS‘eP–gQœjQžlR¡mR¤oS§pT­uV¯vW±xY¶|\¼€_ÆdƉgÈŠhÊŒiÌŽkÎlÿRñF¶k4²g1¯d-­b+ª_(¢Z'}[N€\O‚]O„^O†_Oˆ`O‰aP‹bPcPŽcPdP‘eQ’fQ”gQ•gQ—hR˜iR™jR›kSœkSlTžmT nT¡nU¡oU¢oU£pU¤pU¤pU¤pU¥pU¥pT¥pT¥pT¥pT¥pS¥pS¥oS¦oS¦oS¦oS¦oS¦oS¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¥oR¥oR¥oR¥oR¤oR¤nR¤nR£nR£nR¢nR¢mR¡mR¡mR lRŸlRŸlRžkRkRœkQœjQ›jQšiQ™iQ˜hQ—hQ•gQ”gQ“fP’ePePdPcPŒbPŠbP‰aO‡`O…_Oƒ^O]O~\N|[NzYNwXNtVMpUM—pY”oXzWBuUB…gVlP@jO@|bUx`TcMB3!.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©.R„.R„.R„.R„.R….R….R….R….R….S….S….S…EjœEjœEjœEjœEjœEjœEjœEjœEjœ¦Ø¦ØEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœ\À\À\À\ÀBg™{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| ÒCg™Cg™Cg™Cg™|¡Ó@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–%I{;0/SB;R=4fODpXL‘xkš€r˜vbº“zÀ”x«{[ÃldP•gQ™iQ›jQŸlR£nR¦pS¨qTªrT¬tU°wWµ{Z¸}\¸|\¸}\¹~]»]å}+Ý~6­d.ªa+¨_)§^(¤\'zYN|ZN~\N€]Oƒ^O„_O†_Oˆ`OŠaP‹bPcPŽdPdP‘eQ“fQ”gQ•gQ—hR˜iR™jRšjSœkSlSžlTŸmT mT nT¡nT¢nT¢oT£oT£oT£oT£oT¤oS¤oS¤oS¤oS¤oS¤oS¤oS¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¤oR¤oR¤nR¤nR¤nR£nR£nR£nR¢mR¢mR¡mR¡mR lR lRŸlRžlRžkRkQœjQ›jQšjQ™iQ™iQ˜hQ—hQ•gQ”gQ“fQ’ePePdPŽcPŒbPŠbP‰aO‡`O…_Oƒ^O]O\N}[NzZNxXNuWMrUM™rZ–pY|XCxVCsTBmQAkOA~cVzaU`I>\IARv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©.R….R….R….R….R….S….S….S….S…FjœFjœFjœFjœFjœFjœFjœFjœ‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦ØFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœ\À\ÀBg™{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ó| ÓCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™}¡Ó@e—@e—@e—@e—@e—@e—@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–%I{<1/J82^I@gQFqYN‘xl™€s—vc¢{d¿”yª{\«wUÄi‘eP•gQ˜hQkQ mR¢mR¤nR¥oS§pSªrT¬tU¬tU¬tU¬tU­tU®tUÒt.ƒL&¤](¢['¡Z'žY&xYN{ZN}[N\N]Oƒ^O…_O‡`OˆaOŠaPŒbPcPdPeP‘eQ“fQ”gQ•gQ—hR˜iR™iRšjR›kSœkSlSžlSŸmSŸmS mS nS¡nS¡nS¢nS¢nS¢nS¢nS£nS£nS£nR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR£nR£nR£nR£nR£nR¢nR¢mR¢mR¡mR¡mR¡mR lR lRŸlRžlRžkRkRœkQœjQ›jQšiQ™iQ˜iQ—hQ–hQ•gQ”fQ“fP’ePePdPŽcPŒbP‹bP‰aO‡`O†_O„^O‚]O\O}[N{ZNxYNvWNsVM›s[˜rZ~ZDnYŒkYqSBkPAiOA|cVbK?\G>NB?Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©.S….S….S….S….S….S…FjœFjœFjœFjœFjœFjœ‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦ØFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœCg™Cg™| Ò| Ò| Ò| Ò| Ò| Ó| Ó| Ó| Ó|¡Ó|¡ÓCg™Cg™Cg™Cg™Cg™Cg™Cg™CgšCgšCgšCgšCgš}¡ÓAe—Ae—Ae—@e—@e—@e—@e—@e—@e—@e—@e—@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–%I{@d–@d–<1/H72\I@ePGpYNxm˜€t–vc¡{e¾”zÁ“u‘p«wU¬uQ‘eP•gQ™iQšjQœjQžlR¡mR£nR¤nR¤oR¤oR¤oR¤oR¤oRÇgb;  Z'žY&›W&“S%vXNyYN{ZN~[N€\O‚]Oƒ^O…_O‡`O‰aOŠaPŒbPcPdPdP‘eQ“fQ”gQ•gQ–hQ˜iR™iRšjR›jR›kSœkSlSžlSžlSŸlSŸmS mS mS¡mS¡mS¡mR¡mR¢mR¢mR¢mR¢mR¢nR¢nR¢nR£nR£nR£nR£nR£nR¢nR¢nR¢mR¢mR¢mR¢mR¡mR¡mR¡mR mR lRŸlRŸlRžlRžkRkRkQœjQ›jQ›jQšiQ™iQ˜hQ—hQ–gQ•gQ”fQ“fP‘ePdPdPcPŒbP‹bP‰aO‡`O†_O„^O‚]O€\O}[N{ZNyYNvXNtVMu\„]E€[E’oZŽmZŠkYnRBjOB}cVdL@`I?XGARv¨Rv¨Rv¨Rv¨Rv©Rv©Rw©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwª.S….S….S….S…/S…FjœFjœFjœFjœ‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦ÙFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœ‚¦Ù‚¦ÙCg™Cg™| Ó| Ó|¡Ó|¡Ó|¡Ó|¡Ó|¡ÓCg™Cg™Cg™Cg™CgšCgšCgšCgšCgšCgšCgšCgšChšChšChšChšChš}¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—@e—@e—@e—@e—@e—@e—@e—@d—%I{%I{%I{%I{%I{@d–@d–<10F61o]Vye]„oeŽxmœ‚u”udŸ{e¥}d¨|aÀ’tÁpÃl¬uQdP’eP”fQ–gQ˜iQ›jQœjQœjQœjQœjQœkQœkQkQ_9 œX&™V&•T%rUMuWMwXNzYN|ZN~[N€\O‚]O„^O…_O‡`O‰aOŠbPŒbPcPŽdPdP‘eQ’fQ”fQ•gQ–hQ—hR˜iR™iRšjR›jRœkRœkRkRlRžlRžlRŸlRŸlRŸlR lR mR mR mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR mR lR lRŸlRŸlRŸlRžkRžkRkRkQœjQ›jQ›jQšiQ™iQ˜iQ—hQ–hQ•gQ”gQ“fQ’fP‘ePdPdPcPŒbPŠbP‰aO‡`O†_O„^O‚]O€\O~[N{ZNyYNwXNtVMrUM†^F‚]F”q\o[ŒlZqTD€fX}dWeMAbK@O=6NB@Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxª/S…/S…FjœFjœFjœƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœƒ§Ùƒ§Ùƒ§Ùƒ§ÙCg™Cg™Cg™}¡Ó}¡Ó}¡ÓCg™CgšCgšCgšCgšCgšCgšCgšChšChšChšChšChšChšChšChšChšChšDhšDhšDhš~¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—%I{%I{%I{%I{%I{%I{%I{%I{%I{@d—@d—E:9D61m\Vwe]lXOuaX„k_¨‹z±|¡|e¥|c§|`©z]ªyXÂnÃlÄŽkÄŽidP’eP“fP“fP“fP’fP“fP“fP“fP[7 —U&”T%P%pTMsVMuWMxXNzYN|ZN~[N€\O‚]O„^O†_O‡`O‰aOŠbPŒbPcPŽdPdP‘eP’eQ“fQ”gQ•gQ–hQ—hQ˜iR™iRšjR›jR›jRœkRœkRkRkRžkRžlRžlRŸlRŸlRŸlRŸlR lR lR lR lR lR lR lR lR lR lR lR lR lRŸlRŸlRŸlRŸlRžkRžkRkRkQœkQœjQ›jQ›jQšiQ™iQ˜iQ˜hQ—hQ–gQ•gQ”fQ“fP’eP‘ePdPŽdPcPŒbPŠbP‰aO‡`O…_O„^O‚]O€\O~[N|ZNyYNwXNuWMrUM‡`G„^G–r]|ZFxXFtVEgY~eY{cXbLA[H?REA.R„.R„Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSxªSxªSxªSxªTxªTxªTxªƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙFjFjFjFjFjFjFjFjFjFjFjƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙCg™Cgš}¡Ó}¡ÓCgšCgšCgšCgšChšChšChšChšChšChšChšChšChšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš~¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—%I|%I|%I|%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{@e—@e—B99B51k[Vud]iWPr_Wye] †yªŒ|²}¡|e¤|c¾’w¨{^¨z\©yZÁp«xW«wU«wU«wU«wUÃŽlÃŽlÂŽlÂŽlkD(’S%ŒP%nSMoTMqUMsVMvWNxXNzYN|ZN~[N€\O‚]O„^O†_O‡`O‰aOŠaP‹bPcPŽcPdPeP’eQ“fQ”fQ•gQ–gQ–hQ—hQ˜iQ™iR™iRšjR›jR›jRœjRœkRœkRkRkRkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRžlRžkRžkRžkRkRkQkQœkQœjQ›jQ›jQšjQšiQ™iQ˜iQ˜hQ—hQ–gQ•gQ”gQ“fQ’fP‘ePePdPŽcPcP‹bPŠaPˆaO‡`O…_Oƒ^O‚]O€\O~[N|ZNyYNwXNuWMrUMŸw_œv_˜t^~\GzYGvWF†j[fZ|dYybX\I@VGB5/2.R„.R„.R„.R„Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxªSxªTxªTxªTxªTxªFkFkFkFkƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§ÚFkFkFkFkFkFkFkFkƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Ú}¡Ó}¡Ó}¡Ô}¡ÔChšChšChšChšChšChšChšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš~£ÕAe˜Ae˜Ae˜Ae˜Ae˜%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{%I{%I{%I{%I{@e—@e—<68?31gYVpa\bRMjYTq`Z€j`¡‡z«}²‘}¶’|¸’{º’z»’x¼’w§z^¿‘t¿‘s¿‘s¿s¿r¿r¾r¾r°h2‹O$„L$mSMnSMnTMoTMtVMvWNxXNzYN|ZN~[N€\O‚]O„^O…_O‡`OˆaOŠaP‹bPŒcPŽcPdPdP‘eP’eQ“fQ”fQ•gQ–gQ–hQ—hQ˜hQ˜iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœkQœkQkQkRkRkRkRkRkRkRkRkRkQkQkQœkQœjQœjQœjQ›jQ›jQšjQšiQ™iQ™iQ˜hQ—hQ—hQ–gQ•gQ•gQ”fQ“fP’eP‘ePdPdPcPŒbP‹bP‰aPˆ`O†`O…_Oƒ^O]O€\O~[N|ZNyYNwXNtWM£z` y`w`šu_€]I|[HwXGˆl\ƒi[}eZycYr_WjZU;23.R„.R„.R„.R„.R….R….R…Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxªTxªTxªTxªTxª/S…/S…GkGkGkGkGkGkGkƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨ÚGkGkGkƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Ú}¢Ô}¢Ô}¢Ô}¢Ô~¢ÔDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš£ÕAf˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{Ae—Ae—Ae—?89H=:?YUY`QGfVLudXjeitlm{po|qp}rp~rpsqsq€tqŒr_=1+xJ)’o[~[F€\G‚^H„_I…`IkRLlRMnSMpTMrVMuWMwXNyYN{ZN}[N~\N€\O‚]Oƒ^O„_O†_O‡`Oˆ`O‰aPŠbP‹bPŒcPcPŽcPdPdPeP‘eP’eP’fP“fQ“fQ”fQ”gQ•gQ•gQ•gQ–gQ–gQ–gQ–hQ–hQ—hQ—hQ—hQ—hQ—hQ–hQ–hQ–gQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘eP‘ePdPdPŽdPŽcPcPŒbP‹bPŠaP‰aO‡`O†_O…_Oƒ^O‚]O€\O~\N}[N{ZNyYNwXNuWM“iOhOŽgO‹eOžze›yd—wd”tcrbtYKjTIaOG[KFj]Y^UU?;@.R….R….S….S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…GkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkž…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û…©Û…©Û£Õ£Õ£Õ£Õ£Õ£Õ£Õ£ÕDh›Dh›Dh›Dh›Di›Di›Di›Di›Di›¤Ö¤Ö¤Ö¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|Af˜Ae˜Ae˜%J|%J|%J|%I|%I|%I|%I|���#-#%.()1MEAQIEUMI]SL]TM=4.1+(=.#6,&5( 1%"ŒlYn[“p\•r]]Hƒ_I…`JœwažybkRLmSMpTMrUMtVMvWNxXNzYN|ZN}[N\N€]O‚]Oƒ^O…_O†_O‡`OˆaO‰aPŠaP‹bPŒbPcPŽcPŽdPdPdPeP‘eP‘eP’eP’fP“fP“fQ“fQ”fQ”fQ”fQ”gQ”gQ•gQ•gQ•gQ•gQ•gQ”gQ”fQ”fQ”fQ”fQ“fQ“fP“fP’eP’eP‘eP‘ePdPdPdPŽcPcPŒcPŒbP‹bPŠaP‰aO‡`O†_O…_Oƒ^O‚]O]O\O}[N|ZNzYNxXNvWN¬‚gªg¨€ghPŒfPŸ|fœzf˜xe”vdscsYLiTK_NHYKFh\Z]UV=;@.R….S….S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxª/S…/S…/S…/S…GlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û£Õ£Õ£Õ£Õ£Õ£Õ£Ö£ÖDi›Di›Di›Di›Di›Di›¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Ei›&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Af˜Af˜Af˜Af˜Af˜%J|%J|%J|%J|%J|%J|%I|%I|%I|, +,!.! "`E6†iYŒlZo\“q]•s^^J™va›wbycŸzd {e¤}foTMqUMsVMuWNwXNyYN{ZN|ZN~[N\O]O‚]Oƒ^O…_O†_O‡`Oˆ`O‰aOŠaP‹bPŒbPŒcPcPŽcPŽdPdPdPdPeP‘eP‘eP‘eP’eP’eP’eP’eP’fP’fP’fP“fP’fP’fP’fP’eP’eP’eP‘eP‘eP‘ePePdPdPdPŽdPŽcPcPŒcPŒbP‹bPŠaP‰aOˆ`O‡`O†_O…_Oƒ^O‚]O]O\O~[N|[N{ZNyYNwXN®ƒi¬ƒiª‚i¨i¦€hŒhR‰fQ†dQ‚bP•wfx]Oˆpdkbtd_m`]OEDG?A;:@.S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTx«Tx«Tx«Ty«/S†GlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ£Ö£Ö£Ö£Ö¤Ö¤Ö¤Ö¤Ö¤ÖEi›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×€¥×€¥×€¥×Bg™Bg™Bg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Af˜Af˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|��� +,YA5jPBpSD‹l[o]’q^–t`‚_Kšwbœycžze {f¡}g¤h¨i”lSrVMtWMvWNxXNyYN{ZN|[N~[N\O]O‚]Oƒ^O„_O…_O†`O‡`Oˆ`O‰aPŠaP‹bP‹bPŒbPcPcPŽcPŽcPdPdPdPdPdPdPdPdPePePePePePdPdPdPdPdPdPdPŽcPŽcPcPcPŒbP‹bP‹bPŠaP‰aOˆ`O‡`O†`O…_O„^Oƒ^O‚]O€]O\O~[N|[N{ZNyYNxXN°…j®„j¬„jªƒj¨‚j¦€jŒhSŠgS†eRƒcR|`QŒsf…oe}jcrd`k_]LCDC=@,,3(4F(4F.S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžChšChš¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|#5H71O;3V?4iOBoSDsVFo]{[I^Kƒ`L…bN‡dOŸ{f }g¢~h¥€j’kT•mU˜oVšqWrWwXNxXNzYN{ZN}[N~[N\O€]O‚]Oƒ^O„^O…_O…_O†`O‡`Oˆ`O‰aO‰aPŠaP‹bP‹bPŒbPŒbPŒcPcPcPcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPcPcPcPŒcPŒbP‹bP‹bP‹bPŠaP‰aP‰aOˆ`O‡`O†_O…_O„_O„^Oƒ^O]O€\O\N~[N|ZN{ZNyYN›oTšoT™oT—nT¬„lªƒl¨‚ljUŒiTŠhT†fT€cSvi‰rgnfyidqdah^^HBD?<@)+3OZkMYk(5F(5F(5F/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Ty«Uy«†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžDhšDhšDhšChš&K}&K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|A99N?;L:2T>4gNBlRD‡k\‹n^z[J~^LaN…cO‡dP‰fQŠgRŒhTjU’lV•nW˜pXšrXsY¶‹q¸qºŽr¼r½r¿s©z[©z[ªz[«{[¬{[¬{ZÅ“rÅ’qÅ’qÅ’pÅ’pÅ‘o­yV­xV¬xU¬wT¬wTŠaPŠbP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bPŠaPŠaPŠaP‰aP‰aOˆaOˆ`O‡`O‡`O†_O…_O„^Oƒ^O‚^O‚]O]O€\O~\N}[N|ZNzYNpTœpU›pUšpU˜oV—oV•nV“mV‘lVkVŒjVˆhVƒfU~cUuj†qh~mfugdkaad\^E@D98?$(2minffm^blV^lMYk(5F(5F/S…TxªTxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Uy«Uy«†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}ChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|Ae˜Ae˜;GY<68I=:I82Q=4XA6~fZ„j\‰m^p`|]L€`NƒcP†eQˆgS¡j£€l¦‚m©„n•oX˜qYšrZt[¶Œr¸sºs¼t½t¾‘t¨z]©{]ª{]«{\«{\¬{\¬{[Ä“sÄ“rÄ’rÄ’qÄ’pÄ‘p¬yWÄoÃnÃmÃlÂŽlÂŽkÁkˆaOˆaOˆaOˆaOˆaOˆaOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O…_O„_O„^Oƒ^O‚]O]O€]O\O~\N}[N|ZN¶‰l¶‰lµˆmœqV›qVšqV™pW˜pW–oW¬…nª…n§„n¤‚nŸ€n›~n€eW‘xlŠtk‚piykfodcf_`JDG@>C*,5$1MYktr~tstmolinadmX_lNZkMZkTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«ÝHlŸHlŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™&J}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Af˜Af˜Af˜Af˜;GY;GY;GY1'!D:9N?;N;3]I?zdY€h[†l^‹oasc“ue€bQ„dR‡fT l¢m¦ƒn©…o«‡p®ˆq±Šr³‹sžv] w]¹u»u¼‘u¾‘u¿’v¨{^©{^ª|^«|]«|]«{\¬{\¬{[¬{[¬zZ«zZ«yY«yX«xXÂoÂnÂnÁŽmÁŽm¨uT¨uS§tS§tS§tR¦sR¦sQ…_O…_O…_O„^O„^Oƒ^Oƒ^O‚^O‚]O]O€]O¢rS¡rS¡rS¸‰k·‰l·‰l¶‰m¶‰mµ‰m´‰n³‰n›qWšqX™qX®‡o­‡o«†p¨…p¤ƒp pœp—}o{cXv`Vp]U}nishfhaba\_DAF::B$)4�MYkMYkMYkŒtctq\QPPIKFDI;>H/8GMZkTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸImŸImŸImŸImŸImŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšChšChšChšChšChšChšChšChšCgšCgš&K}&K}&K}&K}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;GY;GY;GY;GY;,#I=:H82YF?^JA|e[‚j]ˆn`Œqcte”wg—yiš|k~l €n£‚o¤ƒp¦…q­‰s°Šs›u]žv^Ÿw^¡x_£y_¤z_¥z_¦{_¿“w¿“wÀ“vÁ“vÁ“v“u“u“tª{\ª{\ªz[ªzZªyZªyY©xXÁpÀo¨wW¨vV§vV§uU¦uU¦uT¥tT½Œl¼‹k¼‹k¼‹k»‹k»‹kºŠk¢sT¢rT¢rT¡rT¡rT¡rU rU rV·Šn¶ŠnµŠnµŠo´Šo³‰o²‰p±‰p™qY®ˆq¬‡qª†r§…r¤„r ‚rœ€q€gZ{dYvaXp^WiYU`TRVNOb]aEBH<+[NL^SQWNNKFJ?AI2:HTx«Ty«Ty«Ty«Uy«Uy«Uy«Uy«Uy«‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝImŸImŸImŸImŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšChš&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}CgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;HY;HY;HY;HY;GY3("D::B41RB=YG@wcZ}g\ƒk_‡nbŒrdug}aRdT„gV‡iX‰kY¢ƒq¤„r¥…s§†t‘p^’q^Ÿw` x`¢y`£z`¤za¥{a½“x¾“x¿“w¿“wÀ“wÀ“vÀ“vÀ“vÀ“uÀ’uÀ’tÀ‘sÀ‘sÀ‘r¿r¿q¿q¾p¾Žp¾Žo½Žo¥vW¼n¼Œn»Œn»Œn»ŒnºŒnº‹m¢tV¡sV¡sV¡sV sV sWŸsWŸsXžsXµŠpµŠp´ŠpœsY›sYšrZ˜r[–r\”q\‘p]¦†t£„tŸƒsœs€h\{e[vbYo^XhZV`USXPQNJMECJRS[47A+((MYkMYkMYkMZk(5F(5F(5FOHJT=+YML_SRZQQMGJABI2:H/T†Uy«Uy«Uy«Uy«Uy«Uy«‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸˆ¬Þˆ¬Þ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}CgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™&J|&J|Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;HY;HY;HY;HY>DM>DM;HY89<:+#9&B52I94ZHAxd[}g^k`†nc‹rey_R}bTeVƒgX…iYˆk[Šl\Œn]o^¥‡v§ˆvšvaœwažxa yb¢zb¤{b¤{a¼“x½“x¦|a§|a§|`§{`§{_§{_§{^§z^¾‘u¾‘t¾‘t¾s½s½r½r¥wZ¤wZ¤vY¤vY£vY£uX¢uX¢uX¢uX¹Œp¸Œp¸Œp·Œp·‹p¶‹p¶‹pµ‹qµ‹qtZ›t[šs\™s\˜s]–r]”r^’q^p^o^Šn^‡l^ƒj^h]{f\ub[n^YgZW_UTWPQOKOEEKST]JNY>=?JJIMYkMYk(5F(5F(5F(5F(5F)5G)5GK=4S<*XMLbWVYPPLGJ@AI/T†/T†Uy«Uy«Uy«‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞImŸImŸImŸIm ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞIm Im Im Im Im Im Im Im ˆ¬Þˆ¬Þˆ¬Þˆ¬Þ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Dh›Dh›Dh›Dh›DhšDhšDhšDhš'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜;HY;HY;HY;HY;HY;HYCIR>DMCIR;HYCIR.$0"8&?*G/V=+w[F{g^€kanXMs\Px_S{bU~dWfYƒhZ†j\ˆl]Šm^¢…v§ˆwªŠx­Œy¯y±Žz´zµz·‘z¹’z£{b£{b¤{b¥{b¥{a¥{a¥{`¥{`¥z_¥z_¥z^¼‘u¥y]¤y]¤x]¤x\£w\£w[¢w[¢v[¢v[¡v[¡v[¸r·r¶r¶ŒsµŒs´Œs´Œs²Œt±‹u°‹u˜t^–s_•s_“r_’r`q`p`¡…wž„v›‚v—€u“~twd]sb[l^ZeYW]TUUORLJOYYaRU^JOZ>>@!$)RXaMYk39B-3<-3<(5F)5G)5G)5G)5G)5GFDJK9*^K=YONg\\TLMIFJ:>I0T†0T†ImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞIm Im In In In In In In ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßIn In In In In ˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ß'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Di›Di›Dh›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}ChšChšChšChšChšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™&J}&J}&J}&J}&J|&J|&J|&J|&J|Bg™Bg™Bg™Bg™Bg™Bf™Bf™EM>EMCIR;HY;HYCIRCIR)6&8&@*H0I1!\B0}_JhTKjM8q[Pt]Sw`U{cW~eYg[ƒi\…k^‡m_Ÿ…v¢†w¥ˆx¨Šyª‹z­z¯Ž{±{²{³{´{žzdŸzd zc zc¡zc¸‘y¸‘y¸‘y¸‘x¸x¸x·w·w·w·wŸw_Ÿw_žw_µŽv´Žv³v²v²w±w°Œw¯Œw®Œw­‹w«‹xªŠx¨‰x¦‰x¥ˆx£‡x¡†xž…x›ƒw—v’~vŽ|t‰ys„vrh\YcXX[TUSNRIHOUXaNS^JFE>>A')+"%(4:C(5F(5F3:B3:B-3<-3<)5G)5G)5G)5G)5G)5GE:4O:*TKLbXWcZZPIKDCJIm Im Im Im ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßIn In In In In In Jn Jn Jn Jn Jn ˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn ‰­ß‰­ß‰­ß‰­ßˆ­ßˆ­ßˆ­ßˆ­ß'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšChšChšChšChšChšChšCgšCgšCgšCgš&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J|&J|&J|Cg™Cg™Cg™Bg™Bg™Bg™EMCIRCIRCIR888DGNCJRCIRBBB(0 8&<)G0M5"X@0z^K†bFŠkUlXPp[Rs^TvaVzcX}fZg\i]™u›‚v„wŸ†x¢‡y¥‰z§Šz©‹{ªŒ{•ve–ve—we˜we°|°|±{²{²{²{²{²{±z±z±Žz±Žz±Žz°Žy™vb˜vb—vb–ub•ub•uc”tc“tc’sbscrcqc¢‡y †y…y›„x˜‚x•w’w|uˆytƒvs~sqyooslmVQTOLR[\dQU`KHHAAD:<@68; &�Z`i-4<%');AJ4:C4:C4:C-4<)5G)5G)5G)5G)6G)6G@84H8-N?5YPQmccoghd`dIn In In In In In ˆ¬ßˆ¬ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßJn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~Ei›Ei›Ei›Ei›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšChšChšChš&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J}Cg™Cg™Cg™Cg™B9;>68;����Z`iZ`iMZk)5G4:C-4<4:C4:C-4<;BJ)5G)6G)6G)6G)6G)6GC6-L;.leg„{{ypqhbeVYcJn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­àJn¡Jn¡Jn¡Jn¡Jn¡Jn¡Jn¡‰­à‰­à‰­à‰­à‰­à'L~'L~'L~'L~'L~'L~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhš'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}Cg™Cg™Cg™<535=AG=?D?AD==1(B3)B2&F4'E4)gTGlXJs^OzcTzaPqfethgvjhbVTcWUdXVeYWfZXg[Yh\Zi]Zi][j^\€us€ususts~tt~tt}tt|st{stut~tt|sszrsyqrwpquoqsmpqloXTXTQWPOULLSSJEA<:=99757335./2113)+.'),)+.8:="(���3@Q���������������JMPV\eT[cNZlNZlZ`iZ`iZ`iZ`iSYbY`h4;C.4=)6GCPaCPaCPaCPaCPaEQbZOGa_emhkŠƒ„nfgeaeJn¡Jn¡Jn¡Jn¡Jn¡Jn¡Š®àŠ®àŠ®àŠ®àŠ®àJo¡Jo¡Jo¡Jo¡Jo¡Jo¡Jo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Š®àŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡ƒ§Úƒ§Úƒ§Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨ÚEjœEiœEiœEiœEiœ'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}Di›Di›Di›Di›Dh›Dh›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}$.>=I[=I[2)>0&A2'C3(I8-^OFbRHfUJjXMq^RwcVzfYfRDfQCdN@zdTqijrjksklrklrklrklqjmpjmpjmojmojmnimmimkhliflscYm`Xg\VbYT^VRE>;A<:>98:77645:873220/0,-/)+.*,/#%( &������15;5BS������������������KKKJMP]dlU[dNZlNZlZ`iTZcZaiZaiZ`iZ`iSZbŽ”LS[V]eDPbDPbDPbDPbDPbDPbWMF^^diei®”†…rkeaeJo¡Jo¡Jo¡Jo¡Š®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Š¯áŠ¯áŠ¯áŠ¯áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡ƒ¨Úƒ¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨ÛGk'L~'L~'L~'L~'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Di›Di›Di›Di›Di›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}%/> ,>=I[=I[ ,> ,>#)2(.7#)2(.7#)2#)2#)2#)2(.7(.7(.767@D>A214$+3#%("$'###""""""&&&888888cB*}\I@!%+%!5*$:/(;0)<1*>3+@4+>1(bUKN@6OA6L=3QB8M?4_RKaTLbUMcVNcVNcVObVOaVOaUO`UO_UO^UO^TO\SOYRNWPNUOMWPKYSOWRN;63953:76755333,/2'),%(+"%(!' ���"&,KXi04:������������������JMP]_b^emU[dNZlNZlT[cU[dU[dU[d[aj•ž•ž•žˆŽ—–¥W]fDPbDPbDPbDPbDPbDPb‘nSž…w—|m¨‚ƒqjKo¡Ko¡Ko¡Š®àŠ®àŠ®àŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áŠ¯áŠ¯áŠ¯áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨Û„¨Û„¨Û„¨Û„©Û„©Û„©Û„©ÛGkGkGkGkGkGk'L~'L~'L~'L~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Di›Di›'K}'K}'K}'K}HlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}*2? ->=I[=I[ ,> ,> ,>#)2#)2#)2(.7(.7#)2#)2(.7(.7(.7(.7/28:79G@A<89',4#%(#%(######""""""8888888887'vS:‹jW;)� + &3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!' ���15;6CT37=������������������������MMMKMP^ad_enY`hNZlNZlU\dV\eŠ‘™Š™Š™–Ÿ–Ÿ–ž•ž“œ—¦Œ’›ƒ¡DQbDQbDQbDQbDQbMUc¤ƒ‘ylŸ‡|€oiKo¡Š¯áŠ¯áŠ¯áŠ¯áŠ¯áŠ¯áŠ¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯áKo¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢‹¯â‹¯â‹¯â‹¯âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨Û„¨Û„¨Û„©Û„©Û„©Û„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©ÛGkžGkžGkžGkžGkžGkžGkžGkžGkž…©Û…©Ü…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}'K}'K}'K}'K}'K}HO\=J[=J[=J[ -> ,> ,>(.7#)2#)2(.7(.7(.7#)2(.7(.7(/7(/7)/8/28114H7,99@.05&,5$&)$$$######"""(((8888888888888884"nO9„gXˆjZE/ (�-" + %' %$#" ! !$ ���48>7CU:GX ���������������������������JJJLLLKMPagp_enNZlLPV˜Ÿ§Œ’›Œ’›Œ’›‹’š‹‘šŠ‘™‘— –Ÿ–Ÿ–Ÿ“œ“œ—¦„¢„¢DQbDQbDQbDQbNVc…uo‡rjѼ³º«§‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯áKp¢Kp¢Kp¢Kp¢Kp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢‹°â‹°â‹°â‹°âŒ°âŒ°âŒ°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢„¨Û„¨Û„¨Û„©Û„©Û„©Û„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGkžGkžGkžGlžGlžGlž…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}DhšDhšDhšIP\=J[=J[=J[=J[ -> ->(.7#)2#)2(.7(.7(.7#)2(.7(/7(/7)/8)/8)/803966:E?AC>A856,07%'*%')$$$######(((DDDBBB8888888880 cF1w]OcS{`QS;+57'   *  ��    ;?E7CU;HY=I[ ���������������������������������JJJMMMKMPacfbhq‘— ƒ¡ƒ¡‘— “œ“œ“œŒ“›Œ’›Œ’›‹‘š‘— ‘— —Ÿ™Ÿ¨”œ“œ“œ„‘¢„‘¢„‘¢„‘¢EQcHScNVd´¨§¿®¨Èµ®¯‘‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯â‹¯â‹¯â‹¯â‹¯â‹¯â‹°â‹°â‹°â‹°â‹°â‹°â‹°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Œ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Ü…©Ü…©ÜGlžGlž…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÝHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž‡«Ý‡«ÝDhšDhšDhšDhš=J[=J[=J[=J[=J[=J[ ->(/7#)2#)2(.7(.7(.7#*2(/7)/8)/8)/8)/8)08*0903:56:88@KBB=;@348*08&(+'(*%%%$$$(((EEE(((&&&���">-"bF3oXMs[Ow]Py^PqbpXMdH5R<,Q;, &%%#'-"'-&3DS_qP\nR_p>J\?K]AG@B::@66:-29'),)'%BBBFFFEEE)))))))))&&&��������������� ������������������������������������������@@@FFFACFZ\_[ajagp„¢„¢„¢ž¥­Ÿ¦®—¦–¥–ž•žŽ•Ž””œ“œ‘— —Ÿ›¡ªš ©™ ¨Ž•Ž”Ž”…‘£…‘£…‘£EQcGRcKTdPWd­¥§¿¯ª‹°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°ãŒ°ãŒ°ãŒ°ãŒ°ãLp£Lp£Lq£Lq£Lq£Lq£Lq£Lq£Lq£Œ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£…©Û…©Û…©Û…©Û…©Û…©Û…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHlžHlžHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«ÞŸ>J\>J\=J[=J[=J[=J[FLU39B#*2(/7)/7)/8$*3$*3$*3)/8)08*09*09*19',5(-5*.6.17338@<=G@BH@BXW]UUXLPWFHKDFHKKKHHH+++%%%%%%$$$###!!!!!!777777777777777777777AAAFFFACFACF\^aeltbhqDQbDQbDQbŸ¥®¡§°¡§°¡§°¡§°—¦–Ÿ”š£”š£“™¢’™¡’˜¡‘˜ ‘— ›¡ª›¡ªš ©•ž™Ÿ¨Ž”ERcERcERcERcHScLUdRXd|njŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°ãŒ°ãŒ°ãŒ°ãŒ°ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬ÞŽŸŽŸŽŸŽŸ>J\=J[=J[FLUFLU(/7(/7*08*08%+3$*3$+3$+3*09*09*19&,5&,5'-6).6*/7-18NPURRVXUVc]^f^_[X]\XYTUZLQYKMPFHJ)))(((&&&%%%%%%$$$$$$###!!!!!!!!!777777777BBBEEEACGADGFIL\ckZ`iTZcDQbDQbDQbagpbiqcircir¢©±¢¨±¡¨°¡§°•œ¤•›¤”›£”š£“™¢’™¡’˜¡œ¢«œ¢«›¡ªš¡©•žY`hY_hERcERcERcGSdJTdNVdTYeLp¢Lp¢Œ°ãŒ°ãŒ°ãŒ°ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£±ã±ã±ã±ä±ä±ä±ä±ä±ä±ä±ä±ä±ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²äMq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞŽŸŽŸŽŸŽŸŽŸŽŸŽŸFLUFLUFLU)/8+08+08&+3&+3%+4%+4%+4*19+1:&,5'-5'-6(.6FLTHMTINUKOVOQWSTXYWX`[^lbac]_f_\a_aY\aRX_,.1*,.*+-***((('''&&&%%%%%%$$$$$$$$$###!!!!!!!!!!!!!!!%%%%%%%%%%%%"""""""""KKKJJJFFFGIL]_b^dm\bkV]eDQbEQcEQcEQccirdjsdksektdjsdjscir£©²¢¨±¢¨±–œ¥•œ¤•›¤”›£”š£“™¢’™¡£¬œ¢«›¢ª[ajZ`iOU^ERcERcFRdFRdITdLUdPWeVZeLp£Lq£Lq£Lq£±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ä±ä±ä±ä±ä±ä²ä²ä²äMq£²ä²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äMr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«ÞHmŸHmŸHmŸ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞŽŸŽŸŽŸŽŸ‚Ž ‚Ž ‚Ž ‚Ž ”›£Š™ŠŽ•-18,18',3',4',4&,4%,4+1:,2:'-5DJSEKSEKTFLTFLUHMUINVKOWLPWQSYTUZWWZpjje^`offb\_h`]eaaCCG8;A27?-/2+-/.+)******)))((('''&&&&&&%%%%%%$$$$$$$$$$$$$$$$$$######???EEEEEEEEE((((((###&&&%%%HJMHJMHJMHJM_en]dlZ`i_enEQcEQcEQcEQcbhqektflufluflufluektektdksdjscjr£©²¢©±¢¨±–œ¥•œ¤•›¤”›£”š£“™¢£¬\ckQW`[ajZaiOU^FRdFRdFRdHSdKUdNVeRXeX\fLq£Mq£Mq£Mq£Mq£±ã±ã±ã±ã±ã±ä±ä±ä±ä±ä²ä²ä²ä²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äMr¤Mr¤Mr¤Mr¤Mr¤Ž²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åNr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬ÞHmŸHmŸHmŸHmŸImŸImŸImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ”›£Š‘™‹•‹•PT[KOVJOV(-4(-4'-5'-5JOXEKSEKSEKTFLTFLTGMUGMUHNVIOWKPWLQXMRYPTZTV[\]a_^asljd^azporjkE@CLEBIEFEDG29A28A17@135,.1+-0+,/./1..0'),)))++++++++++++***FFFFFFACFACFEEEACFACFŠŒJLOJLOKQZ_en]clY_hU[dEQcEQcEQcEQcEQcagp[aj\bk\bkgnvgnvgmvgmvfluflueltektdksdjscjrcir¢©±—¦–œ¥•œ¤•›¤TZcSYbRYaRXaQW`[bj[ajZ`iFSdFSdGSdJTdLVePXeTZfZ]fMq£Mq£Mq£Mq£Mq£Mq£Mq£²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äNr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Ž²åŽ²åŽ²åŽ²åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³å³å³å³å³å³å³å³åNr¤Nr¤Nr¤Nr¤Nr¤³å³å†ªÜ†ªÜ†ªÝHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ­ß‚Ž ‚Ž ‚Ž ‚Ž ‚ ‚ ‚ ‚ ‚ …Œ”’•šŒ•‘”›LPVLPWKPW‹—‹—‹˜•‹‘™FLTFLTFLUGMUGMUHMVHNVINWIOWKPXLQYMRYNSZTX`X[a[]b]^c__ccacib`JDGi__aYYPJLD@C=;AKEDTQR@?A>>A;/5>.4=-4 + + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(Q_OS_SYMBIAN) +# define SRCDIR "" +#endif +typedef QMap QStringMap; +typedef QList 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("fileName"); + QTest::addColumn("lossy"); + QTest::addColumn("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("fileName"); + QTest::addColumn("format"); + QTest::addColumn("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 formats = QImageWriter::supportedImageFormats(); + QList sortedFormats = formats; + qSort(sortedFormats); + + // check that the list is sorted + QCOMPARE(formats, sortedFormats); + + QSet 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("format"); + QTest::addColumn("expectedFormat"); + QTest::addColumn("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 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("fileName"); + QTest::addColumn("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 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("fileName"); + QTest::addColumn("format"); + QTest::addColumn("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("filename"); + QTest::addColumn("expectedDotsPerMeterX"); + QTest::addColumn("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 Binary files /dev/null and b/tests/auto/gui/image/qmovie/animations/comicsecard.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qmovie/animations/corrupt.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qmovie/animations/dutch.mng 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 Binary files /dev/null and b/tests/auto/gui/image/qmovie/animations/trolltech.gif 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 @@ + + + animations/corrupt.gif + + 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 + + +#include +#include +#include + +//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("fileName"); + QTest::addColumn("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 + +#include +#include +#include +#include +#include +#include + +//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("x"); + QTest::addColumn("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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img1.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_0/img2.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img1.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromImage/task31722_1/img2.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_16x16.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_256x256.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_32x32.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_32bpp_48x48.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp.ico 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_16x16.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_32x32.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_48x48.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/designer.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_50_50_100_100.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_-10_dy_0_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_-128_dy_0_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_50_50_100_100.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-10_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_-128_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_50_50_100_100.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_null.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_0_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_10_50_50_100_100.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_10_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_128_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_0_dy_1_null.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_10_dy_0_50_50_100_100.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_10_dy_0_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_10_dy_10_50_50_100_100.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_10_dy_10_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_128_dy_0_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_128_dy_128_64_64_128_128.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_128_dy_128_x_y_w_h.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/images/dx_1_dy_0_null.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_argb32.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha.png 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.jpg 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmap/loadFromData/designer_rgb32.png 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 @@ + + + images/designer.png + images/dx_0_dy_0_50_50_100_100.png + images/dx_0_dy_0_null.png + images/dx_0_dy_0_x_y_w_h.png + images/dx_0_dy_-10_50_50_100_100.png + images/dx_0_dy_10_50_50_100_100.png + images/dx_0_dy_-10_x_y_w_h.png + images/dx_0_dy_10_x_y_w_h.png + images/dx_0_dy_-128_x_y_w_h.png + images/dx_0_dy_128_x_y_w_h.png + images/dx_0_dy_1_null.png + images/dx_-10_dy_0_50_50_100_100.png + images/dx_10_dy_0_50_50_100_100.png + images/dx_-10_dy_0_x_y_w_h.png + images/dx_10_dy_0_x_y_w_h.png + images/dx_-10_dy_-10_50_50_100_100.png + images/dx_10_dy_10_50_50_100_100.png + images/dx_-10_dy_-10_x_y_w_h.png + images/dx_10_dy_10_x_y_w_h.png + images/dx_-128_dy_0_x_y_w_h.png + images/dx_128_dy_0_x_y_w_h.png + images/dx_128_dy_128_64_64_128_128.png + images/dx_-128_dy_-128_x_y_w_h.png + images/dx_128_dy_128_x_y_w_h.png + images/dx_1_dy_0_null.png + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#ifdef Q_WS_WIN +#include +#endif + +#ifdef Q_WS_QWS +#include +#endif + +#ifdef Q_OS_SYMBIAN +#include +#include +#include +#include +#if !defined(QT_NO_OPENVG) +#include +#include +#endif +#endif + +#ifdef Q_WS_X11 +#include +#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("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("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("img1"); + QTest::addColumn("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("input"); + QTest::addColumn("dx"); + QTest::addColumn("dy"); + QTest::addColumn("rect"); + QTest::addColumn("exposed"); + QTest::addColumn("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("pixel"); + QTest::addColumn("syscolor"); + QTest::addColumn("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("pixmap"); + QTest::addColumn("mask"); + QTest::addColumn("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(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("red"); + QTest::addColumn("green"); + QTest::addColumn("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("image"); + QTest::addColumn("width"); + QTest::addColumn("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("format"); + QTest::addColumn("width"); + QTest::addColumn("height"); + QTest::addColumn("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("red"); + QTest::addColumn("green"); + QTest::addColumn("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 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("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("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("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(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(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(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 + + +#include +#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(&key)); +} + +static QPixmapCache::KeyData** getPrivateRef(QPixmapCache::Key &key) +{ + return (reinterpret_cast(&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 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 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 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 Binary files /dev/null and b/tests/auto/gui/image/qpixmapfilter/noise.png 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 +#include +#include +#include + +//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 +#include +#include +#include +#ifdef Q_OS_SYMBIAN +#include +#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(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(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 +#include +#include +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 +#include +#include + +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 +#include +#include +#include +#ifdef Q_WS_MAC +#include +#endif +#ifdef Q_OS_SYMBIAN +#include "private/qcore_symbian_p.h" +#include "txtetext.h" +#include +#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"); + + 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(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(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(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 + +#include +#include +#include + +//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 + +#include +#include + +//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("hint"); + QTest::addColumn("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 +#include +#include + +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(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 +#include + +#ifdef Q_OS_SYMBIAN +#include +#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 > 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 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 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(event); + appendFileContent(*fileOpenEvent, "+received"); + return true; +} + +void tst_qfileopenevent::sendAndReceive() +{ + QScopedPointer 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("filename"); + QTest::addColumn("targetContent"); + QTest::addColumn("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 + +#include + + + +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(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 Binary files /dev/null and b/tests/auto/gui/kernel/qkeysequence/keys_de.qm 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 @@ + + + + tst_QKeySequence + + + Shift+K + Umschalt+K + + + + Ctrl+K + Strg+K + + + + Alt+K + Alt+K + + + + Shift++ + Umschalt++ + + + + Ctrl++ + Strg++ + + + + Alt++ + Alt++ + + + + Meta++ + Meta++ + + + + Shift+,, Shift++ + Umschalt+,, Umschalt++ + + + + Shift+,, Ctrl++ + Umschalt+,, Strg++ + + + + Shift+,, Alt++ + Umschalt+,, Alt++ + + + + Shift+,, Meta++ + Umschalt+,, Meta++ + + + 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 @@ + + + keys_de.qm + qt_de.qm + + 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 Binary files /dev/null and b/tests/auto/gui/kernel/qkeysequence/qt_de.qm 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 +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +#ifdef Q_WS_MAC +#include +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("modifiers"); + QTest::addColumn("keycode"); + QTest::addColumn("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("modifiers"); + QTest::addColumn("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("standardKey"); + QTest::addColumn("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 bindings = QKeySequence::keyBindings(QKeySequence::Copy); + QList 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("string"); + QTest::addColumn("key"); + QTest::addColumn("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("strSequence"); + QTest::addColumn("neutralString"); + QTest::addColumn("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("transKey"); + QTest::addColumn("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("keycode"); + QTest::addColumn("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 +#include +#include +#include +#include + + +#include +#include + +//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("buttonPressed"); + QTest::addColumn("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("buttonReleased"); + QTest::addColumn("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 +#include +#include + + +#include +#include +#include + +#include + + +//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 + +#include "qpalette.h" +#include + +//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("role"); + QTest::addColumn("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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 shortcuts; + QTextEdit *edit; + QString sbText; + Result ambigResult; +}; + +QT_BEGIN_NAMESPACE +template<> struct QMetaTypeId +{ enum { Defined = 1 }; static inline int qt_metatype_id() { return QMetaType::Int; } }; +template<> struct QMetaTypeId +{ enum { Defined = 1 }; static inline int qt_metatype_id() { return QMetaType::Int; } }; +template<> struct QMetaTypeId +{ 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(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(e); + if (ke->modifiers() && ke->key() > Qt::Key_Any + && ke->key() < Qt::Key_ydiaeresis) { + if (ke->modifiers() == Qt::ControlModifier) + insertPlainText(QString("").arg(char(ke->key()))); + else if (ke->modifiers() == Qt::AltModifier) + insertPlainText(QString("").arg(char(ke->key()))); + else if (ke->modifiers() == Qt::ShiftModifier) + insertPlainText(QString("").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("action"); + QTest::addColumn("testWidget"); + QTest::addColumn("txt"); + QTest::addColumn("k1"); + QTest::addColumn("c1"); + QTest::addColumn("k2"); + QTest::addColumn("c2"); + QTest::addColumn("k3"); + QTest::addColumn("c3"); + QTest::addColumn("k4"); + QTest::addColumn("c4"); + QTest::addColumn("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<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("")); + + sendKeyEvents(edit, Qt::Key_A, 'a'); // Send key to edit + QCOMPARE( currentResult, NoResult ); + QCOMPARE( ambigResult, NoResult ); + QVERIFY(edit->toPlainText().endsWith("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("")); + 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(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(k1), c, b1); + QTest::sendKeyEvent(QTest::Release, w, static_cast(k1), c, b1); + } + + if (k2 || c2.toAscii()) { + QString c(c2.unicode() == QChar::Null ? QString() : QString(c2)); + QTest::sendKeyEvent(QTest::Press, w, static_cast(k2), c, b2); + QTest::sendKeyEvent(QTest::Release, w, static_cast(k2), c, b2); + } + + if (k3 || c3.toAscii()) { + QString c(c3.unicode() == QChar::Null ? QString() : QString(c3)); + QTest::sendKeyEvent(QTest::Press, w, static_cast(k3), c, b3); + QTest::sendKeyEvent(QTest::Release, w, static_cast(k3), c, b3); + } + + if (k4 || c4.toAscii()) { + QString c(c4.unicode() == QChar::Null ? QString() : QString(c4)); + QTest::sendKeyEvent(QTest::Press, w, static_cast(k4), c, b4); + QTest::sendKeyEvent(QTest::Release, w, static_cast(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 +#include + +class tst_QTouchEventWidget : public QWidget +{ +public: + QList 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(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(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(event)->touchPoints(); + event->setAccepted(acceptTouchEnd); + if (deleteInTouchEnd) + delete this; + break; + default: + return QWidget::event(event); + } + return true; + } +}; + +class tst_QTouchEventGraphicsItem : public QGraphicsItem +{ +public: + QList 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(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(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(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 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() << 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 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() << 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 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() << 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() << 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 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() << 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() << 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() << 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() << 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() << 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() << 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 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 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 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 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 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 pl = leftWidget, pc = centerWidget, pr = rightWidget; + + QList 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 +#include +#include + +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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("factor"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("factor"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("factor"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("factor"); + QTest::addColumn("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("m1Values"); + QTest::addColumn("m2Values"); + QTest::addColumn("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("x"); + QTest::addColumn("y"); + QTest::addColumn("z"); + QTest::addColumn("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("x"); + QTest::addColumn("y"); + QTest::addColumn("z"); + QTest::addColumn("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("angle"); + QTest::addColumn("x"); + QTest::addColumn("y"); + QTest::addColumn("z"); + QTest::addColumn("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("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("mValues"); + QTest::addColumn("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(&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("x"); + QTest::addColumn("y"); + QTest::addColumn("width"); + QTest::addColumn("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("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(obj.property("matrix")); + QVERIFY(isSame(m2, uniqueValues4)); + + QMatrix4x4 m3(transposedValues4); + obj.setProperty("matrix", qVariantFromValue(m3)); + + m2 = qVariantValue(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() == 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 +#include +#include + +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("x"); + QTest::addColumn("y"); + QTest::addColumn("z"); + QTest::addColumn("w"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("w1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("w2"); + QTest::addColumn("x3"); + QTest::addColumn("y3"); + QTest::addColumn("z3"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("w1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("w1"); + QTest::addColumn("factor"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("angle1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("angle2"); + QTest::addColumn("t"); + QTest::addColumn("x3"); + QTest::addColumn("y3"); + QTest::addColumn("z3"); + QTest::addColumn("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(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(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() == 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 +#include +#include +#include +#include + +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("x"); + QTest::addColumn("y"); + QTest::addColumn("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("x"); + QTest::addColumn("y"); + QTest::addColumn("z"); + QTest::addColumn("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("x"); + QTest::addColumn("y"); + QTest::addColumn("z"); + QTest::addColumn("w"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("x3"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("x3"); + QTest::addColumn("y3"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("w1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("w2"); + QTest::addColumn("x3"); + QTest::addColumn("y3"); + QTest::addColumn("z3"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("x3"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("x3"); + QTest::addColumn("y3"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("w1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("w2"); + QTest::addColumn("x3"); + QTest::addColumn("y3"); + QTest::addColumn("z3"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("factor"); + QTest::addColumn("x2"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("factor"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("w1"); + QTest::addColumn("factor"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("x3"); + QTest::addColumn("y3"); + QTest::addColumn("z3"); + QTest::addColumn("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("x1"); // Point on plane + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("x2"); // Normal to plane + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("x3"); // Point to test for distance + QTest::addColumn("y3"); + QTest::addColumn("z3"); + QTest::addColumn("x4"); // Second point on plane + QTest::addColumn("y4"); + QTest::addColumn("z4"); + QTest::addColumn("x5"); // Third point on plane + QTest::addColumn("y5"); + QTest::addColumn("z5"); + QTest::addColumn("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("x1"); // Point on line + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("x2"); // Direction of the line + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("x3"); // Point to test for distance + QTest::addColumn("y3"); + QTest::addColumn("z3"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("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("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("w1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("w2"); + QTest::addColumn("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(obj.property("vector2D")); + QCOMPARE(v2.x(), (qreal)1.0f); + QCOMPARE(v2.y(), (qreal)2.0f); + + QVector3D v3 = qVariantValue(obj.property("vector3D")); + QCOMPARE(v3.x(), (qreal)3.0f); + QCOMPARE(v3.y(), (qreal)4.0f); + QCOMPARE(v3.z(), (qreal)5.0f); + + QVector4D v4 = qVariantValue(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(obj.property("vector2D")); + QCOMPARE(v2.x(), (qreal)-1.0f); + QCOMPARE(v2.y(), (qreal)-2.0f); + + v3 = qVariantValue(obj.property("vector3D")); + QCOMPARE(v3.x(), (qreal)-3.0f); + QCOMPARE(v3.y(), (qreal)-4.0f); + QCOMPARE(v3.z(), (qreal)-5.0f); + + v4 = qVariantValue(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() == QMetaType::QVector2D); + QVERIFY(qMetaTypeId() == QMetaType::QVector3D); + QVERIFY(qMetaTypeId() == 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 + +#include "qbrush.h" +#include +#include + +#include + +//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("brush1"); + QTest::addColumn("brush2"); + QTest::addColumn("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("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 + +#include + +#include +#include + +//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("color"); + QTest::addColumn("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("color"); + QTest::addColumn("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("color"); + QTest::addColumn("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("expectedColor"); + QTest::addColumn("hsvColor"); + QTest::addColumn("cmykColor"); + QTest::addColumn("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("expectedColor"); + QTest::addColumn("rgbColor"); + QTest::addColumn("cmykColor"); + QTest::addColumn("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("expectedColor"); + QTest::addColumn("rgbColor"); + QTest::addColumn("hsvColor"); + QTest::addColumn("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("expectedColor"); + QTest::addColumn("hsvColor"); + QTest::addColumn("rgbColor"); + QTest::addColumn("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("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 + +#include +#include +#include +#include + +//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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.png 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 Binary files /dev/null and b/tests/auto/gui/painting/qpainter/task217400.png 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 +#include "../../../../shared/util.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) +#include +#include +#endif +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#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("dest"); + QTest::addColumn("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 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("font"); + QTest::addColumn("pen"); + QTest::addColumn("brush"); + QTest::addColumn("backgroundColor"); + QTest::addColumn("backgroundMode"); + QTest::addColumn("brushOrigin"); + QTest::addColumn("clipRegion"); + QTest::addColumn("window"); + QTest::addColumn("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("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(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(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(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("path"); + QTest::addColumn("expectedBounds"); + QTest::addColumn("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("size"); + QTest::addColumn("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("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("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("rect"); + QTest::addColumn("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 +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(img); + testClipping(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("deviceSize"); + QTest::addColumn("region"); + + QTest::newRow("empty") << QSize(100, 100) << QRegion(); + QTest::newRow("simple rect") << QSize(100, 100) + << QRegion(QRect(5, 5, 10, 10)); + + QVector 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("imageSize"); + QTest::addColumn("path"); + QTest::addColumn("clipRect"); + QTest::addColumn("brush"); + QTest::addColumn("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("imageSize"); + QTest::addColumn("line"); + QTest::addColumn("clipRect"); + QTest::addColumn("pen"); + + QPen pen2(QColor(223, 223, 0, 223)); + pen2.setWidth(2); + + QVector 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("destFormat"); + QTest::addColumn("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 opacities = (QList() << 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 opacities = (QList() << 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 + +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("transform"); + QTest::addColumn("line"); + QTest::addColumn("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("format"); + QTest::addColumn("width"); + QTest::addColumn("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("width"); + QTest::addColumn("height"); + QTest::addColumn("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 discovered; + discovered.enqueue(QPoint(x, y)); + + QVector 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("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("x"); + QTest::addColumn("y"); + QTest::addColumn("w"); + QTest::addColumn("h"); + QTest::addColumn("srcFormat"); + QTest::addColumn("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("sourceFormat"); + QTest::addColumn("destFormat"); + QTest::addColumn("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("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(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(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 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 +#include +#include +#include + +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 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 + +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +//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("path"); + QTest::addColumn("pt"); + QTest::addColumn("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("path"); + QTest::addColumn("rect"); + QTest::addColumn("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("path"); + QTest::addColumn("rect"); + QTest::addColumn("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("path"); + QTest::addColumn("candidate"); + QTest::addColumn("contained"); + QTest::addColumn("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("path"); + QTest::addColumn("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("path"); + QTest::addColumn("pen"); + QTest::addColumn("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("rect"); + QTest::addColumn("angle"); + + QList 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("test"); + QTest::addColumn("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("path"); + QTest::addColumn("start"); + QTest::addColumn("middle"); + QTest::addColumn("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("path"); + QTest::addColumn("percent"); + QTest::addColumn("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("path"); + QTest::addColumn("point"); + QTest::addColumn("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 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 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 + +#include +#include + +#define _USE_MATH_DEFINES +#include + +//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 + +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 + +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 + +#include +#include +#include +#include + +#include + +class tst_QPathClipper : public QObject +{ + Q_OBJECT + +public: + tst_QPathClipper(); + virtual ~tst_QPathClipper(); + +private: + void clipTest(int subjectIndex, int clipIndex, QPathClipper::Operation op); + + QList 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("subject"); + QTest::addColumn("clip"); + QTest::addColumn("op"); + QTest::addColumn("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("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 + +#include "qpen.h" +#include "qbrush.h" + +#include + +//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("pen1"); + QTest::addColumn("pen2"); + QTest::addColumn("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("pen"); + QTest::addColumn("brush"); + QTest::addColumn("width"); + QTest::addColumn("style"); + QTest::addColumn("capStyle"); + QTest::addColumn("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("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 + +#include +#include +#include + +#include +#include + + + +//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(0,0) << QPoint(10,10) << QPoint(-10,10)); + QPolygon p2(QVector() << 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef Q_WS_WIN +#include +#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("orientation"); + QTest::addColumn("withPainter"); + QTest::addColumn("resolution"); + QTest::addColumn("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("orientation"); + QTest::addColumn("fullpage"); + QTest::addColumn("pagesize"); + QTest::addColumn("width"); + QTest::addColumn("height"); + QTest::addColumn("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("resolution"); + QTest::addColumn("pageSize"); + QTest::addColumn("widthMMAfter"); + QTest::addColumn("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("left"); + QTest::addColumn("top"); + QTest::addColumn("right"); + QTest::addColumn("bottom"); + QTest::addColumn("unit"); + + QTest::newRow("data0") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Millimeter); + QTest::newRow("data1") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Point); + QTest::newRow("data2") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Inch); + QTest::newRow("data3") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Pica); + QTest::newRow("data4") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Didot); + QTest::newRow("data5") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(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(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 ø 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 ø 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 +#include +#include +#include + +#ifndef QT_NO_PRINTER +#include + +#ifdef Q_OS_UNIX +# include +# include +# include +#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 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 printers = QPrinterInfo::availablePrinters(); + + QCOMPARE(printers.size(), sysPrinters.size()); + + QHash 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 > hardSizes; + hardSizes + << QList() + << QList() + ; + 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 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 sizes = printers[i].supportedPaperSizes(); + qSort(sizes); + qSort(hardSizes[j]); + QCOMPARE(sizes, hardSizes[j]); + } + } + } +} + +void tst_QPrinterInfo::testConstructors() +{ + QList prns(QPrinterInfo::availablePrinters()); + + for (int c = 0; c < prns.size(); ++c) { + QList list1, list2; + list1 = prns[c].supportedPaperSizes(); + QPrinter pr(prns[c]); + list2 = QPrinterInfo(pr).supportedPaperSizes(); + QCOMPARE(list2, list1); + } +} + +void tst_QPrinterInfo::testAssignment() +{ + QList 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 +#include + +#include +#include +#include +#ifdef Q_WS_X11 +#include +#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) +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("pa"); + QTest::addColumn("isEmpty"); + QTest::addColumn("numRects"); + QTest::addColumn >("rects"); + + QPolygon pa; + + + QTest::newRow("no points") << pa << true << 0 << QVector(); + pa = QPolygon() << QPoint(10,10); + QTest::newRow("one point") << pa << true << 0 << QVector(); + pa = QPolygon() << QPoint(10,10) << QPoint(10,20); + QTest::newRow("two points, horizontal") << pa << true << 0 << QVector(); + + pa = QPolygon() << QPoint(10,10) << QPoint(20,10); + QTest::newRow("two points, vertical") << pa << true << 0 << QVector(); + + pa = QPolygon() << QPoint(10,10) << QPoint(20,20); + QTest::newRow("two points, diagonal") << pa << true << 0 << QVector(); + + pa = QPolygon() << QPoint(10,10) << QPoint(15,15) << QPoint(10,15) << QPoint(10, 10) ; + QVector 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("r1"); + QTest::addColumn("r2"); + QTest::addColumn("intersects"); + // QTest::addColumn("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("r1"); + QTest::addColumn("r2"); + QTest::addColumn("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("region"); + QTest::addColumn("rect"); + QTest::addColumn("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("r1"); + QTest::addColumn("r2"); + QTest::addColumn("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 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("dest"); + QTest::addColumn("subtract"); + QTest::addColumn("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 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("r1"); + QTest::addColumn("r2"); + QTest::addColumn("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 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("dest"); + QTest::addColumn("arg"); + QTest::addColumn("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 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("region"); + QTest::addColumn("expected"); + + QTest::newRow("empty") << QRegion() << 0; + QTest::newRow("rect") << QRegion(10, 10, 10, 10) << 1; + + QRegion dest; + QVector 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("region"); + + QTest::newRow("QRegion") << QRegion(); + + QVector 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(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("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 ®ion); +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 +#include "qtransform.h" +#include +#include +#include + +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("matrix"); + QTest::addColumn("src"); + QTest::addColumn("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("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 +#include +#include +#include + +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("matrix"); + QTest::addColumn("src"); + QTest::addColumn("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 + +#include +#include +#include +#include +#include + +//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(var1), obj1.paintDevice()); + obj1.setPaintDevice((QPaintDevice *)0); + QCOMPARE(static_cast(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 +#include +#if defined(Q_OS_WINCE) +#include +#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("input"); + QTest::addColumn("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 &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 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("parseSuccess"); + QTest::addColumn("css"); + QTest::addColumn("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) + +void tst_QCssParser::expr_data() +{ + QTest::addColumn("parseSuccess"); + QTest::addColumn("css"); + QTest::addColumn >("expectedValues"); + + QVector 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, expectedValues); + + QCss::Parser parser(css); + QVector 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("css"); + QTest::addColumn("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("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("css"); + QTest::addColumn("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(node.ptr)->tagName()); } + virtual QString attribute(NodePtr node, const QString &name) const { return reinterpret_cast(node.ptr)->attribute(name); } + virtual bool hasAttribute(NodePtr node, const QString &name) const { return reinterpret_cast(node.ptr)->hasAttribute(name); } + virtual bool hasAttributes(NodePtr node) const { return reinterpret_cast(node.ptr)->hasAttributes(); } + + virtual bool isNullNode(NodePtr node) const { + return reinterpret_cast(node.ptr)->isNull(); + } + virtual NodePtr parentNode(NodePtr node) const { + NodePtr parent; + parent.ptr = new QDomElement(reinterpret_cast(node.ptr)->parentNode().toElement()); + return parent; + } + virtual NodePtr duplicateNode(NodePtr node) const { + NodePtr n; + n.ptr = new QDomElement(*reinterpret_cast(node.ptr)); + return n; + } + virtual NodePtr previousSiblingNode(NodePtr node) const { + NodePtr sibling; + sibling.ptr = new QDomElement(reinterpret_cast(node.ptr)->previousSiblingElement()); + return sibling; + } + virtual void freeNode(NodePtr node) const { + delete reinterpret_cast(node.ptr); + } + +private: + QDomDocument doc; +}; + +Q_DECLARE_METATYPE(QDomDocument) + +void tst_QCssParser::marginValue_data() +{ + QTest::addColumn("css"); + QTest::addColumn("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(" "))); + + 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 rules = testSelector.styleRulesForNode(n); + QVector 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("match"); + QTest::addColumn("selector"); + QTest::addColumn("xml"); + QTest::addColumn("elementToCheck"); + + QTest::newRow("plain") << true << QString("p") << QString("

") << QString(); + QTest::newRow("noplain") << false << QString("bar") << QString("

") << QString(); + + QTest::newRow("class") << true << QString(".foo") << QString("

") << QString(); + QTest::newRow("noclass") << false << QString(".bar") << QString("

") << QString(); + + QTest::newRow("attrset") << true << QString("[justset]") << QString("

") << QString(); + QTest::newRow("notattrset") << false << QString("[justset]") << QString("

") << QString(); + + QTest::newRow("attrmatch") << true << QString("[foo=bar]") << QString("

") << QString(); + QTest::newRow("noattrmatch") << false << QString("[foo=bar]") << QString("

") << QString(); + + QTest::newRow("contains") << true << QString("[foo~=bar]") << QString("

") << QString(); + QTest::newRow("notcontains") << false << QString("[foo~=bar]") << QString("

") << QString(); + + QTest::newRow("beingswith") << true << QString("[foo|=bar]") << QString("

") << QString(); + QTest::newRow("notbeingswith") << false << QString("[foo|=bar]") << QString("

") << QString(); + + QTest::newRow("attr2") << true << QString("[bar=foo]") << QString("

") << QString(); + + QTest::newRow("universal1") << true << QString("*") << QString("

") << QString(); + + QTest::newRow("universal3") << false << QString("*[foo=bar]") << QString("

") << QString(); + QTest::newRow("universal4") << true << QString("*[foo=bar]") << QString("

") << QString(); + + QTest::newRow("universal5") << false << QString("[foo=bar]") << QString("

") << QString(); + QTest::newRow("universal6") << true << QString("[foo=bar]") << QString("

") << QString(); + + QTest::newRow("universal7") << true << QString(".charfmt1") << QString("

") << QString(); + + QTest::newRow("id") << true << QString("#blub") << QString("

") << QString(); + QTest::newRow("noid") << false << QString("#blub") << QString("

") << QString(); + + QTest::newRow("childselector") << true << QString("parent > child") + << QString("") + << QString("parent/child"); + + QTest::newRow("nochildselector2") << false << QString("parent > child") + << QString("") + << QString("child/parent"); + + QTest::newRow("nochildselector3") << false << QString("parent > child") + << QString("") + << QString("parent/intermediate/child"); + + QTest::newRow("childselector2") << true << QString("parent[foo=bar] > child") + << QString("") + << QString("parent/child"); + + QTest::newRow("nochildselector4") << false << QString("parent[foo=bar] > child") + << QString("") + << QString("parent/child"); + + QTest::newRow("nochildselector5") << false << QString("parent[foo=bar] > child") + << QString("") + << QString("parent/parent/child"); + + QTest::newRow("childselectors") << true << QString("grandparent > parent > child") + << QString("") + << QString("grandparent/parent/child"); + + QTest::newRow("descendant") << true << QString("grandparent child") + << QString("") + << QString("grandparent/parent/child"); + + QTest::newRow("nodescendant") << false << QString("grandparent child") + << QString("") + << QString("other/parent/child"); + + QTest::newRow("descendant2") << true << QString("grandgrandparent grandparent child") + << QString("") + << QString("grandgrandparent/inbetween/grandparent/parent/child"); + + QTest::newRow("combined") << true << QString("grandparent parent > child") + << QString("") + << QString("grandparent/inbetween/parent/child"); + + QTest::newRow("combined2") << true << QString("grandparent > parent child") + << QString("") + << QString("grandparent/parent/inbetween/child"); + + QTest::newRow("combined3") << true << QString("grandparent > parent child") + << QString("") + << QString("grandparent/parent/inbetween/child"); + + QTest::newRow("nocombined") << false << QString("grandparent parent > child") + << QString("") + << QString("inbetween/parent/child"); + + QTest::newRow("nocombined2") << false << QString("grandparent parent > child") + << QString("") + << QString("parent/child"); + + QTest::newRow("previoussibling") << true << QString("p1 + p2") + << QString("") + << QString("p2"); + + QTest::newRow("noprevioussibling") << false << QString("p2 + p1") + << QString("") + << QString("p2"); + + QTest::newRow("ancestry_firstmismatch") << false << QString("parent child[foo=bar]") + << QString("") + << QString("parent/child"); + + QTest::newRow("unknown-pseudo") << false << QString("p:enabled:foobar") << QString("

") << 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(""); + xml.append(""); + 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 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("selector"); + QTest::addColumn("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("firstSelector"); + QTest::addColumn("secondSelector"); + QTest::addColumn("xml"); + + QTest::newRow("universal1") << QString("*") << QString("p") << QString("

"); + QTest::newRow("attr") << QString("p") << QString("p[foo=bar]") << QString("

"); + QTest::newRow("id") << QString("p") << QString("#hey") << QString("

"); + QTest::newRow("id2") << QString("[id=hey]") << QString("#hey") << QString("

"); + QTest::newRow("class") << QString("p") << QString(".hey") << QString("

"); +} + +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(""); + xml.append(""); + 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 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("xml"); + QTest::addColumn("css"); + QTest::addColumn("pseudoClass"); + QTest::addColumn("declCount"); + QTest::addColumn("value0"); + QTest::addColumn("value1"); + + QTest::newRow("universal1") << QString("

") << QString("* { color: red }") + << (quint64)QCss::PseudoClass_Unspecified << 1 << "red" << ""; + + QTest::newRow("basic") << QString("

") << QString("p:enabled { color: red; bg:blue; }") + << (quint64)QCss::PseudoClass_Enabled << 2 << "red" << "blue"; + + QTest::newRow("single") << QString("

") + << QString("p:enabled { color: red; } *:hover { color: white }") + << (quint64)QCss::PseudoClass_Hover << 1 << "white" << ""; + + QTest::newRow("multisel") << QString("

") + << QString("p:enabled { color: red; } p:hover { color: gray } *:hover { color: white } ") + << (quint64)QCss::PseudoClass_Hover << 2 << "white" << "gray"; + + QTest::newRow("multisel2") << QString("

") + << 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("

") + << QString("p:enabled { color: red; } p:hover:focus { color: gray } *:hover { color: white } ") + << quint64(QCss::PseudoClass_Hover) << 1 << "white" << ""; + + QTest::newRow("!-1") << QString("

") + << 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("

") + << 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("

") + << 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(""); + xml.append(""); + 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 rules = testSelector.styleRulesForNode(n); + + QVector 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("css"); + QTest::addColumn("expectedBrush"); + QTest::addColumn("expectedImage"); + QTest::addColumn("expectedRepeatValue"); + QTest::addColumn("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(" "))); + + 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 rules = testSelector.styleRulesForNode(n); + QVector 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("css"); + QTest::addColumn("pseudoElement"); + QTest::addColumn("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(" "))); + + 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 rules = testSelector.styleRulesForNode(n); + QVector 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("css"); + QTest::addColumn("type"); + QTest::addColumn("start"); + QTest::addColumn("finalStop"); + QTest::addColumn("spread"); + QTest::addColumn("stop0"); + QTest::addColumn("color0"); + QTest::addColumn("stop1"); + QTest::addColumn("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(" "))); + + 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 rules = testSelector.styleRulesForNode(n); + QVector 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(sbg.gradient()); + QCOMPARE(lg->start(), start); + QCOMPARE(lg->finalStop(), finalStop); + } else if (type == "conical") { + QVERIFY(sbg.style() == Qt::ConicalGradientPattern); + const QConicalGradient *cg = static_cast(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("css"); + QTest::addColumn("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 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("css"); + QTest::addColumn("expectedTopWidth"); + QTest::addColumn("expectedTopStyle"); + QTest::addColumn("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 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 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 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 + + +#include +#include +#include +#include +#include +#include +#include + +//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 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 sizes = fdb.pointSizes(family, style); + QVERIFY(!sizes.isEmpty()); + QList::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 Binary files /dev/null and b/tests/auto/gui/text/qfontdatabase/FreeMono.ttf 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 + + +#include + +#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("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("font"); + QTest::addColumn("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("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("font"); + QTest::addColumn("pixelSize"); + QTest::addColumn("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("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 @@ + + + ucs4font.ttf + + 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 +#include +#include +#include +#include +#include + + + +//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 sizes = fdb.pointSizes(family, style); + QVERIFY(!sizes.isEmpty()); + QList::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("font"); + QTest::addColumn("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 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(); +} + +void tst_QFontMetrics::elidedMultiLengthF() +{ + elidedMultiLength_helper(); +} + +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 Binary files /dev/null and b/tests/auto/gui/text/qfontmetrics/ucs4font.ttf 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 Binary files /dev/null and b/tests/auto/gui/text/qglyphrun/test.ttf 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 + +#include +#include +#include +#include + +// #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 glyphIndexes; + QVector 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 glyphIndexes; + QVector 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("one"); + QTest::addColumn("two"); + QTest::addColumn("equals"); + + QGlyphRun one(make_dummy_indexes()); + QGlyphRun two(make_dummy_indexes()); + + QTest::newRow("Identical") << one << two << true; + + { + QGlyphRun busted(two); + + QVector 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 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 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() << 2 << 2 << 2); + glyphRun.setPositions(QVector() << 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 glyphIndexArray; + glyphIndexArray << 3 << 2 << 1 << 4; + + QVector glyphPositionArray; + glyphPositionArray << QPointF(1, 2) << QPointF(3, 4) << QPointF(5, 6) << QPointF(7, 8); + + QGlyphRun glyphRun; + glyphRun.setRawData(glyphIndexArray.constData(), glyphPositionArray.constData(), 4); + + QVector glyphIndexes = glyphRun.glyphIndexes(); + QVector 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 glyphIndexes; + glyphIndexes.append(3); + + QVector 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 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 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() << 1 << 2 << 3); + + QGlyphRun otherGlyphs; + otherGlyphs = glyphs; + + QCOMPARE(otherGlyphs.glyphIndexes(), glyphs.glyphIndexes()); + + otherGlyphs.setGlyphIndexes(QVector() << 4 << 5 << 6); + + QCOMPARE(otherGlyphs.glyphIndexes(), QVector() << 4 << 5 << 6); + QCOMPARE(glyphs.glyphIndexes(), QVector() << 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 Binary files /dev/null and b/tests/auto/gui/text/qrawfont/testfont.ttf 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 Binary files /dev/null and b/tests/auto/gui/text/qrawfont/testfont_bold_italic.ttf 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 + +#include +#include + +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("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("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("fileName"); + QTest::addColumn("expectedFamilyName"); + QTest::addColumn("style"); + QTest::addColumn("weight"); + QTest::addColumn("hintingPreference"); + QTest::addColumn("unitsPerEm"); + QTest::addColumn("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 glyphIndices = font.glyphIndexesForString(QLatin1String("Foobar")); + QVector expectedGlyphIndices; + expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; + + QCOMPARE(glyphIndices, expectedGlyphIndices); +} + +void tst_QRawFont::advances_data() +{ + QTest::addColumn("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 glyphIndices; + glyphIndices << 44 << 83 << 83 << 70 << 69 << 86; // "Foobar" + + bool supportsSubPixelPositions = font_d->fontEngine->supportsSubPixelPositions(); + QVector advances = font.advancesForGlyphIndexes(glyphIndices); + for (int i=0; i 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 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 expectedGlyphIndices; + expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; + + QCOMPARE(glyphs.glyphIndexes(), expectedGlyphIndices); + + QVERIFY(fontDatabase.removeApplicationFont(id)); +} + +void tst_QRawFont::fontTable_data() +{ + QTest::addColumn("tagName"); + QTest::addColumn("hintingPreference"); + QTest::addColumn("offset"); + QTest::addColumn("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(table.constData() + offset); + QCOMPARE(*value, expectedValue); +} + +typedef QList WritingSystemList; +Q_DECLARE_METATYPE(WritingSystemList) + +void tst_QRawFont::supportedWritingSystems_data() +{ + QTest::addColumn("fileName"); + QTest::addColumn("writingSystems"); + QTest::addColumn("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::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::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("fileName"); + QTest::addColumn("hintingPreference"); + QTest::addColumn("character"); + QTest::addColumn("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("fileName"); + QTest::addColumn("hintingPreference"); + QTest::addColumn("ucs4"); + QTest::addColumn("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("fileName"); + QTest::addColumn("hintingPreference"); + QTest::addColumn("familyName"); + QTest::addColumn("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("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("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("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 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("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 +#include +#include +#include + +#include +#include + +#include +#include + +// #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(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("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("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("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("FOObar"); + 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; xXXXXX"); + staticText.setTextFormat(Qt::RichText); + p.drawStaticText(0, 0, staticText); + } + + QImage img = image.toImage(); + for (int x=0; xXXXXX"); + staticText.setTextFormat(Qt::RichText); + p.drawStaticText(0, 0, staticText); + } + + QImage img = image.toImage(); + for (int x=0; xitemCount, 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("AB"); + 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 +#include +#include +#include +#include +#include + +//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 &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 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 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 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 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 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 + + +#define protected public +#include +#undef protected +#include +#ifndef Q_WS_WIN +#include +#endif + + + +#include +#include + + +//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) 'helloworld' + * 2) '' + * (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 + + +#include +#include +#include +#include +#include +#include +#include +#include + +//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) + +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("sl"); + QTest::addColumn >("movement"); + QTest::addColumn("finalPos"); + + QTest::newRow("startBlock1") << QStringList("Happy happy happy joy joy joy") + << (QList() << QVariant(QTextCursor::StartOfBlock)) << 0; + QTest::newRow("endBlock1") << QStringList("Happy happy happy joy joy joy") + << (QList() << QVariant(QTextCursor::StartOfBlock) + << QVariant(QTextCursor::EndOfBlock)) << 29; + QTest::newRow("startBlock2") << QStringList("Happy happy happy joy joy joy") + << (QList() << QVariant(QTextCursor::StartOfBlock) + << QVariant(QTextCursor::EndOfBlock) + << QVariant(QTextCursor::StartOfBlock)) << 0; + QTest::newRow("endBlock2") << QStringList("Happy happy happy joy joy joy") + << (QList() << 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(QTextCursor::StartOfBlock)) + << 18; + QTest::newRow("multiBlock2") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::StartOfBlock) + << QVariant(QTextCursor::EndOfBlock)) + << 29; + QTest::newRow("multiBlock3") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::StartOfBlock) + << QVariant(QTextCursor::StartOfBlock)) + << 18; + QTest::newRow("multiBlock4") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::Start) + << QVariant(QTextCursor::EndOfBlock)) + << 17; + QTest::newRow("multiBlock5") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::Start) + << QVariant(QTextCursor::EndOfBlock) + << QVariant(QTextCursor::EndOfBlock)) + << 17; + QTest::newRow("multiBlock6") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::End) + << QVariant(QTextCursor::StartOfBlock)) + << 18; + QTest::newRow("multiBlock7") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousBlock)) + << 0; + QTest::newRow("multiBlock8") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousBlock) + << QVariant(QTextCursor::EndOfBlock)) + << 17; + QTest::newRow("multiBlock9") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousBlock) + << QVariant(QTextCursor::NextBlock)) + << 18; + QTest::newRow("multiBlock10") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousBlock) + << QVariant(QTextCursor::NextBlock) + << QVariant(QTextCursor::NextBlock)) + << 18; + QTest::newRow("multiBlock11") << (QStringList() << QString("Happy happy happy") + << QString("Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousBlock) + << QVariant(QTextCursor::NextBlock) + << QVariant(QTextCursor::EndOfBlock)) + << 29; + QTest::newRow("PreviousWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousWord)) + << 26; + QTest::newRow("PreviousWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousWord) + << QVariant(QTextCursor::PreviousWord)) + << 22; + QTest::newRow("EndWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousWord) + << QVariant(QTextCursor::PreviousWord) + << QVariant(QTextCursor::EndOfWord)) + << 25; + QTest::newRow("NextWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousWord) + << QVariant(QTextCursor::PreviousWord) + << QVariant(QTextCursor::NextWord)) + << 26; + QTest::newRow("NextWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::Start) + << QVariant(QTextCursor::NextWord) + << QVariant(QTextCursor::EndOfWord)) + << 11; + QTest::newRow("StartWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousWord) + << QVariant(QTextCursor::PreviousWord) + << QVariant(QTextCursor::StartOfWord)) + << 22; + QTest::newRow("StartWord3") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) + << (QList() << QVariant(QTextCursor::Start) + << QVariant(QTextCursor::NextWord) + << QVariant(QTextCursor::EndOfWord) + << QVariant(QTextCursor::StartOfWord)) + << 6; + + QTest::newRow("PreviousCharacter") << (QStringList() << QString("Happy happy Joy Joy")) + << (QList() << QVariant(QTextCursor::PreviousCharacter) + << QVariant(QTextCursor::PreviousCharacter)) + << 17; +} + +void tst_QTextCursor::navigation2() +{ + QFETCH(QStringList, sl); + QFETCH(QList, 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("

just a simple paragraph.

" + "" + "" + "" + "" + "
Cell number 1another cellprevious
is
empty
row 2foo barlast cell
row 3a
clear(); + doc->setHtml("tr>
ab
c
"); + 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 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 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("text"); + QTest::addColumn("initialPosition"); + QTest::addColumn("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("text"); + QTest::addColumn("position"); + QTest::addColumn("anchor"); + QTest::addColumn("modifyPosition"); + QTest::addColumn("modifyAnchor"); + QTest::addColumn("insertText"); + QTest::addColumn("expectedPosition"); + QTest::addColumn("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("input"); + QTest::addColumn("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 +#include + +#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 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 + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 var1 = new MyAbstractTextDocumentLayout(0); + obj1.setDocumentLayout(var1); + QCOMPARE(static_cast(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("\n" + "" + "\n"); + htmlHead = htmlHead.arg(defaultFont.family()).arg(defaultFont.pointSizeF()).arg(defaultFont.weight() * 8).arg((defaultFont.italic() ? "italic" : "normal")); + + htmlTail = QString(""); +} + +void tst_QTextDocument::cleanup() +{ + cursor = QTextCursor(); + delete doc; + doc = 0; +} + +void tst_QTextDocument::isEmpty() +{ + QVERIFY(doc->isEmpty()); +} + +void tst_QTextDocument::find_data() +{ + QTest::addColumn("haystack"); + QTest::addColumn("needle"); + QTest::addColumn("flags"); + QTest::addColumn("from"); + QTest::addColumn("anchor"); + QTest::addColumn("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("haystack"); + QTest::addColumn("needle"); + QTest::addColumn("flags"); + QTest::addColumn("from"); + QTest::addColumn("anchor"); + QTest::addColumn("position"); + + // match integers 0 to 99 + QTest::newRow("1") << "23" << "^\\d\\d?$" << int(QTextDocument::FindCaseSensitively) << 0 << 0 << 2; + // match ampersands but not & + QTest::newRow("2") << "His & 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("Foobar Foobar Foobar Foobar"); + + 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;lineIdxlineCount();++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("stylesheet"); + QTest::addColumn("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("" + "" + "
" + "Foobar" + "
" + "" + "").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[] = "\n" + "\n" + ""; + QVERIFY(Qt::mightBeRichText(QString::fromLatin1(qtDocuHeader))); + QTest::addColumn("input"); + QTest::addColumn("result"); + + QTest::newRow("documentation-header") << QString("\n" + "\n" + "") + << true; + QTest::newRow("br-nospace") << QString("Test
new line") << true; + QTest::newRow("br-space") << QString("Test
new line") << true; + QTest::newRow("br-invalidspace") << QString("Test
new line") << false; + QTest::newRow("invalid closing tag") << QString("Test
("input"); + QTest::addColumn("expectedOutput"); + + { + CREATE_DOC_AND_CURSOR(); + + cursor.insertText("Blah"); + + QTest::newRow("simple") << QTextDocumentFragment(&doc) << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + cursor.insertText("&<>"); + + QTest::newRow("entities") << QTextDocumentFragment(&doc) << QString("

&<>

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setFontFamily("Times"); + cursor.insertText("Blah", fmt); + + QTest::newRow("font-family") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setFontFamily("Foo's Family"); + cursor.insertText("Blah", fmt); + + QTest::newRow("font-family-with-quotes1") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setFontFamily("Foo\"s Family"); + cursor.insertText("Blah", fmt); + + QTest::newRow("font-family-with-quotes2") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextBlockFormat fmt; + fmt.setNonBreakableLines(true); + cursor.insertBlock(fmt); + cursor.insertText("Blah"); + + QTest::newRow("pre") << QTextDocumentFragment(&doc) + << + QString("EMPTYBLOCK") + + QString("
Blah
"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setFontPointSize(40); + cursor.insertText("Blah", fmt); + + QTest::newRow("font-size") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setProperty(QTextFormat::FontSizeIncrement, 2); + cursor.insertText("Blah", fmt); + + QTest::newRow("logical-font-size") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + 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("

Foo

\n

Blub

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextBlockFormat fmt; + fmt.setLayoutDirection(Qt::RightToLeft); + cursor.insertBlock(fmt); + cursor.insertText("Blah"); + + QTest::newRow("rtl") << QTextDocumentFragment(&doc) + << + QString("EMPTYBLOCK") + + QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextBlockFormat fmt; + fmt.setAlignment(Qt::AlignJustify); + cursor.insertBlock(fmt); + cursor.insertText("Blah"); + + QTest::newRow("blockalign") << QTextDocumentFragment(&doc) + << + QString("EMPTYBLOCK") + + QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextBlockFormat fmt; + fmt.setAlignment(Qt::AlignCenter); + cursor.insertBlock(fmt); + cursor.insertText("Blah"); + + QTest::newRow("blockalign2") << QTextDocumentFragment(&doc) + << + QString("EMPTYBLOCK") + + QString("

Blah

"); + } + + { + 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("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextBlockFormat fmt; + fmt.setBackground(QColor("#0000ff")); + cursor.insertBlock(fmt); + cursor.insertText("Blah"); + + QTest::newRow("bgcolor") << QTextDocumentFragment(&doc) + << QString("EMPTYBLOCK") + + QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setFontWeight(40); + cursor.insertText("Blah", fmt); + + QTest::newRow("font-weight") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setFontItalic(true); + cursor.insertText("Blah", fmt); + + QTest::newRow("font-italic") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setFontUnderline(true); + fmt.setFontOverline(false); + cursor.insertText("Blah", fmt); + + QTest::newRow("text-decoration-1") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setForeground(QColor("#00ff00")); + cursor.insertText("Blah", fmt); + + QTest::newRow("color") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setBackground(QColor("#00ff00")); + cursor.insertText("Blah", fmt); + + QTest::newRow("span-bgcolor") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setVerticalAlignment(QTextCharFormat::AlignSubScript); + cursor.insertText("Blah", fmt); + + QTest::newRow("valign-sub") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setVerticalAlignment(QTextCharFormat::AlignSuperScript); + cursor.insertText("Blah", fmt); + + QTest::newRow("valign-super") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextCharFormat fmt; + fmt.setAnchor(true); + fmt.setAnchorName("blub"); + cursor.insertText("Blah", fmt); + + QTest::newRow("named anchor") << QTextDocumentFragment(&doc) + << QString("

Blah

"); + } + + { + 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("

Blah

"); + } + + { + 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("

Blah

"); + } + + { + 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("

Blah

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + cursor.insertTable(2, 2); + + QTest::newRow("simpletable") << QTextDocumentFragment(&doc) + << QString("" + "\n\n\n" + "\n\n\n" + "
"); + } + + { + 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("" + "\n\n\n" + "
"); + } + + { + 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("" + "\n\n\n" + "\n\n\n" + "
"); + } + + { + 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("" + "\n\n\n" + "\n\n\n" + "
"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextTableFormat fmt; + fmt.setHeaderRowCount(2); + cursor.insertTable(4, 2, fmt); + + QTest::newRow("tableheader") << QTextDocumentFragment(&doc) + << QString("" + "\n\n\n" + "\n\n\n" + "\n\n\n" + "\n\n\n" + "
"); + } + + { + 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("" + "\n\n\n" + "\n\n\n" + "
\n\n\n
\n

Hey

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextTableFormat fmt; + QVector 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("" + "\n\n\n\n" + "
"); + } + + // ### 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("" + "\n\n" + "
"); + } + + { + CREATE_DOC_AND_CURSOR(); + + // ### fixme: use programmatic api as soon as we can create floats through it + const char html[] = "BlahBlubb"; + + QTest::newRow("image") << QTextDocumentFragment::fromHtml(QString::fromLatin1(html)) + << QString("

BlahBlubb

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextImageFormat fmt; + fmt.setName("foo"); + fmt.setVerticalAlignment(QTextCharFormat::AlignMiddle); + cursor.insertImage(fmt); + + QTest::newRow("image-malign") << QTextDocumentFragment(&doc) + << QString("

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextImageFormat fmt; + fmt.setName("foo"); + fmt.setVerticalAlignment(QTextCharFormat::AlignTop); + cursor.insertImage(fmt); + + QTest::newRow("image-malign") << QTextDocumentFragment(&doc) + << QString("

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextImageFormat fmt; + fmt.setName("foo"); + cursor.insertImage(fmt); + cursor.insertImage(fmt); + + QTest::newRow("2images") << QTextDocumentFragment(&doc) + << QString("

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QString txt = QLatin1String("Blah"); + txt += QChar::LineSeparator; + txt += QLatin1String("Bar"); + cursor.insertText(txt); + + QTest::newRow("linebreaks") << QTextDocumentFragment(&doc) + << QString("

Blah
Bar

"); + } + + { + 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("

Blah

"); + } + + { + 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("
  • Blubb
  • \n
  • Blah
"); + } + + { + 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("
  • Blubb
  • \n
  • Blah
"); + } + + { + 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("

Test

"); + } + + { + 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("
  • Blah
"); + } + + { + 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

Test

"); + } + + { + 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("

Test

"); + } + + { + QTest::newRow("horizontal-ruler") << QTextDocumentFragment::fromHtml("
") + << + QString("EMPTYBLOCK") + + QString("
"); + } + { + QTest::newRow("horizontal-ruler-with-width") << QTextDocumentFragment::fromHtml("
") + << + QString("EMPTYBLOCK") + + QString("
"); + } + { + 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("\n\n
\n

Hello World

"); + } + + { + 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("

Test

"); + QTest::newRow("nostylebrush") << QTextDocumentFragment(&doc) << QString("

Test

"); + } + + { + CREATE_DOC_AND_CURSOR(); + + QTextTable *table = cursor.insertTable(2, 2); + table->mergeCells(0, 0, 1, 2); + QTextTableFormat fmt = table->format(); + QVector 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("" + "\n\n" + "\n\n\n" + "
"); + } + + { + 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("

Blah

\n" + "

Green " + "yellow" + " green

"); + } + + { + 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("

Blah

"); + } + + { + 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("" + "\n\n" + "\n" + "\n\n" + "\n" + "
\n" + "

Blah

"); + } + + { + 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("" + "\n\n" + "\n" + "\n\n" + "\n" + "
\n" + "

Blah

"); + } + + { + 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("" + "\n\n\n" + "\n\n\n" + "
"); + } + + { + CREATE_DOC_AND_CURSOR(); + + cursor.insertBlock(); + cursor.insertText("Foo"); + + cursor.block().setUserState(42); + + QTest::newRow("userstate") << QTextDocumentFragment(&doc) + << QString("EMPTYBLOCK") + + QString("

Foo

"); + } + + { + 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("

Foo

" + "\n

Bar

" + "\n\n\n
"); + } + + { + 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("
  • Blah
"); + } +} + +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", "


\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("

text text

"); // 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("
foo
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(""), QString("")); + expected += QString("

TestBlah

") + 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(""), QString("")); + expected += QString("

Test

") + 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("\n" + "" + "\n" + "

Blah

" + ""); + + 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("\n" + "\n
\n" + "

Blah

"); + + 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("

Foo

Bar

Baz

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(""); + 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(parent()); + QTextBlock block = doc->findBlock(from); + + QTestDocumentLayout *lout = qobject_cast(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(parent()); + QTextBlock block = doc->findBlock(from); + QTextCursor cursor(block); + + QTestDocumentLayout *lout = qobject_cast(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("" + title + "Hrm"); + 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("Mooo"); + 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("Mooo"); + 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 World"); + QCOMPARE(doc->toPlainText(), QLatin1String("Hello World")); +} + +void tst_QTextDocument::deleteTextObjectsOnClear() +{ + QPointer 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("

test"); + QTextBlockFormat fmt = doc->begin().blockFormat(); + QVERIFY(fmt.background().color() == QColor("green")); + + doc->clear(); + cursor.insertHtml("

test"); + fmt = doc->begin().blockFormat(); + QVERIFY(fmt.background().color() == QColor("green")); + + QTextDocument *clone = doc->clone(); + QCOMPARE(clone->defaultStyleSheet(), sheet); + cursor = QTextCursor(clone); + cursor.insertHtml("

test"); + fmt = clone->begin().blockFormat(); + QVERIFY(fmt.background().color() == QColor("green")); + delete clone; + + cursor = QTextCursor(doc); + cursor.insertHtml("

test"); + fmt = doc->begin().blockFormat(); + QVERIFY(fmt.background().color() == QColor("green")); + + doc->clear(); + cursor.insertHtml("

test"); + fmt = doc->begin().blockFormat(); + QVERIFY(fmt.background().color() == QColor("red")); + + doc->clear(); + doc->setDefaultStyleSheet("invalid style sheet...."); + cursor.insertHtml("

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("") + .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("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("

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("
Blah
"); + +void tst_QTextDocument::backgroundImage_checkExpectedHtml(const QTextDocument &doc) +{ + QString expectedHtml("\n" + "" + "\n" + "" + "\n\n
" + "\n

Blah

" + "
"); + + 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("original"); + QTest::addColumn("expected"); + + QTest::newRow("1") << "Hello World\n" << "Hello World\n"; + QTest::newRow("2") << "#include " << "#include <QtCore>"; + QTest::newRow("3") << "

plop -->

" + << "<p class="cool"><a href="http://example.com/?foo=bar&amp;bar=foo">plop --&gt; </a></p>"; + QTest::newRow("4") << QString::fromUtf8("<\320\222\321\201>") << QString::fromUtf8("<\320\222\321\201>"); +} + +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 + + +#include +#include +#include +#include +#include +#include + + +#include + +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 +#include +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[] = "" +"" +" " +" " +" " +" " +" " +" " +"
First Cell" +" Second Cell" +"
Third Cell" +"
Fourth Cell" +" Fifth Cell" +"
"; + 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[] = "" +"" +" " +" " +" " +"
First Cell
"; + 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("
HeyBlah")); + QVERIFY(!fragment.isEmpty()); +} + +void tst_QTextDocumentFragment::tableImport2() +{ + { + const char html[] = "" + "" + "" + "" + "
First CellSecond Cell
Third CellFourth Cell
"; + + 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[] = "" + "" + "" + "" + "
First CellSecond Cell
Third Cell" + " " + " " + " " + " " + "
First Nested CellSecond Nested Cell
Third Nested CellFourth Nested Cell
Fifth Nested CellSixth Nested Cell
"; + + 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[] = "" + "" + "
First CellSecond Cell" + "
Third CellFourth Cell" + "
"; + + 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[] = "" + "" + "
First CellSecond Cell" + "
Third CellFourth Cell" + "
"; + + 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[] = "

"; + QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(QString::fromLatin1(html)); + QVERIFY(!fragment.isEmpty()); +} + +void tst_QTextDocumentFragment::tableImport4() +{ + const char html[] = "" + "" + "" + "
blah
blahblah
"; + 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[] = "" + "" + " " + " " + " " + " " + "" + "" + " " + " " + "" + "
FooBarBlehBlub
AhhGah
"; + + 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("TestBlah")); + QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), QString::fromLatin1("Test")); +} + +void tst_QTextDocumentFragment::html_listIndents1() +{ + const char html[] = "
  • Hey
  • Hah
"; + 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[] = "
  • Hey

    Hah

"; + 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[] = "
  • Hah

"; + 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[] = "
  • Foo

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[] = "

  • Foo

  • Bar
"; + 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[] = "
  • Outer List
    • Nested Item 1
"; + 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[] = "

Test

"; + 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[] = "

Test

"; + 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[] = "
cell onecell two
cell threecell four
"; + 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[] = "
Test\r\n
Bar"; + setHtml(QString::fromLatin1(html)); + QVERIFY(!doc->toPlainText().contains('\r')); + QCOMPARE(doc->toPlainText(), QString("Test\nBar")); +} + +void tst_QTextDocumentFragment::unorderedListEnumeration() +{ + const char html[] = "
      • Blah
    "; + setHtml(QString::fromLatin1(html)); + cursor.movePosition(QTextCursor::End); + QVERIFY(cursor.currentList()); + QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListCircle); + + const char html2[] = "
        • Blah
      "; + 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[] = "

      "; + setHtml(QString::fromLatin1(html)); + QVERIFY(!doc->isEmpty()); +} + +void tst_QTextDocumentFragment::ignoreStyleTags() +{ + const char html[] = "Hello"; + setHtml(QString::fromLatin1(html)); + QCOMPARE(doc->toPlainText(), QString("Hello")); +} + +void tst_QTextDocumentFragment::hrefAnchor() +{ + { + const char html[] = "blah"; + 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[] = "blah"; + 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[] = "ablah"; + 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[] = "

      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("Text"); + + 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[] = "
      Hey
      "; + 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[] = "
      Hey
      "; + 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[] = "

      Hey

      "; + 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[] = "
      "; + setHtml(QString::fromLatin1(html)); + QVERIFY(true); // don't crash with a failing assertion +} + +void tst_QTextDocumentFragment::emptyTable2() +{ + const char html[] = "

      blah

      "; + setHtml(QString::fromLatin1(html)); + QVERIFY(true); // don't crash with a failing assertion +} + +void tst_QTextDocumentFragment::emptyTable3() +{ + const char html[] = "
      Foobar
      "; + 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[] = "
      Blah
      Hm
      "; + 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[] = "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[] = "

      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[] = "

      Blah

      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 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[] = "Blah"; + 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[] = "Link"; + cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); + QVERIFY(true); + } + + { + const char html[] = "Test

      "; + cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); + QCOMPARE(cursor.blockFormat().indent(), 3); +} + +void tst_QTextDocumentFragment::html_listIndent() +{ + const char html[] = "
      • Blah
      "; + cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); + QVERIFY(cursor.currentList()); + QCOMPARE(cursor.currentList()->format().indent(), 4); +} + +void tst_QTextDocumentFragment::html_whitespace_data() +{ + QTest::addColumn("html"); + QTest::addColumn("expectedPlainText"); + + QTest::newRow("1") << QString("This is some test with spaces between words") + << QString("This is some test with spaces between words"); + + QTest::newRow("2") << QString(" nowhitespacehereplease") + << QString::fromLatin1("nowhitespacehereplease"); + + QTest::newRow("3") << QString(" white space here ") + << QString::fromLatin1(" white space here "); + + QTest::newRow("4") << QString(" white space here ") + << QString::fromLatin1(" white space here "); + + QTest::newRow("5") << QString("
      One Two Three\n" + "Four") + << QString::fromLatin1("One Two Three Four"); + + QTest::newRow("6") << QString("

      Testing: BoldItalic Italic

      ") + << QString("Testing: BoldItalic Italic"); + + QTest::newRow("7") << QString("
      Blah
      Foo
      ") + << QString("\nBlah\n\nFoo\n"); + + QTest::newRow("8") << QString("
      Blah
      Blub") + << QString("\nBlah\nBlub"); + + QTest::newRow("task116492") << QString("

      a b c

      ") + << QString("a b c"); + + QTest::newRow("task121653") << QString("abc def") + << QString("abc def"); + + QTest::newRow("task122650") << QString("

      Foo

      Bar") + << QString("Foo\nBar"); + + QTest::newRow("task122650-2") << QString("

      Foo

      Bar") + << QString("Foo \nBar"); + + QTest::newRow("task122650-3") << QString("Before

      \nTest
      ") + << QString("Before\nTest"); + + QTest::newRow("br-with-whitespace") << QString("Foo
      \nBlah") + << QString("Foo\nBlah"); + + QTest::newRow("collapse-p-with-newline") << QString("Foo

      \n

      \n

      \n

      \n

      \n

      \nBar") + << QString("Foo\nBar"); + + QTest::newRow("table") << QString("
      Blah
      \nTest") + << QString("\nBlah\nTest"); + + QTest::newRow("table2") << QString("\n
      \nTest\n
      ") + << QString("\nTest\n"); + + QTest::newRow("table3") << QString("
      \nTest\n
      \n \n
      ") + << 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("") + + text + + QString(""); + + 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("" + "blah blah") + + text + + QString(""); + + 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("") + + text + + QString(""); + + cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); + + QCOMPARE(doc->toPlainText(), text); +} + +void tst_QTextDocumentFragment::html_listStart1() +{ + // don't create a block for the

        element, even if there's some whitespace between + // it and the
      • + const char html[] = "
        • list item
          • "; + 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[] = "
              buggy, but text should appear
            • list item
              • "; + cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0])))); + + QCOMPARE(doc->blockCount(), 2); +} + +void tst_QTextDocumentFragment::html_cssMargin() +{ + const char html[] = "

                Test

                "; + 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[] = "@"; + cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); + QCOMPARE(doc->begin().begin().fragment().text(), QString("@")); +} + +void tst_QTextDocumentFragment::html_decEntities() +{ + const char html[] = "@"; + cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); + QCOMPARE(doc->begin().begin().fragment().text(), QString("@")); +} + +void tst_QTextDocumentFragment::html_thCentered() +{ + const char html[] = "
                This should be centered
                "; + 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[] = "" + "
                1. elem 1
                " + "
                1. elem 1
                " + ""; + + 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[] = "
                • Foo
                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[] = "Subby"; + const char superHtml[] = "Super"; + const char subHtmlCss[] = "Subby"; + const char superHtmlCss[] = "Super"; + const char alignmentInherited[] = "Subby"; + + 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[] = "Blue"; + setHtml(color); + QVERIFY(cursor.charFormat().foreground().color() == Qt::blue); + + const char rgbColor[] = "Blue"; + setHtml(rgbColor); + QVERIFY(cursor.charFormat().foreground().color() == Qt::blue); +} + +void tst_QTextDocumentFragment::obeyFragmentMarkersInImport() +{ + const char html[] = "This leading text should not appearTextThis 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%1This 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[] = "

                 

                Two paragraphs

                "; + 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[] = "

                One paragraph

                "; + setHtml(html); + + QCOMPARE(doc->blockCount(), 1); + QCOMPARE(cursor.blockFormat().leftMargin(), qreal(0)); + + const char html2[] = "

                One paragraph"; + setHtml(html2); + QCOMPARE(doc->blockCount(), 1); + QCOMPARE(cursor.blockFormat().leftMargin(), qreal(0)); + + const char html3[] = "

                Foo

                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[] = "

                  Foo

                Bar

                "; + + setHtml(html); + + QCOMPARE(doc->blockCount(), 2); + + cursor = QTextCursor(doc); + QCOMPARE(cursor.block().next().blockFormat().indent(), 0); +} + +void tst_QTextDocumentFragment::html_emptyParagraphs4() +{ + const char html[] = "

                foo

                bar

                "; + 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[] = "

                foo

                bar

                "; + 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[] = "

                Hah

                "; + setHtml(html); + + QVERIFY(cursor.charFormat().foreground().color() == Qt::blue); + QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue); +} + +void tst_QTextDocumentFragment::html_fontSize() +{ + const char html[] = "Hah"; + setHtml(html); + + QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), -1); +} + +void tst_QTextDocumentFragment::html_fontSizeAdjustment() +{ + const char html[] = "Hah"; + 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[] = "Foo"; + setHtml(html); + + QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 50); + + const char html2[] = "Foo"; + setHtml(html2); + + QCOMPARE(cursor.charFormat().property(QTextFormat::FontPixelSize).toInt(), 50); + + const char html3[] = "Foo"; + setHtml(html3); + + QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), 1); +} + +void tst_QTextDocumentFragment::html_cssShorthandFont() +{ + { + const char html[] = "Foo"; + setHtml(html); + QCOMPARE(cursor.charFormat().property(QTextFormat::FontPixelSize).toInt(), 50); + QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("sans-serif")); + } + { + const char html[] = "Foo"; + setHtml(html); + QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 50); + QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("sans-serif")); + } + { + const char html[] = "Foo"; + setHtml(html); + QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 7); + QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("Times New Roman")); + } + { + const char html[] = "Foo"; + setHtml(html); + QCOMPARE(cursor.charFormat().property(QTextFormat::FontWeight).toInt(), int(QFont::Bold)); + QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 7); + } + { + const char html[] = "Foo"; + 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[] = "Foo"; + doc->setHtml(html); + + QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue); +} + +void tst_QTextDocumentFragment::html_qtBgColor() +{ + const char html[] = "Foo"; + doc->setHtml(html); + + QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue); +} + +void tst_QTextDocumentFragment::html_bodyBackground() +{ + const char html[] = "Foo"; + doc->setHtml(html); + + QVERIFY(doc->rootFrame()->frameFormat().background().style() == Qt::TexturePattern); +} + +void tst_QTextDocumentFragment::html_tableCellBackground() +{ + const char html[] = "
                Foo
                "; + 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[] = "Foo"; + doc->setHtml(html); + + QVERIFY(doc->rootFrame()->frameFormat().background().style() == Qt::TexturePattern); +} + +void tst_QTextDocumentFragment::css_tableCellBackground() +{ + const char html[] = "
                Foo
                "; + 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[] = "" + "" + "
                Foo
                "; + 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[] = "
                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[] = "abcd"; + 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[] = "

                • Foo
                  • In nested list
                • Last item

                "; + 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[] = "

                Blah

                "; + 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[] = "FooBar"; + 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[] = "

                Foo"; + 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("

                ") + input + QString::fromLatin1("

                "); + 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[] = "BlahFoo"; + 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[] = "

                "; + setHtml(html); + QCOMPARE(doc->blockCount(), 1); +} + +void tst_QTextDocumentFragment::html_closingTag() +{ + const char html[] = "text"; + setHtml(html); + + QVERIFY(!cursor.charFormat().fontItalic()); +} + +void tst_QTextDocumentFragment::html_anchorAroundImage() +{ + const char html[] = ""; + 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[] = "
                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 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 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[] = "

                Foo

                "; + cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html))); + + QList 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[] = "
                This should be centered
                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[] = "
                Test

                Second Parag

                "; + 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[] = "
                Blah
                "; + 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[] = "" +"" +" " +" " +" " +" " +" " +" " +" " +"
                First Cell
                Second CellThird Cell
                "; + + 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("Hello World"); + 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("

                foo

                bar"); + QCOMPARE(doc->blockCount(), 2); +} + +void tst_QTextDocumentFragment::html_quotedFontFamily() +{ + setHtml("
                Test
                "); + QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar")); + + setHtml("
                Test
                "); + QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar")); + + setHtml("
                Test
                "); + QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar")); + + setHtml("
                Test
                "); + QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar")); + + setHtml("
                Test
                "); + 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(""); + QVERIFY(html.contains(str)); +} + +void tst_QTextDocumentFragment::html_spanBackgroundColor() +{ + setHtml("Foo"); + QVERIFY(doc->begin().begin().fragment().charFormat().background().color() == QColor(Qt::blue)); +} + +void tst_QTextDocumentFragment::html_brokenTitle_data() +{ + QTest::addColumn("html"); + QTest::addColumn("expectedBody"); + QTest::addColumn("expectedTitle"); + + QTest::newRow("brokentitle") << QString("Foo<b>bar</b>Blah") + << QString("Blah") << QString("Foo"); + QTest::newRow("brokentitle2") << QString("Foo<font color=red>i</font>t<font color=red>i</font>BlubBlah") + << QString("Blah") << QString("Foo"); + QTest::newRow("entities") << QString("Foo<barBlah") + << QString("Blah") << QString("FooFoo</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> 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>TestBlah")); + 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("html"); + QTest::addColumn("code"); + + for (int i = 0; i < MAX_ENTITY; ++i) { + QTest::newRow(entities[i].name) << QString("
                &") + QString::fromLatin1(entities[i].name) + QString(";
                ") + << 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("Blah")); + QCOMPARE(doc->toPlainText(), QString("Blah")); +} + +void tst_QTextDocumentFragment::html_directionWithHtml() +{ + doc->setHtml(QString::fromLatin1("

                Test

                RTL

                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("

                Test

                RTL

                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("HelloWorld"); + QCOMPARE(doc->toPlainText(), QString("HelloWorld")); +} + +void tst_QTextDocumentFragment::html_importImageWithoutAspectRatio() +{ + doc->setHtml(""); + 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(""); + 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(""); + 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 Test\nText then selecting all and copying will + // result in the following text on the clipboard (for text/html) + doc->setHtml(QString::fromLatin1("Test\nText\n\n")); + 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 + +#include +#include +#include +#include +#include +#include +#include + +//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("
                Column 1
                Data

                "); + QString html_text("bla bla bla bla bla bla bla bla
                "); + QString html_end("
                Column 1
                Data
                "); + + 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("
                hello hello hello" + "thisisabigwordthisisabigwordthisisabigwordthisisabigwordthisisabigword" + "hello hello hello
                "); + 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 = + "
                "; + + 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//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 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 &tabs, const QList &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 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 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 + + + +#include +#include + +#include + + +#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("text"); + QTest::addColumn("startPos"); + QTest::addColumn("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 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 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 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 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 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 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 + +#include +#include +#include +#include +#include +#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 + + /* + * 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 + + /* + * 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 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("format"); + QTest::addColumn("number"); + QTest::addColumn("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 + +#include +#include +#include +#include +#include +#include + +//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 +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_SYMBIAN +#define SRCDIR "." +#endif + +#include + +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(" 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("input"); + QTest::addColumn("xml"); + + QTest::newRow("empty") << "" << + ""; + QTest::newRow("spaces") << "foobar word" << + "foobar word"; + QTest::newRow("starting spaces") << " starting spaces" << + "starting spaces"; + QTest::newRow("trailing spaces") << "trailing spaces " << + "trailing spaces "; + QTest::newRow("tab") << "word\ttab x" << + "wordtab x"; + QTest::newRow("tab2") << "word\t\ttab\tx" << + "wordtabx"; + QTest::newRow("misc") << "foobar word\ttab x" << + "foobar wordtab x"; + QTest::newRow("misc2") << "\t \tFoo" << + " Foo"; + QTest::newRow("linefeed") << QString("line1%1line2").arg(QChar(0x2028)) << + "line1line2"; + QTest::newRow("spaces") << "The quick brown fox jumped over the lazy dog" << + "The quick brown fox jumped over the lazy dog"; +} + +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("htmlInput"); + QTest::addColumn("cursorPosition"); + QTest::addColumn("xml"); + + QString text1 = "NormalbolditalicBold/Italic"; + QTest::newRow("normal") << text1 << 2 << + ""; + QTest::newRow("bold") << text1 << 10 << + ""; + QTest::newRow("italic") << text1 << 14 << + ""; + QTest::newRow("bold+italic") << text1 << 25 << + ""; + QString colorText = " Color Text "; + QTest::newRow("green/red") << colorText << 3 << + ""; + +} + +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 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( + "" + "" + "" + "" + "" + "" + "" + ""); + 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( + "" + "" + //"" + //"")+ QChar(0x25cf) + QString::fromLatin1("" // 0x25cf is a bullet + "ListItem 2" + "" + ""); + + 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( + "" + "" + //"" + //"")+ QChar(0x25cf) + QString::fromLatin1("" // 0x25cf is a bullet + "Cars" + "" + "" + "" + "" + "Model T" + "" + "" + "Kitt" + "" + "" + "" + "" + "Animals" + "" + "" + "" + "" + "Foo" + "" + "" + "Bar"); + + // 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("= 0); + QVERIFY(result.indexOf("= 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( + "foo" + "Bar" + "" + "baz" + "" + ""); + + 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( + "" + "" + "" + "" + "" + "a" + "" + "" + "b" + "" + "" + "" + "" + "c" + "" + "" + "d" + "" + "" + "" + "" + "e" + "" + "" + "" + ""); + + 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 + +#define protected public + +#include +#undef protected +#include +#include +#include +#include +#include +#include +#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 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 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 +#include +#include +#include +#include +#include + +#define private public +#include +#include +#include +#include +#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 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 + +#ifdef Q_WS_X11 +#undef private +#endif + +#include + + + +#if defined(Q_WS_X11) || defined(Q_WS_MAC) +#define private public +#include +#include +#undef private +#else +#include +#include +#endif + +#include +#include + + + + + +//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("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 + + +#include +#include +#include +#include +#include +#include +#include + +//TESTED_FILES= + +typedef QList 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(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 table1 = QTextCursor(cursor).insertTable(4, 4); + QPointer table2 = QTextCursor(cursor).insertTable(4, 4); + QPointer 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 table1 = QTextCursor(cursor).insertTable(4, 4); + QPointer table2 = QTextCursor(cursor).insertTable(4, 4); + QPointer 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("rows"); + QTest::addColumn("columns"); + QTest::addColumn >("merge"); + QTest::addColumn >("insert"); + + QTest::newRow("2x3, merge two, insert one") << 2 << 3 << (QList() << 1 << 2 << 2) + << (QList() << 1 << 1) ; + QTest::newRow("3x4, merge three, insert one") << 3 << 4 << (QList() << 1 << 3 << 3) + << (QList() << 1 << 1) ; + QTest::newRow("4x3, merge two, insert two") << 4 << 3 << (QList() << 1 << 4 << 2) + << (QList() << 1 << 2) ; + QTest::newRow("4x4, merge middle two, insert one") << 4 << 4 << (QList() << 1 << 4 << 2) + << (QList() << 1 << 1) ; +} + +void tst_QTextTable::QTBUG11282_insertBeforeMergedEnding() +{ + QFETCH(int, rows); + QFETCH(int, columns); + QFETCH(QList, merge); + QFETCH(QList, 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 Binary files /dev/null and b/tests/auto/gui/text/qzip/testdata/symlink.zip 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 Binary files /dev/null and b/tests/auto/gui/text/qzip/testdata/test.zip 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 +#include +#include +#include + +#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 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 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 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 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 +#include +#include +#include + +//#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("url"); + QTest::addColumn("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("url"); + QTest::addColumn("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("url"); + QTest::addColumn("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("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 \ + diff --git a/tests/auto/other.pro b/tests/auto/other.pro index 739174de35..48c5dcccdb 100644 --- a/tests/auto/other.pro +++ b/tests/auto/other.pro @@ -7,22 +7,15 @@ SUBDIRS=\ lancelot \ qalgorithms \ qcombobox \ - qcssparser \ qfocusevent \ - qimage \ qitemmodel \ qlayout \ qmdiarea \ qmenu \ qmenubar \ - qmouseevent \ - qpainter \ - qpixmap \ - qprinter \ qsplitter \ qtabwidget \ qtextbrowser \ - qtextdocument \ qtextedit \ qtoolbutton \ qvariant \ @@ -32,7 +25,6 @@ SUBDIRS=\ contains(QT_CONFIG, accessibility):SUBDIRS += qaccessibility -contains(QT_CONFIG, OdfWriter):SUBDIRS += qzip qtextodfwriter mac:!qpa { SUBDIRS += macgui \ macnativeevents \ @@ -56,6 +48,4 @@ symbian { # Following tests depends on private API !contains(QT_CONFIG, private_tests): SUBDIRS -= \ qcombobox \ - qcssparser \ qtextedit \ - diff --git a/tests/auto/qabstracttextdocumentlayout/.gitignore b/tests/auto/qabstracttextdocumentlayout/.gitignore deleted file mode 100644 index d747466790..0000000000 --- a/tests/auto/qabstracttextdocumentlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qabstracttextdocumentlayout diff --git a/tests/auto/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro b/tests/auto/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro deleted file mode 100644 index 22b013e37e..0000000000 --- a/tests/auto/qabstracttextdocumentlayout/qabstracttextdocumentlayout.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qabstracttextdocumentlayout.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qabstracttextdocumentlayout.cpp - - diff --git a/tests/auto/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp b/tests/auto/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp deleted file mode 100644 index 90f212e832..0000000000 --- a/tests/auto/qabstracttextdocumentlayout/tst_qabstracttextdocumentlayout.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include - -//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(var1), obj1.paintDevice()); - obj1.setPaintDevice((QPaintDevice *)0); - QCOMPARE(static_cast(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/qbrush/.gitignore b/tests/auto/qbrush/.gitignore deleted file mode 100644 index e9321a18bd..0000000000 --- a/tests/auto/qbrush/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qbrush diff --git a/tests/auto/qbrush/qbrush.pro b/tests/auto/qbrush/qbrush.pro deleted file mode 100644 index 1c3efd46be..0000000000 --- a/tests/auto/qbrush/qbrush.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qbrush.cpp diff --git a/tests/auto/qbrush/tst_qbrush.cpp b/tests/auto/qbrush/tst_qbrush.cpp deleted file mode 100644 index 9ee679e0f7..0000000000 --- a/tests/auto/qbrush/tst_qbrush.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include "qbrush.h" -#include -#include - -#include - -//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("brush1"); - QTest::addColumn("brush2"); - QTest::addColumn("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("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/qclipboard/.gitignore b/tests/auto/qclipboard/.gitignore deleted file mode 100644 index 4fcf7d55fc..0000000000 --- a/tests/auto/qclipboard/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -tst_qclipboard -copier/copier -copier/copier.exe -paster/paster -paster/paster.exe diff --git a/tests/auto/qclipboard/copier/copier.pro b/tests/auto/qclipboard/copier/copier.pro deleted file mode 100644 index d345d33eb5..0000000000 --- a/tests/auto/qclipboard/copier/copier.pro +++ /dev/null @@ -1,10 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -CONFIG -= app_bundle -QT += widgets -win32: DESTDIR = ../copier -# Input -SOURCES += main.cpp - diff --git a/tests/auto/qclipboard/copier/main.cpp b/tests/auto/qclipboard/copier/main.cpp deleted file mode 100644 index e4417352ff..0000000000 --- a/tests/auto/qclipboard/copier/main.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -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/qclipboard/paster/main.cpp b/tests/auto/qclipboard/paster/main.cpp deleted file mode 100644 index 4df4d7fb45..0000000000 --- a/tests/auto/qclipboard/paster/main.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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/qclipboard/paster/paster.pro b/tests/auto/qclipboard/paster/paster.pro deleted file mode 100644 index d214c9e90a..0000000000 --- a/tests/auto/qclipboard/paster/paster.pro +++ /dev/null @@ -1,11 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -win32: DESTDIR = ../paster -CONFIG -= app_bundle -QT += widgets -# Input -SOURCES += main.cpp - - diff --git a/tests/auto/qclipboard/qclipboard.pro b/tests/auto/qclipboard/qclipboard.pro deleted file mode 100644 index 692ca5dd3f..0000000000 --- a/tests/auto/qclipboard/qclipboard.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = test copier paster - - diff --git a/tests/auto/qclipboard/test/test.pro b/tests/auto/qclipboard/test/test.pro deleted file mode 100644 index 12c6b6ce4f..0000000000 --- a/tests/auto/qclipboard/test/test.pro +++ /dev/null @@ -1,32 +0,0 @@ -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/qclipboard/tst_qclipboard.cpp b/tests/auto/qclipboard/tst_qclipboard.cpp deleted file mode 100644 index 4d3bb29e13..0000000000 --- a/tests/auto/qclipboard/tst_qclipboard.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#ifdef Q_WS_MAC -#include -#endif -#ifdef Q_OS_SYMBIAN -#include "private/qcore_symbian_p.h" -#include "txtetext.h" -#include -#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"); - - 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(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(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(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/qcolor/.gitignore b/tests/auto/qcolor/.gitignore deleted file mode 100644 index 92f91eb54e..0000000000 --- a/tests/auto/qcolor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcolor diff --git a/tests/auto/qcolor/qcolor.pro b/tests/auto/qcolor/qcolor.pro deleted file mode 100644 index b9d437ef7c..0000000000 --- a/tests/auto/qcolor/qcolor.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qcolor.cpp - - - diff --git a/tests/auto/qcolor/tst_qcolor.cpp b/tests/auto/qcolor/tst_qcolor.cpp deleted file mode 100644 index 2b6896ae5d..0000000000 --- a/tests/auto/qcolor/tst_qcolor.cpp +++ /dev/null @@ -1,1538 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include - -#include -#include - -//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("color"); - QTest::addColumn("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("color"); - QTest::addColumn("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("color"); - QTest::addColumn("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("expectedColor"); - QTest::addColumn("hsvColor"); - QTest::addColumn("cmykColor"); - QTest::addColumn("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("expectedColor"); - QTest::addColumn("rgbColor"); - QTest::addColumn("cmykColor"); - QTest::addColumn("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("expectedColor"); - QTest::addColumn("rgbColor"); - QTest::addColumn("hsvColor"); - QTest::addColumn("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("expectedColor"); - QTest::addColumn("hsvColor"); - QTest::addColumn("rgbColor"); - QTest::addColumn("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("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/qcssparser/.gitignore b/tests/auto/qcssparser/.gitignore deleted file mode 100644 index 6cc99800e0..0000000000 --- a/tests/auto/qcssparser/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcssparser diff --git a/tests/auto/qcssparser/qcssparser.pro b/tests/auto/qcssparser/qcssparser.pro deleted file mode 100644 index 16fa265231..0000000000 --- a/tests/auto/qcssparser/qcssparser.pro +++ /dev/null @@ -1,17 +0,0 @@ -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/qcssparser/testdata/scanner/comments/input b/tests/auto/qcssparser/testdata/scanner/comments/input deleted file mode 100644 index af2b659a5b..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/comments/input +++ /dev/null @@ -1 +0,0 @@ -/* let's see if comments actually work *//*foo*/ "it /*should be preserved \"in strings*/ though" diff --git a/tests/auto/qcssparser/testdata/scanner/comments/output b/tests/auto/qcssparser/testdata/scanner/comments/output deleted file mode 100644 index 80ede0ba22..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/comments/output +++ /dev/null @@ -1,4 +0,0 @@ -S|/* let's see if comments actually work */ -S|/*foo*/ -S| -STRING|"it /*should be preserved "in strings*/ though" diff --git a/tests/auto/qcssparser/testdata/scanner/comments2/input b/tests/auto/qcssparser/testdata/scanner/comments2/input deleted file mode 100644 index 3135acd78c..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/comments2/input +++ /dev/null @@ -1 +0,0 @@ -/*foo*/{/*foo*/+/*foo*/>/*foo*/,/*foo*/}/*foo*/- diff --git a/tests/auto/qcssparser/testdata/scanner/comments2/output b/tests/auto/qcssparser/testdata/scanner/comments2/output deleted file mode 100644 index d1f1259869..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/comments2/output +++ /dev/null @@ -1,12 +0,0 @@ -S|/*foo*/ -LBRACE|{ -S|/*foo*/ -PLUS|+ -S|/*foo*/ -GREATER|> -S|/*foo*/ -COMMA|, -S|/*foo*/ -RBRACE|} -S|/*foo*/ -MINUS|- diff --git a/tests/auto/qcssparser/testdata/scanner/comments3/input b/tests/auto/qcssparser/testdata/scanner/comments3/input deleted file mode 100644 index 8634543a8f..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/comments3/input +++ /dev/null @@ -1 +0,0 @@ -url(/*comment*/"www.kde.org") diff --git a/tests/auto/qcssparser/testdata/scanner/comments3/output b/tests/auto/qcssparser/testdata/scanner/comments3/output deleted file mode 100644 index af7bad752a..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/comments3/output +++ /dev/null @@ -1,4 +0,0 @@ -FUNCTION|url( -S|/*comment*/ -STRING|"www.kde.org" -RPAREN|) diff --git a/tests/auto/qcssparser/testdata/scanner/comments4/input b/tests/auto/qcssparser/testdata/scanner/comments4/input deleted file mode 100644 index 62d039b00c..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/comments4/input +++ /dev/null @@ -1 +0,0 @@ -!/*hmm*/important diff --git a/tests/auto/qcssparser/testdata/scanner/comments4/output b/tests/auto/qcssparser/testdata/scanner/comments4/output deleted file mode 100644 index eb86e7bd15..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/comments4/output +++ /dev/null @@ -1,3 +0,0 @@ -EXCLAMATION_SYM|! -S|/*hmm*/ -IDENT|important diff --git a/tests/auto/qcssparser/testdata/scanner/quotedstring/input b/tests/auto/qcssparser/testdata/scanner/quotedstring/input deleted file mode 100644 index deae3a8dab..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/quotedstring/input +++ /dev/null @@ -1 +0,0 @@ -background: 'test_bug.png'; diff --git a/tests/auto/qcssparser/testdata/scanner/quotedstring/output b/tests/auto/qcssparser/testdata/scanner/quotedstring/output deleted file mode 100644 index ed52419594..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/quotedstring/output +++ /dev/null @@ -1,5 +0,0 @@ -IDENT|background -COLON|: -S| -STRING|'test_bug.png' -SEMICOLON|; diff --git a/tests/auto/qcssparser/testdata/scanner/simple/input b/tests/auto/qcssparser/testdata/scanner/simple/input deleted file mode 100644 index b37e587661..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/simple/input +++ /dev/null @@ -1 +0,0 @@ -p { display:block; } diff --git a/tests/auto/qcssparser/testdata/scanner/simple/output b/tests/auto/qcssparser/testdata/scanner/simple/output deleted file mode 100644 index 71c60ec9bf..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/simple/output +++ /dev/null @@ -1,9 +0,0 @@ -IDENT|p -LBRACE| { -S| -IDENT|display -COLON|: -IDENT|block -SEMICOLON|; -S| -RBRACE|} diff --git a/tests/auto/qcssparser/testdata/scanner/unicode/input b/tests/auto/qcssparser/testdata/scanner/unicode/input deleted file mode 100644 index 2c33f7be97..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/unicode/input +++ /dev/null @@ -1 +0,0 @@ -\41"\7E"\00006Df diff --git a/tests/auto/qcssparser/testdata/scanner/unicode/output b/tests/auto/qcssparser/testdata/scanner/unicode/output deleted file mode 100644 index 0829c37e28..0000000000 --- a/tests/auto/qcssparser/testdata/scanner/unicode/output +++ /dev/null @@ -1,3 +0,0 @@ -IDENT|A -STRING|"~" -IDENT|mf diff --git a/tests/auto/qcssparser/tst_qcssparser.cpp b/tests/auto/qcssparser/tst_qcssparser.cpp deleted file mode 100644 index 1e82431a48..0000000000 --- a/tests/auto/qcssparser/tst_qcssparser.cpp +++ /dev/null @@ -1,1718 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#if defined(Q_OS_WINCE) -#include -#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("input"); - QTest::addColumn("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 &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 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("parseSuccess"); - QTest::addColumn("css"); - QTest::addColumn("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) - -void tst_QCssParser::expr_data() -{ - QTest::addColumn("parseSuccess"); - QTest::addColumn("css"); - QTest::addColumn >("expectedValues"); - - QVector 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, expectedValues); - - QCss::Parser parser(css); - QVector 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("css"); - QTest::addColumn("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("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("css"); - QTest::addColumn("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(node.ptr)->tagName()); } - virtual QString attribute(NodePtr node, const QString &name) const { return reinterpret_cast(node.ptr)->attribute(name); } - virtual bool hasAttribute(NodePtr node, const QString &name) const { return reinterpret_cast(node.ptr)->hasAttribute(name); } - virtual bool hasAttributes(NodePtr node) const { return reinterpret_cast(node.ptr)->hasAttributes(); } - - virtual bool isNullNode(NodePtr node) const { - return reinterpret_cast(node.ptr)->isNull(); - } - virtual NodePtr parentNode(NodePtr node) const { - NodePtr parent; - parent.ptr = new QDomElement(reinterpret_cast(node.ptr)->parentNode().toElement()); - return parent; - } - virtual NodePtr duplicateNode(NodePtr node) const { - NodePtr n; - n.ptr = new QDomElement(*reinterpret_cast(node.ptr)); - return n; - } - virtual NodePtr previousSiblingNode(NodePtr node) const { - NodePtr sibling; - sibling.ptr = new QDomElement(reinterpret_cast(node.ptr)->previousSiblingElement()); - return sibling; - } - virtual void freeNode(NodePtr node) const { - delete reinterpret_cast(node.ptr); - } - -private: - QDomDocument doc; -}; - -Q_DECLARE_METATYPE(QDomDocument) - -void tst_QCssParser::marginValue_data() -{ - QTest::addColumn("css"); - QTest::addColumn("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(" "))); - - 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 rules = testSelector.styleRulesForNode(n); - QVector 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("match"); - QTest::addColumn("selector"); - QTest::addColumn("xml"); - QTest::addColumn("elementToCheck"); - - QTest::newRow("plain") << true << QString("p") << QString("

                ") << QString(); - QTest::newRow("noplain") << false << QString("bar") << QString("

                ") << QString(); - - QTest::newRow("class") << true << QString(".foo") << QString("

                ") << QString(); - QTest::newRow("noclass") << false << QString(".bar") << QString("

                ") << QString(); - - QTest::newRow("attrset") << true << QString("[justset]") << QString("

                ") << QString(); - QTest::newRow("notattrset") << false << QString("[justset]") << QString("

                ") << QString(); - - QTest::newRow("attrmatch") << true << QString("[foo=bar]") << QString("

                ") << QString(); - QTest::newRow("noattrmatch") << false << QString("[foo=bar]") << QString("

                ") << QString(); - - QTest::newRow("contains") << true << QString("[foo~=bar]") << QString("

                ") << QString(); - QTest::newRow("notcontains") << false << QString("[foo~=bar]") << QString("

                ") << QString(); - - QTest::newRow("beingswith") << true << QString("[foo|=bar]") << QString("

                ") << QString(); - QTest::newRow("notbeingswith") << false << QString("[foo|=bar]") << QString("

                ") << QString(); - - QTest::newRow("attr2") << true << QString("[bar=foo]") << QString("

                ") << QString(); - - QTest::newRow("universal1") << true << QString("*") << QString("

                ") << QString(); - - QTest::newRow("universal3") << false << QString("*[foo=bar]") << QString("

                ") << QString(); - QTest::newRow("universal4") << true << QString("*[foo=bar]") << QString("

                ") << QString(); - - QTest::newRow("universal5") << false << QString("[foo=bar]") << QString("

                ") << QString(); - QTest::newRow("universal6") << true << QString("[foo=bar]") << QString("

                ") << QString(); - - QTest::newRow("universal7") << true << QString(".charfmt1") << QString("

                ") << QString(); - - QTest::newRow("id") << true << QString("#blub") << QString("

                ") << QString(); - QTest::newRow("noid") << false << QString("#blub") << QString("

                ") << QString(); - - QTest::newRow("childselector") << true << QString("parent > child") - << QString("") - << QString("parent/child"); - - QTest::newRow("nochildselector2") << false << QString("parent > child") - << QString("") - << QString("child/parent"); - - QTest::newRow("nochildselector3") << false << QString("parent > child") - << QString("") - << QString("parent/intermediate/child"); - - QTest::newRow("childselector2") << true << QString("parent[foo=bar] > child") - << QString("") - << QString("parent/child"); - - QTest::newRow("nochildselector4") << false << QString("parent[foo=bar] > child") - << QString("") - << QString("parent/child"); - - QTest::newRow("nochildselector5") << false << QString("parent[foo=bar] > child") - << QString("") - << QString("parent/parent/child"); - - QTest::newRow("childselectors") << true << QString("grandparent > parent > child") - << QString("") - << QString("grandparent/parent/child"); - - QTest::newRow("descendant") << true << QString("grandparent child") - << QString("") - << QString("grandparent/parent/child"); - - QTest::newRow("nodescendant") << false << QString("grandparent child") - << QString("") - << QString("other/parent/child"); - - QTest::newRow("descendant2") << true << QString("grandgrandparent grandparent child") - << QString("") - << QString("grandgrandparent/inbetween/grandparent/parent/child"); - - QTest::newRow("combined") << true << QString("grandparent parent > child") - << QString("") - << QString("grandparent/inbetween/parent/child"); - - QTest::newRow("combined2") << true << QString("grandparent > parent child") - << QString("") - << QString("grandparent/parent/inbetween/child"); - - QTest::newRow("combined3") << true << QString("grandparent > parent child") - << QString("") - << QString("grandparent/parent/inbetween/child"); - - QTest::newRow("nocombined") << false << QString("grandparent parent > child") - << QString("") - << QString("inbetween/parent/child"); - - QTest::newRow("nocombined2") << false << QString("grandparent parent > child") - << QString("") - << QString("parent/child"); - - QTest::newRow("previoussibling") << true << QString("p1 + p2") - << QString("") - << QString("p2"); - - QTest::newRow("noprevioussibling") << false << QString("p2 + p1") - << QString("") - << QString("p2"); - - QTest::newRow("ancestry_firstmismatch") << false << QString("parent child[foo=bar]") - << QString("") - << QString("parent/child"); - - QTest::newRow("unknown-pseudo") << false << QString("p:enabled:foobar") << QString("

                ") << 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(""); - xml.append(""); - 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 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("selector"); - QTest::addColumn("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("firstSelector"); - QTest::addColumn("secondSelector"); - QTest::addColumn("xml"); - - QTest::newRow("universal1") << QString("*") << QString("p") << QString("

                "); - QTest::newRow("attr") << QString("p") << QString("p[foo=bar]") << QString("

                "); - QTest::newRow("id") << QString("p") << QString("#hey") << QString("

                "); - QTest::newRow("id2") << QString("[id=hey]") << QString("#hey") << QString("

                "); - QTest::newRow("class") << QString("p") << QString(".hey") << QString("

                "); -} - -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(""); - xml.append(""); - 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 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("xml"); - QTest::addColumn("css"); - QTest::addColumn("pseudoClass"); - QTest::addColumn("declCount"); - QTest::addColumn("value0"); - QTest::addColumn("value1"); - - QTest::newRow("universal1") << QString("

                ") << QString("* { color: red }") - << (quint64)QCss::PseudoClass_Unspecified << 1 << "red" << ""; - - QTest::newRow("basic") << QString("

                ") << QString("p:enabled { color: red; bg:blue; }") - << (quint64)QCss::PseudoClass_Enabled << 2 << "red" << "blue"; - - QTest::newRow("single") << QString("

                ") - << QString("p:enabled { color: red; } *:hover { color: white }") - << (quint64)QCss::PseudoClass_Hover << 1 << "white" << ""; - - QTest::newRow("multisel") << QString("

                ") - << QString("p:enabled { color: red; } p:hover { color: gray } *:hover { color: white } ") - << (quint64)QCss::PseudoClass_Hover << 2 << "white" << "gray"; - - QTest::newRow("multisel2") << QString("

                ") - << 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("

                ") - << QString("p:enabled { color: red; } p:hover:focus { color: gray } *:hover { color: white } ") - << quint64(QCss::PseudoClass_Hover) << 1 << "white" << ""; - - QTest::newRow("!-1") << QString("

                ") - << 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("

                ") - << 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("

                ") - << 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(""); - xml.append(""); - 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 rules = testSelector.styleRulesForNode(n); - - QVector 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("css"); - QTest::addColumn("expectedBrush"); - QTest::addColumn("expectedImage"); - QTest::addColumn("expectedRepeatValue"); - QTest::addColumn("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(" "))); - - 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 rules = testSelector.styleRulesForNode(n); - QVector 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("css"); - QTest::addColumn("pseudoElement"); - QTest::addColumn("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(" "))); - - 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 rules = testSelector.styleRulesForNode(n); - QVector 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("css"); - QTest::addColumn("type"); - QTest::addColumn("start"); - QTest::addColumn("finalStop"); - QTest::addColumn("spread"); - QTest::addColumn("stop0"); - QTest::addColumn("color0"); - QTest::addColumn("stop1"); - QTest::addColumn("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(" "))); - - 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 rules = testSelector.styleRulesForNode(n); - QVector 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(sbg.gradient()); - QCOMPARE(lg->start(), start); - QCOMPARE(lg->finalStop(), finalStop); - } else if (type == "conical") { - QVERIFY(sbg.style() == Qt::ConicalGradientPattern); - const QConicalGradient *cg = static_cast(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("css"); - QTest::addColumn("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 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("css"); - QTest::addColumn("expectedTopWidth"); - QTest::addColumn("expectedTopStyle"); - QTest::addColumn("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 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 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 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/qdesktopservices/.gitignore b/tests/auto/qdesktopservices/.gitignore deleted file mode 100644 index c7ce852ccd..0000000000 --- a/tests/auto/qdesktopservices/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdesktopservices diff --git a/tests/auto/qdesktopservices/qdesktopservices.pro b/tests/auto/qdesktopservices/qdesktopservices.pro deleted file mode 100644 index 0e51ed0459..0000000000 --- a/tests/auto/qdesktopservices/qdesktopservices.pro +++ /dev/null @@ -1,30 +0,0 @@ -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/qdesktopservices/tst_qdesktopservices.cpp b/tests/auto/qdesktopservices/tst_qdesktopservices.cpp deleted file mode 100644 index 8bea0a245b..0000000000 --- a/tests/auto/qdesktopservices/tst_qdesktopservices.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -//#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("url"); - QTest::addColumn("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("url"); - QTest::addColumn("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("url"); - QTest::addColumn("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("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/qdrag/.gitignore b/tests/auto/qdrag/.gitignore deleted file mode 100644 index d210808afe..0000000000 --- a/tests/auto/qdrag/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdrag diff --git a/tests/auto/qdrag/qdrag.pro b/tests/auto/qdrag/qdrag.pro deleted file mode 100644 index d9d645559b..0000000000 --- a/tests/auto/qdrag/qdrag.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qdrag.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qdrag.cpp - - diff --git a/tests/auto/qdrag/tst_qdrag.cpp b/tests/auto/qdrag/tst_qdrag.cpp deleted file mode 100644 index 4d18cefb2c..0000000000 --- a/tests/auto/qdrag/tst_qdrag.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - -//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/qevent/.gitignore b/tests/auto/qevent/.gitignore deleted file mode 100644 index 2a3ef2a115..0000000000 --- a/tests/auto/qevent/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qevent diff --git a/tests/auto/qevent/qevent.pro b/tests/auto/qevent/qevent.pro deleted file mode 100644 index 6042b6cdc9..0000000000 --- a/tests/auto/qevent/qevent.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qevent.cpp -QT = core -CONFIG += parallel_test diff --git a/tests/auto/qevent/tst_qevent.cpp b/tests/auto/qevent/tst_qevent.cpp deleted file mode 100644 index ae39380883..0000000000 --- a/tests/auto/qevent/tst_qevent.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include - -//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("hint"); - QTest::addColumn("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/qfileopenevent/qfileopenevent.pro b/tests/auto/qfileopenevent/qfileopenevent.pro deleted file mode 100644 index 73724828db..0000000000 --- a/tests/auto/qfileopenevent/qfileopenevent.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs -QT += widgets -SUBDIRS = test qfileopeneventexternal diff --git a/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp b/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp deleted file mode 100644 index 5d1a6a390f..0000000000 --- a/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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(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/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro b/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro deleted file mode 100644 index cb61b82e38..0000000000 --- a/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro +++ /dev/null @@ -1,10 +0,0 @@ -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/qfileopenevent/test/test.pro b/tests/auto/qfileopenevent/test/test.pro deleted file mode 100644 index 3f16dcf6ee..0000000000 --- a/tests/auto/qfileopenevent/test/test.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -TARGET = tst_qfileopenevent -HEADERS += -SOURCES += tst_qfileopenevent.cpp -symbian { - LIBS+=-lefsrv -lapgrfx -lapmime -} diff --git a/tests/auto/qfileopenevent/test/tst_qfileopenevent.cpp b/tests/auto/qfileopenevent/test/tst_qfileopenevent.cpp deleted file mode 100644 index 69cc4ccc01..0000000000 --- a/tests/auto/qfileopenevent/test/tst_qfileopenevent.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -#ifdef Q_OS_SYMBIAN -#include -#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 > 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 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 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(event); - appendFileContent(*fileOpenEvent, "+received"); - return true; -} - -void tst_qfileopenevent::sendAndReceive() -{ - QScopedPointer 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("filename"); - QTest::addColumn("targetContent"); - QTest::addColumn("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/qfont/.gitignore b/tests/auto/qfont/.gitignore deleted file mode 100644 index 61aa3df16c..0000000000 --- a/tests/auto/qfont/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfont diff --git a/tests/auto/qfont/qfont.pro b/tests/auto/qfont/qfont.pro deleted file mode 100644 index 891cb0a093..0000000000 --- a/tests/auto/qfont/qfont.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qfont.cpp - - diff --git a/tests/auto/qfont/tst_qfont.cpp b/tests/auto/qfont/tst_qfont.cpp deleted file mode 100644 index a564e71e19..0000000000 --- a/tests/auto/qfont/tst_qfont.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include -#include - -//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 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 sizes = fdb.pointSizes(family, style); - QVERIFY(!sizes.isEmpty()); - QList::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/qfontdatabase/.gitignore b/tests/auto/qfontdatabase/.gitignore deleted file mode 100644 index 65edf9b279..0000000000 --- a/tests/auto/qfontdatabase/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfontdatabase diff --git a/tests/auto/qfontdatabase/FreeMono.ttf b/tests/auto/qfontdatabase/FreeMono.ttf deleted file mode 100644 index d7ce52ddc7..0000000000 Binary files a/tests/auto/qfontdatabase/FreeMono.ttf and /dev/null differ diff --git a/tests/auto/qfontdatabase/qfontdatabase.pro b/tests/auto/qfontdatabase/qfontdatabase.pro deleted file mode 100644 index e7dfc3c73d..0000000000 --- a/tests/auto/qfontdatabase/qfontdatabase.pro +++ /dev/null @@ -1,10 +0,0 @@ -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/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/qfontdatabase/tst_qfontdatabase.cpp deleted file mode 100644 index 1df61d0a06..0000000000 --- a/tests/auto/qfontdatabase/tst_qfontdatabase.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include - -#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("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("font"); - QTest::addColumn("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("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("font"); - QTest::addColumn("pixelSize"); - QTest::addColumn("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("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/qfontmetrics/.gitignore b/tests/auto/qfontmetrics/.gitignore deleted file mode 100644 index 0b428672a3..0000000000 --- a/tests/auto/qfontmetrics/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfontmetrics diff --git a/tests/auto/qfontmetrics/qfontmetrics.pro b/tests/auto/qfontmetrics/qfontmetrics.pro deleted file mode 100644 index c0dc1abbe6..0000000000 --- a/tests/auto/qfontmetrics/qfontmetrics.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qfontmetrics.cpp -RESOURCES += testfont.qrc - diff --git a/tests/auto/qfontmetrics/testfont.qrc b/tests/auto/qfontmetrics/testfont.qrc deleted file mode 100644 index bc0c0b0959..0000000000 --- a/tests/auto/qfontmetrics/testfont.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - ucs4font.ttf - - diff --git a/tests/auto/qfontmetrics/tst_qfontmetrics.cpp b/tests/auto/qfontmetrics/tst_qfontmetrics.cpp deleted file mode 100644 index 982cfc11d9..0000000000 --- a/tests/auto/qfontmetrics/tst_qfontmetrics.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - - - -//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 sizes = fdb.pointSizes(family, style); - QVERIFY(!sizes.isEmpty()); - QList::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("font"); - QTest::addColumn("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 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(); -} - -void tst_QFontMetrics::elidedMultiLengthF() -{ - elidedMultiLength_helper(); -} - -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/qfontmetrics/ucs4font.ttf b/tests/auto/qfontmetrics/ucs4font.ttf deleted file mode 100644 index 31b6997779..0000000000 Binary files a/tests/auto/qfontmetrics/ucs4font.ttf and /dev/null differ diff --git a/tests/auto/qgl/qgl.qrc b/tests/auto/qgl/qgl.qrc index 653794a166..42281afc98 100644 --- a/tests/auto/qgl/qgl.qrc +++ b/tests/auto/qgl/qgl.qrc @@ -1,5 +1,5 @@ - ../qpixmap/images/designer.png + ../gui/image/qpixmap/images/designer.png diff --git a/tests/auto/qglyphrun/qglyphrun.pro b/tests/auto/qglyphrun/qglyphrun.pro deleted file mode 100644 index 480ad5b9a4..0000000000 --- a/tests/auto/qglyphrun/qglyphrun.pro +++ /dev/null @@ -1,11 +0,0 @@ -load(qttest_p4) -QT = core gui - -SOURCES += \ - tst_qglyphrun.cpp - -wince*|symbian*: { - DEFINES += SRCDIR=\\\"\\\" -} else { - DEFINES += SRCDIR=\\\"$$PWD/\\\" -} diff --git a/tests/auto/qglyphrun/test.ttf b/tests/auto/qglyphrun/test.ttf deleted file mode 100644 index 9043a576ef..0000000000 Binary files a/tests/auto/qglyphrun/test.ttf and /dev/null differ diff --git a/tests/auto/qglyphrun/tst_qglyphrun.cpp b/tests/auto/qglyphrun/tst_qglyphrun.cpp deleted file mode 100644 index e84915428f..0000000000 --- a/tests/auto/qglyphrun/tst_qglyphrun.cpp +++ /dev/null @@ -1,679 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - -// #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 glyphIndexes; - QVector 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 glyphIndexes; - QVector 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("one"); - QTest::addColumn("two"); - QTest::addColumn("equals"); - - QGlyphRun one(make_dummy_indexes()); - QGlyphRun two(make_dummy_indexes()); - - QTest::newRow("Identical") << one << two << true; - - { - QGlyphRun busted(two); - - QVector 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 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 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() << 2 << 2 << 2); - glyphRun.setPositions(QVector() << 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 glyphIndexArray; - glyphIndexArray << 3 << 2 << 1 << 4; - - QVector glyphPositionArray; - glyphPositionArray << QPointF(1, 2) << QPointF(3, 4) << QPointF(5, 6) << QPointF(7, 8); - - QGlyphRun glyphRun; - glyphRun.setRawData(glyphIndexArray.constData(), glyphPositionArray.constData(), 4); - - QVector glyphIndexes = glyphRun.glyphIndexes(); - QVector 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 glyphIndexes; - glyphIndexes.append(3); - - QVector 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 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 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() << 1 << 2 << 3); - - QGlyphRun otherGlyphs; - otherGlyphs = glyphs; - - QCOMPARE(otherGlyphs.glyphIndexes(), glyphs.glyphIndexes()); - - otherGlyphs.setGlyphIndexes(QVector() << 4 << 5 << 6); - - QCOMPARE(otherGlyphs.glyphIndexes(), QVector() << 4 << 5 << 6); - QCOMPARE(glyphs.glyphIndexes(), QVector() << 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/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index b8741fe3aa..194e023d05 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -50,7 +50,7 @@ #include #include #include "../../shared/util.h" -#include "../qpathclipper/pathcompare.h" +#include "../gui/painting/qpathclipper/pathcompare.h" #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) #include diff --git a/tests/auto/qguivariant/.gitignore b/tests/auto/qguivariant/.gitignore deleted file mode 100644 index ea64ae90a0..0000000000 --- a/tests/auto/qguivariant/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qguivariant diff --git a/tests/auto/qguivariant/qguivariant.pro b/tests/auto/qguivariant/qguivariant.pro deleted file mode 100644 index 68082f0037..0000000000 --- a/tests/auto/qguivariant/qguivariant.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qguivariant.cpp - - - diff --git a/tests/auto/qguivariant/tst_qguivariant.cpp b/tests/auto/qguivariant/tst_qguivariant.cpp deleted file mode 100644 index 988580b874..0000000000 --- a/tests/auto/qguivariant/tst_qguivariant.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include - - - -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(v) == QColor(Qt::red)); -} - - -QTEST_APPLESS_MAIN(tst_QGuiVariant) -#include "tst_qguivariant.moc" diff --git a/tests/auto/qicoimageformat/.gitignore b/tests/auto/qicoimageformat/.gitignore deleted file mode 100644 index 9f673c5635..0000000000 --- a/tests/auto/qicoimageformat/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qicoimageformat diff --git a/tests/auto/qicoimageformat/icons/invalid/35floppy.ico b/tests/auto/qicoimageformat/icons/invalid/35floppy.ico deleted file mode 100644 index 96087612fb..0000000000 Binary files a/tests/auto/qicoimageformat/icons/invalid/35floppy.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/35FLOPPY.ICO b/tests/auto/qicoimageformat/icons/valid/35FLOPPY.ICO deleted file mode 100644 index e9551d6390..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/35FLOPPY.ICO and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/AddPerfMon.ico b/tests/auto/qicoimageformat/icons/valid/AddPerfMon.ico deleted file mode 100644 index 3368d3634a..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/AddPerfMon.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/App.ico b/tests/auto/qicoimageformat/icons/valid/App.ico deleted file mode 100644 index 03b80a68f8..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/App.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico b/tests/auto/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico deleted file mode 100644 index 8da119efdd..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/Obj_N2_Internal_Mem.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/Qt.ico b/tests/auto/qicoimageformat/icons/valid/Qt.ico deleted file mode 100644 index fef1dee146..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/Qt.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/Status_Play.ico b/tests/auto/qicoimageformat/icons/valid/Status_Play.ico deleted file mode 100644 index d05782cce9..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/Status_Play.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/TIMER01.ICO b/tests/auto/qicoimageformat/icons/valid/TIMER01.ICO deleted file mode 100644 index 5563beec8c..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/TIMER01.ICO and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/WORLD.ico b/tests/auto/qicoimageformat/icons/valid/WORLD.ico deleted file mode 100644 index 7a8ab39f56..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/WORLD.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/WORLDH.ico b/tests/auto/qicoimageformat/icons/valid/WORLDH.ico deleted file mode 100644 index c2b48f8d99..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/WORLDH.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/abcardWindow.ico b/tests/auto/qicoimageformat/icons/valid/abcardWindow.ico deleted file mode 100644 index e78a15c42b..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/abcardWindow.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/semitransparent.ico b/tests/auto/qicoimageformat/icons/valid/semitransparent.ico deleted file mode 100644 index 893ceb254c..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/semitransparent.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/icons/valid/trolltechlogo_tiny.ico b/tests/auto/qicoimageformat/icons/valid/trolltechlogo_tiny.ico deleted file mode 100644 index 3e02a53e58..0000000000 Binary files a/tests/auto/qicoimageformat/icons/valid/trolltechlogo_tiny.ico and /dev/null differ diff --git a/tests/auto/qicoimageformat/qicoimageformat.pro b/tests/auto/qicoimageformat/qicoimageformat.pro deleted file mode 100644 index c150c9af9f..0000000000 --- a/tests/auto/qicoimageformat/qicoimageformat.pro +++ /dev/null @@ -1,28 +0,0 @@ -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/qicoimageformat/tst_qicoimageformat.cpp b/tests/auto/qicoimageformat/tst_qicoimageformat.cpp deleted file mode 100644 index 3aace12fdb..0000000000 --- a/tests/auto/qicoimageformat/tst_qicoimageformat.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -#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(fmt.data()), "ico" ); -} - -void tst_QIcoImageFormat::canRead_data() -{ - QTest::addColumn("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("index"); - QTest::addColumn("width"); - QTest::addColumn("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/qicon/.gitignore b/tests/auto/qicon/.gitignore deleted file mode 100644 index c101ef9d28..0000000000 --- a/tests/auto/qicon/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qicon diff --git a/tests/auto/qicon/heart.svg b/tests/auto/qicon/heart.svg deleted file mode 100644 index 8c982cd93c..0000000000 --- a/tests/auto/qicon/heart.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - -Heart Left-Highlight -This is a normal valentines day heart. - - -holiday -valentines - -valentine -hash(0x8a091c0) -hash(0x8a0916c) -signs_and_symbols -hash(0x8a091f0) -day - - - - -Jon Phillips - - - - -Jon Phillips - - - - -Jon Phillips - - - -image/svg+xml - - -en - - - - - - - - - - - - - - - diff --git a/tests/auto/qicon/heart.svgz b/tests/auto/qicon/heart.svgz deleted file mode 100644 index 0f0913ffa7..0000000000 Binary files a/tests/auto/qicon/heart.svgz and /dev/null differ diff --git a/tests/auto/qicon/icons/testtheme/16x16/actions/appointment-new.png b/tests/auto/qicon/icons/testtheme/16x16/actions/appointment-new.png deleted file mode 100644 index 18b7c6781e..0000000000 Binary files a/tests/auto/qicon/icons/testtheme/16x16/actions/appointment-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/testtheme/22x22/actions/appointment-new.png b/tests/auto/qicon/icons/testtheme/22x22/actions/appointment-new.png deleted file mode 100644 index d676ffd463..0000000000 Binary files a/tests/auto/qicon/icons/testtheme/22x22/actions/appointment-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/testtheme/32x32/actions/appointment-new.png b/tests/auto/qicon/icons/testtheme/32x32/actions/appointment-new.png deleted file mode 100644 index 85daef3b0b..0000000000 Binary files a/tests/auto/qicon/icons/testtheme/32x32/actions/appointment-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/testtheme/index.theme b/tests/auto/qicon/icons/testtheme/index.theme deleted file mode 100644 index e18736ab43..0000000000 --- a/tests/auto/qicon/icons/testtheme/index.theme +++ /dev/null @@ -1,492 +0,0 @@ -[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/qicon/icons/testtheme/scalable/actions/svg-only.svg b/tests/auto/qicon/icons/testtheme/scalable/actions/svg-only.svg deleted file mode 100644 index 4cb14f82f0..0000000000 --- a/tests/auto/qicon/icons/testtheme/scalable/actions/svg-only.svg +++ /dev/null @@ -1,425 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - Jakub Steiner - - - http://jimmac.musichall.cz - - New Appointment - - - appointment - new - meeting - rvsp - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/auto/qicon/icons/themeparent/16x16/actions/address-book-new.png b/tests/auto/qicon/icons/themeparent/16x16/actions/address-book-new.png deleted file mode 100644 index 2098cfdf36..0000000000 Binary files a/tests/auto/qicon/icons/themeparent/16x16/actions/address-book-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/themeparent/16x16/actions/appointment-new.png b/tests/auto/qicon/icons/themeparent/16x16/actions/appointment-new.png deleted file mode 100644 index 18b7c6781e..0000000000 Binary files a/tests/auto/qicon/icons/themeparent/16x16/actions/appointment-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/themeparent/22x22/actions/address-book-new.png b/tests/auto/qicon/icons/themeparent/22x22/actions/address-book-new.png deleted file mode 100644 index fad446cd92..0000000000 Binary files a/tests/auto/qicon/icons/themeparent/22x22/actions/address-book-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/themeparent/22x22/actions/appointment-new.png b/tests/auto/qicon/icons/themeparent/22x22/actions/appointment-new.png deleted file mode 100644 index d676ffd463..0000000000 Binary files a/tests/auto/qicon/icons/themeparent/22x22/actions/appointment-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/themeparent/32x32/actions/address-book-new.png b/tests/auto/qicon/icons/themeparent/32x32/actions/address-book-new.png deleted file mode 100644 index 420139d307..0000000000 Binary files a/tests/auto/qicon/icons/themeparent/32x32/actions/address-book-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/themeparent/32x32/actions/appointment-new.png b/tests/auto/qicon/icons/themeparent/32x32/actions/appointment-new.png deleted file mode 100644 index 85daef3b0b..0000000000 Binary files a/tests/auto/qicon/icons/themeparent/32x32/actions/appointment-new.png and /dev/null differ diff --git a/tests/auto/qicon/icons/themeparent/index.theme b/tests/auto/qicon/icons/themeparent/index.theme deleted file mode 100644 index e536a0bf2f..0000000000 --- a/tests/auto/qicon/icons/themeparent/index.theme +++ /dev/null @@ -1,492 +0,0 @@ -[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/qicon/icons/themeparent/scalable/actions/address-book-new.svg b/tests/auto/qicon/icons/themeparent/scalable/actions/address-book-new.svg deleted file mode 100644 index 600a82c1b0..0000000000 --- a/tests/auto/qicon/icons/themeparent/scalable/actions/address-book-new.svg +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - Addess Book - New - - - - Jakub Steiner - - - http://jimmac.musichall.cz - - - address - contact - book - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/auto/qicon/icons/themeparent/scalable/actions/appointment-new.svg b/tests/auto/qicon/icons/themeparent/scalable/actions/appointment-new.svg deleted file mode 100644 index 4cb14f82f0..0000000000 --- a/tests/auto/qicon/icons/themeparent/scalable/actions/appointment-new.svg +++ /dev/null @@ -1,425 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - Jakub Steiner - - - http://jimmac.musichall.cz - - New Appointment - - - appointment - new - meeting - rvsp - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/auto/qicon/image.png b/tests/auto/qicon/image.png deleted file mode 100644 index 8d703640c1..0000000000 Binary files a/tests/auto/qicon/image.png and /dev/null differ diff --git a/tests/auto/qicon/qicon.pro b/tests/auto/qicon/qicon.pro deleted file mode 100644 index cc87fae539..0000000000 --- a/tests/auto/qicon/qicon.pro +++ /dev/null @@ -1,30 +0,0 @@ -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/qicon/rect.png b/tests/auto/qicon/rect.png deleted file mode 100644 index b5d3ecbddf..0000000000 Binary files a/tests/auto/qicon/rect.png and /dev/null differ diff --git a/tests/auto/qicon/rect.svg b/tests/auto/qicon/rect.svg deleted file mode 100644 index 8eb24727be..0000000000 --- a/tests/auto/qicon/rect.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/tests/auto/qicon/trash.svg b/tests/auto/qicon/trash.svg deleted file mode 100644 index c44e4c75a2..0000000000 --- a/tests/auto/qicon/trash.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - - -Keep Tidy Inside - - - - -symbol -bin -signs_and_symbols -clean -rubish -trash -inside -garbage -sign - - - - -Martin Owens - - - - -Martin Owens - - - - -Martin Owens - - - -image/svg+xml - - -en - - - - - - - - - - - - - - - - - diff --git a/tests/auto/qicon/tst_qicon.cpp b/tests/auto/qicon/tst_qicon.cpp deleted file mode 100644 index 4c430f9435..0000000000 --- a/tests/auto/qicon/tst_qicon.cpp +++ /dev/null @@ -1,781 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -#if defined(Q_OS_SYMBIAN) -#define SRCDIR "." -#endif -#include - -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("source"); - QTest::addColumn("argument"); - QTest::addColumn("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("argument"); - QTest::addColumn("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 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 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 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 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 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("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/qicon/tst_qicon.qrc b/tests/auto/qicon/tst_qicon.qrc deleted file mode 100644 index 7925a33c84..0000000000 --- a/tests/auto/qicon/tst_qicon.qrc +++ /dev/null @@ -1,20 +0,0 @@ - - -image.png -rect.png -./icons/testtheme/16x16/actions/appointment-new.png -./icons/testtheme/22x22/actions/appointment-new.png -./icons/testtheme/32x32/actions/appointment-new.png -./icons/testtheme/index.theme -./icons/testtheme/scalable/actions/svg-only.svg -./icons/themeparent/16x16/actions/address-book-new.png -./icons/themeparent/16x16/actions/appointment-new.png -./icons/themeparent/22x22/actions/address-book-new.png -./icons/themeparent/22x22/actions/appointment-new.png -./icons/themeparent/32x32/actions/address-book-new.png -./icons/themeparent/32x32/actions/appointment-new.png -./icons/themeparent/index.theme -./icons/themeparent/scalable/actions/address-book-new.svg -./icons/themeparent/scalable/actions/appointment-new.svg - - diff --git a/tests/auto/qimage/.gitignore b/tests/auto/qimage/.gitignore deleted file mode 100644 index d8afbffa72..0000000000 --- a/tests/auto/qimage/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qimage diff --git a/tests/auto/qimage/images/image.bmp b/tests/auto/qimage/images/image.bmp deleted file mode 100644 index 39640e43e9..0000000000 Binary files a/tests/auto/qimage/images/image.bmp and /dev/null differ diff --git a/tests/auto/qimage/images/image.gif b/tests/auto/qimage/images/image.gif deleted file mode 100644 index 2c5a7f87e9..0000000000 Binary files a/tests/auto/qimage/images/image.gif and /dev/null differ diff --git a/tests/auto/qimage/images/image.ico b/tests/auto/qimage/images/image.ico deleted file mode 100644 index 7312d20f87..0000000000 Binary files a/tests/auto/qimage/images/image.ico and /dev/null differ diff --git a/tests/auto/qimage/images/image.jpg b/tests/auto/qimage/images/image.jpg deleted file mode 100644 index 7611322b1b..0000000000 Binary files a/tests/auto/qimage/images/image.jpg and /dev/null differ diff --git a/tests/auto/qimage/images/image.pbm b/tests/auto/qimage/images/image.pbm deleted file mode 100644 index 67e5efa3e9..0000000000 --- a/tests/auto/qimage/images/image.pbm +++ /dev/null @@ -1,8 +0,0 @@ -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/qimage/images/image.pgm b/tests/auto/qimage/images/image.pgm deleted file mode 100644 index 443bf40964..0000000000 --- a/tests/auto/qimage/images/image.pgm +++ /dev/null @@ -1,10 +0,0 @@ -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/qimage/images/image.png b/tests/auto/qimage/images/image.png deleted file mode 100644 index 7d4890a7ff..0000000000 Binary files a/tests/auto/qimage/images/image.png and /dev/null differ diff --git a/tests/auto/qimage/images/image.ppm b/tests/auto/qimage/images/image.ppm deleted file mode 100644 index 2a5640e189..0000000000 --- a/tests/auto/qimage/images/image.ppm +++ /dev/null @@ -1,7 +0,0 @@ -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/qimage/images/image.tif b/tests/auto/qimage/images/image.tif deleted file mode 100644 index ee0637cf25..0000000000 Binary files a/tests/auto/qimage/images/image.tif and /dev/null differ diff --git a/tests/auto/qimage/images/image.xbm b/tests/auto/qimage/images/image.xbm deleted file mode 100644 index d0e0fcf2c1..0000000000 --- a/tests/auto/qimage/images/image.xbm +++ /dev/null @@ -1,5 +0,0 @@ -#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/qimage/images/image.xpm b/tests/auto/qimage/images/image.xpm deleted file mode 100644 index 264ba401e6..0000000000 --- a/tests/auto/qimage/images/image.xpm +++ /dev/null @@ -1,261 +0,0 @@ -/* XPM */ -static char * foo_xpm[] = { -"256 256 2 1", -" c None", -". c #E22626", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................", -"................................................................................................................................................................................................................................................................"}; diff --git a/tests/auto/qimage/qimage.pro b/tests/auto/qimage/qimage.pro deleted file mode 100644 index b517bc1237..0000000000 --- a/tests/auto/qimage/qimage.pro +++ /dev/null @@ -1,23 +0,0 @@ -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/qimage/tst_qimage.cpp b/tests/auto/qimage/tst_qimage.cpp deleted file mode 100644 index dce2957ae4..0000000000 --- a/tests/auto/qimage/tst_qimage.cpp +++ /dev/null @@ -1,2014 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include - -#include -#include - - -//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("testFormat"); - QTest::addColumn("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 formats = QImageReader::supportedImageFormats(); - // qDebug("Image input formats : %s", formats.join(" | ").latin1()); - - bool formatSupported = false; - for (QList::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("red"); - QTest::addColumn("green"); - QTest::addColumn("blue"); - QTest::addColumn("alpha"); - QTest::addColumn("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("inFormat"); - QTest::addColumn("inPixel"); - QTest::addColumn("resFormat"); - QTest::addColumn("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("x"); - QTest::addColumn("y"); - QTest::addColumn("alpha1"); - QTest::addColumn("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("format"); - QTest::addColumn("degrees"); - - QVector 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("format"); - QTest::addColumn("value"); - QTest::addColumn("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 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("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("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 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 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("format"); - QTest::addColumn("color"); - QTest::addColumn("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 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("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 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/qimageiohandler/.gitignore b/tests/auto/qimageiohandler/.gitignore deleted file mode 100644 index 6ea7bdb667..0000000000 --- a/tests/auto/qimageiohandler/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qimageiohandler diff --git a/tests/auto/qimageiohandler/qimageiohandler.pro b/tests/auto/qimageiohandler/qimageiohandler.pro deleted file mode 100644 index 46e5cfb2cf..0000000000 --- a/tests/auto/qimageiohandler/qimageiohandler.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qimageiohandler.h -############################################################ - -load(qttest_p4) - -SOURCES += tst_qimageiohandler.cpp - - diff --git a/tests/auto/qimageiohandler/tst_qimageiohandler.cpp b/tests/auto/qimageiohandler/tst_qimageiohandler.cpp deleted file mode 100644 index dd132302f8..0000000000 --- a/tests/auto/qimageiohandler/tst_qimageiohandler.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - -//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/qimagereader/.gitignore b/tests/auto/qimagereader/.gitignore deleted file mode 100644 index fdf03f239d..0000000000 --- a/tests/auto/qimagereader/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tst_qimagereader -junk diff --git a/tests/auto/qimagereader/baseline/35floppy.png b/tests/auto/qimagereader/baseline/35floppy.png deleted file mode 100644 index 56b9b44c47..0000000000 Binary files a/tests/auto/qimagereader/baseline/35floppy.png and /dev/null differ diff --git a/tests/auto/qimagereader/baseline/connect.png b/tests/auto/qimagereader/baseline/connect.png deleted file mode 100644 index 9544bb9c76..0000000000 Binary files a/tests/auto/qimagereader/baseline/connect.png and /dev/null differ diff --git a/tests/auto/qimagereader/baseline/kde_favicon.png b/tests/auto/qimagereader/baseline/kde_favicon.png deleted file mode 100644 index e19287b49d..0000000000 Binary files a/tests/auto/qimagereader/baseline/kde_favicon.png and /dev/null differ diff --git a/tests/auto/qimagereader/baseline/semitransparent.png b/tests/auto/qimagereader/baseline/semitransparent.png deleted file mode 100644 index a3ad780699..0000000000 Binary files a/tests/auto/qimagereader/baseline/semitransparent.png and /dev/null differ diff --git a/tests/auto/qimagereader/images/16bpp.bmp b/tests/auto/qimagereader/images/16bpp.bmp deleted file mode 100644 index 74ce63edd4..0000000000 Binary files a/tests/auto/qimagereader/images/16bpp.bmp and /dev/null differ diff --git a/tests/auto/qimagereader/images/4bpp-rle.bmp b/tests/auto/qimagereader/images/4bpp-rle.bmp deleted file mode 100644 index ae71e678fd..0000000000 Binary files a/tests/auto/qimagereader/images/4bpp-rle.bmp and /dev/null differ diff --git a/tests/auto/qimagereader/images/YCbCr_cmyk.jpg b/tests/auto/qimagereader/images/YCbCr_cmyk.jpg deleted file mode 100644 index b8aa9ea609..0000000000 Binary files a/tests/auto/qimagereader/images/YCbCr_cmyk.jpg and /dev/null differ diff --git a/tests/auto/qimagereader/images/YCbCr_cmyk.png b/tests/auto/qimagereader/images/YCbCr_cmyk.png deleted file mode 100644 index a24db1b13f..0000000000 Binary files a/tests/auto/qimagereader/images/YCbCr_cmyk.png and /dev/null differ diff --git a/tests/auto/qimagereader/images/YCbCr_rgb.jpg b/tests/auto/qimagereader/images/YCbCr_rgb.jpg deleted file mode 100644 index 8771224cb5..0000000000 Binary files a/tests/auto/qimagereader/images/YCbCr_rgb.jpg and /dev/null differ diff --git a/tests/auto/qimagereader/images/away.png b/tests/auto/qimagereader/images/away.png deleted file mode 100644 index 0e21a37883..0000000000 Binary files a/tests/auto/qimagereader/images/away.png and /dev/null differ diff --git a/tests/auto/qimagereader/images/ball.mng b/tests/auto/qimagereader/images/ball.mng deleted file mode 100644 index 81544780fd..0000000000 Binary files a/tests/auto/qimagereader/images/ball.mng and /dev/null differ diff --git a/tests/auto/qimagereader/images/bat1.gif b/tests/auto/qimagereader/images/bat1.gif deleted file mode 100644 index cb6f4f7a8e..0000000000 Binary files a/tests/auto/qimagereader/images/bat1.gif and /dev/null differ diff --git a/tests/auto/qimagereader/images/bat2.gif b/tests/auto/qimagereader/images/bat2.gif deleted file mode 100644 index fbbda4ef76..0000000000 Binary files a/tests/auto/qimagereader/images/bat2.gif and /dev/null differ diff --git a/tests/auto/qimagereader/images/beavis.jpg b/tests/auto/qimagereader/images/beavis.jpg deleted file mode 100644 index d55504779b..0000000000 Binary files a/tests/auto/qimagereader/images/beavis.jpg and /dev/null differ diff --git a/tests/auto/qimagereader/images/black.png b/tests/auto/qimagereader/images/black.png deleted file mode 100644 index 6c94085ed5..0000000000 Binary files a/tests/auto/qimagereader/images/black.png and /dev/null differ diff --git a/tests/auto/qimagereader/images/black.xpm b/tests/auto/qimagereader/images/black.xpm deleted file mode 100644 index d7925bf211..0000000000 --- a/tests/auto/qimagereader/images/black.xpm +++ /dev/null @@ -1,65 +0,0 @@ -/* 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/qimagereader/images/colorful.bmp b/tests/auto/qimagereader/images/colorful.bmp deleted file mode 100644 index 8ea6f4acd7..0000000000 Binary files a/tests/auto/qimagereader/images/colorful.bmp and /dev/null differ diff --git a/tests/auto/qimagereader/images/corrupt-colors.xpm b/tests/auto/qimagereader/images/corrupt-colors.xpm deleted file mode 100644 index f8d80edbbc..0000000000 --- a/tests/auto/qimagereader/images/corrupt-colors.xpm +++ /dev/null @@ -1,26 +0,0 @@ -/* 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/qimagereader/images/corrupt-data.tif b/tests/auto/qimagereader/images/corrupt-data.tif deleted file mode 100644 index d63c688b27..0000000000 Binary files a/tests/auto/qimagereader/images/corrupt-data.tif and /dev/null differ diff --git a/tests/auto/qimagereader/images/corrupt-pixel-count.xpm b/tests/auto/qimagereader/images/corrupt-pixel-count.xpm deleted file mode 100644 index 3a736ff262..0000000000 --- a/tests/auto/qimagereader/images/corrupt-pixel-count.xpm +++ /dev/null @@ -1,11 +0,0 @@ -/* 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/qimagereader/images/corrupt-pixels.xpm b/tests/auto/qimagereader/images/corrupt-pixels.xpm deleted file mode 100644 index 21031ee604..0000000000 --- a/tests/auto/qimagereader/images/corrupt-pixels.xpm +++ /dev/null @@ -1,7 +0,0 @@ -/* XPM */ -static char * test_xpm[] = { -"256 256 1 1", -" c grey", -" ", -" ", -" "}; diff --git a/tests/auto/qimagereader/images/corrupt.bmp b/tests/auto/qimagereader/images/corrupt.bmp deleted file mode 100644 index 824190bdeb..0000000000 Binary files a/tests/auto/qimagereader/images/corrupt.bmp and /dev/null differ diff --git a/tests/auto/qimagereader/images/corrupt.gif b/tests/auto/qimagereader/images/corrupt.gif deleted file mode 100644 index 07259454c9..0000000000 Binary files a/tests/auto/qimagereader/images/corrupt.gif and /dev/null differ diff --git a/tests/auto/qimagereader/images/corrupt.jpg b/tests/auto/qimagereader/images/corrupt.jpg deleted file mode 100644 index 1959662922..0000000000 Binary files a/tests/auto/qimagereader/images/corrupt.jpg and /dev/null differ diff --git a/tests/auto/qimagereader/images/corrupt.mng b/tests/auto/qimagereader/images/corrupt.mng deleted file mode 100644 index 17fd43a5ca..0000000000 Binary files a/tests/auto/qimagereader/images/corrupt.mng and /dev/null differ diff --git a/tests/auto/qimagereader/images/corrupt.png b/tests/auto/qimagereader/images/corrupt.png deleted file mode 100644 index 9d8911c64e..0000000000 Binary files a/tests/auto/qimagereader/images/corrupt.png and /dev/null differ diff --git a/tests/auto/qimagereader/images/corrupt.svg b/tests/auto/qimagereader/images/corrupt.svg deleted file mode 100644 index 8747df008f..0000000000 --- a/tests/auto/qimagereader/images/corrupt.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/auto/qimagereader/images/rect.svgz b/tests/auto/qimagereader/images/rect.svgz deleted file mode 100644 index c2e193b989..0000000000 Binary files a/tests/auto/qimagereader/images/rect.svgz and /dev/null differ diff --git a/tests/auto/qimagereader/images/rgba_adobedeflate_littleendian.tif b/tests/auto/qimagereader/images/rgba_adobedeflate_littleendian.tif deleted file mode 100644 index 78868b0d48..0000000000 Binary files a/tests/auto/qimagereader/images/rgba_adobedeflate_littleendian.tif and /dev/null differ diff --git a/tests/auto/qimagereader/images/rgba_lzw_littleendian.tif b/tests/auto/qimagereader/images/rgba_lzw_littleendian.tif deleted file mode 100644 index 107eab74e7..0000000000 Binary files a/tests/auto/qimagereader/images/rgba_lzw_littleendian.tif and /dev/null differ diff --git a/tests/auto/qimagereader/images/rgba_nocompression_bigendian.tif b/tests/auto/qimagereader/images/rgba_nocompression_bigendian.tif deleted file mode 100644 index c314bae4c0..0000000000 Binary files a/tests/auto/qimagereader/images/rgba_nocompression_bigendian.tif and /dev/null differ diff --git a/tests/auto/qimagereader/images/rgba_nocompression_littleendian.tif b/tests/auto/qimagereader/images/rgba_nocompression_littleendian.tif deleted file mode 100644 index 4f820f6649..0000000000 Binary files a/tests/auto/qimagereader/images/rgba_nocompression_littleendian.tif and /dev/null differ diff --git a/tests/auto/qimagereader/images/rgba_packbits_littleendian.tif b/tests/auto/qimagereader/images/rgba_packbits_littleendian.tif deleted file mode 100644 index ddeec38fbc..0000000000 Binary files a/tests/auto/qimagereader/images/rgba_packbits_littleendian.tif and /dev/null differ diff --git a/tests/auto/qimagereader/images/rgba_zipdeflate_littleendian.tif b/tests/auto/qimagereader/images/rgba_zipdeflate_littleendian.tif deleted file mode 100644 index 50a3024246..0000000000 Binary files a/tests/auto/qimagereader/images/rgba_zipdeflate_littleendian.tif and /dev/null differ diff --git a/tests/auto/qimagereader/images/runners.ppm b/tests/auto/qimagereader/images/runners.ppm deleted file mode 100644 index fda1c97073..0000000000 Binary files a/tests/auto/qimagereader/images/runners.ppm and /dev/null differ diff --git a/tests/auto/qimagereader/images/teapot.ppm b/tests/auto/qimagereader/images/teapot.ppm deleted file mode 100644 index b8ab85f3a5..0000000000 --- a/tests/auto/qimagereader/images/teapot.ppm +++ /dev/null @@ -1,31 +0,0 @@ -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!j@#k@$h>"dµf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&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: X/K%���������&4$+2F=;HPEJL&\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlR¶xT­sTµd)ŠO$w; m6 -g3 -a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d!Y0�����������W+]. s=‡M$dPŸlR\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀoTM¥oRdPvE"V+K%A 99���†F¤['qUMtVM99H:9H:9H:9H:9H:9H:9H:9H:9H:9H99H99H99H99H99H99H:9H;:H>;HB=HPDJ\JKmSMwXN|ZN°y[ᦆ֘uº{W¹yU¿€]Á„b­tU£nR—hQˆaO{ZNvWNtVMvXNwXNyYNzYN{ZN|ZN}[N}[N~[N~[N~[N~[N~[N~[N~[N}[N}[N{ZNzYNxXN…L$f3 -���I$L&P(U*\. €J#\O›jQ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀžkR‰aOo9 L&C!:4���f3 -X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?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$���G#K%Q(W+zG#nTM˜iQ\À\À\À\À\À\À\À\À\À\À\À\ÀdOLrUMuWNwXNyYN{ZN}[N{ZNwXNsVM \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àˆ`OcPnA"M&@ 8F#���m6 -›W&rVMvWNyYNzYN|ZN}[N}[N>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%���F#B!Y,L&U*~I#„^O†`O\À\À\À\ÀcNLrUMzYN\O„^Oˆ`OŠbPŒcPdPeP’fP“fP“fQ“fQ”fQ‘ePcP‰aP~[N�\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À’fPsVM^/ C!7 ������ŽQ%tVMwXNzYN|ZN}[N\N\O€\O]O]O‚]O‚]OA=HB=HB=HB>HC>HC>ID?IE?IF@IG@IIAIKBIŒcPdP’eP–gQšiQŸlR£nR¤\'´d)¿i*Æm+Îs/Ïs/Êo+Én+Ål*¾i*ºg)³c(ª_(ªqS¦oR¡mRkQ™iQ•gQ“fP‘ePŽdPcPŒbP‹bPŠbPŠaP‰aP‰aO‰aOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O„^Oƒ^O‚]O\O}[N›Q��D"?D"K%_/ kRL’fPODJSFJ†_OŠbPŽcP‘eP“fQ–gQ™iQœjQžkR lR¡mR£nR¤nR¥oR¥oR¥oR¤nR¢mRŸlRšiQ‘eP…_O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀB+‘ePI#L&90���y< šPxXN{ZN}[N\N€\O]O‚]Oƒ^Oƒ^O„^O„_O…_O…_O†_O†`O‡`O‡`Oˆ`O‰aOŠaP‹bPŒbPcPŽdP‘eP“fP•gQ˜hQšiQžkR¢mR¡Z'«_(¶e)½h)Âk*Çn,Çn,Æm*Æl*Áj*ºf)¶e)²c(«_(¦]'§pR¤nR¡mRžkR›jQ™iQ–gQ”gQ“fP‘ePdPdPŽdPŽcPcPŒcPŒbP‹bP‹bP‹bPŠbPŠaP‰aP‰aO‰aOˆ`O‡`O†_O…_Oƒ^O]Oª_(@ ���B!I$B!N'w=‘eP`LKbNLeOLkR mR£nR¥oR§pSªqS¬rS®sS¯tS°tS°tS±uS±uS°tS¯tS­sSªrS§pS¢mRšjQŒbPjQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‹bPpTME"5���������‡M$tVM{ZN}[N\O]O‚^Oƒ^O„_O…_O†_O†`O‡`Oˆ`Oˆ`O‰aO‰aPŠaPŠbP‹bPŒbPcPŽcPdPdP’eP“fP•gQ—hQ™iQ›jQkR lR¢mR¡Z'¬`(µd)ºg)ÇgÀj*Àj*¾i*¿i*»g)µd)²c(¯a(ª_(¤\'§pR¥oR¢nR mRžkRœjQšiQ˜iQ—hQ•gQ”gQ“fP’eP‘eP‘ePdPdPdPŽcPŽcPcPcPŒcPŒbP‹bP‹bPŠbPŠaP‰aOˆ`O†_O„^O\NœQ����@ <G#_LKŽcPlSMnTMpUMsVM°tS²uT³vTµwT¶wT¶xT¶xT¶wTµwT´vT²uT¯tS¬sSªqS§pS¤oR¢nRžkR˜hQ‹bPeOL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN\NJ%0������1ŽJvWN}[N\O]Oƒ^O…_O†_O†`O‡`Oˆ`O‰aO‰aPŠaPŠbP‹bPŒbPŒbPcPŽcPŽdPdPdP‘eP’eP”fQ•gQ–gQ˜hQ™iQ›jQkQŸlR¡mRžY&¦]'­`(³c(·e)Àc¸\¸\¹\º]»]¶^®a(¬`(©^'£['¢['¥oR£nR¡mR lRžkRœkQ›jQšiQ˜iQ—hQ–gQ•gQ”gQ”fQ“fP’eP’eP‘eP‘ePdPdPdPdPŽdPŽcPcPcPŒbP‹bPŠaPˆaO†`O]O˜O������G#7F#uWMƒ^OwXNxXNzYN{ZN|ZN¹yT¸yT·xT´wT±uT­sS¨pS¡mRœjQ•gQdPŒbP‰aP‰aPŒbPŽcP‘ePcP|ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[JKŠbP^/ 1 01|> wXN}[N]Oƒ^O…_O‡`O‡`OˆaO‰aPŠaP‹bP‹bPŒbPŒcPcPŽcPŽcPdPdPdP‘eP’eP“fP”fQ•gQ–gQ—hQ˜hQ™iQ›jQœkQžkRŸlR mRžY&¦]'­`(±b(·[ÇgÉiÉhÅfÂdÃe¿c«Uª_(§]'£[' Z'¤nR£nR¡mR mRŸlRžkRkQœjQšjQšiQ™iQ˜hQ—hQ–gQ•gQ•gQ”fQ”fQ“fP“fP’eP’eP‘eP‘ePePdPdPdPŽcPcPŒbPŠbPˆ`Oƒ^O‰D �����4M&dPnSM|[N|[O|[OzZOxXNªrS¢nR˜hQŽcPƒ^OvXNiQL^KKRFJMCJJAIKBISFJ\JKnSMxYN†_O€\OaMK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀB!qUMŠaPC!/00a0 uWN}[N‚]O…_O†`Oˆ`O‰aPŠaP‹bPŒbPŒcPcPŽcPŽcPdPdPdP‘eP‘eP’eP“fP“fQ”fQ•gQ–gQ—hQ˜hQ™iQ™iQ›jQœjQkRžlRŸlRœX&¢['¨^'¬`(´ZÂdÄfÈiÆgÂd¿c¿c¼a¸_©T¥\'£[' Z'ŸY&£nR¢mR¡mR lRŸlRžkRkQœjQ›jQšjQšiQ™iQ˜hQ—hQ—hQ–hQ–gQ•gQ•gQ”gQ”fQ”fQ“fQ“fP’fP’eP‘eP‘ePdPdPŽcPŒbP‰aOƒ^Ox< �������:ŠaP]Oj8sVMmSMfOL^KKUGJIAIQEJ?IeZY638*  B\À\À\À\À\À,  4 .G1!\TU¡ƒrsVM{ZN`MK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[JKyYNŒbP/0������ˆN$]O…_Oˆ`O‹bPŒbPcPŽcPdPdPdP‘eP‘eP’eP’fP“fP“fQ”fQ”gQ•gQ–gQ–gQ—hQ—hQ˜hQ™iQ™iQšiQ›jQœjQœkQkRžkRŸlRœO¡Z'¥\'©^'­V¼a¾bÁeÆi!Ãf¾b»a¹`·_³]²\µZ¢[' Z'ŸY&œQ¡mR¡mR mR lRŸlRŸlRžkRkRkQœkQœjQ›jQ›jQšjQšiQšiQ™iQ™iQ˜iQ˜hQ˜hQ—hQ—hQ—hQ–hQ–gQ–gQ•gQ•gQ”fQ’fPdPcPšW&������������dPŠaPrUM - B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6 - ���X,uWM‚]O‡`OŠbPcPŽdPdPdP‘eP’eP’fP“fP“fQ”fQ”gQ•gQ•gQ–gQ–gQ—hQ—hQ˜hQ˜iQ™iQ™iQšiQ›jQ›jQœjQœkQkQžkRžlRŸlR¢Z'¤\'§]'·_¹`¼a½bÁeÅi"Áe¼aº`·_¶_²]²\±\«Y¡Z' Z'¡Z'¡mR¡mR mR lR lRŸlRŸlRžlRžkRžkRkRkQœkQœjQœjQ›jQ›jQ›jQšjQšiQšiQšiQ™iQ™iQ™iQ˜iQ˜hQ˜hQ—hQ–gQ•gQ“fQdP†_Oq8 ���������–gQˆ`OuWM”T%\À\À\À\À\À\À\À\À\À\À B B!!T,c5ƒF‚T3È›~Æ“qƒ^OfOL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK_LKsVM‡`OcP������ ’S%]OŠbPcPdP‘eP’eP“fP“fQ”fQ”gQ•gQ•gQ–gQ–gQ—hQ—hQ—hQ˜hQ˜iQ™iQ™iQšiQšiQ›jQ›jQœjQœjQkQkRžkRžlRŸlRŸlR¥\'¦]'¨^'­Vº`»a½bÁfÄi"Àe»a¹`·_¶_³]±\±\¤R¢Z'¢Z'£['¡mR¡mR¡mR¡mR mR lR lRŸlRŸlRŸlRžlRžkRžkRkRkRkQkQœjQœjQœjQœjQœjQ›jQ›jQ›jQ›jQšjQšiQ™iQ™iQ˜hQ–gQ‘eP§Sq8 ������‰aO•gQ‡`OtVMœX&\À\À\À\À\À\À\À\À\À\À B B B l@!{A…L$›Y'½†a“fPˆaO]KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀODJ[JKaMKqUM\OcPƒ^O������vE"‚]OŠaPdP‘eP“fP”fQ•gQ•gQ–gQ–hQ—hQ—hQ˜hQ˜hQ˜iQ™iQ™iQ™iQšiQšjQ›jQ›jQœjQœjQœkQkQkRžkRžkRŸlRŸlRŸlR lR©^'©^'ª_(®W»a¼a¾cÂg Äi"¿e»a¹`·_¶_³^±\±\¤R£['£['§]'¢mR¢mR¡mR¡mR¡mR¡mR mR lR lR lR lRŸlRŸlRŸlRŸlRžlRžlRžkRžkRžkRžkRkRkRkRkRkQkQkQœjQœjQšiQ˜hQ’ePšW&M&���oTMšiQ‘eP…_OtVMmSMdOL\À\À\À\À\À\À\À\À\À B B B ‘J Z'ª_(œkQ™iQ‡`OSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJ\JKcNLlRMzYN‡`O’ePzZN��� �\Nˆ`OdP“fQ•gQ–gQ—hQ˜hQ˜hQ™iQ™iQ™iQšiQšiQšiQ›jQ›jQ›jQœjQœjQœjQœkQkQkRžkRžkRžlRŸlRŸlRŸlR lR lR mR®a(­`(¬`(¶[½a½b¿dÃh!Äi"¿d»a¹`¸_¶_µ^²]³]¦S¤\'§]'«_(¢nR¢mR¢mR¢mR¢mR¢mR¢mR¡mR¡mR¡mR¡mR¡mR mR mR mR mR lR lR lR lR lR lR lR lR lRŸlRŸlR lRŸlRžkRœkQ™iQePt: ������kQ˜hQcP€]OtVMlSMa2 \À\À\À\À\À\À\À\À\À B B -$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�oTM•gQ™iQkQŸlRŸlR lR mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR£nR£nR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nRÆl*Ãl+¾j+¹g)¸f)¶e)µd)¶e)¶e)·e)·e)¸f)¾i*Ìs0Ðs.¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦pR§pR§pR§pR§pR§pS§pS¨pS¨qS©qS©qS©qS¨pS©qS§pS¤nRŸlR‘I˜hQ§pR¥oR¡mRšiQ’ePŠaP€\OsVMpTMnTMlRM–X)\À\À\À\À\À\À\À B%C)D$;J/[8"LBITGJYIKWHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK_LKcNLgPLjQLlRMpUMzYNƒ^O‹bP‘eP˜hQkQŸlR”fQ- —hQ›jQŸlR¢mR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦oR¦oR¦oR¦pR¦pR§pRàpßy-Ûw-Ûw-Þy.â{-ãu§pS§pS§pS§pS§pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨qS©qS©qS©qS©qS©qS©qS©qSªqSªrS«rS«rS¬rS¬rS¬rS¬rS¬sS«rSªqS¦oRšiQ™iQ©qSªqS§pR¡mRœjQ•gQcP„_O{ZNtVMpUMoTMmSMjQL_9 \À\À\À\À\À B "C(D#*A$[<)dI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JKaMKeOLhPLkRLmSMoTMuWM}[N…_O‹bP’eP˜hQžkR¢mR£nRžkR!-EkR¡mR¤nR¥oR¦pR§pR§pS§pS§pS§pS§pS§pS§pS§pR§pS§pS§pS§pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨qS¨qS¨qS©qS©qS©qS©qS©qS©qS©qS©qS©qS©qS©qSªqSªqSªqSªqSªrS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬sS­sS®sS®sS¯tS¯tS¯tS¯tS°tS°uS°tS®sS«rS£nR¦oR®sS­sS«rS§pR¢mRœjQ–gQdPˆaO\OyYNuWMqUMoTMnSMkRLo8 \À\À\À\À\À B'D+E$(1 J/jH1NCJUGJYIKUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK]KKbNLfOLiQLkRMmSMoTMqUMxXN\N†_OŒbP’fP˜hQkQ¡mR¥oR§pS¦pR˜hQ¢mR¥oR¨pSªqS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rSªrSªrSªrS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬rS¬rS¬rS¬rS¬sS¬sS­sS­sS­sS­sS­sS­sS®sS®sS®sS®sS®tS¯tS°tS°uS±uS±uT±uT²uT²uT²uT´vTµwT´vT³vT²uT¯tS¢mR¯tS±uT±uS®tS«rS§pR¢mRkQ—hQ‘ePŠaPƒ^O\N{ZNvXNqUMpTMnSMlRMP%\À\À\À\À B#C*E$.E- .!G$Y:%d<"SFJYIKZIKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀPDJZIK_LKdNLgPLjQLlRMnSMpTMqUMuWMyYN€\O†`OcP’fP—hQœjQ¡mR¥oR¨qS«rS«rSªrS mR�«rS­sS¯tS°tS°tS°tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS®tS®sS®sS®sS®sS®sS®sS®sS®sS®sS®tS®tS®tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS°tS°tS°tS±uS±uS±uT²uT²vT³vT³vT´vT´vT´wTµwTµwTµwT·xT·xT¸xT¸yT¸yU·xU¥\'©qS³vTµwTµwT´vT±uT®tTªrS¦oR¡mRkQ˜hQ’eP‹bP‡`Oƒ^O€\O|ZNxXNtVMpTMoTMmSMjQLh7\À\À\À B(D"-E*1F, 4#K)pL5PEJWHK[JKXHK:9H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀUGJ\JKaMLeOLhPLkRLmSMoTMpUMrVMvWNyYN|ZN]O‡`OŒcP‘eP—hQ›jQ lR¤nR§pSªqS­sS¯tS°uS¯tS­sS mR^/ ²vT³vT´vT´wTµwT´wT´vT³vT´vT´vT´vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT´vT´vT´vT´vT´wTµwTµwTµwTµwT¶wT¶wT¶xT·xT·xT·xT¸xT¸xT¸xT¹yTºyT»zU¼zU½{U½{V½|V•gQ¬rSµwT¸xT¹yU¹yU¹zV·yVµxV±vU­tT©qS¥oS mRœjQ—hQ’ePcPŠbP‡`O„_O]O}[NyYNuWMpUMoTMmSMkRL}H#\À\À &D -E(1F/!2#8 W7"iA&UGJ[JK\JKREJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀMCIXIK^KKcNLfOLiQLkRMmSMoTMqUMsVMwXNzYN}[N€\Oƒ^O‡`OŒbP‘eP–gQšjQžkR¢mR¥oR©qS¬rS¯tS±uS³vT´vTµwT´wT²uT­sS lR«_(¹yT¹yTºyTºyTºyTºyTºyT¹yT¹yT¸yT¸xT¸xT¸xT¸xT¸xT¸xT¸yT¸yT¸yT¸yT¹yT¹yT¹yT¹yT¹yT¹yT¹yTºyTºyTºyTºyTºzT»zT¼zU¼{U½{U¾{U¾|U¿|UÀ}VÁ~VÂWÀY™iQ«rSµwT¹yT¼zU½|V¿}XÁ€ZÂ]Á]¾€]»~[¶zY±wW¬tU¨qS¤nSŸlR›jQ–gQ“fPePŽcP‹bPˆ`O…_O‚]O~\NzZNvXNqUMoTMnSMlRMiQLg=!\À -!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?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 |> ���������������’eP¦oR¨qS¦oR¡mRšjQ‘eP„^OhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ\KKaMLeOLhPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_Oˆ`OŠbPcPdP‘eP“fQ•gQ—hQ™iQ›jRkRŸmS¢nT¤qV¨sX¬w[±{_¶€c½†hÄŒnË’tÒ™zØŸ€Þ¥…㩉ç­ê¯Žê¯Žê®ç«Šä§†ß£Ûž|Õ˜vГpËŽkljfÃ…bÀ‚_½\»}Yº{X¸zW¸yV·xU·xU·xT¶xT¶xT¶xU¶xU·xU·xU·yV·yV·zW¸zX¸{Y¹|Y¹|Z¹}[¹}[¹}\¹}\¸}\·}\¶|\µ{[³zZ²yZ°wY®vX¬tWªsV¨rU¦pT¤oS£nS¡mRŸlRžkRœjQšiQ˜hQ–gQ”fQ’ePdPŽcP‹bPˆ`O…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQLfOLJ(V.]KKePNkUQcNLQEJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‚]O¡mR©qS¬rS°tS³vTµwT·xUº{WĆbÒ“qךxÊo -���������������K«rS´vT¶wT´vT²uT®sSªqS¤nRkQ•gQˆ`OuWNY,\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^KKbNLfOLhQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N]O„^O†_O‰aO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRkRŸmS¢oT¥qV¨tX­w[±|_·d½†iÄŒnË“tÒ™zØŸ€Þ¥…㩉笌鮎ꮎ魌檉㧅ߢ€Ú{Õ—uÏ’pËjƈfÂ…b¿^½\»|Y¹{X¸zV·yV·xU·xU¶xT¶xT¶xT¶xU¶xU¶xU¶xU·yV·yV·yW¸zW¸{X¸{Y¸|Z¹|Z¹|[¹}[¸}\¸}\·|\¶|[µ{[³zZ±xY°wX®vX¬tWªsV¨rU¦pT¥oS£nS¡mRŸlRžkRœjQšjQ˜iQ—hQ”gQ’fPdPŽcP‹bP‰aO†_Oƒ^O€\O|ZNxXNtVMoTMnSMlRMjQLgPLzG#\JKcOMoXUgPMZIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À’fP”gQ•gQ—hQ™iQkQ lR¤nR§pRªqS¬sS¯tS������:"r<zYN­sS¹yT¾|UÁ~WÆ„^ËŠeË‹gƈe¾‚aµz[­tV¦pS¢mRkQ–gQŠbPzYNkRL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀRFJZJK`LKcNLfPLiQLkRMmSMoTMqUMrVMvWNyYN|ZN\N]O„^O‡`O‰aO‹bPcPdP’eP”fQ–gQ—hQ™iQ›jRlR mS¢oU¥qV©tY­x\²|`¸d¾‡iÅoË“uÒ™{ÙŸ€Þ¥…㩉笌é®é®è¬‹å©ˆâ¦„Þ¡ÙœzÔ—tÏ‘oÊŒjƈe„a¿^½~[»|Y¹{X¸zV·yV·xU¶xU¶xT¶xT¶xT¶xT¶xU¶xU¶xU¶xV·yV·yW·zW·zX¸{Y¸{Y¸|Z¸|Z¸|[¸|[·|[·|[¶{[´z[³yZ±xY°wX®vW¬tWªsV¨rU¦pT¥oS£nS¡mRŸlRžkRœkRšjQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aP†`Oƒ^O€]O}[NyYNuWNqUMnSMlSMkRLhPLcNLbNLpYVlUP`LK>;H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À›jQ‡`O{ZN©^'¨^'­`(·e)½h)Ãk*Êo+±b(£nRºyTÃ~UÇXÒdãŸwò°‰ñ°‹è©…ÝŸ}Ô˜vÈm¾„eµ}_®x[°y\®x[«tW§qT¡mRœjQ–gQ‹bP}[NlRM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\JKaMKdNLgPLjQLlRMnSMpTMqUMsVMvXNzYN|[N\O‚]O…_O‡`O‰aPŒbPŽcPdP’eP”fQ–gQ˜hQšiQœjRžlS mS£oU¦rW©uY®x\³|`¸d¾‡jÅoÌ“uÒš{Ù €Þ¥…㩉欋è­è­Œç«Šå©‡á¥ƒÝ ~Ø›yÓ–tΑoÊŒjňe„a¿^¼~[º|Y¹{W¸zV·yV·xU¶xU¶xT¶xT¶xT¶xT¶xU¶xU¶xU¶xU¶xV·yV·yW·zX·zX¸{Y¸{Z¸{Z·|Z·|[·|[¶{[µ{[´zZ³yZ±xY¯wX®uW¬tVªsV¨rU¦pT¥oS£nS¡mR lRžkRœkR›jQ™iQ—hQ•gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O~[NzYNvWNrUMnSMmSMkRLiQLeOLoXUu]XdOLKBI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À:9H\N–hQ¸}\¯uU­sT¯tT¯tS¨qS¤nR£nR¢nRŸlR›jQšiQ˜hQ—hQ–gQ”fQ’eP‘eP—hQœkR mS¥pUªtX«uY¨sW¦qU mS›jQ•gQƒB’S%jQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀLBIXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMtVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽcPeP’fP”fQ–gQ˜hQšiRœkRžlS nT£pU¦rWªuY®y]³}`¹‚e¿ˆjÅŽpÌ”vÓš{Ù Þ¤…⨉櫋笌笋櫊䨆ंܟ~ךxÒ•sÎnÉŒiŇeÁ„a¾€^¼~[º|Y¹{W¸yV·yV·xU¶xU¶xT¶wT¶wT¶wT¶xT¶xU¶xU¶xU¶xV¶yV¶yW·zW·zX·zY·{Y·{Z·{Z·{Z¶{Z¶{ZµzZ³yZ²yY±xY¯vX­uW¬tVªsU¨rU¦pT¥oS£nS¡mR lRžlRkR›jQ™iQ—hQ•gQ“fQ‘ePdPcPŠaP‡`O…_O‚]O\N{ZNwXNsVMnSMmSMkRMiQLfOL_LKhQMUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À (6BFP>=DKHMqjk€trwf`~kc„ndŠqesete¯Ž{w`¡v[\N†_OcP“fP˜iQœjRŸlS£oT¦qV¥qV£oTžlR™iQº^‡`OQ%hPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJZIK_LKcNLfOLiQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N€]Oƒ^O…_Oˆ`OŠaPŒcPŽdP‘eP“fP”gQ–hQ˜iQšjRœkRžlS¡nT£pU¦rWªuZ®y]³}a¹‚e¿ˆkÆŽpÌ”vÓš{ÙŸ€Þ¤…⨈媊櫋櫊婈⦅ߣ۞}ÖšxÑ•rÍmÈ‹ićdÁƒa¾€]¼~[º|Y¹zW¸yV·yU¶xU¶xU¶wT¶wT¶wT¶wT¶wT¶xU¶xU¶xU¶xU¶xV¶yV¶yW¶zX·zX·zY¶zY¶{Y¶{Z¶{ZµzZ´zZ³yY²xY°wX¯vX­uW«tVªsU¨rU¦pT¥oS£nS¡mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ‘ePdPcP‹bPˆ`O…_O‚]O\O|ZNxXNtVMoTMmSMlRMjQLgPLbML[JK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À%5 (6$/79CEEKjgkrc_›…{‘uf±{Ÿw_ºq]Oˆ`OŽcP”fQ˜hQ›jRžlR¡nT¢oT¡nTkR˜hQŽdP¦]'ŽQ%\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀUGJ[JK`MKdNLgPLiQLkRMmSMoTMqUMrUMuWNxXN{ZN~[N]Oƒ^O†_Oˆ`OŠbPcPdP£['µd)•gQ—hQ˜iQšjRœkRžlS¡nT£pU§rWªvZ¯y]´~aºƒfÀˆkÆŽpÌ”vÓš{ØŸ€Ý¤„ᧇ䩉媊媉䨇᥄ޡ€Ú|Õ˜wДrÌmÈŠhĆdÀƒ`¾€]»}[º|Y¸zW·yV·xU¶xU¶xU¶wTµwTµwTµwTµwTµwUµwUµxUµxUµxV¶xV¶yW¶yW¶yX¶zX¶zY¶zYµzYµzY´zY´yY²yY±xY°wX®vW­uW«tVªsU¨qU¦pT¥oS£nS¢mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ’ePdPcP‹bPˆaO†_Oƒ^O€\O|[NxYNtWMpUMmSMlRMjQLgPLcNLA;=\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À#*6+.8;:AHEJmgjd\]‡pe«}œxc w^»pƒ^OŠaP‘eP–gQšiQžlR mS¢nT mS›jR•gQ»h*œX&ˆM$\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀC+WHJ]KKaMLdOLgPLjQLlRMnSMoTMqUMrVMvWNyYN|ZN\N]O„^O†_OˆaO‹bPcPžY&«_(³c(•gQ—hQ™iQšjRœkRŸlS¡nT¤pV§sX«vZ¯z^´~bºƒfÀ‰kÆŽpÌ”vÒš{ØŸ€Ý£„ই㩉䩉䩈⧆ःܠØœ{Ô—vÏ“qËŽlljgÆcÀ‚`½]»}Z¹{Y¸zW·yV¶xU¶xU¶wUµwTµwTµwTµwTµwTµwTµwUµwUµxUµxVµxVµxVµyWµyWµyXµyXµyYµzY´yY´yY³yY²xY±wX°wX®vW­uV«tVªrU¨qU¦pT¥oS£nS¢mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ’ePdPŽcP‹bP‰aO†_Oƒ^O€\O}[NyYNuWNqUMmSMlRMjQLhPLdNL\1\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À+.775;ICFphhŠztŠre¯}Ÿya¢vZ]OŠaP‘eP–gQšiQkRŸlS¡nTžlS™iQÌq.¯b*“S%zG#\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀMCJXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMsVMvWNyYN|ZN\N‚]O„^O†`O‰aO‹bP—U&¥\'¯a(»g)Ìr/—hQ™iQ›jRkRŸmS¡nT¤pV§sX«v[¯z^´~bºƒfÀ‰kÆŽpÌ”vÒ™{מÜ£ƒà¦†â¨ˆã¨ˆã¨‡á¦…Þ£‚ÛŸ~×›yÓ–uÎ’pÊkƉgÂ…c¿‚_½]»}Z¹{X¸zW·yV¶xU¶xUµwTµwTµwTµwTµwTµwTµwTµwUµwUµwUµxUµxVµxVµxWµyWµyWµyXµyX´yX´yY³yY³xX²xX°wX¯vW®uW¬tV«sV©rU¨qT¦pT¥oS£nS¡mR mRžlRkR›jQšiQ˜hQ–gQ”fQ’ePdPŽcPŒbP‰aO†`Oƒ^O€]O}[NzYNvWNrUMmSMlRMjQLhQLeOL_LK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À,)/ZTVXON„uq‡od®}Ÿyb»s]OŠaPeP•gQšiQkRžlRŸlSœkR–hQ»g*¤\(ŽQ%`LK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À B B_LKcNLfOLiQLkRLmSMoTMpTMrUMtVMwXNzYN}[N\O‚]O„_O‡`O‰aOQ%ŸY&©^'±b(¾i*Õ{8—hQ™iQ›jRkRŸmS¡nT¤qV§sX«v[°z^µ~bºƒfÀ‰kÆŽpÌ”vÒ™{מÛ¢ƒß¥…ᧇ⧇ᦆऄݢڞ}ÖšxÒ•tÍ‘oÉŒjňfÂ…b¿_¼\º}Z¹{X·zW·yV¶xU¶xUµwTµwTµwTµwTµwTµwTµwTµwT´wU´wU´wU´xVµxVµxVµxW´xW´yW´yX´yX³xX³xX²xX±wX°wW¯vW­uW¬tV«sU©rU§qT¦pT¤oS£nS¡mR mRžlRkR›jQšiQ˜hQ–gQ”gQ’fPdPŽcPŒbP‰aP‡`O„^O]O~[N{ZNvXNrVMnSMlRMjRLhQLeOLaML+O+O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀHFLXQRTJH~pm‚la¬Ž}Ÿzc»t¤tT‰aPdP•gQšiQœjRžlRžlS›jRÖ|:´e*˜V&ˆN$\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À B B`LKdNLgPLiQLkRMmSMoTMpUMrUMtVMwXNzYN}[N€\O‚]O…_O‡`O‰aPšW&£['«_(´d)Âl,݃@Òt.™iQ›jRkRŸmS¡oU¤qV¨sX«w[°z^µbºƒgÀ‰kÆŽpÌ”uÑ™zÖ~Ú¡‚Þ¤„ॆআॅޣ‚Ü Ø{Õ™wÑ”sÌnÈŒjňfÁ„b¾_¼~\º|Z¸{X·yW¶yV¶xUµwUµwTµwTµwTµwT´wT´wT´wT´wT´wU´wU´wU´wU´wV´xV´xV´xW´xW³xW³xW³xX²xX±wX°wW¯vW®uW­uV¬tVªsU©rU§qT¦pT¤oS£nS¡mR lRžlRkR›jQšiQ˜hQ–hQ”gQ’fPdPŽcPŒbPŠaP‡`O„^O]O~[N{ZNwXNsVMoTMlRMjRLiQLfOLbML+O+O‚+O‚+O‚\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À6./fZXeVRHAIZIKiQLuWM¤tU‰aOdP–gQšjQkRžlRkR˜iQÄn/¬b,‘R%rC"\À\À\À\À\À\À\À\À\À\À\À\À"Fx"Fx!Fx!Fx B B BdNLgPLjQLlRMmSMoTMqUMrUMtWMwXNzZN}[N€\O‚^O…_O‡`O“S%X&¥\'®a(·g+Ês2Ó{9Àj*™iQ›jRkSŸmS¢oU¤qV¨sX«w[°z^µbº„gÀ‰kÆŽpË“uИyÕœ}٠ܢƒÞ¤„ߤ„Þ£ƒÝ¡ÚŸ~×›zÓ—vÏ“rËmÇ‹ićeÀƒa¾€^»~\¹|Z¸zX·yW¶xVµxUµwUµwTµwT´wT´wT´wT´wT´wT´wT´wT´wU´wU´wU´wU´wV³wV³xV³xW³xW²wW²wW±wW±wW°vW¯vW®uV¬tV«sUªsU¨rT§qT¦pT¤oS£nS¡mR lRžlRkR›jQšiQ˜hQ–gQ”gQ’fPePŽcPŒbPŠaP‡`O„_O]O~\N{ZNxXNsVMoTMlRMjRLiQLfPLbNL +O‚+O‚+P‚+P‚+P‚\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@89dWT@IIAI\JKlRMyYN„^OcP”gQ™iQkRžlRžkR™iRÍt3±d-’S%I#\À\À\À:^‘:^‘:^‘:^‘:^:^:^:^:^"Fx"Fx B B B BeOLhPLjRLlSMnSMpTMqUMrVMuWMxXN{ZN~[N€]Oƒ^O…_O“S%›W&¢['©^(¹k2½i+Ó{:•gQ—hQ™iQ›jRkSŸmT¢oU¤qV¨tY¬w[°{_µbºƒf¿ˆkÄoÊ’tÏ–xÓš|×~Ù €Û¡Û¡Û €Ùž~×›{Ô˜wДsÌoÉŒkʼngÂ…c¿‚`¼]º}[¸{Y·zX¶yVµxVµwU´wU´wT´wT´vT´vT´vT´vT³vT³vT³vT³vT³vU³vU³vU³wU²wU²wV²wV²wV±wV±vV°vV°vV¯uV®uV­tV¬tUªsU©rU¨qT§pT¥pS¤oS¢nS¡mR lRžlRkR›jQ™iQ˜hQ–gQ”gQ’fPePŽdPŒbPŠaPˆ`O…_O‚]O\N|ZNxYNtWMpTMlRMjRLiQLgPLcNL_LK+P‚+P‚+P‚,P‚,P‚,P‚,P‚,P‚Nr¤\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À]QNl\VG@IMCI_LKoTM|ZN†`OdP–gQšjQkRžlRœkR—hQºh*¤^,ŒP%X3:_‘:_‘:_‘:_‘:_‘:_‘:_‘:_‘:^‘:^‘:^‘:^‘"Fx B B B BfOLiQLkRLmSMnTMpTMqUMrVMuWNxYN{ZN~[N€]Oƒ^OŽP%—U&X&£['¬`)½n4Ãn/Àj*•gQ—hQ™iQ›jRkSŸmT¢oU¤qW¨tY«w[°z^´~b¹ƒf¿ˆjÄŒoÉ‘sΕwÒ™{Õœ}ØžÙŸ€ÚŸ€Ùž~ל|ÕšyÒ—vÏ“rËnÇ‹jĈfÁ„c¾`¼]¹}[¸{Y·zW¶xVµxU´wU´wT´wT´vT´vT³vT³vT³vT³vT³vT³vT³vT³vT²vU²vU²vU²vU²vU±vV±vV±vV°vV°vV¯uV®uV­uV¬tU«sUªrU©rT¨qT¦pT¥oS£oS¢nS¡mRŸlRžkRœkR›jQ™iQ˜hQ–gQ”gQ“fPePŽdPŒbPŠaPˆ`O…_O‚]O\N|ZNyYNuWMpUMlRMjQLiQLgPLdNL_LK,P‚,P‚,P‚,P‚,P‚Nr¤Nr¤Nr¤Nr¤Nr¥Nr¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaSOD>IJAIQEJbNLrUM~[NˆaO‘eP—hQœjQžkRŸlR›jRÌs0²e,“T&ƒK$;_‘;_‘;_‘;_‘;_‘;_‘;_‘:_‘:_‘:_‘:_‘:_‘:_‘ B B B BgPLiQLkRLmSMoTMpTMqUMsVMuWNxYN{ZN~[N]O‡M$“S%™V&ŸY&¥\'±e-¹j/Ñz:”fQ•gQ—hQ™iR›jRkSŸmT¢oU¤qW¨tY«w[¯z^´~b¹ƒf¾‡jÃŒnÈrÍ”vјyÔ›|Ö~מ~Øž~×}Õ›{Ó˜xЕtÍ’qÊŽmÆŠiÇeÀ„b½_»~\¹|Z·{Y¶yWµxVµxU´wU´wT´vT³vT³vT³vT³vT³vT³vT³vT³vT²vT²vT²vT²vU²vU²vU±vU±vU±vU°vV°vV¯uV®uV®uV­tU¬sU«sUªrU¨qT§qT¦pS¥oS£nS¢nR¡mRŸlRžkRœkR›jQ™iQ˜hQ–gQ”gQ’fPePŽdPŒbPŠaPˆ`O…_O‚]O\O|ZNyYNuWMqUMlSMjQLhQLfPLdNL_LK,P‚,P‚Nr¤Nr¤Nr¤Nr¤Nr¥Nr¥Nr¥Ns¥Ns¥Ns¥Ns¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀdUOG@IMCITFJeOLtWM€]O‹bP“fP™iQkRŸlRkR™iQ¾j,©c/P%[JK;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘ B B B BgPLiQLkRMmSMoTMpTMqUMsVMvWNyYN{ZN~[N|H#ŽQ%•T%›W& Z'¦]'ºm5¸f*Ív5”fQ•gQ—hQ™iR›jRkSŸmT¡oU¤qW§sY«v[¯z^³~b¸‚e½‡i‹nÇqË“uÏ–xÒ™zÔ›|Öœ}Öœ|Õ›{Ô™yÑ–vÏ“sÌoÈlʼnh†e¿ƒa¼€_º~\¸|Z·zX¶yWµxV´wU´wU³vT³vT³vT³vT³vT³vT³vT²vT²vT²vT²vT²vT²vT±vT±vU±vU±vU°uU°uU°uU¯uU®uU®tU­tU¬tU«sUªrU©rT¨qT§pT¥pS¤oS£nS¢mR mRŸlRžkRœjR›jQ™iQ—hQ–gQ”fQ’fPePŽcPŒbPŠaPˆ`O…_O‚^O\O|ZNyYNuWNqUMmSMjQLhQLfPLdNL`LKNr¤Nr¤Nr¥Nr¥Nr¥Ns¥Ns¥Ns¥Ns¥Os¥Os¥Os¥Os¥Os¥Os¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À2#TB3REJVGJ`LKpTM}[N‰aO’ePšiQžkR lRžlR˜hQ·e)¢^.P%^8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMrUMsVMxF#‡M$ŽQ%’S%–U&šW&žY&¢['ªa+¿s;¹g+dP‘eP“fQ”gQ–hQ˜iQšjRœkSžlS nU£pV¦rX©uZ¬x]°{_´~b¸‚e¼…iÀ‰kÃŒnÆŽpÈrÊ‘sË’sË‘rÊqÉoÇmÅ‹kÈhÀ…e¾ƒb¼€`º~^¸|[¶{ZµyX´xW³wV²vU²vU²vT±uT±uT±uT±uT±uT±uT±uT±uT°uT°uT°tT°tT¯tT¯tT¯tT¯tT®tT®tT­sT­sT¬sT¬sT«rTªrT©rT©qT¨qS§pS¦pS¥oS£nS¢nR¡mR lRŸlRkRœjQ›jQ™iQ˜hQ–gQ•gQ“fP‘ePdPcP‹bP‰aO‡`O„^O‚]O\N|ZNxXNuWMqUMmSMhPLgPLeOLcNL`LKZIK,Pƒ,Pƒ,QƒOs¦Os¦Ot¦Ot¦Ot¦Ot¦Pt¦Pt¦Pt¦Pt¦Pt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀvšÍvšÍv›Ív›Ív›Ív›Ív›Íw›Íw›Í=a“=a“=a“#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GymYPODJUGJXIKeOLtWM‚]OcP•gQœjQ lR mRkRÈp.´g0”T&ˆN$]8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMrUMv>„L$ŒP%‘R%•T%˜V&œX& Z'¤\'°f0¹m5Äq3dP‘eP“fQ”gQ–gQ˜hQ™jR›kSlS nT¢pV¥rX¨tZ«w\¯z_³}a·dº„g¾‡jÁŠlÄŒnÆŽpÇqÈqÈpÇŽoÆmÅ‹kÉiÁ‡g¿„d½‚aº_¸}]·|[µzY´yX³xW³wV²vU²vU±uT±uT±uT±uT±uT±uT°uS°uS°tS°tS°tS¯tS¯tT¯tT¯tT®tT®tT®sT­sT­sT¬sT¬sT«rTªrTªrT©qT¨qS§pS¦pS¥oS¤oS£nS¢mR¡mRŸlRžlRkRœjQšjQ™iQ—hQ–gQ”fQ’fP‘ePdPcP‹bP‰aO†`O„^O]O~\N{ZNxXNuWMqUMiQLgPLfOLeOLbNL_LKZIK,Qƒ,Qƒ,Qƒ,Qƒ,QƒOt¦Pt¦Pt¦Pt¦Pt¦Pt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àv›Ív›Ív›Ív›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Í=a“=a“=a“=a“=a“#Gz#Gz#Gz#Gz#Gz#Gz#GzgUOS=2RFJWHJ[JKlRMzYN†`OeP˜iQžkR mRŸlR™iQ¼h*°h4‘R%ˆN$^9 [JK#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMI#†L$‹O$Q%“S%—U&šW&X&¡Z'¦](·l5´f,Èt5dPeP’fP”fQ–gQ—hQ™iR›kRlSŸmT¢oV¤qW§tY«v[®y^±|aµc¸‚f¼…h¿ˆkÁŠlÃŒnÅnÅoÅnÅŒmÄ‹k‰iÁ‡g¿…e½ƒc»€`¹~^·|\¶{Z´yY³xW²wV²vU±vU±uT±uT±uT°uT°uT°tS°tS°tS°tS°tS¯tS¯tS¯tS¯tS®tS®tS®sS­sT­sT­sT¬sT¬rT«rTªrTªrS©qS¨qS§pS¦pS¦oS¥oS¤nS¢nR¡mR mRŸlRžkRkR›jQšiQ˜iQ—hQ•gQ”fQ’ePePdPcPŠbPˆ`O†_Oƒ^O]O~[N{ZNxXNtVMqUMhPLgPLfOLdNLbML_LKbE6,Qƒ,Qƒ,Qƒ,Qƒ-Qƒ-Qƒ-QƒPt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Q„-Q„-Q„\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@d–w›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Îw›Îw›Î=a”=a”=a”=a”=a”=a”=a“#Hz#Gz#Gz#Gz#Gz#Gz#GzmYPPDJUGJYIKbMLqUM\NŠbP”fQ›jQŸlR¡mRžlRËp,µe+ \+R%ˆN$b; ]8 [7 XHKO+N1L/L/L/K/K/ eb”>b”>b”>b”>b”>b”>b”>b”=b”=b”=b”=b”=b”=b”=b”=b”YEUGJYIK_LKnSM|ZNˆ`O’ePšiQŸlR¡mR mR™iQºg*´j4šW'‘R%ŽQ%h>!g=!f=!db”>b”>b”>b”>b”>b”>b”$Hz$Hz$Hz$Hz$Hz>b”>b”>b”>b”>b”gVOS=2RFJWHK[JKeOLsVM€]OŒbP•gQœjQ lR¡mRžlRÌr/¹g*²h2–U&“S%‘R%Q%ŽQ%ŒP%£['¨]'¬`(°b(´d)¸f)»g)¾i*Áj*I#¡Z'¡Z' Z' Z'¡Z'£['¤['¥\'¦]'ª_)±d,³d)Äq3‹bPcPdP‘eP’fQ”fQ–gQ—hQ™iR›kSlSŸmU¡oV¤qW¦sY©u[¬x]¯z^±|`´~b¶€d¸‚eºƒf»„f»„f¼„f»ƒe»‚dºb¹€a·~_¶}^µ{\´zZ³yY²wX±wW°vV°uU¯uU¯tT¯tT¯tT®tS®tS®tS®sS®sS®sS®sS®sS­sS­sS­sS­sS¬sS¬rS¬rS«rS«rSªrSªqS©qS©qS¨pS§pS¦pS¦oS¥oS¤oR£nR¢nR¡mR mRŸlRžkRkRœjQšjQ™iQ˜hQ–hQ•gQ“fQ’ePdPŽcPŒcPŠbPˆ`O†_O„^O]O\N|ZNyYNuWNrUMnSMjQLdNLcNLaMK_LK[JK`D6Pt¦Pt¦Pt§Pt§Pt§Pu§Pu§Pu§Pu§Qu§Qu§Qu§Qu§Qu§Qu§-Q„-Q„-Q„-R„-R„-R„-R„-R„-R„-R„-R„-R„.R„.R„Rv¨Rv¨Rv¨~¢Ô~¢Ô~¢Ô~¢Ô\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@e—@e—@e—@e—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—xœÏxœÏxœÏxÏxÏxÏxÏyÏyÏ>b•>b”>b”$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b”>b”>b”>b”>b”YDb”>b”>b”>b”Q@:R<2fL@WHJZJKaMKoTM|ZNˆ`O‘eP™iQŸlR¡mR¡mRœjRÇo-»i-´h0«`)§]'¨]'¬`(°b(´d)¸f)¼h)Àj*Ãk*Æm*Én+Ìp+Ïq+Òr,§]'§]'§]'¨^'ª_(«_(¬`(­`(¯b)²c)ºi.ˆ`OŠaPŒbPŽcPdP‘eP“fQ”gQ–hQ˜iRšjR›kSlTŸnU¢oV¤qW¦sY©uZ«w\­y]°{_²|`³}aµ~b¶b¶b¶b¶a¶~`µ}_µ|^´{]³z[²yZ±xY°wX¯vW¯uV®uU®tU®tT­tT­sT­sS­sS­sS­sS­sS­sS­sS­sS¬sS¬rS¬rS¬rS«rS«rS«rSªrSªqS©qS©qS¨qS¨pS§pS¦pS¦oS¥oR¤oR¤nR£nR¢mR¡mR lRŸlRžkRkRœjQšjQ™iQ˜hQ–hQ•gQ“fQ’ePdPdPcP‹bP‰aO‡`O…_O‚]O\O}[NzYNwXNtVMpTMlRMhPLcNLaMK_LK]KKbR]C5Pu§Pu§Pu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨-R„-R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae˜Ae˜Ae˜Ae˜yÏyÏyÏAf˜Af˜Af˜$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b•>b•>b”>b”WD3TFJXHK[JKfOLsVM€]O‹bP”gQœjQ lR¡mR mRœkRÅm,½i,ºj/²d+±c)²c(¶e)ºf)¾h*Áj*Ål*Én+Ëo+Îq+Ñr+Ós,Õt,ƒK$ª^(ª_(«_(¬`(®a(¯a)°b)³d*¶f+¾m1‡`O‰aP‹bPcPdPeP’fQ”fQ•gQ—hR™iR›kSlTŸmT¡oV£pW¥rX§tY©v[¬w\®y]¯z^±{_²|`³}`´}`´}`´}_´|^³{^³{\²z[±yZ°xY°wX¯vW®uV®tU­tU­tT­sT­sT­sS­sS¬sS¬sS¬sS¬rS¬rS¬rS¬rS¬rS«rS«rS«rS«rSªrSªqSªqS©qS©qS¨qS¨pS§pS¦pS¦oS¥oR¤oR¤nR£nR¢mR¡mR mRŸlRžlRkRœjQ›jQšiQ˜iQ—hQ–gQ”fQ“fP‘ePdPŽcPŒbPŠaPˆ`O†_O„^O]O\N|ZNyYNvWNsVMoTMkRLgPLbML`LK^KK\JK~aR[B5Pu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe—Ae—Ae—Ae—Ae—Ae—Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Af˜Af˜Af˜yÐAf˜Af˜Af˜Af˜Af˜Bf˜$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c•>c•>b•>b•O?:[E|aRZA5-QƒQu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„Rv¨Rv¨Rv©Rv©Rv©Rw©£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe˜Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Af˜Af˜Af˜Af˜Af˜yžÐyžÐyžÐzžÐzžÐzžÐBf˜Bf˜Bf˜Bf˜Bf˜$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c•>c•>c•>c•VC^C6W@5-Q„-Q„Qu§Qu§Qu§Qu§Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„Rv©Rw©Rw©Rw©¤Ö¤Ö¤Ö¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö¤Ö¤Ö¤Ö\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAf˜Af˜Af˜Af˜Af˜Af˜Af˜Af˜zžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐBf˜Bf˜Bf˜Bf˜$I{$I{$I{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz YE\C6T>4-Q„-Q„-Q„-R„Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„Rw©Sw©€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAf˜Af˜Bf˜Bf˜Bf˜zžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑBf˜Bf˜Bf˜$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$H{$H{$H{$H{?c•?c•?c•?c•$H{$H{$H{SB;R<2zbVUGJXIK[JK[JKuWN€\OŠaP’fP™iQŸlR¡mR£nS£nS¥pTà€9Þ9Õw2Öw0Öv/Öv.Ùx/Üz0Þz0á|1ã~2æ€3è5éƒ6ë…8ë…8ºm4¼o7¾q8Äu;Ãs9Ãs8ºj0‚]O„^O†_Oˆ`OŠaPŒbPcPdP‘eP’fQ”fQ•gQ—hR™iRšjSœkSlTŸnU¡oV¢pV¤qW¦rX§sY¨tY©uYªuZ«uZ«vZ«vY«uY«uX«uX«tW«tV«sVªsUªsUªrTªrTªrTªrSªqSªqSªqSªqSªqS©qS©qS©qS©qS©qS©qS©qS©qS¨qS¨pS¨pS§pS§pR§pR¦oR¦oR¥oR¥oR¤nR£nR£nR¢mR¡mR mR lRŸlRžkRkRœjQ›jQšiQ™iQ—hQ–gQ•gQ”fQ’eP‘ePdPcPŒbPŠaPˆ`O†_O„^O‚]O\O}[NzYNwXNtVMqUMnSMiQLeOL`LK]KKmP?kN?|aSZA5P<4-R„-R„-R„-R„-R„-R„Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×Ei›Ei›Ei›Ei›Ei›Ei›Ei›\À\À\À\À\À\À\À\À\À\À\À\ÀBf˜zžÐzžÐzžÐzžÐzžÐzžÐzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑBf™Bf™Bf™%I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{?c–?c–?c–?c–?c–?c•?c•?c•?c•$H{$H{$H{jXP^H=}dXUGJXHKZIKkRLwXN‚]O‹bP”fQšiQžkR mR£nS¥pT¨qU¨rUç…;ç†>ì‰?è†<å‚9ê†;î‰=ðŠ=ðŠ>ôŽAø‘Dü•Hÿ˜Kù’E¿r:Àt;Àt;Át<Ãt:½n4´f,]Oƒ^O…_O‡`O‰aO‹bPŒcPŽcPdP‘eP“fQ”gQ–hQ˜iR™jR›kSœlSžmTŸnU¡oV¢pV¤qW¥rW¦rX§sX¨tX©tX©tX©tX©tXªtWªsW©sV©sV©rU©rU©rT©qT©qT©qS©qS©qS©qS©qS©qS©qS©qS©qS¨qS¨qS¨pS¨pS¨pS¨pS§pS§pS§pR¦pR¦oR¦oR¥oR¥oR¤nR¤nR£nR¢nR¢mR¡mR mR lRŸlRžkRkRœjQ›jQšiQ™iQ˜hQ–hQ•gQ”fQ’fP‘ePdPŽcPŒcP‹bP‰aO‡`O…_Oƒ^O]O~[N{ZNyYNvWNsVMpTMlRMgPLcNL†gUƒeUlO?~bT{`SW@5-R„-R„-R„-R„-R„-R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R….R…Ei›Ei›Ei›€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›\À\À\À\À\À\À\À\À\À\ÀzžÑzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒBg™Bg™Bg™%I{%I{%I{%I{%I{%I{%I{@d–?d–?d–?d–?d–?d–?d–?d–?d–?c–?c–?c–?c–$I{$I{L=:WD`KA-R„-R„-R„.R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R….R….R….R…EiœEiœEiœEiœEiœEiœ¥×¥×¥×¥×¥×¥×¥×EiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœ\À\À\À\À\À\À\À\ÀzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒ{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| ÒCg™Cg™%I{%I{%I{@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–?d–?d–?d–?d–?d–?d–$I{$I{dUPYEXG@-R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©.R„.R„.R„.R„.R„.R„.R„.R„.R….R….R….R….R….R….S…EiœEiœEiœEjœEjœEjœEjœEjœ¥×¥×¥×EjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEiœEiœEiœ\À\À\À\À\À\À{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| ÒCg™@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–?d–$I{$I{RA;P<3zcXnVIuh™~pdNLpUMÁ”w¬zZ«vS‘eP–gQœjQžlR¡mR¤oS§pT­uV¯vW±xY¶|\¼€_ÆdƉgÈŠhÊŒiÌŽkÎlÿRñF¶k4²g1¯d-­b+ª_(¢Z'}[N€\O‚]O„^O†_Oˆ`O‰aP‹bPcPŽcPdP‘eQ’fQ”gQ•gQ—hR˜iR™jR›kSœkSlTžmT nT¡nU¡oU¢oU£pU¤pU¤pU¤pU¥pU¥pT¥pT¥pT¥pT¥pS¥pS¥oS¦oS¦oS¦oS¦oS¦oS¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¥oR¥oR¥oR¥oR¤oR¤nR¤nR£nR£nR¢nR¢mR¡mR¡mR lRŸlRŸlRžkRkRœkQœjQ›jQšiQ™iQ˜hQ—hQ•gQ”gQ“fP’ePePdPcPŒbPŠbP‰aO‡`O…_Oƒ^O]O~\N|[NzYNwXNtVMpUM—pY”oXzWBuUB…gVlP@jO@|bUx`TcMB3!.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©.R„.R„.R„.R„.R….R….R….R….R….S….S….S…EjœEjœEjœEjœEjœEjœEjœEjœEjœ¦Ø¦ØEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœ\À\À\À\ÀBg™{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| ÒCg™Cg™Cg™Cg™|¡Ó@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–%I{;0/SB;R=4fODpXL‘xkš€r˜vbº“zÀ”x«{[ÃldP•gQ™iQ›jQŸlR£nR¦pS¨qTªrT¬tU°wWµ{Z¸}\¸|\¸}\¹~]»]å}+Ý~6­d.ªa+¨_)§^(¤\'zYN|ZN~\N€]Oƒ^O„_O†_Oˆ`OŠaP‹bPcPŽdPdP‘eQ“fQ”gQ•gQ—hR˜iR™jRšjSœkSlSžlTŸmT mT nT¡nT¢nT¢oT£oT£oT£oT£oT¤oS¤oS¤oS¤oS¤oS¤oS¤oS¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¤oR¤oR¤nR¤nR¤nR£nR£nR£nR¢mR¢mR¡mR¡mR lR lRŸlRžlRžkRkQœjQ›jQšjQ™iQ™iQ˜hQ—hQ•gQ”gQ“fQ’ePePdPŽcPŒbPŠbP‰aO‡`O…_Oƒ^O]O\N}[NzZNxXNuWMrUM™rZ–pY|XCxVCsTBmQAkOA~cVzaU`I>\IARv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©.R….R….R….R….R….S….S….S….S…FjœFjœFjœFjœFjœFjœFjœFjœ‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦ØFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœ\À\ÀBg™{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ó| ÓCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™}¡Ó@e—@e—@e—@e—@e—@e—@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–%I{<1/J82^I@gQFqYN‘xl™€s—vc¢{d¿”yª{\«wUÄi‘eP•gQ˜hQkQ mR¢mR¤nR¥oS§pSªrT¬tU¬tU¬tU¬tU­tU®tUÒt.ƒL&¤](¢['¡Z'žY&xYN{ZN}[N\N]Oƒ^O…_O‡`OˆaOŠaPŒbPcPdPeP‘eQ“fQ”gQ•gQ—hR˜iR™iRšjR›kSœkSlSžlSŸmSŸmS mS nS¡nS¡nS¢nS¢nS¢nS¢nS£nS£nS£nR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR£nR£nR£nR£nR£nR¢nR¢mR¢mR¡mR¡mR¡mR lR lRŸlRžlRžkRkRœkQœjQ›jQšiQ™iQ˜iQ—hQ–hQ•gQ”fQ“fP’ePePdPŽcPŒbP‹bP‰aO‡`O†_O„^O‚]O\O}[N{ZNxYNvWNsVM›s[˜rZ~ZDnYŒkYqSBkPAiOA|cVbK?\G>NB?Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©.S….S….S….S….S….S…FjœFjœFjœFjœFjœFjœ‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦ØFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœCg™Cg™| Ò| Ò| Ò| Ò| Ò| Ó| Ó| Ó| Ó|¡Ó|¡ÓCg™Cg™Cg™Cg™Cg™Cg™Cg™CgšCgšCgšCgšCgš}¡ÓAe—Ae—Ae—@e—@e—@e—@e—@e—@e—@e—@e—@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–%I{@d–@d–<1/H72\I@ePGpYNxm˜€t–vc¡{e¾”zÁ“u‘p«wU¬uQ‘eP•gQ™iQšjQœjQžlR¡mR£nR¤nR¤oR¤oR¤oR¤oR¤oRÇgb;  Z'žY&›W&“S%vXNyYN{ZN~[N€\O‚]Oƒ^O…_O‡`O‰aOŠaPŒbPcPdPdP‘eQ“fQ”gQ•gQ–hQ˜iR™iRšjR›jR›kSœkSlSžlSžlSŸlSŸmS mS mS¡mS¡mS¡mR¡mR¢mR¢mR¢mR¢mR¢nR¢nR¢nR£nR£nR£nR£nR£nR¢nR¢nR¢mR¢mR¢mR¢mR¡mR¡mR¡mR mR lRŸlRŸlRžlRžkRkRkQœjQ›jQ›jQšiQ™iQ˜hQ—hQ–gQ•gQ”fQ“fP‘ePdPdPcPŒbP‹bP‰aO‡`O†_O„^O‚]O€\O}[N{ZNyYNvXNtVMu\„]E€[E’oZŽmZŠkYnRBjOB}cVdL@`I?XGARv¨Rv¨Rv¨Rv¨Rv©Rv©Rw©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwª.S….S….S….S…/S…FjœFjœFjœFjœ‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦ÙFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœ‚¦Ù‚¦ÙCg™Cg™| Ó| Ó|¡Ó|¡Ó|¡Ó|¡Ó|¡ÓCg™Cg™Cg™Cg™CgšCgšCgšCgšCgšCgšCgšCgšChšChšChšChšChš}¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—@e—@e—@e—@e—@e—@e—@e—@d—%I{%I{%I{%I{%I{@d–@d–<10F61o]Vye]„oeŽxmœ‚u”udŸ{e¥}d¨|aÀ’tÁpÃl¬uQdP’eP”fQ–gQ˜iQ›jQœjQœjQœjQœjQœkQœkQkQ_9 œX&™V&•T%rUMuWMwXNzYN|ZN~[N€\O‚]O„^O…_O‡`O‰aOŠbPŒbPcPŽdPdP‘eQ’fQ”fQ•gQ–hQ—hR˜iR™iRšjR›jRœkRœkRkRlRžlRžlRŸlRŸlRŸlR lR mR mR mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR mR lR lRŸlRŸlRŸlRžkRžkRkRkQœjQ›jQ›jQšiQ™iQ˜iQ—hQ–hQ•gQ”gQ“fQ’fP‘ePdPdPcPŒbPŠbP‰aO‡`O†_O„^O‚]O€\O~[N{ZNyYNwXNtVMrUM†^F‚]F”q\o[ŒlZqTD€fX}dWeMAbK@O=6NB@Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxª/S…/S…FjœFjœFjœƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœƒ§Ùƒ§Ùƒ§Ùƒ§ÙCg™Cg™Cg™}¡Ó}¡Ó}¡ÓCg™CgšCgšCgšCgšCgšCgšCgšChšChšChšChšChšChšChšChšChšChšDhšDhšDhš~¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—%I{%I{%I{%I{%I{%I{%I{%I{%I{@d—@d—E:9D61m\Vwe]lXOuaX„k_¨‹z±|¡|e¥|c§|`©z]ªyXÂnÃlÄŽkÄŽidP’eP“fP“fP“fP’fP“fP“fP“fP[7 —U&”T%P%pTMsVMuWMxXNzYN|ZN~[N€\O‚]O„^O†_O‡`O‰aOŠbPŒbPcPŽdPdP‘eP’eQ“fQ”gQ•gQ–hQ—hQ˜iR™iRšjR›jR›jRœkRœkRkRkRžkRžlRžlRŸlRŸlRŸlRŸlR lR lR lR lR lR lR lR lR lR lR lR lR lRŸlRŸlRŸlRŸlRžkRžkRkRkQœkQœjQ›jQ›jQšiQ™iQ˜iQ˜hQ—hQ–gQ•gQ”fQ“fP’eP‘ePdPŽdPcPŒbPŠbP‰aO‡`O…_O„^O‚]O€\O~[N|ZNyYNwXNuWMrUM‡`G„^G–r]|ZFxXFtVEgY~eY{cXbLA[H?REA.R„.R„Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSxªSxªSxªSxªTxªTxªTxªƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙFjFjFjFjFjFjFjFjFjFjFjƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙCg™Cgš}¡Ó}¡ÓCgšCgšCgšCgšChšChšChšChšChšChšChšChšChšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš~¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—%I|%I|%I|%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{@e—@e—B99B51k[Vud]iWPr_Wye] †yªŒ|²}¡|e¤|c¾’w¨{^¨z\©yZÁp«xW«wU«wU«wU«wUÃŽlÃŽlÂŽlÂŽlkD(’S%ŒP%nSMoTMqUMsVMvWNxXNzYN|ZN~[N€\O‚]O„^O†_O‡`O‰aOŠaP‹bPcPŽcPdPeP’eQ“fQ”fQ•gQ–gQ–hQ—hQ˜iQ™iR™iRšjR›jR›jRœjRœkRœkRkRkRkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRžlRžkRžkRžkRkRkQkQœkQœjQ›jQ›jQšjQšiQ™iQ˜iQ˜hQ—hQ–gQ•gQ”gQ“fQ’fP‘ePePdPŽcPcP‹bPŠaPˆaO‡`O…_Oƒ^O‚]O€\O~[N|ZNyYNwXNuWMrUMŸw_œv_˜t^~\GzYGvWF†j[fZ|dYybX\I@VGB5/2.R„.R„.R„.R„Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxªSxªTxªTxªTxªTxªFkFkFkFkƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§ÚFkFkFkFkFkFkFkFkƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Ú}¡Ó}¡Ó}¡Ô}¡ÔChšChšChšChšChšChšChšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš~£ÕAe˜Ae˜Ae˜Ae˜Ae˜%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{%I{%I{%I{%I{@e—@e—<68?31gYVpa\bRMjYTq`Z€j`¡‡z«}²‘}¶’|¸’{º’z»’x¼’w§z^¿‘t¿‘s¿‘s¿s¿r¿r¾r¾r°h2‹O$„L$mSMnSMnTMoTMtVMvWNxXNzYN|ZN~[N€\O‚]O„^O…_O‡`OˆaOŠaP‹bPŒcPŽcPdPdP‘eP’eQ“fQ”fQ•gQ–gQ–hQ—hQ˜hQ˜iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœkQœkQkQkRkRkRkRkRkRkRkRkRkQkQkQœkQœjQœjQœjQ›jQ›jQšjQšiQ™iQ™iQ˜hQ—hQ—hQ–gQ•gQ•gQ”fQ“fP’eP‘ePdPdPcPŒbP‹bP‰aPˆ`O†`O…_Oƒ^O]O€\O~[N|ZNyYNwXNtWM£z` y`w`šu_€]I|[HwXGˆl\ƒi[}eZycYr_WjZU;23.R„.R„.R„.R„.R….R….R…Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxªTxªTxªTxªTxª/S…/S…GkGkGkGkGkGkGkƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨ÚGkGkGkƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Ú}¢Ô}¢Ô}¢Ô}¢Ô~¢ÔDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš£ÕAf˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{Ae—Ae—Ae—?89H=:?YUY`QGfVLudXjeitlm{po|qp}rp~rpsqsq€tqŒr_=1+xJ)’o[~[F€\G‚^H„_I…`IkRLlRMnSMpTMrVMuWMwXNyYN{ZN}[N~\N€\O‚]Oƒ^O„_O†_O‡`Oˆ`O‰aPŠbP‹bPŒcPcPŽcPdPdPeP‘eP’eP’fP“fQ“fQ”fQ”gQ•gQ•gQ•gQ–gQ–gQ–gQ–hQ–hQ—hQ—hQ—hQ—hQ—hQ–hQ–hQ–gQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘eP‘ePdPdPŽdPŽcPcPŒbP‹bPŠaP‰aO‡`O†_O…_Oƒ^O‚]O€\O~\N}[N{ZNyYNwXNuWM“iOhOŽgO‹eOžze›yd—wd”tcrbtYKjTIaOG[KFj]Y^UU?;@.R….R….S….S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…GkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkž…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û…©Û…©Û£Õ£Õ£Õ£Õ£Õ£Õ£Õ£ÕDh›Dh›Dh›Dh›Di›Di›Di›Di›Di›¤Ö¤Ö¤Ö¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|Af˜Ae˜Ae˜%J|%J|%J|%I|%I|%I|%I|���#-#%.()1MEAQIEUMI]SL]TM=4.1+(=.#6,&5( 1%"ŒlYn[“p\•r]]Hƒ_I…`JœwažybkRLmSMpTMrUMtVMvWNxXNzYN|ZN}[N\N€]O‚]Oƒ^O…_O†_O‡`OˆaO‰aPŠaP‹bPŒbPcPŽcPŽdPdPdPeP‘eP‘eP’eP’fP“fP“fQ“fQ”fQ”fQ”fQ”gQ”gQ•gQ•gQ•gQ•gQ•gQ”gQ”fQ”fQ”fQ”fQ“fQ“fP“fP’eP’eP‘eP‘ePdPdPdPŽcPcPŒcPŒbP‹bPŠaP‰aO‡`O†_O…_Oƒ^O‚]O]O\O}[N|ZNzYNxXNvWN¬‚gªg¨€ghPŒfPŸ|fœzf˜xe”vdscsYLiTK_NHYKFh\Z]UV=;@.R….S….S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxª/S…/S…/S…/S…GlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û£Õ£Õ£Õ£Õ£Õ£Õ£Ö£ÖDi›Di›Di›Di›Di›Di›¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Ei›&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Af˜Af˜Af˜Af˜Af˜%J|%J|%J|%J|%J|%J|%I|%I|%I|, +,!.! "`E6†iYŒlZo\“q]•s^^J™va›wbycŸzd {e¤}foTMqUMsVMuWNwXNyYN{ZN|ZN~[N\O]O‚]Oƒ^O…_O†_O‡`Oˆ`O‰aOŠaP‹bPŒbPŒcPcPŽcPŽdPdPdPdPeP‘eP‘eP‘eP’eP’eP’eP’eP’fP’fP’fP“fP’fP’fP’fP’eP’eP’eP‘eP‘eP‘ePePdPdPdPŽdPŽcPcPŒcPŒbP‹bPŠaP‰aOˆ`O‡`O†_O…_Oƒ^O‚]O]O\O~[N|[N{ZNyYNwXN®ƒi¬ƒiª‚i¨i¦€hŒhR‰fQ†dQ‚bP•wfx]Oˆpdkbtd_m`]OEDG?A;:@.S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTx«Tx«Tx«Ty«/S†GlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ£Ö£Ö£Ö£Ö¤Ö¤Ö¤Ö¤Ö¤ÖEi›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×€¥×€¥×€¥×Bg™Bg™Bg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Af˜Af˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|��� +,YA5jPBpSD‹l[o]’q^–t`‚_Kšwbœycžze {f¡}g¤h¨i”lSrVMtWMvWNxXNyYN{ZN|[N~[N\O]O‚]Oƒ^O„_O…_O†`O‡`Oˆ`O‰aPŠaP‹bP‹bPŒbPcPcPŽcPŽcPdPdPdPdPdPdPdPdPePePePePePdPdPdPdPdPdPdPŽcPŽcPcPcPŒbP‹bP‹bPŠaP‰aOˆ`O‡`O†`O…_O„^Oƒ^O‚]O€]O\O~[N|[N{ZNyYNxXN°…j®„j¬„jªƒj¨‚j¦€jŒhSŠgS†eRƒcR|`QŒsf…oe}jcrd`k_]LCDC=@,,3(4F(4F.S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžChšChš¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|#5H71O;3V?4iOBoSDsVFo]{[I^Kƒ`L…bN‡dOŸ{f }g¢~h¥€j’kT•mU˜oVšqWrWwXNxXNzYN{ZN}[N~[N\O€]O‚]Oƒ^O„^O…_O…_O†`O‡`Oˆ`O‰aO‰aPŠaP‹bP‹bPŒbPŒbPŒcPcPcPcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPcPcPcPŒcPŒbP‹bP‹bP‹bPŠaP‰aP‰aOˆ`O‡`O†_O…_O„_O„^Oƒ^O]O€\O\N~[N|ZN{ZNyYN›oTšoT™oT—nT¬„lªƒl¨‚ljUŒiTŠhT†fT€cSvi‰rgnfyidqdah^^HBD?<@)+3OZkMYk(5F(5F(5F/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Ty«Uy«†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžDhšDhšDhšChš&K}&K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|A99N?;L:2T>4gNBlRD‡k\‹n^z[J~^LaN…cO‡dP‰fQŠgRŒhTjU’lV•nW˜pXšrXsY¶‹q¸qºŽr¼r½r¿s©z[©z[ªz[«{[¬{[¬{ZÅ“rÅ’qÅ’qÅ’pÅ’pÅ‘o­yV­xV¬xU¬wT¬wTŠaPŠbP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bPŠaPŠaPŠaP‰aP‰aOˆaOˆ`O‡`O‡`O†_O…_O„^Oƒ^O‚^O‚]O]O€\O~\N}[N|ZNzYNpTœpU›pUšpU˜oV—oV•nV“mV‘lVkVŒjVˆhVƒfU~cUuj†qh~mfugdkaad\^E@D98?$(2minffm^blV^lMYk(5F(5F/S…TxªTxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Uy«Uy«†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}ChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|Ae˜Ae˜;GY<68I=:I82Q=4XA6~fZ„j\‰m^p`|]L€`NƒcP†eQˆgS¡j£€l¦‚m©„n•oX˜qYšrZt[¶Œr¸sºs¼t½t¾‘t¨z]©{]ª{]«{\«{\¬{\¬{[Ä“sÄ“rÄ’rÄ’qÄ’pÄ‘p¬yWÄoÃnÃmÃlÂŽlÂŽkÁkˆaOˆaOˆaOˆaOˆaOˆaOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O…_O„_O„^Oƒ^O‚]O]O€]O\O~\N}[N|ZN¶‰l¶‰lµˆmœqV›qVšqV™pW˜pW–oW¬…nª…n§„n¤‚nŸ€n›~n€eW‘xlŠtk‚piykfodcf_`JDG@>C*,5$1MYktr~tstmolinadmX_lNZkMZkTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«ÝHlŸHlŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™&J}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Af˜Af˜Af˜Af˜;GY;GY;GY1'!D:9N?;N;3]I?zdY€h[†l^‹oasc“ue€bQ„dR‡fT l¢m¦ƒn©…o«‡p®ˆq±Šr³‹sžv] w]¹u»u¼‘u¾‘u¿’v¨{^©{^ª|^«|]«|]«{\¬{\¬{[¬{[¬zZ«zZ«yY«yX«xXÂoÂnÂnÁŽmÁŽm¨uT¨uS§tS§tS§tR¦sR¦sQ…_O…_O…_O„^O„^Oƒ^Oƒ^O‚^O‚]O]O€]O¢rS¡rS¡rS¸‰k·‰l·‰l¶‰m¶‰mµ‰m´‰n³‰n›qWšqX™qX®‡o­‡o«†p¨…p¤ƒp pœp—}o{cXv`Vp]U}nishfhaba\_DAF::B$)4�MYkMYkMYkŒtctq\QPPIKFDI;>H/8GMZkTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸImŸImŸImŸImŸImŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšChšChšChšChšChšChšChšChšCgšCgš&K}&K}&K}&K}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;GY;GY;GY;GY;,#I=:H82YF?^JA|e[‚j]ˆn`Œqcte”wg—yiš|k~l €n£‚o¤ƒp¦…q­‰s°Šs›u]žv^Ÿw^¡x_£y_¤z_¥z_¦{_¿“w¿“wÀ“vÁ“vÁ“v“u“u“tª{\ª{\ªz[ªzZªyZªyY©xXÁpÀo¨wW¨vV§vV§uU¦uU¦uT¥tT½Œl¼‹k¼‹k¼‹k»‹k»‹kºŠk¢sT¢rT¢rT¡rT¡rT¡rU rU rV·Šn¶ŠnµŠnµŠo´Šo³‰o²‰p±‰p™qY®ˆq¬‡qª†r§…r¤„r ‚rœ€q€gZ{dYvaXp^WiYU`TRVNOb]aEBH<+[NL^SQWNNKFJ?AI2:HTx«Ty«Ty«Ty«Uy«Uy«Uy«Uy«Uy«‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝImŸImŸImŸImŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšChš&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}CgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;HY;HY;HY;HY;GY3("D::B41RB=YG@wcZ}g\ƒk_‡nbŒrdug}aRdT„gV‡iX‰kY¢ƒq¤„r¥…s§†t‘p^’q^Ÿw` x`¢y`£z`¤za¥{a½“x¾“x¿“w¿“wÀ“wÀ“vÀ“vÀ“vÀ“uÀ’uÀ’tÀ‘sÀ‘sÀ‘r¿r¿q¿q¾p¾Žp¾Žo½Žo¥vW¼n¼Œn»Œn»Œn»ŒnºŒnº‹m¢tV¡sV¡sV¡sV sV sWŸsWŸsXžsXµŠpµŠp´ŠpœsY›sYšrZ˜r[–r\”q\‘p]¦†t£„tŸƒsœs€h\{e[vbYo^XhZV`USXPQNJMECJRS[47A+((MYkMYkMYkMZk(5F(5F(5FOHJT=+YML_SRZQQMGJABI2:H/T†Uy«Uy«Uy«Uy«Uy«Uy«‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸˆ¬Þˆ¬Þ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}CgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™&J|&J|Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;HY;HY;HY;HY>DM>DM;HY89<:+#9&B52I94ZHAxd[}g^k`†nc‹rey_R}bTeVƒgX…iYˆk[Šl\Œn]o^¥‡v§ˆvšvaœwažxa yb¢zb¤{b¤{a¼“x½“x¦|a§|a§|`§{`§{_§{_§{^§z^¾‘u¾‘t¾‘t¾s½s½r½r¥wZ¤wZ¤vY¤vY£vY£uX¢uX¢uX¢uX¹Œp¸Œp¸Œp·Œp·‹p¶‹p¶‹pµ‹qµ‹qtZ›t[šs\™s\˜s]–r]”r^’q^p^o^Šn^‡l^ƒj^h]{f\ub[n^YgZW_UTWPQOKOEEKST]JNY>=?JJIMYkMYk(5F(5F(5F(5F(5F)5G)5GK=4S<*XMLbWVYPPLGJ@AI/T†/T†Uy«Uy«Uy«‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞImŸImŸImŸIm ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞIm Im Im Im Im Im Im Im ˆ¬Þˆ¬Þˆ¬Þˆ¬Þ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Dh›Dh›Dh›Dh›DhšDhšDhšDhš'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜;HY;HY;HY;HY;HY;HYCIR>DMCIR;HYCIR.$0"8&?*G/V=+w[F{g^€kanXMs\Px_S{bU~dWfYƒhZ†j\ˆl]Šm^¢…v§ˆwªŠx­Œy¯y±Žz´zµz·‘z¹’z£{b£{b¤{b¥{b¥{a¥{a¥{`¥{`¥z_¥z_¥z^¼‘u¥y]¤y]¤x]¤x\£w\£w[¢w[¢v[¢v[¡v[¡v[¸r·r¶r¶ŒsµŒs´Œs´Œs²Œt±‹u°‹u˜t^–s_•s_“r_’r`q`p`¡…wž„v›‚v—€u“~twd]sb[l^ZeYW]TUUORLJOYYaRU^JOZ>>@!$)RXaMYk39B-3<-3<(5F)5G)5G)5G)5G)5GFDJK9*^K=YONg\\TLMIFJ:>I0T†0T†ImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞIm Im In In In In In In ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßIn In In In In ˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ß'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Di›Di›Dh›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}ChšChšChšChšChšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™&J}&J}&J}&J}&J|&J|&J|&J|&J|Bg™Bg™Bg™Bg™Bg™Bf™Bf™EM>EMCIR;HY;HYCIRCIR)6&8&@*H0I1!\B0}_JhTKjM8q[Pt]Sw`U{cW~eYg[ƒi\…k^‡m_Ÿ…v¢†w¥ˆx¨Šyª‹z­z¯Ž{±{²{³{´{žzdŸzd zc zc¡zc¸‘y¸‘y¸‘y¸‘x¸x¸x·w·w·w·wŸw_Ÿw_žw_µŽv´Žv³v²v²w±w°Œw¯Œw®Œw­‹w«‹xªŠx¨‰x¦‰x¥ˆx£‡x¡†xž…x›ƒw—v’~vŽ|t‰ys„vrh\YcXX[TUSNRIHOUXaNS^JFE>>A')+"%(4:C(5F(5F3:B3:B-3<-3<)5G)5G)5G)5G)5G)5GE:4O:*TKLbXWcZZPIKDCJIm Im Im Im ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßIn In In In In In Jn Jn Jn Jn Jn ˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn ‰­ß‰­ß‰­ß‰­ßˆ­ßˆ­ßˆ­ßˆ­ß'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšChšChšChšChšChšChšCgšCgšCgšCgš&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J|&J|&J|Cg™Cg™Cg™Bg™Bg™Bg™EMCIRCIRCIR888DGNCJRCIRBBB(0 8&<)G0M5"X@0z^K†bFŠkUlXPp[Rs^TvaVzcX}fZg\i]™u›‚v„wŸ†x¢‡y¥‰z§Šz©‹{ªŒ{•ve–ve—we˜we°|°|±{²{²{²{²{²{±z±z±Žz±Žz±Žz°Žy™vb˜vb—vb–ub•ub•uc”tc“tc’sbscrcqc¢‡y †y…y›„x˜‚x•w’w|uˆytƒvs~sqyooslmVQTOLR[\dQU`KHHAAD:<@68; &�Z`i-4<%');AJ4:C4:C4:C-4<)5G)5G)5G)5G)6G)6G@84H8-N?5YPQmccoghd`dIn In In In In In ˆ¬ßˆ¬ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßJn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~Ei›Ei›Ei›Ei›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšChšChšChš&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J}Cg™Cg™Cg™Cg™B9;>68;����Z`iZ`iMZk)5G4:C-4<4:C4:C-4<;BJ)5G)6G)6G)6G)6G)6GC6-L;.leg„{{ypqhbeVYcJn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­àJn¡Jn¡Jn¡Jn¡Jn¡Jn¡Jn¡‰­à‰­à‰­à‰­à‰­à'L~'L~'L~'L~'L~'L~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhš'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}Cg™Cg™Cg™<535=AG=?D?AD==1(B3)B2&F4'E4)gTGlXJs^OzcTzaPqfethgvjhbVTcWUdXVeYWfZXg[Yh\Zi]Zi][j^\€us€ususts~tt~tt}tt|st{stut~tt|sszrsyqrwpquoqsmpqloXTXTQWPOULLSSJEA<:=99757335./2113)+.'),)+.8:="(���3@Q���������������JMPV\eT[cNZlNZlZ`iZ`iZ`iZ`iSYbY`h4;C.4=)6GCPaCPaCPaCPaCPaEQbZOGa_emhkŠƒ„nfgeaeJn¡Jn¡Jn¡Jn¡Jn¡Jn¡Š®àŠ®àŠ®àŠ®àŠ®àJo¡Jo¡Jo¡Jo¡Jo¡Jo¡Jo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Š®àŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡ƒ§Úƒ§Úƒ§Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨ÚEjœEiœEiœEiœEiœ'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}Di›Di›Di›Di›Dh›Dh›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}$.>=I[=I[2)>0&A2'C3(I8-^OFbRHfUJjXMq^RwcVzfYfRDfQCdN@zdTqijrjksklrklrklrklqjmpjmpjmojmojmnimmimkhliflscYm`Xg\VbYT^VRE>;A<:>98:77645:873220/0,-/)+.*,/#%( &������15;5BS������������������KKKJMP]dlU[dNZlNZlZ`iTZcZaiZaiZ`iZ`iSZbŽ”LS[V]eDPbDPbDPbDPbDPbDPbWMF^^diei®”†…rkeaeJo¡Jo¡Jo¡Jo¡Š®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Š¯áŠ¯áŠ¯áŠ¯áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡ƒ¨Úƒ¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨ÛGk'L~'L~'L~'L~'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Di›Di›Di›Di›Di›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}%/> ,>=I[=I[ ,> ,>#)2(.7#)2(.7#)2#)2#)2#)2(.7(.7(.767@D>A214$+3#%("$'###""""""&&&888888cB*}\I@!%+%!5*$:/(;0)<1*>3+@4+>1(bUKN@6OA6L=3QB8M?4_RKaTLbUMcVNcVNcVObVOaVOaUO`UO_UO^UO^TO\SOYRNWPNUOMWPKYSOWRN;63953:76755333,/2'),%(+"%(!' ���"&,KXi04:������������������JMP]_b^emU[dNZlNZlT[cU[dU[dU[d[aj•ž•ž•žˆŽ—–¥W]fDPbDPbDPbDPbDPbDPb‘nSž…w—|m¨‚ƒqjKo¡Ko¡Ko¡Š®àŠ®àŠ®àŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áŠ¯áŠ¯áŠ¯áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨Û„¨Û„¨Û„¨Û„©Û„©Û„©Û„©ÛGkGkGkGkGkGk'L~'L~'L~'L~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Di›Di›'K}'K}'K}'K}HlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}*2? ->=I[=I[ ,> ,> ,>#)2#)2#)2(.7(.7#)2#)2(.7(.7(.7(.7/28:79G@A<89',4#%(#%(######""""""8888888887'vS:‹jW;)� - &3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!' ���15;6CT37=������������������������MMMKMP^ad_enY`hNZlNZlU\dV\eŠ‘™Š™Š™–Ÿ–Ÿ–ž•ž“œ—¦Œ’›ƒ¡DQbDQbDQbDQbDQbMUc¤ƒ‘ylŸ‡|€oiKo¡Š¯áŠ¯áŠ¯áŠ¯áŠ¯áŠ¯áŠ¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯áKo¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢‹¯â‹¯â‹¯â‹¯âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨Û„¨Û„¨Û„©Û„©Û„©Û„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©ÛGkžGkžGkžGkžGkžGkžGkžGkžGkž…©Û…©Ü…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}'K}'K}'K}'K}'K}HO\=J[=J[=J[ -> ,> ,>(.7#)2#)2(.7(.7(.7#)2(.7(.7(/7(/7)/8/28114H7,99@.05&,5$&)$$$######"""(((8888888888888884"nO9„gXˆjZE/ (�-" - %' %$#" ! !$ ���48>7CU:GX ���������������������������JJJLLLKMPagp_enNZlLPV˜Ÿ§Œ’›Œ’›Œ’›‹’š‹‘šŠ‘™‘— –Ÿ–Ÿ–Ÿ“œ“œ—¦„¢„¢DQbDQbDQbDQbNVc…uo‡rjѼ³º«§‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯áKp¢Kp¢Kp¢Kp¢Kp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢‹°â‹°â‹°â‹°âŒ°âŒ°âŒ°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢„¨Û„¨Û„¨Û„©Û„©Û„©Û„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGkžGkžGkžGlžGlžGlž…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}DhšDhšDhšIP\=J[=J[=J[=J[ -> ->(.7#)2#)2(.7(.7(.7#)2(.7(/7(/7)/8)/8)/803966:E?AC>A856,07%'*%')$$$######(((DDDBBB8888888880 cF1w]OcS{`QS;+57'   *  ��    ;?E7CU;HY=I[ ���������������������������������JJJMMMKMPacfbhq‘— ƒ¡ƒ¡‘— “œ“œ“œŒ“›Œ’›Œ’›‹‘š‘— ‘— —Ÿ™Ÿ¨”œ“œ“œ„‘¢„‘¢„‘¢„‘¢EQcHScNVd´¨§¿®¨Èµ®¯‘‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯â‹¯â‹¯â‹¯â‹¯â‹¯â‹°â‹°â‹°â‹°â‹°â‹°â‹°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Œ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Ü…©Ü…©ÜGlžGlž…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÝHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž‡«Ý‡«ÝDhšDhšDhšDhš=J[=J[=J[=J[=J[=J[ ->(/7#)2#)2(.7(.7(.7#*2(/7)/8)/8)/8)/8)08*0903:56:88@KBB=;@348*08&(+'(*%%%$$$(((EEE(((&&&���">-"bF3oXMs[Ow]Py^PqbpXMdH5R<,Q;, &%%#'-"'-&3DS_qP\nR_p>J\?K]AG@B::@66:-29'),)'%BBBFFFEEE)))))))))&&&��������������� ������������������������������������������@@@FFFACFZ\_[ajagp„¢„¢„¢ž¥­Ÿ¦®—¦–¥–ž•žŽ•Ž””œ“œ‘— —Ÿ›¡ªš ©™ ¨Ž•Ž”Ž”…‘£…‘£…‘£EQcGRcKTdPWd­¥§¿¯ª‹°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°ãŒ°ãŒ°ãŒ°ãŒ°ãLp£Lp£Lq£Lq£Lq£Lq£Lq£Lq£Lq£Œ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£…©Û…©Û…©Û…©Û…©Û…©Û…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHlžHlžHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«ÞŸ>J\>J\=J[=J[=J[=J[FLU39B#*2(/7)/7)/8$*3$*3$*3)/8)08*09*09*19',5(-5*.6.17338@<=G@BH@BXW]UUXLPWFHKDFHKKKHHH+++%%%%%%$$$###!!!!!!777777777777777777777AAAFFFACFACF\^aeltbhqDQbDQbDQbŸ¥®¡§°¡§°¡§°¡§°—¦–Ÿ”š£”š£“™¢’™¡’˜¡‘˜ ‘— ›¡ª›¡ªš ©•ž™Ÿ¨Ž”ERcERcERcERcHScLUdRXd|njŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°ãŒ°ãŒ°ãŒ°ãŒ°ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬ÞŽŸŽŸŽŸŽŸ>J\=J[=J[FLUFLU(/7(/7*08*08%+3$*3$+3$+3*09*09*19&,5&,5'-6).6*/7-18NPURRVXUVc]^f^_[X]\XYTUZLQYKMPFHJ)))(((&&&%%%%%%$$$$$$###!!!!!!!!!777777777BBBEEEACGADGFIL\ckZ`iTZcDQbDQbDQbagpbiqcircir¢©±¢¨±¡¨°¡§°•œ¤•›¤”›£”š£“™¢’™¡’˜¡œ¢«œ¢«›¡ªš¡©•žY`hY_hERcERcERcGSdJTdNVdTYeLp¢Lp¢Œ°ãŒ°ãŒ°ãŒ°ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£±ã±ã±ã±ä±ä±ä±ä±ä±ä±ä±ä±ä±ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²äMq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞŽŸŽŸŽŸŽŸŽŸŽŸŽŸFLUFLUFLU)/8+08+08&+3&+3%+4%+4%+4*19+1:&,5'-5'-6(.6FLTHMTINUKOVOQWSTXYWX`[^lbac]_f_\a_aY\aRX_,.1*,.*+-***((('''&&&%%%%%%$$$$$$$$$###!!!!!!!!!!!!!!!%%%%%%%%%%%%"""""""""KKKJJJFFFGIL]_b^dm\bkV]eDQbEQcEQcEQccirdjsdksektdjsdjscir£©²¢¨±¢¨±–œ¥•œ¤•›¤”›£”š£“™¢’™¡£¬œ¢«›¢ª[ajZ`iOU^ERcERcFRdFRdITdLUdPWeVZeLp£Lq£Lq£Lq£±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ä±ä±ä±ä±ä±ä²ä²ä²äMq£²ä²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äMr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«ÞHmŸHmŸHmŸ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞŽŸŽŸŽŸŽŸ‚Ž ‚Ž ‚Ž ‚Ž ”›£Š™ŠŽ•-18,18',3',4',4&,4%,4+1:,2:'-5DJSEKSEKTFLTFLUHMUINVKOWLPWQSYTUZWWZpjje^`offb\_h`]eaaCCG8;A27?-/2+-/.+)******)))((('''&&&&&&%%%%%%$$$$$$$$$$$$$$$$$$######???EEEEEEEEE((((((###&&&%%%HJMHJMHJMHJM_en]dlZ`i_enEQcEQcEQcEQcbhqektflufluflufluektektdksdjscjr£©²¢©±¢¨±–œ¥•œ¤•›¤”›£”š£“™¢£¬\ckQW`[ajZaiOU^FRdFRdFRdHSdKUdNVeRXeX\fLq£Mq£Mq£Mq£Mq£±ã±ã±ã±ã±ã±ä±ä±ä±ä±ä²ä²ä²ä²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äMr¤Mr¤Mr¤Mr¤Mr¤Ž²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åNr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬ÞHmŸHmŸHmŸHmŸImŸImŸImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ”›£Š‘™‹•‹•PT[KOVJOV(-4(-4'-5'-5JOXEKSEKSEKTFLTFLTGMUGMUHNVIOWKPWLQXMRYPTZTV[\]a_^asljd^azporjkE@CLEBIEFEDG29A28A17@135,.1+-0+,/./1..0'),)))++++++++++++***FFFFFFACFACFEEEACFACFŠŒJLOJLOKQZ_en]clY_hU[dEQcEQcEQcEQcEQcagp[aj\bk\bkgnvgnvgmvgmvfluflueltektdksdjscjrcir¢©±—¦–œ¥•œ¤•›¤TZcSYbRYaRXaQW`[bj[ajZ`iFSdFSdGSdJTdLVePXeTZfZ]fMq£Mq£Mq£Mq£Mq£Mq£Mq£²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äNr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Ž²åŽ²åŽ²åŽ²åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³å³å³å³å³å³å³å³åNr¤Nr¤Nr¤Nr¤Nr¤³å³å†ªÜ†ªÜ†ªÝHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ­ß‚Ž ‚Ž ‚Ž ‚Ž ‚ ‚ ‚ ‚ ‚ …Œ”’•šŒ•‘”›LPVLPWKPW‹—‹—‹˜•‹‘™FLTFLTFLUGMUGMUHMVHNVINWIOWKPXLQYMRYNSZTX`X[a[]b]^c__ccacib`JDGi__aYYPJLD@C=;AKEDTQR@?A>>A;/5>.4=-4 - - images/16bpp.bmp - images/4bpp-rle.bmp - images/YCbCr_cmyk.jpg - images/YCbCr_cmyk.png - images/YCbCr_rgb.jpg - images/away.png - images/ball.mng - images/bat1.gif - images/bat2.gif - images/beavis.jpg - images/black.png - images/black.xpm - images/colorful.bmp - images/corrupt-colors.xpm - images/corrupt-pixels.xpm - images/corrupt.bmp - images/corrupt.gif - images/corrupt.jpg - images/corrupt.mng - images/corrupt.png - images/corrupt.xbm - images/crash-signed-char.bmp - images/earth.gif - images/fire.mng - images/font.bmp - images/gnus.xbm - images/image.pbm - images/image.pgm - images/image.png - images/image.ppm - images/image_100dpi.tif - images/kollada.png - images/marble.xpm - images/namedcolors.xpm - images/negativeheight.bmp - images/noclearcode.bmp - images/noclearcode.gif - images/nontransparent.xpm - images/runners.ppm - images/teapot.ppm - images/test.ppm - images/test.xpm - images/test32bfv4.bmp - images/test32v5.bmp - images/tst7.bmp - images/tst7.png - images/transparent.xpm - images/trolltech.gif - images/qt.gif - images/qt1.gif - images/qt2.gif - images/qt3.gif - images/qt4.gif - images/qt5.gif - images/qt6.gif - images/qt7.gif - images/qt8.gif - images/endless-anim.gif - images/four-frames.gif - images/qt-gif-anim.gif - images/qt-gif-noanim.gif - images/rect.svg - images/rect.svgz - images/corrupt.svg - images/corrupt.svgz - images/qtbug13653-no_eoi.jpg - images/txts.png - - diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp deleted file mode 100644 index 6359468597..0000000000 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ /dev/null @@ -1,2026 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../platformquirks.h" - -#if defined(Q_OS_SYMBIAN) -# define SRCDIR "." -#endif - -typedef QMap QStringMap; -typedef QList 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("fileName"); - QTest::addColumn("success"); - QTest::addColumn("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("fileName"); - QTest::addColumn("newSize"); - QTest::addColumn("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("fileName"); - QTest::addColumn("newRect"); - QTest::addColumn("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("fileName"); - QTest::addColumn("newRect"); - QTest::addColumn("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("fileName"); - QTest::addColumn("format"); - QTest::addColumn("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 formats = QImageReader::supportedImageFormats(); - QList sortedFormats = formats; - qSort(sortedFormats); - - // check that the list is sorted - QCOMPARE(formats, sortedFormats); - - QSet 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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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("fileName"); - QTest::addColumn("format"); - QTest::addColumn("size"); - QTest::addColumn("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("fileName"); - QTest::addColumn("shouldFail"); - QTest::addColumn("message"); - QTest::addColumn("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("fileName"); - QTest::addColumn("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 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("uncompressedFile"); - QTest::addColumn("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("expected"); - QTest::addColumn("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("fileName"); - QTest::addColumn("expectedDotsPerMeterX"); - QTest::addColumn("expectedDotsPerMeterY"); - QTest::addColumn("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("fileName"); - QTest::addColumn("expectedPhysicalDpiX"); - QTest::addColumn("expectedPhysicalDpiY"); - QTest::addColumn("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("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("name"); - QTest::addColumn("extension"); - QTest::addColumn("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 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("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("fileName"); - QTest::addColumn("key"); - QTest::addColumn("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("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/qimagewriter/.gitignore b/tests/auto/qimagewriter/.gitignore deleted file mode 100644 index 9355bcd1bf..0000000000 --- a/tests/auto/qimagewriter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qimagewriter diff --git a/tests/auto/qimagewriter/images/YCbCr_cmyk.jpg b/tests/auto/qimagewriter/images/YCbCr_cmyk.jpg deleted file mode 100644 index b8aa9ea609..0000000000 Binary files a/tests/auto/qimagewriter/images/YCbCr_cmyk.jpg and /dev/null differ diff --git a/tests/auto/qimagewriter/images/YCbCr_rgb.jpg b/tests/auto/qimagewriter/images/YCbCr_rgb.jpg deleted file mode 100644 index 8771224cb5..0000000000 Binary files a/tests/auto/qimagewriter/images/YCbCr_rgb.jpg and /dev/null differ diff --git a/tests/auto/qimagewriter/images/beavis.jpg b/tests/auto/qimagewriter/images/beavis.jpg deleted file mode 100644 index d55504779b..0000000000 Binary files a/tests/auto/qimagewriter/images/beavis.jpg and /dev/null differ diff --git a/tests/auto/qimagewriter/images/colorful.bmp b/tests/auto/qimagewriter/images/colorful.bmp deleted file mode 100644 index 8ea6f4acd7..0000000000 Binary files a/tests/auto/qimagewriter/images/colorful.bmp and /dev/null differ diff --git a/tests/auto/qimagewriter/images/earth.gif b/tests/auto/qimagewriter/images/earth.gif deleted file mode 100644 index 2c229eb110..0000000000 Binary files a/tests/auto/qimagewriter/images/earth.gif and /dev/null differ diff --git a/tests/auto/qimagewriter/images/font.bmp b/tests/auto/qimagewriter/images/font.bmp deleted file mode 100644 index 28b8c66924..0000000000 Binary files a/tests/auto/qimagewriter/images/font.bmp and /dev/null differ diff --git a/tests/auto/qimagewriter/images/gnus.xbm b/tests/auto/qimagewriter/images/gnus.xbm deleted file mode 100644 index 58d1ac845a..0000000000 --- a/tests/auto/qimagewriter/images/gnus.xbm +++ /dev/null @@ -1,622 +0,0 @@ -#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/qimagewriter/images/kollada.png b/tests/auto/qimagewriter/images/kollada.png deleted file mode 100644 index 2abd4bb763..0000000000 Binary files a/tests/auto/qimagewriter/images/kollada.png and /dev/null differ diff --git a/tests/auto/qimagewriter/images/marble.xpm b/tests/auto/qimagewriter/images/marble.xpm deleted file mode 100644 index e59830bbe9..0000000000 --- a/tests/auto/qimagewriter/images/marble.xpm +++ /dev/null @@ -1,329 +0,0 @@ -/* 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/qimagewriter/images/ship63.pbm b/tests/auto/qimagewriter/images/ship63.pbm deleted file mode 100644 index 4da971a2d7..0000000000 Binary files a/tests/auto/qimagewriter/images/ship63.pbm and /dev/null differ diff --git a/tests/auto/qimagewriter/images/teapot.ppm b/tests/auto/qimagewriter/images/teapot.ppm deleted file mode 100644 index b8ab85f3a5..0000000000 --- a/tests/auto/qimagewriter/images/teapot.ppm +++ /dev/null @@ -1,31 +0,0 @@ -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!j@#k@$h>"dµf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&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: X/K%���������&4$+2F=;HPEJL&\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlR¶xT­sTµd)ŠO$w; m6 -g3 -a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d!Y0�����������W+]. s=‡M$dPŸlR\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀoTM¥oRdPvE"V+K%A 99���†F¤['qUMtVM99H:9H:9H:9H:9H:9H:9H:9H:9H:9H99H99H99H99H99H99H:9H;:H>;HB=HPDJ\JKmSMwXN|ZN°y[ᦆ֘uº{W¹yU¿€]Á„b­tU£nR—hQˆaO{ZNvWNtVMvXNwXNyYNzYN{ZN|ZN}[N}[N~[N~[N~[N~[N~[N~[N~[N}[N}[N{ZNzYNxXN…L$f3 -���I$L&P(U*\. €J#\O›jQ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀžkR‰aOo9 L&C!:4���f3 -X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?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$���G#K%Q(W+zG#nTM˜iQ\À\À\À\À\À\À\À\À\À\À\À\ÀdOLrUMuWNwXNyYN{ZN}[N{ZNwXNsVM \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àˆ`OcPnA"M&@ 8F#���m6 -›W&rVMvWNyYNzYN|ZN}[N}[N>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%���F#B!Y,L&U*~I#„^O†`O\À\À\À\ÀcNLrUMzYN\O„^Oˆ`OŠbPŒcPdPeP’fP“fP“fQ“fQ”fQ‘ePcP‰aP~[N�\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À’fPsVM^/ C!7 ������ŽQ%tVMwXNzYN|ZN}[N\N\O€\O]O]O‚]O‚]OA=HB=HB=HB>HC>HC>ID?IE?IF@IG@IIAIKBIŒcPdP’eP–gQšiQŸlR£nR¤\'´d)¿i*Æm+Îs/Ïs/Êo+Én+Ål*¾i*ºg)³c(ª_(ªqS¦oR¡mRkQ™iQ•gQ“fP‘ePŽdPcPŒbP‹bPŠbPŠaP‰aP‰aO‰aOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O„^Oƒ^O‚]O\O}[N›Q��D"?D"K%_/ kRL’fPODJSFJ†_OŠbPŽcP‘eP“fQ–gQ™iQœjQžkR lR¡mR£nR¤nR¥oR¥oR¥oR¤nR¢mRŸlRšiQ‘eP…_O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀB+‘ePI#L&90���y< šPxXN{ZN}[N\N€\O]O‚]Oƒ^Oƒ^O„^O„_O…_O…_O†_O†`O‡`O‡`Oˆ`O‰aOŠaP‹bPŒbPcPŽdP‘eP“fP•gQ˜hQšiQžkR¢mR¡Z'«_(¶e)½h)Âk*Çn,Çn,Æm*Æl*Áj*ºf)¶e)²c(«_(¦]'§pR¤nR¡mRžkR›jQ™iQ–gQ”gQ“fP‘ePdPdPŽdPŽcPcPŒcPŒbP‹bP‹bP‹bPŠbPŠaP‰aP‰aO‰aOˆ`O‡`O†_O…_Oƒ^O]Oª_(@ ���B!I$B!N'w=‘eP`LKbNLeOLkR mR£nR¥oR§pSªqS¬rS®sS¯tS°tS°tS±uS±uS°tS¯tS­sSªrS§pS¢mRšjQŒbPjQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‹bPpTME"5���������‡M$tVM{ZN}[N\O]O‚^Oƒ^O„_O…_O†_O†`O‡`Oˆ`Oˆ`O‰aO‰aPŠaPŠbP‹bPŒbPcPŽcPdPdP’eP“fP•gQ—hQ™iQ›jQkR lR¢mR¡Z'¬`(µd)ºg)ÇgÀj*Àj*¾i*¿i*»g)µd)²c(¯a(ª_(¤\'§pR¥oR¢nR mRžkRœjQšiQ˜iQ—hQ•gQ”gQ“fP’eP‘eP‘ePdPdPdPŽcPŽcPcPcPŒcPŒbP‹bP‹bPŠbPŠaP‰aOˆ`O†_O„^O\NœQ����@ <G#_LKŽcPlSMnTMpUMsVM°tS²uT³vTµwT¶wT¶xT¶xT¶wTµwT´vT²uT¯tS¬sSªqS§pS¤oR¢nRžkR˜hQ‹bPeOL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN\NJ%0������1ŽJvWN}[N\O]Oƒ^O…_O†_O†`O‡`Oˆ`O‰aO‰aPŠaPŠbP‹bPŒbPŒbPcPŽcPŽdPdPdP‘eP’eP”fQ•gQ–gQ˜hQ™iQ›jQkQŸlR¡mRžY&¦]'­`(³c(·e)Àc¸\¸\¹\º]»]¶^®a(¬`(©^'£['¢['¥oR£nR¡mR lRžkRœkQ›jQšiQ˜iQ—hQ–gQ•gQ”gQ”fQ“fP’eP’eP‘eP‘ePdPdPdPdPŽdPŽcPcPcPŒbP‹bPŠaPˆaO†`O]O˜O������G#7F#uWMƒ^OwXNxXNzYN{ZN|ZN¹yT¸yT·xT´wT±uT­sS¨pS¡mRœjQ•gQdPŒbP‰aP‰aPŒbPŽcP‘ePcP|ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[JKŠbP^/ 1 01|> wXN}[N]Oƒ^O…_O‡`O‡`OˆaO‰aPŠaP‹bP‹bPŒbPŒcPcPŽcPŽcPdPdPdP‘eP’eP“fP”fQ•gQ–gQ—hQ˜hQ™iQ›jQœkQžkRŸlR mRžY&¦]'­`(±b(·[ÇgÉiÉhÅfÂdÃe¿c«Uª_(§]'£[' Z'¤nR£nR¡mR mRŸlRžkRkQœjQšjQšiQ™iQ˜hQ—hQ–gQ•gQ•gQ”fQ”fQ“fP“fP’eP’eP‘eP‘ePePdPdPdPŽcPcPŒbPŠbPˆ`Oƒ^O‰D �����4M&dPnSM|[N|[O|[OzZOxXNªrS¢nR˜hQŽcPƒ^OvXNiQL^KKRFJMCJJAIKBISFJ\JKnSMxYN†_O€\OaMK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀB!qUMŠaPC!/00a0 uWN}[N‚]O…_O†`Oˆ`O‰aPŠaP‹bPŒbPŒcPcPŽcPŽcPdPdPdP‘eP‘eP’eP“fP“fQ”fQ•gQ–gQ—hQ˜hQ™iQ™iQ›jQœjQkRžlRŸlRœX&¢['¨^'¬`(´ZÂdÄfÈiÆgÂd¿c¿c¼a¸_©T¥\'£[' Z'ŸY&£nR¢mR¡mR lRŸlRžkRkQœjQ›jQšjQšiQ™iQ˜hQ—hQ—hQ–hQ–gQ•gQ•gQ”gQ”fQ”fQ“fQ“fP’fP’eP‘eP‘ePdPdPŽcPŒbP‰aOƒ^Ox< �������:ŠaP]Oj8sVMmSMfOL^KKUGJIAIQEJ?IeZY638*  B\À\À\À\À\À,  4 .G1!\TU¡ƒrsVM{ZN`MK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[JKyYNŒbP/0������ˆN$]O…_Oˆ`O‹bPŒbPcPŽcPdPdPdP‘eP‘eP’eP’fP“fP“fQ”fQ”gQ•gQ–gQ–gQ—hQ—hQ˜hQ™iQ™iQšiQ›jQœjQœkQkRžkRŸlRœO¡Z'¥\'©^'­V¼a¾bÁeÆi!Ãf¾b»a¹`·_³]²\µZ¢[' Z'ŸY&œQ¡mR¡mR mR lRŸlRŸlRžkRkRkQœkQœjQ›jQ›jQšjQšiQšiQ™iQ™iQ˜iQ˜hQ˜hQ—hQ—hQ—hQ–hQ–gQ–gQ•gQ•gQ”fQ’fPdPcPšW&������������dPŠaPrUM - B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6 - ���X,uWM‚]O‡`OŠbPcPŽdPdPdP‘eP’eP’fP“fP“fQ”fQ”gQ•gQ•gQ–gQ–gQ—hQ—hQ˜hQ˜iQ™iQ™iQšiQ›jQ›jQœjQœkQkQžkRžlRŸlR¢Z'¤\'§]'·_¹`¼a½bÁeÅi"Áe¼aº`·_¶_²]²\±\«Y¡Z' Z'¡Z'¡mR¡mR mR lR lRŸlRŸlRžlRžkRžkRkRkQœkQœjQœjQ›jQ›jQ›jQšjQšiQšiQšiQ™iQ™iQ™iQ˜iQ˜hQ˜hQ—hQ–gQ•gQ“fQdP†_Oq8 ���������–gQˆ`OuWM”T%\À\À\À\À\À\À\À\À\À\À B B!!T,c5ƒF‚T3È›~Æ“qƒ^OfOL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK_LKsVM‡`OcP������ ’S%]OŠbPcPdP‘eP’eP“fP“fQ”fQ”gQ•gQ•gQ–gQ–gQ—hQ—hQ—hQ˜hQ˜iQ™iQ™iQšiQšiQ›jQ›jQœjQœjQkQkRžkRžlRŸlRŸlR¥\'¦]'¨^'­Vº`»a½bÁfÄi"Àe»a¹`·_¶_³]±\±\¤R¢Z'¢Z'£['¡mR¡mR¡mR¡mR mR lR lRŸlRŸlRŸlRžlRžkRžkRkRkRkQkQœjQœjQœjQœjQœjQ›jQ›jQ›jQ›jQšjQšiQ™iQ™iQ˜hQ–gQ‘eP§Sq8 ������‰aO•gQ‡`OtVMœX&\À\À\À\À\À\À\À\À\À\À B B B l@!{A…L$›Y'½†a“fPˆaO]KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀODJ[JKaMKqUM\OcPƒ^O������vE"‚]OŠaPdP‘eP“fP”fQ•gQ•gQ–gQ–hQ—hQ—hQ˜hQ˜hQ˜iQ™iQ™iQ™iQšiQšjQ›jQ›jQœjQœjQœkQkQkRžkRžkRŸlRŸlRŸlR lR©^'©^'ª_(®W»a¼a¾cÂg Äi"¿e»a¹`·_¶_³^±\±\¤R£['£['§]'¢mR¢mR¡mR¡mR¡mR¡mR mR lR lR lR lRŸlRŸlRŸlRŸlRžlRžlRžkRžkRžkRžkRkRkRkRkRkQkQkQœjQœjQšiQ˜hQ’ePšW&M&���oTMšiQ‘eP…_OtVMmSMdOL\À\À\À\À\À\À\À\À\À B B B ‘J Z'ª_(œkQ™iQ‡`OSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJ\JKcNLlRMzYN‡`O’ePzZN��� �\Nˆ`OdP“fQ•gQ–gQ—hQ˜hQ˜hQ™iQ™iQ™iQšiQšiQšiQ›jQ›jQ›jQœjQœjQœjQœkQkQkRžkRžkRžlRŸlRŸlRŸlR lR lR mR®a(­`(¬`(¶[½a½b¿dÃh!Äi"¿d»a¹`¸_¶_µ^²]³]¦S¤\'§]'«_(¢nR¢mR¢mR¢mR¢mR¢mR¢mR¡mR¡mR¡mR¡mR¡mR mR mR mR mR lR lR lR lR lR lR lR lR lRŸlRŸlR lRŸlRžkRœkQ™iQePt: ������kQ˜hQcP€]OtVMlSMa2 \À\À\À\À\À\À\À\À\À B B -$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�oTM•gQ™iQkQŸlRŸlR lR mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR£nR£nR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nRÆl*Ãl+¾j+¹g)¸f)¶e)µd)¶e)¶e)·e)·e)¸f)¾i*Ìs0Ðs.¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦pR§pR§pR§pR§pR§pS§pS¨pS¨qS©qS©qS©qS¨pS©qS§pS¤nRŸlR‘I˜hQ§pR¥oR¡mRšiQ’ePŠaP€\OsVMpTMnTMlRM–X)\À\À\À\À\À\À\À B%C)D$;J/[8"LBITGJYIKWHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK_LKcNLgPLjQLlRMpUMzYNƒ^O‹bP‘eP˜hQkQŸlR”fQ- —hQ›jQŸlR¢mR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦oR¦oR¦oR¦pR¦pR§pRàpßy-Ûw-Ûw-Þy.â{-ãu§pS§pS§pS§pS§pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨qS©qS©qS©qS©qS©qS©qS©qSªqSªrS«rS«rS¬rS¬rS¬rS¬rS¬sS«rSªqS¦oRšiQ™iQ©qSªqS§pR¡mRœjQ•gQcP„_O{ZNtVMpUMoTMmSMjQL_9 \À\À\À\À\À B "C(D#*A$[<)dI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JKaMKeOLhPLkRLmSMoTMuWM}[N…_O‹bP’eP˜hQžkR¢mR£nRžkR!-EkR¡mR¤nR¥oR¦pR§pR§pS§pS§pS§pS§pS§pS§pS§pR§pS§pS§pS§pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨pS¨qS¨qS¨qS©qS©qS©qS©qS©qS©qS©qS©qS©qS©qS©qSªqSªqSªqSªqSªrS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬sS­sS®sS®sS¯tS¯tS¯tS¯tS°tS°uS°tS®sS«rS£nR¦oR®sS­sS«rS§pR¢mRœjQ–gQdPˆaO\OyYNuWMqUMoTMnSMkRLo8 \À\À\À\À\À B'D+E$(1 J/jH1NCJUGJYIKUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK]KKbNLfOLiQLkRMmSMoTMqUMxXN\N†_OŒbP’fP˜hQkQ¡mR¥oR§pS¦pR˜hQ¢mR¥oR¨pSªqS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rSªrSªrSªrS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬rS¬rS¬rS¬rS¬sS¬sS­sS­sS­sS­sS­sS­sS®sS®sS®sS®sS®tS¯tS°tS°uS±uS±uT±uT²uT²uT²uT´vTµwT´vT³vT²uT¯tS¢mR¯tS±uT±uS®tS«rS§pR¢mRkQ—hQ‘ePŠaPƒ^O\N{ZNvXNqUMpTMnSMlRMP%\À\À\À\À B#C*E$.E- .!G$Y:%d<"SFJYIKZIKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀPDJZIK_LKdNLgPLjQLlRMnSMpTMqUMuWMyYN€\O†`OcP’fP—hQœjQ¡mR¥oR¨qS«rS«rSªrS mR�«rS­sS¯tS°tS°tS°tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS®tS®sS®sS®sS®sS®sS®sS®sS®sS®sS®tS®tS®tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS¯tS°tS°tS°tS±uS±uS±uT²uT²vT³vT³vT´vT´vT´wTµwTµwTµwT·xT·xT¸xT¸yT¸yU·xU¥\'©qS³vTµwTµwT´vT±uT®tTªrS¦oR¡mRkQ˜hQ’eP‹bP‡`Oƒ^O€\O|ZNxXNtVMpTMoTMmSMjQLh7\À\À\À B(D"-E*1F, 4#K)pL5PEJWHK[JKXHK:9H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀUGJ\JKaMLeOLhPLkRLmSMoTMpUMrVMvWNyYN|ZN]O‡`OŒcP‘eP—hQ›jQ lR¤nR§pSªqS­sS¯tS°uS¯tS­sS mR^/ ²vT³vT´vT´wTµwT´wT´vT³vT´vT´vT´vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT³vT´vT´vT´vT´vT´wTµwTµwTµwTµwT¶wT¶wT¶xT·xT·xT·xT¸xT¸xT¸xT¹yTºyT»zU¼zU½{U½{V½|V•gQ¬rSµwT¸xT¹yU¹yU¹zV·yVµxV±vU­tT©qS¥oS mRœjQ—hQ’ePcPŠbP‡`O„_O]O}[NyYNuWMpUMoTMmSMkRL}H#\À\À &D -E(1F/!2#8 W7"iA&UGJ[JK\JKREJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀMCIXIK^KKcNLfOLiQLkRMmSMoTMqUMsVMwXNzYN}[N€\Oƒ^O‡`OŒbP‘eP–gQšjQžkR¢mR¥oR©qS¬rS¯tS±uS³vT´vTµwT´wT²uT­sS lR«_(¹yT¹yTºyTºyTºyTºyTºyT¹yT¹yT¸yT¸xT¸xT¸xT¸xT¸xT¸xT¸yT¸yT¸yT¸yT¹yT¹yT¹yT¹yT¹yT¹yT¹yTºyTºyTºyTºyTºzT»zT¼zU¼{U½{U¾{U¾|U¿|UÀ}VÁ~VÂWÀY™iQ«rSµwT¹yT¼zU½|V¿}XÁ€ZÂ]Á]¾€]»~[¶zY±wW¬tU¨qS¤nSŸlR›jQ–gQ“fPePŽcP‹bPˆ`O…_O‚]O~\NzZNvXNqUMoTMnSMlRMiQLg=!\À -!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?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 |> ���������������’eP¦oR¨qS¦oR¡mRšjQ‘eP„^OhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ\KKaMLeOLhPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_Oˆ`OŠbPcPdP‘eP“fQ•gQ—hQ™iQ›jRkRŸmS¢nT¤qV¨sX¬w[±{_¶€c½†hÄŒnË’tÒ™zØŸ€Þ¥…㩉ç­ê¯Žê¯Žê®ç«Šä§†ß£Ûž|Õ˜vГpËŽkljfÃ…bÀ‚_½\»}Yº{X¸zW¸yV·xU·xU·xT¶xT¶xT¶xU¶xU·xU·xU·yV·yV·zW¸zX¸{Y¹|Y¹|Z¹}[¹}[¹}\¹}\¸}\·}\¶|\µ{[³zZ²yZ°wY®vX¬tWªsV¨rU¦pT¤oS£nS¡mRŸlRžkRœjQšiQ˜hQ–gQ”fQ’ePdPŽcP‹bPˆ`O…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQLfOLJ(V.]KKePNkUQcNLQEJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‚]O¡mR©qS¬rS°tS³vTµwT·xUº{WĆbÒ“qךxÊo -���������������K«rS´vT¶wT´vT²uT®sSªqS¤nRkQ•gQˆ`OuWNY,\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^KKbNLfOLhQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N]O„^O†_O‰aO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRkRŸmS¢oT¥qV¨tX­w[±|_·d½†iÄŒnË“tÒ™zØŸ€Þ¥…㩉笌鮎ꮎ魌檉㧅ߢ€Ú{Õ—uÏ’pËjƈfÂ…b¿^½\»|Y¹{X¸zV·yV·xU·xU¶xT¶xT¶xT¶xU¶xU¶xU¶xU·yV·yV·yW¸zW¸{X¸{Y¸|Z¹|Z¹|[¹}[¸}\¸}\·|\¶|[µ{[³zZ±xY°wX®vX¬tWªsV¨rU¦pT¥oS£nS¡mRŸlRžkRœjQšjQ˜iQ—hQ”gQ’fPdPŽcP‹bP‰aO†_Oƒ^O€\O|ZNxXNtVMoTMnSMlRMjQLgPLzG#\JKcOMoXUgPMZIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À’fP”gQ•gQ—hQ™iQkQ lR¤nR§pRªqS¬sS¯tS������:"r<zYN­sS¹yT¾|UÁ~WÆ„^ËŠeË‹gƈe¾‚aµz[­tV¦pS¢mRkQ–gQŠbPzYNkRL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀRFJZJK`LKcNLfPLiQLkRMmSMoTMqUMrVMvWNyYN|ZN\N]O„^O‡`O‰aO‹bPcPdP’eP”fQ–gQ—hQ™iQ›jRlR mS¢oU¥qV©tY­x\²|`¸d¾‡iÅoË“uÒ™{ÙŸ€Þ¥…㩉笌é®é®è¬‹å©ˆâ¦„Þ¡ÙœzÔ—tÏ‘oÊŒjƈe„a¿^½~[»|Y¹{X¸zV·yV·xU¶xU¶xT¶xT¶xT¶xT¶xU¶xU¶xU¶xV·yV·yW·zW·zX¸{Y¸{Y¸|Z¸|Z¸|[¸|[·|[·|[¶{[´z[³yZ±xY°wX®vW¬tWªsV¨rU¦pT¥oS£nS¡mRŸlRžkRœkRšjQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aP†`Oƒ^O€]O}[NyYNuWNqUMnSMlSMkRLhPLcNLbNLpYVlUP`LK>;H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À›jQ‡`O{ZN©^'¨^'­`(·e)½h)Ãk*Êo+±b(£nRºyTÃ~UÇXÒdãŸwò°‰ñ°‹è©…ÝŸ}Ô˜vÈm¾„eµ}_®x[°y\®x[«tW§qT¡mRœjQ–gQ‹bP}[NlRM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\JKaMKdNLgPLjQLlRMnSMpTMqUMsVMvXNzYN|[N\O‚]O…_O‡`O‰aPŒbPŽcPdP’eP”fQ–gQ˜hQšiQœjRžlS mS£oU¦rW©uY®x\³|`¸d¾‡jÅoÌ“uÒš{Ù €Þ¥…㩉欋è­è­Œç«Šå©‡á¥ƒÝ ~Ø›yÓ–tΑoÊŒjňe„a¿^¼~[º|Y¹{W¸zV·yV·xU¶xU¶xT¶xT¶xT¶xT¶xU¶xU¶xU¶xU¶xV·yV·yW·zX·zX¸{Y¸{Z¸{Z·|Z·|[·|[¶{[µ{[´zZ³yZ±xY¯wX®uW¬tVªsV¨rU¦pT¥oS£nS¡mR lRžkRœkR›jQ™iQ—hQ•gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O~[NzYNvWNrUMnSMmSMkRLiQLeOLoXUu]XdOLKBI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À:9H\N–hQ¸}\¯uU­sT¯tT¯tS¨qS¤nR£nR¢nRŸlR›jQšiQ˜hQ—hQ–gQ”fQ’eP‘eP—hQœkR mS¥pUªtX«uY¨sW¦qU mS›jQ•gQƒB’S%jQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀLBIXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMtVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽcPeP’fP”fQ–gQ˜hQšiRœkRžlS nT£pU¦rWªuY®y]³}`¹‚e¿ˆjÅŽpÌ”vÓš{Ù Þ¤…⨉櫋笌笋櫊䨆ंܟ~ךxÒ•sÎnÉŒiŇeÁ„a¾€^¼~[º|Y¹{W¸yV·yV·xU¶xU¶xT¶wT¶wT¶wT¶xT¶xU¶xU¶xU¶xV¶yV¶yW·zW·zX·zY·{Y·{Z·{Z·{Z¶{Z¶{ZµzZ³yZ²yY±xY¯vX­uW¬tVªsU¨rU¦pT¥oS£nS¡mR lRžlRkR›jQ™iQ—hQ•gQ“fQ‘ePdPcPŠaP‡`O…_O‚]O\N{ZNwXNsVMnSMmSMkRMiQLfOL_LKhQMUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À (6BFP>=DKHMqjk€trwf`~kc„ndŠqesete¯Ž{w`¡v[\N†_OcP“fP˜iQœjRŸlS£oT¦qV¥qV£oTžlR™iQº^‡`OQ%hPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJZIK_LKcNLfOLiQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N€]Oƒ^O…_Oˆ`OŠaPŒcPŽdP‘eP“fP”gQ–hQ˜iQšjRœkRžlS¡nT£pU¦rWªuZ®y]³}a¹‚e¿ˆkÆŽpÌ”vÓš{ÙŸ€Þ¤…⨈媊櫋櫊婈⦅ߣ۞}ÖšxÑ•rÍmÈ‹ićdÁƒa¾€]¼~[º|Y¹zW¸yV·yU¶xU¶xU¶wT¶wT¶wT¶wT¶wT¶xU¶xU¶xU¶xU¶xV¶yV¶yW¶zX·zX·zY¶zY¶{Y¶{Z¶{ZµzZ´zZ³yY²xY°wX¯vX­uW«tVªsU¨rU¦pT¥oS£nS¡mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ‘ePdPcP‹bPˆ`O…_O‚]O\O|ZNxXNtVMoTMmSMlRMjQLgPLbML[JK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À%5 (6$/79CEEKjgkrc_›…{‘uf±{Ÿw_ºq]Oˆ`OŽcP”fQ˜hQ›jRžlR¡nT¢oT¡nTkR˜hQŽdP¦]'ŽQ%\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀUGJ[JK`MKdNLgPLiQLkRMmSMoTMqUMrUMuWNxXN{ZN~[N]Oƒ^O†_Oˆ`OŠbPcPdP£['µd)•gQ—hQ˜iQšjRœkRžlS¡nT£pU§rWªvZ¯y]´~aºƒfÀˆkÆŽpÌ”vÓš{ØŸ€Ý¤„ᧇ䩉媊媉䨇᥄ޡ€Ú|Õ˜wДrÌmÈŠhĆdÀƒ`¾€]»}[º|Y¸zW·yV·xU¶xU¶xU¶wTµwTµwTµwTµwTµwUµwUµxUµxUµxV¶xV¶yW¶yW¶yX¶zX¶zY¶zYµzYµzY´zY´yY²yY±xY°wX®vW­uW«tVªsU¨qU¦pT¥oS£nS¢mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ’ePdPcP‹bPˆaO†_Oƒ^O€\O|[NxYNtWMpUMmSMlRMjQLgPLcNLA;=\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À#*6+.8;:AHEJmgjd\]‡pe«}œxc w^»pƒ^OŠaP‘eP–gQšiQžlR mS¢nT mS›jR•gQ»h*œX&ˆM$\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀC+WHJ]KKaMLdOLgPLjQLlRMnSMoTMqUMrVMvWNyYN|ZN\N]O„^O†_OˆaO‹bPcPžY&«_(³c(•gQ—hQ™iQšjRœkRŸlS¡nT¤pV§sX«vZ¯z^´~bºƒfÀ‰kÆŽpÌ”vÒš{ØŸ€Ý£„ই㩉䩉䩈⧆ःܠØœ{Ô—vÏ“qËŽlljgÆcÀ‚`½]»}Z¹{Y¸zW·yV¶xU¶xU¶wUµwTµwTµwTµwTµwTµwTµwUµwUµxUµxVµxVµxVµyWµyWµyXµyXµyYµzY´yY´yY³yY²xY±wX°wX®vW­uV«tVªrU¨qU¦pT¥oS£nS¢mS mRžlRkR›jQ™iQ˜hQ–gQ”fQ’ePdPŽcP‹bP‰aO†_Oƒ^O€\O}[NyYNuWNqUMmSMlRMjQLhPLdNL\1\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À+.775;ICFphhŠztŠre¯}Ÿya¢vZ]OŠaP‘eP–gQšiQkRŸlS¡nTžlS™iQÌq.¯b*“S%zG#\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀMCJXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMsVMvWNyYN|ZN\N‚]O„^O†`O‰aO‹bP—U&¥\'¯a(»g)Ìr/—hQ™iQ›jRkRŸmS¡nT¤pV§sX«v[¯z^´~bºƒfÀ‰kÆŽpÌ”vÒ™{מÜ£ƒà¦†â¨ˆã¨ˆã¨‡á¦…Þ£‚ÛŸ~×›yÓ–uÎ’pÊkƉgÂ…c¿‚_½]»}Z¹{X¸zW·yV¶xU¶xUµwTµwTµwTµwTµwTµwTµwTµwUµwUµwUµxUµxVµxVµxWµyWµyWµyXµyX´yX´yY³yY³xX²xX°wX¯vW®uW¬tV«sV©rU¨qT¦pT¥oS£nS¡mR mRžlRkR›jQšiQ˜hQ–gQ”fQ’ePdPŽcPŒbP‰aO†`Oƒ^O€]O}[NzYNvWNrUMmSMlRMjQLhQLeOL_LK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À,)/ZTVXON„uq‡od®}Ÿyb»s]OŠaPeP•gQšiQkRžlRŸlSœkR–hQ»g*¤\(ŽQ%`LK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À B B_LKcNLfOLiQLkRLmSMoTMpTMrUMtVMwXNzYN}[N\O‚]O„_O‡`O‰aOQ%ŸY&©^'±b(¾i*Õ{8—hQ™iQ›jRkRŸmS¡nT¤qV§sX«v[°z^µ~bºƒfÀ‰kÆŽpÌ”vÒ™{מÛ¢ƒß¥…ᧇ⧇ᦆऄݢڞ}ÖšxÒ•tÍ‘oÉŒjňfÂ…b¿_¼\º}Z¹{X·zW·yV¶xU¶xUµwTµwTµwTµwTµwTµwTµwTµwT´wU´wU´wU´xVµxVµxVµxW´xW´yW´yX´yX³xX³xX²xX±wX°wW¯vW­uW¬tV«sU©rU§qT¦pT¤oS£nS¡mR mRžlRkR›jQšiQ˜hQ–gQ”gQ’fPdPŽcPŒbP‰aP‡`O„^O]O~[N{ZNvXNrVMnSMlRMjRLhQLeOLaML+O+O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀHFLXQRTJH~pm‚la¬Ž}Ÿzc»t¤tT‰aPdP•gQšiQœjRžlRžlS›jRÖ|:´e*˜V&ˆN$\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À B B`LKdNLgPLiQLkRMmSMoTMpUMrUMtVMwXNzYN}[N€\O‚]O…_O‡`O‰aPšW&£['«_(´d)Âl,݃@Òt.™iQ›jRkRŸmS¡oU¤qV¨sX«w[°z^µbºƒgÀ‰kÆŽpÌ”uÑ™zÖ~Ú¡‚Þ¤„ॆআॅޣ‚Ü Ø{Õ™wÑ”sÌnÈŒjňfÁ„b¾_¼~\º|Z¸{X·yW¶yV¶xUµwUµwTµwTµwTµwT´wT´wT´wT´wT´wU´wU´wU´wU´wV´xV´xV´xW´xW³xW³xW³xX²xX±wX°wW¯vW®uW­uV¬tVªsU©rU§qT¦pT¤oS£nS¡mR lRžlRkR›jQšiQ˜hQ–hQ”gQ’fPdPŽcPŒbPŠaP‡`O„^O]O~[N{ZNwXNsVMoTMlRMjRLiQLfOLbML+O+O‚+O‚+O‚\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À6./fZXeVRHAIZIKiQLuWM¤tU‰aOdP–gQšjQkRžlRkR˜iQÄn/¬b,‘R%rC"\À\À\À\À\À\À\À\À\À\À\À\À"Fx"Fx!Fx!Fx B B BdNLgPLjQLlRMmSMoTMqUMrUMtWMwXNzZN}[N€\O‚^O…_O‡`O“S%X&¥\'®a(·g+Ês2Ó{9Àj*™iQ›jRkSŸmS¢oU¤qV¨sX«w[°z^µbº„gÀ‰kÆŽpË“uИyÕœ}٠ܢƒÞ¤„ߤ„Þ£ƒÝ¡ÚŸ~×›zÓ—vÏ“rËmÇ‹ićeÀƒa¾€^»~\¹|Z¸zX·yW¶xVµxUµwUµwTµwT´wT´wT´wT´wT´wT´wT´wT´wU´wU´wU´wU´wV³wV³xV³xW³xW²wW²wW±wW±wW°vW¯vW®uV¬tV«sUªsU¨rT§qT¦pT¤oS£nS¡mR lRžlRkR›jQšiQ˜hQ–gQ”gQ’fPePŽcPŒbPŠaP‡`O„_O]O~\N{ZNxXNsVMoTMlRMjRLiQLfPLbNL +O‚+O‚+P‚+P‚+P‚\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@89dWT@IIAI\JKlRMyYN„^OcP”gQ™iQkRžlRžkR™iRÍt3±d-’S%I#\À\À\À:^‘:^‘:^‘:^‘:^:^:^:^:^"Fx"Fx B B B BeOLhPLjRLlSMnSMpTMqUMrVMuWMxXN{ZN~[N€]Oƒ^O…_O“S%›W&¢['©^(¹k2½i+Ó{:•gQ—hQ™iQ›jRkSŸmT¢oU¤qV¨tY¬w[°{_µbºƒf¿ˆkÄoÊ’tÏ–xÓš|×~Ù €Û¡Û¡Û €Ùž~×›{Ô˜wДsÌoÉŒkʼngÂ…c¿‚`¼]º}[¸{Y·zX¶yVµxVµwU´wU´wT´wT´vT´vT´vT´vT³vT³vT³vT³vT³vU³vU³vU³wU²wU²wV²wV²wV±wV±vV°vV°vV¯uV®uV­tV¬tUªsU©rU¨qT§pT¥pS¤oS¢nS¡mR lRžlRkR›jQ™iQ˜hQ–gQ”gQ’fPePŽdPŒbPŠaPˆ`O…_O‚]O\N|ZNxYNtWMpTMlRMjRLiQLgPLcNL_LK+P‚+P‚+P‚,P‚,P‚,P‚,P‚,P‚Nr¤\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À]QNl\VG@IMCI_LKoTM|ZN†`OdP–gQšjQkRžlRœkR—hQºh*¤^,ŒP%X3:_‘:_‘:_‘:_‘:_‘:_‘:_‘:_‘:^‘:^‘:^‘:^‘"Fx B B B BfOLiQLkRLmSMnTMpTMqUMrVMuWNxYN{ZN~[N€]Oƒ^OŽP%—U&X&£['¬`)½n4Ãn/Àj*•gQ—hQ™iQ›jRkSŸmT¢oU¤qW¨tY«w[°z^´~b¹ƒf¿ˆjÄŒoÉ‘sΕwÒ™{Õœ}ØžÙŸ€ÚŸ€Ùž~ל|ÕšyÒ—vÏ“rËnÇ‹jĈfÁ„c¾`¼]¹}[¸{Y·zW¶xVµxU´wU´wT´wT´vT´vT³vT³vT³vT³vT³vT³vT³vT³vT²vU²vU²vU²vU²vU±vV±vV±vV°vV°vV¯uV®uV­uV¬tU«sUªrU©rT¨qT¦pT¥oS£oS¢nS¡mRŸlRžkRœkR›jQ™iQ˜hQ–gQ”gQ“fPePŽdPŒbPŠaPˆ`O…_O‚]O\N|ZNyYNuWMpUMlRMjQLiQLgPLdNL_LK,P‚,P‚,P‚,P‚,P‚Nr¤Nr¤Nr¤Nr¤Nr¥Nr¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaSOD>IJAIQEJbNLrUM~[NˆaO‘eP—hQœjQžkRŸlR›jRÌs0²e,“T&ƒK$;_‘;_‘;_‘;_‘;_‘;_‘;_‘:_‘:_‘:_‘:_‘:_‘:_‘ B B B BgPLiQLkRLmSMoTMpTMqUMsVMuWNxYN{ZN~[N]O‡M$“S%™V&ŸY&¥\'±e-¹j/Ñz:”fQ•gQ—hQ™iR›jRkSŸmT¢oU¤qW¨tY«w[¯z^´~b¹ƒf¾‡jÃŒnÈrÍ”vјyÔ›|Ö~מ~Øž~×}Õ›{Ó˜xЕtÍ’qÊŽmÆŠiÇeÀ„b½_»~\¹|Z·{Y¶yWµxVµxU´wU´wT´vT³vT³vT³vT³vT³vT³vT³vT³vT²vT²vT²vT²vU²vU²vU±vU±vU±vU°vV°vV¯uV®uV®uV­tU¬sU«sUªrU¨qT§qT¦pS¥oS£nS¢nR¡mRŸlRžkRœkR›jQ™iQ˜hQ–gQ”gQ’fPePŽdPŒbPŠaPˆ`O…_O‚]O\O|ZNyYNuWMqUMlSMjQLhQLfPLdNL_LK,P‚,P‚Nr¤Nr¤Nr¤Nr¤Nr¥Nr¥Nr¥Ns¥Ns¥Ns¥Ns¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀdUOG@IMCITFJeOLtWM€]O‹bP“fP™iQkRŸlRkR™iQ¾j,©c/P%[JK;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘;_‘ B B B BgPLiQLkRMmSMoTMpTMqUMsVMvWNyYN{ZN~[N|H#ŽQ%•T%›W& Z'¦]'ºm5¸f*Ív5”fQ•gQ—hQ™iR›jRkSŸmT¡oU¤qW§sY«v[¯z^³~b¸‚e½‡i‹nÇqË“uÏ–xÒ™zÔ›|Öœ}Öœ|Õ›{Ô™yÑ–vÏ“sÌoÈlʼnh†e¿ƒa¼€_º~\¸|Z·zX¶yWµxV´wU´wU³vT³vT³vT³vT³vT³vT³vT²vT²vT²vT²vT²vT²vT±vT±vU±vU±vU°uU°uU°uU¯uU®uU®tU­tU¬tU«sUªrU©rT¨qT§pT¥pS¤oS£nS¢mR mRŸlRžkRœjR›jQ™iQ—hQ–gQ”fQ’fPePŽcPŒbPŠaPˆ`O…_O‚^O\O|ZNyYNuWNqUMmSMjQLhQLfPLdNL`LKNr¤Nr¤Nr¥Nr¥Nr¥Ns¥Ns¥Ns¥Ns¥Os¥Os¥Os¥Os¥Os¥Os¥\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À2#TB3REJVGJ`LKpTM}[N‰aO’ePšiQžkR lRžlR˜hQ·e)¢^.P%^8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMrUMsVMxF#‡M$ŽQ%’S%–U&šW&žY&¢['ªa+¿s;¹g+dP‘eP“fQ”gQ–hQ˜iQšjRœkSžlS nU£pV¦rX©uZ¬x]°{_´~b¸‚e¼…iÀ‰kÃŒnÆŽpÈrÊ‘sË’sË‘rÊqÉoÇmÅ‹kÈhÀ…e¾ƒb¼€`º~^¸|[¶{ZµyX´xW³wV²vU²vU²vT±uT±uT±uT±uT±uT±uT±uT±uT°uT°uT°tT°tT¯tT¯tT¯tT¯tT®tT®tT­sT­sT¬sT¬sT«rTªrT©rT©qT¨qS§pS¦pS¥oS£nS¢nR¡mR lRŸlRkRœjQ›jQ™iQ˜hQ–gQ•gQ“fP‘ePdPcP‹bP‰aO‡`O„^O‚]O\N|ZNxXNuWMqUMmSMhPLgPLeOLcNL`LKZIK,Pƒ,Pƒ,QƒOs¦Os¦Ot¦Ot¦Ot¦Ot¦Pt¦Pt¦Pt¦Pt¦Pt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀvšÍvšÍv›Ív›Ív›Ív›Ív›Íw›Íw›Í=a“=a“=a“#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GymYPODJUGJXIKeOLtWM‚]OcP•gQœjQ lR mRkRÈp.´g0”T&ˆN$]8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMrUMv>„L$ŒP%‘R%•T%˜V&œX& Z'¤\'°f0¹m5Äq3dP‘eP“fQ”gQ–gQ˜hQ™jR›kSlS nT¢pV¥rX¨tZ«w\¯z_³}a·dº„g¾‡jÁŠlÄŒnÆŽpÇqÈqÈpÇŽoÆmÅ‹kÉiÁ‡g¿„d½‚aº_¸}]·|[µzY´yX³xW³wV²vU²vU±uT±uT±uT±uT±uT±uT°uS°uS°tS°tS°tS¯tS¯tT¯tT¯tT®tT®tT®sT­sT­sT¬sT¬sT«rTªrTªrT©qT¨qS§pS¦pS¥oS¤oS£nS¢mR¡mRŸlRžlRkRœjQšjQ™iQ—hQ–gQ”fQ’fP‘ePdPcP‹bP‰aO†`O„^O]O~\N{ZNxXNuWMqUMiQLgPLfOLeOLbNL_LKZIK,Qƒ,Qƒ,Qƒ,Qƒ,QƒOt¦Pt¦Pt¦Pt¦Pt¦Pt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àv›Ív›Ív›Ív›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Í=a“=a“=a“=a“=a“#Gz#Gz#Gz#Gz#Gz#Gz#GzgUOS=2RFJWHJ[JKlRMzYN†`OeP˜iQžkR mRŸlR™iQ¼h*°h4‘R%ˆN$^9 [JK#Gy#Gy#Gy#Gy#Gy * B B B B BjQLlRMnSMoTMpUMI#†L$‹O$Q%“S%—U&šW&X&¡Z'¦](·l5´f,Èt5dPeP’fP”fQ–gQ—hQ™iR›kRlSŸmT¢oV¤qW§tY«v[®y^±|aµc¸‚f¼…h¿ˆkÁŠlÃŒnÅnÅoÅnÅŒmÄ‹k‰iÁ‡g¿…e½ƒc»€`¹~^·|\¶{Z´yY³xW²wV²vU±vU±uT±uT±uT°uT°uT°tS°tS°tS°tS°tS¯tS¯tS¯tS¯tS®tS®tS®sS­sT­sT­sT¬sT¬rT«rTªrTªrS©qS¨qS§pS¦pS¦oS¥oS¤nS¢nR¡mR mRŸlRžkRkR›jQšiQ˜iQ—hQ•gQ”fQ’ePePdPcPŠbPˆ`O†_Oƒ^O]O~[N{ZNxXNtVMqUMhPLgPLfOLdNLbML_LKbE6,Qƒ,Qƒ,Qƒ,Qƒ-Qƒ-Qƒ-QƒPt¦-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Qƒ-Q„-Q„-Q„\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@d–w›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Íw›Îw›Îw›Î=a”=a”=a”=a”=a”=a”=a“#Hz#Gz#Gz#Gz#Gz#Gz#GzmYPPDJUGJYIKbMLqUM\NŠbP”fQ›jQŸlR¡mRžlRËp,µe+ \+R%ˆN$b; ]8 [7 XHKO+N1L/L/L/K/K/ eb”>b”>b”>b”>b”>b”>b”>b”=b”=b”=b”=b”=b”=b”=b”=b”YEUGJYIK_LKnSM|ZNˆ`O’ePšiQŸlR¡mR mR™iQºg*´j4šW'‘R%ŽQ%h>!g=!f=!db”>b”>b”>b”>b”>b”>b”$Hz$Hz$Hz$Hz$Hz>b”>b”>b”>b”>b”gVOS=2RFJWHK[JKeOLsVM€]OŒbP•gQœjQ lR¡mRžlRÌr/¹g*²h2–U&“S%‘R%Q%ŽQ%ŒP%£['¨]'¬`(°b(´d)¸f)»g)¾i*Áj*I#¡Z'¡Z' Z' Z'¡Z'£['¤['¥\'¦]'ª_)±d,³d)Äq3‹bPcPdP‘eP’fQ”fQ–gQ—hQ™iR›kSlSŸmU¡oV¤qW¦sY©u[¬x]¯z^±|`´~b¶€d¸‚eºƒf»„f»„f¼„f»ƒe»‚dºb¹€a·~_¶}^µ{\´zZ³yY²wX±wW°vV°uU¯uU¯tT¯tT¯tT®tS®tS®tS®sS®sS®sS®sS®sS­sS­sS­sS­sS¬sS¬rS¬rS«rS«rSªrSªqS©qS©qS¨pS§pS¦pS¦oS¥oS¤oR£nR¢nR¡mR mRŸlRžkRkRœjQšjQ™iQ˜hQ–hQ•gQ“fQ’ePdPŽcPŒcPŠbPˆ`O†_O„^O]O\N|ZNyYNuWNrUMnSMjQLdNLcNLaMK_LK[JK`D6Pt¦Pt¦Pt§Pt§Pt§Pu§Pu§Pu§Pu§Qu§Qu§Qu§Qu§Qu§Qu§-Q„-Q„-Q„-R„-R„-R„-R„-R„-R„-R„-R„-R„.R„.R„Rv¨Rv¨Rv¨~¢Ô~¢Ô~¢Ô~¢Ô\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@e—@e—@e—@e—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—xœÏxœÏxœÏxÏxÏxÏxÏyÏyÏ>b•>b”>b”$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b”>b”>b”>b”>b”YDb”>b”>b”>b”Q@:R<2fL@WHJZJKaMKoTM|ZNˆ`O‘eP™iQŸlR¡mR¡mRœjRÇo-»i-´h0«`)§]'¨]'¬`(°b(´d)¸f)¼h)Àj*Ãk*Æm*Én+Ìp+Ïq+Òr,§]'§]'§]'¨^'ª_(«_(¬`(­`(¯b)²c)ºi.ˆ`OŠaPŒbPŽcPdP‘eP“fQ”gQ–hQ˜iRšjR›kSlTŸnU¢oV¤qW¦sY©uZ«w\­y]°{_²|`³}aµ~b¶b¶b¶b¶a¶~`µ}_µ|^´{]³z[²yZ±xY°wX¯vW¯uV®uU®tU®tT­tT­sT­sS­sS­sS­sS­sS­sS­sS­sS¬sS¬rS¬rS¬rS«rS«rS«rSªrSªqS©qS©qS¨qS¨pS§pS¦pS¦oS¥oR¤oR¤nR£nR¢mR¡mR lRŸlRžkRkRœjQšjQ™iQ˜hQ–hQ•gQ“fQ’ePdPdPcP‹bP‰aO‡`O…_O‚]O\O}[NzYNwXNtVMpTMlRMhPLcNLaMK_LK]KKbR]C5Pu§Pu§Pu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨-R„-R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae˜Ae˜Ae˜Ae˜yÏyÏyÏAf˜Af˜Af˜$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b•>b•>b”>b”WD3TFJXHK[JKfOLsVM€]O‹bP”gQœjQ lR¡mR mRœkRÅm,½i,ºj/²d+±c)²c(¶e)ºf)¾h*Áj*Ål*Én+Ëo+Îq+Ñr+Ós,Õt,ƒK$ª^(ª_(«_(¬`(®a(¯a)°b)³d*¶f+¾m1‡`O‰aP‹bPcPdPeP’fQ”fQ•gQ—hR™iR›kSlTŸmT¡oV£pW¥rX§tY©v[¬w\®y]¯z^±{_²|`³}`´}`´}`´}_´|^³{^³{\²z[±yZ°xY°wX¯vW®uV®tU­tU­tT­sT­sT­sS­sS¬sS¬sS¬sS¬rS¬rS¬rS¬rS¬rS«rS«rS«rS«rSªrSªqSªqS©qS©qS¨qS¨pS§pS¦pS¦oS¥oR¤oR¤nR£nR¢mR¡mR mRŸlRžlRkRœjQ›jQšiQ˜iQ—hQ–gQ”fQ“fP‘ePdPŽcPŒbPŠaPˆ`O†_O„^O]O\N|ZNyYNvWNsVMoTMkRLgPLbML`LK^KK\JK~aR[B5Pu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ£Õ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe—Ae—Ae—Ae—Ae—Ae—Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Af˜Af˜Af˜yÐAf˜Af˜Af˜Af˜Af˜Bf˜$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c•>c•>b•>b•O?:[E|aRZA5-QƒQu§Qu§Qu§Qu§Qu§Qu§Qu§Qu¨Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„Rv¨Rv¨Rv©Rv©Rv©Rw©£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö£Ö\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAe˜Ae˜Ae˜Ae˜Ae˜Ae˜Ae˜Af˜Af˜Af˜Af˜Af˜yžÐyžÐyžÐzžÐzžÐzžÐBf˜Bf˜Bf˜Bf˜Bf˜$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c•>c•>c•>c•VC^C6W@5-Q„-Q„Qu§Qu§Qu§Qu§Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„Rv©Rw©Rw©Rw©¤Ö¤Ö¤Ö¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö¤Ö¤Ö¤Ö\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAf˜Af˜Af˜Af˜Af˜Af˜Af˜Af˜zžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐBf˜Bf˜Bf˜Bf˜$I{$I{$I{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz YE\C6T>4-Q„-Q„-Q„-R„Qu¨Qu¨Qv¨Qv¨Qv¨Qv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„Rw©Sw©€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀAf˜Af˜Bf˜Bf˜Bf˜zžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÐzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑBf˜Bf˜Bf˜$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$H{$H{$H{$H{?c•?c•?c•?c•$H{$H{$H{SB;R<2zbVUGJXIK[JK[JKuWN€\OŠaP’fP™iQŸlR¡mR£nS£nS¥pTà€9Þ9Õw2Öw0Öv/Öv.Ùx/Üz0Þz0á|1ã~2æ€3è5éƒ6ë…8ë…8ºm4¼o7¾q8Äu;Ãs9Ãs8ºj0‚]O„^O†_Oˆ`OŠaPŒbPcPdP‘eP’fQ”fQ•gQ—hR™iRšjSœkSlTŸnU¡oV¢pV¤qW¦rX§sY¨tY©uYªuZ«uZ«vZ«vY«uY«uX«uX«tW«tV«sVªsUªsUªrTªrTªrTªrSªqSªqSªqSªqSªqS©qS©qS©qS©qS©qS©qS©qS©qS¨qS¨pS¨pS§pS§pR§pR¦oR¦oR¥oR¥oR¤nR£nR£nR¢mR¡mR mR lRŸlRžkRkRœjQ›jQšiQ™iQ—hQ–gQ•gQ”fQ’eP‘ePdPcPŒbPŠaPˆ`O†_O„^O‚]O\O}[NzYNwXNtVMqUMnSMiQLeOL`LK]KKmP?kN?|aSZA5P<4-R„-R„-R„-R„-R„-R„Qv¨Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×€¤×Ei›Ei›Ei›Ei›Ei›Ei›Ei›\À\À\À\À\À\À\À\À\À\À\À\ÀBf˜zžÐzžÐzžÐzžÐzžÐzžÐzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑBf™Bf™Bf™%I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{?c–?c–?c–?c–?c–?c•?c•?c•?c•$H{$H{$H{jXP^H=}dXUGJXHKZIKkRLwXN‚]O‹bP”fQšiQžkR mR£nS¥pT¨qU¨rUç…;ç†>ì‰?è†<å‚9ê†;î‰=ðŠ=ðŠ>ôŽAø‘Dü•Hÿ˜Kù’E¿r:Àt;Àt;Át<Ãt:½n4´f,]Oƒ^O…_O‡`O‰aO‹bPŒcPŽcPdP‘eP“fQ”gQ–hQ˜iR™jR›kSœlSžmTŸnU¡oV¢pV¤qW¥rW¦rX§sX¨tX©tX©tX©tX©tXªtWªsW©sV©sV©rU©rU©rT©qT©qT©qS©qS©qS©qS©qS©qS©qS©qS©qS¨qS¨qS¨pS¨pS¨pS¨pS§pS§pS§pR¦pR¦oR¦oR¥oR¥oR¤nR¤nR£nR¢nR¢mR¡mR mR lRŸlRžkRkRœjQ›jQšiQ™iQ˜hQ–hQ•gQ”fQ’fP‘ePdPŽcPŒcP‹bP‰aO‡`O…_Oƒ^O]O~[N{ZNyYNvWNsVMpTMlRMgPLcNL†gUƒeUlO?~bT{`SW@5-R„-R„-R„-R„-R„-R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R….R…Ei›Ei›Ei›€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×€¥×Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›\À\À\À\À\À\À\À\À\À\ÀzžÑzžÑzžÑzžÑzŸÑzŸÑzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒBg™Bg™Bg™%I{%I{%I{%I{%I{%I{%I{@d–?d–?d–?d–?d–?d–?d–?d–?d–?c–?c–?c–?c–$I{$I{L=:WD`KA-R„-R„-R„.R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R„.R….R….R….R…EiœEiœEiœEiœEiœEiœ¥×¥×¥×¥×¥×¥×¥×EiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœEiœ\À\À\À\À\À\À\À\ÀzŸÑzŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒ{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| ÒCg™Cg™%I{%I{%I{@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–?d–?d–?d–?d–?d–?d–$I{$I{dUPYEXG@-R„.R„.R„.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©.R„.R„.R„.R„.R„.R„.R„.R„.R….R….R….R….R….R….S…EiœEiœEiœEjœEjœEjœEjœEjœ¥×¥×¥×EjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEiœEiœEiœ\À\À\À\À\À\À{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÑ{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| ÒCg™@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–?d–$I{$I{RA;P<3zcXnVIuh™~pdNLpUMÁ”w¬zZ«vS‘eP–gQœjQžlR¡mR¤oS§pT­uV¯vW±xY¶|\¼€_ÆdƉgÈŠhÊŒiÌŽkÎlÿRñF¶k4²g1¯d-­b+ª_(¢Z'}[N€\O‚]O„^O†_Oˆ`O‰aP‹bPcPŽcPdP‘eQ’fQ”gQ•gQ—hR˜iR™jR›kSœkSlTžmT nT¡nU¡oU¢oU£pU¤pU¤pU¤pU¥pU¥pT¥pT¥pT¥pT¥pS¥pS¥oS¦oS¦oS¦oS¦oS¦oS¦oR¦oR¦oR¦oR¦oR¦oR¦oR¦oR¥oR¥oR¥oR¥oR¤oR¤nR¤nR£nR£nR¢nR¢mR¡mR¡mR lRŸlRŸlRžkRkRœkQœjQ›jQšiQ™iQ˜hQ—hQ•gQ”gQ“fP’ePePdPcPŒbPŠbP‰aO‡`O…_Oƒ^O]O~\N|[NzYNwXNtVMpUM—pY”oXzWBuUB…gVlP@jO@|bUx`TcMB3!.R„Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©.R„.R„.R„.R„.R….R….R….R….R….S….S….S…EjœEjœEjœEjœEjœEjœEjœEjœEjœ¦Ø¦ØEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœEjœ\À\À\À\ÀBg™{ŸÒ{ŸÒ{ŸÒ{ Ò{ Ò{ Ò{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| ÒCg™Cg™Cg™Cg™|¡Ó@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–%I{;0/SB;R=4fODpXL‘xkš€r˜vbº“zÀ”x«{[ÃldP•gQ™iQ›jQŸlR£nR¦pS¨qTªrT¬tU°wWµ{Z¸}\¸|\¸}\¹~]»]å}+Ý~6­d.ªa+¨_)§^(¤\'zYN|ZN~\N€]Oƒ^O„_O†_Oˆ`OŠaP‹bPcPŽdPdP‘eQ“fQ”gQ•gQ—hR˜iR™jRšjSœkSlSžlTŸmT mT nT¡nT¢nT¢oT£oT£oT£oT£oT¤oS¤oS¤oS¤oS¤oS¤oS¤oS¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¥oR¤oR¤oR¤nR¤nR¤nR£nR£nR£nR¢mR¢mR¡mR¡mR lR lRŸlRžlRžkRkQœjQ›jQšjQ™iQ™iQ˜hQ—hQ•gQ”gQ“fQ’ePePdPŽcPŒbPŠbP‰aO‡`O…_Oƒ^O]O\N}[NzZNxXNuWMrUM™rZ–pY|XCxVCsTBmQAkOA~cVzaU`I>\IARv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©.R….R….R….R….R….S….S….S….S…FjœFjœFjœFjœFjœFjœFjœFjœ‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦ØFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœ\À\ÀBg™{ Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ò| Ó| ÓCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™}¡Ó@e—@e—@e—@e—@e—@e—@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–@d–%I{<1/J82^I@gQFqYN‘xl™€s—vc¢{d¿”yª{\«wUÄi‘eP•gQ˜hQkQ mR¢mR¤nR¥oS§pSªrT¬tU¬tU¬tU¬tU­tU®tUÒt.ƒL&¤](¢['¡Z'žY&xYN{ZN}[N\N]Oƒ^O…_O‡`OˆaOŠaPŒbPcPdPeP‘eQ“fQ”gQ•gQ—hR˜iR™iRšjR›kSœkSlSžlSŸmSŸmS mS nS¡nS¡nS¢nS¢nS¢nS¢nS£nS£nS£nR£nR£nR£nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR£nR£nR£nR£nR£nR¢nR¢mR¢mR¡mR¡mR¡mR lR lRŸlRžlRžkRkRœkQœjQ›jQšiQ™iQ˜iQ—hQ–hQ•gQ”fQ“fP’ePePdPŽcPŒbP‹bP‰aO‡`O†_O„^O‚]O\O}[N{ZNxYNvWNsVM›s[˜rZ~ZDnYŒkYqSBkPAiOA|cVbK?\G>NB?Rv¨Rv¨Rv¨Rv¨Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©.S….S….S….S….S….S…FjœFjœFjœFjœFjœFjœ‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦Ø‚¦ØFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœCg™Cg™| Ò| Ò| Ò| Ò| Ò| Ó| Ó| Ó| Ó|¡Ó|¡ÓCg™Cg™Cg™Cg™Cg™Cg™Cg™CgšCgšCgšCgšCgš}¡ÓAe—Ae—Ae—@e—@e—@e—@e—@e—@e—@e—@e—@d—@d—@d—@d—@d—@d—@d–@d–@d–@d–%I{@d–@d–<1/H72\I@ePGpYNxm˜€t–vc¡{e¾”zÁ“u‘p«wU¬uQ‘eP•gQ™iQšjQœjQžlR¡mR£nR¤nR¤oR¤oR¤oR¤oR¤oRÇgb;  Z'žY&›W&“S%vXNyYN{ZN~[N€\O‚]Oƒ^O…_O‡`O‰aOŠaPŒbPcPdPdP‘eQ“fQ”gQ•gQ–hQ˜iR™iRšjR›jR›kSœkSlSžlSžlSŸlSŸmS mS mS¡mS¡mS¡mR¡mR¢mR¢mR¢mR¢mR¢nR¢nR¢nR£nR£nR£nR£nR£nR¢nR¢nR¢mR¢mR¢mR¢mR¡mR¡mR¡mR mR lRŸlRŸlRžlRžkRkRkQœjQ›jQ›jQšiQ™iQ˜hQ—hQ–gQ•gQ”fQ“fP‘ePdPdPcPŒbP‹bP‰aO‡`O†_O„^O‚]O€\O}[N{ZNyYNvXNtVMu\„]E€[E’oZŽmZŠkYnRBjOB}cVdL@`I?XGARv¨Rv¨Rv¨Rv¨Rv©Rv©Rw©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwª.S….S….S….S…/S…FjœFjœFjœFjœ‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦Ù‚¦ÙFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœ‚¦Ù‚¦ÙCg™Cg™| Ó| Ó|¡Ó|¡Ó|¡Ó|¡Ó|¡ÓCg™Cg™Cg™Cg™CgšCgšCgšCgšCgšCgšCgšCgšChšChšChšChšChš}¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—@e—@e—@e—@e—@e—@e—@e—@d—%I{%I{%I{%I{%I{@d–@d–<10F61o]Vye]„oeŽxmœ‚u”udŸ{e¥}d¨|aÀ’tÁpÃl¬uQdP’eP”fQ–gQ˜iQ›jQœjQœjQœjQœjQœkQœkQkQ_9 œX&™V&•T%rUMuWMwXNzYN|ZN~[N€\O‚]O„^O…_O‡`O‰aOŠbPŒbPcPŽdPdP‘eQ’fQ”fQ•gQ–hQ—hR˜iR™iRšjR›jRœkRœkRkRlRžlRžlRŸlRŸlRŸlR lR mR mR mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR¡mR mR lR lRŸlRŸlRŸlRžkRžkRkRkQœjQ›jQ›jQšiQ™iQ˜iQ—hQ–hQ•gQ”gQ“fQ’fP‘ePdPdPcPŒbPŠbP‰aO‡`O†_O„^O‚]O€\O~[N{ZNyYNwXNtVMrUM†^F‚]F”q\o[ŒlZqTD€fX}dWeMAbK@O=6NB@Rv¨Rv©Rv©Rv©Rw©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxª/S…/S…FjœFjœFjœƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœFjœƒ§Ùƒ§Ùƒ§Ùƒ§ÙCg™Cg™Cg™}¡Ó}¡Ó}¡ÓCg™CgšCgšCgšCgšCgšCgšCgšChšChšChšChšChšChšChšChšChšChšDhšDhšDhš~¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—%I{%I{%I{%I{%I{%I{%I{%I{%I{@d—@d—E:9D61m\Vwe]lXOuaX„k_¨‹z±|¡|e¥|c§|`©z]ªyXÂnÃlÄŽkÄŽidP’eP“fP“fP“fP’fP“fP“fP“fP[7 —U&”T%P%pTMsVMuWMxXNzYN|ZN~[N€\O‚]O„^O†_O‡`O‰aOŠbPŒbPcPŽdPdP‘eP’eQ“fQ”gQ•gQ–hQ—hQ˜iR™iRšjR›jR›jRœkRœkRkRkRžkRžlRžlRŸlRŸlRŸlRŸlR lR lR lR lR lR lR lR lR lR lR lR lR lRŸlRŸlRŸlRŸlRžkRžkRkRkQœkQœjQ›jQ›jQšiQ™iQ˜iQ˜hQ—hQ–gQ•gQ”fQ“fP’eP‘ePdPŽdPcPŒbPŠbP‰aO‡`O…_O„^O‚]O€\O~[N|ZNyYNwXNuWMrUM‡`G„^G–r]|ZFxXFtVEgY~eY{cXbLA[H?REA.R„.R„Rv©Rw©Rw©Rw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSxªSxªSxªSxªTxªTxªTxªƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙFjFjFjFjFjFjFjFjFjFjFjƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§Ùƒ§ÙCg™Cgš}¡Ó}¡ÓCgšCgšCgšCgšChšChšChšChšChšChšChšChšChšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš~¢ÔAe—Ae—Ae—Ae—Ae—Ae—Ae—Ae—Ae—%I|%I|%I|%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{@e—@e—B99B51k[Vud]iWPr_Wye] †yªŒ|²}¡|e¤|c¾’w¨{^¨z\©yZÁp«xW«wU«wU«wU«wUÃŽlÃŽlÂŽlÂŽlkD(’S%ŒP%nSMoTMqUMsVMvWNxXNzYN|ZN~[N€\O‚]O„^O†_O‡`O‰aOŠaP‹bPcPŽcPdPeP’eQ“fQ”fQ•gQ–gQ–hQ—hQ˜iQ™iR™iRšjR›jR›jRœjRœkRœkRkRkRkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRŸlRžlRžkRžkRžkRkRkQkQœkQœjQ›jQ›jQšjQšiQ™iQ˜iQ˜hQ—hQ–gQ•gQ”gQ“fQ’fP‘ePePdPŽcPcP‹bPŠaPˆaO‡`O…_Oƒ^O‚]O€\O~[N|ZNyYNwXNuWMrUMŸw_œv_˜t^~\GzYGvWF†j[fZ|dYybX\I@VGB5/2.R„.R„.R„.R„Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxªSxªTxªTxªTxªTxªFkFkFkFkƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§ÚFkFkFkFkFkFkFkFkƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Úƒ§Ú}¡Ó}¡Ó}¡Ô}¡ÔChšChšChšChšChšChšChšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš~£ÕAe˜Ae˜Ae˜Ae˜Ae˜%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{%I{%I{%I{%I{@e—@e—<68?31gYVpa\bRMjYTq`Z€j`¡‡z«}²‘}¶’|¸’{º’z»’x¼’w§z^¿‘t¿‘s¿‘s¿s¿r¿r¾r¾r°h2‹O$„L$mSMnSMnTMoTMtVMvWNxXNzYN|ZN~[N€\O‚]O„^O…_O‡`OˆaOŠaP‹bPŒcPŽcPdPdP‘eP’eQ“fQ”fQ•gQ–gQ–hQ—hQ˜hQ˜iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœkQœkQkQkRkRkRkRkRkRkRkRkRkQkQkQœkQœjQœjQœjQ›jQ›jQšjQšiQ™iQ™iQ˜hQ—hQ—hQ–gQ•gQ•gQ”fQ“fP’eP‘ePdPdPcPŒbP‹bP‰aPˆ`O†`O…_Oƒ^O]O€\O~[N|ZNyYNwXNtWM£z` y`w`šu_€]I|[HwXGˆl\ƒi[}eZycYr_WjZU;23.R„.R„.R„.R„.R….R….R…Sw©Sw©Sw©Sw©Sw©SwªSwªSwªSxªSxªSxªTxªTxªTxªTxª/S…/S…GkGkGkGkGkGkGkƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨ÚGkGkGkƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Ú}¢Ô}¢Ô}¢Ô}¢Ô~¢ÔDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš£ÕAf˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{Ae—Ae—Ae—?89H=:?YUY`QGfVLudXjeitlm{po|qp}rp~rpsqsq€tqŒr_=1+xJ)’o[~[F€\G‚^H„_I…`IkRLlRMnSMpTMrVMuWMwXNyYN{ZN}[N~\N€\O‚]Oƒ^O„_O†_O‡`Oˆ`O‰aPŠbP‹bPŒcPcPŽcPdPdPeP‘eP’eP’fP“fQ“fQ”fQ”gQ•gQ•gQ•gQ–gQ–gQ–gQ–hQ–hQ—hQ—hQ—hQ—hQ—hQ–hQ–hQ–gQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘eP‘ePdPdPŽdPŽcPcPŒbP‹bPŠaP‰aO‡`O†_O…_Oƒ^O‚]O€\O~\N}[N{ZNyYNwXNuWM“iOhOŽgO‹eOžze›yd—wd”tcrbtYKjTIaOG[KFj]Y^UU?;@.R….R….S….S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…/S…GkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkžGkž…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û…©Û…©Û£Õ£Õ£Õ£Õ£Õ£Õ£Õ£ÕDh›Dh›Dh›Dh›Di›Di›Di›Di›Di›¤Ö¤Ö¤Ö¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|Af˜Ae˜Ae˜%J|%J|%J|%I|%I|%I|%I|���#-#%.()1MEAQIEUMI]SL]TM=4.1+(=.#6,&5( 1%"ŒlYn[“p\•r]]Hƒ_I…`JœwažybkRLmSMpTMrUMtVMvWNxXNzYN|ZN}[N\N€]O‚]Oƒ^O…_O†_O‡`OˆaO‰aPŠaP‹bPŒbPcPŽcPŽdPdPdPeP‘eP‘eP’eP’fP“fP“fQ“fQ”fQ”fQ”fQ”gQ”gQ•gQ•gQ•gQ•gQ•gQ”gQ”fQ”fQ”fQ”fQ“fQ“fP“fP’eP’eP‘eP‘ePdPdPdPŽcPcPŒcPŒbP‹bPŠaP‰aO‡`O†_O…_Oƒ^O‚]O]O\O}[N|ZNzYNxXNvWN¬‚gªg¨€ghPŒfPŸ|fœzf˜xe”vdscsYLiTK_NHYKFh\Z]UV=;@.R….S….S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxª/S…/S…/S…/S…GlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlžGlž…©Û…©Û…©Û…©Û£Õ£Õ£Õ£Õ£Õ£Õ£Ö£ÖDi›Di›Di›Di›Di›Di›¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Ei›&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Af˜Af˜Af˜Af˜Af˜%J|%J|%J|%J|%J|%J|%I|%I|%I|, +,!.! "`E6†iYŒlZo\“q]•s^^J™va›wbycŸzd {e¤}foTMqUMsVMuWNwXNyYN{ZN|ZN~[N\O]O‚]Oƒ^O…_O†_O‡`Oˆ`O‰aOŠaP‹bPŒbPŒcPcPŽcPŽdPdPdPdPeP‘eP‘eP‘eP’eP’eP’eP’eP’fP’fP’fP“fP’fP’fP’fP’eP’eP’eP‘eP‘eP‘ePePdPdPdPŽdPŽcPcPŒcPŒbP‹bPŠaP‰aOˆ`O‡`O†_O…_Oƒ^O‚]O]O\O~[N|[N{ZNyYNwXN®ƒi¬ƒiª‚i¨i¦€hŒhR‰fQ†dQ‚bP•wfx]Oˆpdkbtd_m`]OEDG?A;:@.S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTx«Tx«Tx«Ty«/S†GlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ£Ö£Ö£Ö£Ö¤Ö¤Ö¤Ö¤Ö¤ÖEi›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×€¥×€¥×€¥×Bg™Bg™Bg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Af˜Af˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|��� +,YA5jPBpSD‹l[o]’q^–t`‚_Kšwbœycžze {f¡}g¤h¨i”lSrVMtWMvWNxXNyYN{ZN|[N~[N\O]O‚]Oƒ^O„_O…_O†`O‡`Oˆ`O‰aPŠaP‹bP‹bPŒbPcPcPŽcPŽcPdPdPdPdPdPdPdPdPePePePePePdPdPdPdPdPdPdPŽcPŽcPcPcPŒbP‹bP‹bPŠaP‰aOˆ`O‡`O†`O…_O„^Oƒ^O‚]O€]O\O~[N|[N{ZNyYNxXN°…j®„j¬„jªƒj¨‚j¦€jŒhSŠgS†eRƒcR|`QŒsf…oe}jcrd`k_]LCDC=@,,3(4F(4F.S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžChšChš¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|#5H71O;3V?4iOBoSDsVFo]{[I^Kƒ`L…bN‡dOŸ{f }g¢~h¥€j’kT•mU˜oVšqWrWwXNxXNzYN{ZN}[N~[N\O€]O‚]Oƒ^O„^O…_O…_O†`O‡`Oˆ`O‰aO‰aPŠaP‹bP‹bPŒbPŒbPŒcPcPcPcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPcPcPcPŒcPŒbP‹bP‹bP‹bPŠaP‰aP‰aOˆ`O‡`O†_O…_O„_O„^Oƒ^O]O€\O\N~[N|ZN{ZNyYN›oTšoT™oT—nT¬„lªƒl¨‚ljUŒiTŠhT†fT€cSvi‰rgnfyidqdah^^HBD?<@)+3OZkMYk(5F(5F(5F/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Ty«Uy«†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžDhšDhšDhšChš&K}&K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|A99N?;L:2T>4gNBlRD‡k\‹n^z[J~^LaN…cO‡dP‰fQŠgRŒhTjU’lV•nW˜pXšrXsY¶‹q¸qºŽr¼r½r¿s©z[©z[ªz[«{[¬{[¬{ZÅ“rÅ’qÅ’qÅ’pÅ’pÅ‘o­yV­xV¬xU¬wT¬wTŠaPŠbP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bPŠaPŠaPŠaP‰aP‰aOˆaOˆ`O‡`O‡`O†_O…_O„^Oƒ^O‚^O‚]O]O€\O~\N}[N|ZNzYNpTœpU›pUšpU˜oV—oV•nV“mV‘lVkVŒjVˆhVƒfU~cUuj†qh~mfugdkaad\^E@D98?$(2minffm^blV^lMYk(5F(5F/S…TxªTxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Uy«Uy«†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}ChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|Ae˜Ae˜;GY<68I=:I82Q=4XA6~fZ„j\‰m^p`|]L€`NƒcP†eQˆgS¡j£€l¦‚m©„n•oX˜qYšrZt[¶Œr¸sºs¼t½t¾‘t¨z]©{]ª{]«{\«{\¬{\¬{[Ä“sÄ“rÄ’rÄ’qÄ’pÄ‘p¬yWÄoÃnÃmÃlÂŽlÂŽkÁkˆaOˆaOˆaOˆaOˆaOˆaOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O…_O„_O„^Oƒ^O‚]O]O€]O\O~\N}[N|ZN¶‰l¶‰lµˆmœqV›qVšqV™pW˜pW–oW¬…nª…n§„n¤‚nŸ€n›~n€eW‘xlŠtk‚piykfodcf_`JDG@>C*,5$1MYktr~tstmolinadmX_lNZkMZkTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«ÝHlŸHlŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™&J}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Af˜Af˜Af˜Af˜;GY;GY;GY1'!D:9N?;N;3]I?zdY€h[†l^‹oasc“ue€bQ„dR‡fT l¢m¦ƒn©…o«‡p®ˆq±Šr³‹sžv] w]¹u»u¼‘u¾‘u¿’v¨{^©{^ª|^«|]«|]«{\¬{\¬{[¬{[¬zZ«zZ«yY«yX«xXÂoÂnÂnÁŽmÁŽm¨uT¨uS§tS§tS§tR¦sR¦sQ…_O…_O…_O„^O„^Oƒ^Oƒ^O‚^O‚]O]O€]O¢rS¡rS¡rS¸‰k·‰l·‰l¶‰m¶‰mµ‰m´‰n³‰n›qWšqX™qX®‡o­‡o«†p¨…p¤ƒp pœp—}o{cXv`Vp]U}nishfhaba\_DAF::B$)4�MYkMYkMYkŒtctq\QPPIKFDI;>H/8GMZkTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸImŸImŸImŸImŸImŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšChšChšChšChšChšChšChšChšCgšCgš&K}&K}&K}&K}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;GY;GY;GY;GY;,#I=:H82YF?^JA|e[‚j]ˆn`Œqcte”wg—yiš|k~l €n£‚o¤ƒp¦…q­‰s°Šs›u]žv^Ÿw^¡x_£y_¤z_¥z_¦{_¿“w¿“wÀ“vÁ“vÁ“v“u“u“tª{\ª{\ªz[ªzZªyZªyY©xXÁpÀo¨wW¨vV§vV§uU¦uU¦uT¥tT½Œl¼‹k¼‹k¼‹k»‹k»‹kºŠk¢sT¢rT¢rT¡rT¡rT¡rU rU rV·Šn¶ŠnµŠnµŠo´Šo³‰o²‰p±‰p™qY®ˆq¬‡qª†r§…r¤„r ‚rœ€q€gZ{dYvaXp^WiYU`TRVNOb]aEBH<+[NL^SQWNNKFJ?AI2:HTx«Ty«Ty«Ty«Uy«Uy«Uy«Uy«Uy«‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝImŸImŸImŸImŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšChš&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}CgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;HY;HY;HY;HY;GY3("D::B41RB=YG@wcZ}g\ƒk_‡nbŒrdug}aRdT„gV‡iX‰kY¢ƒq¤„r¥…s§†t‘p^’q^Ÿw` x`¢y`£z`¤za¥{a½“x¾“x¿“w¿“wÀ“wÀ“vÀ“vÀ“vÀ“uÀ’uÀ’tÀ‘sÀ‘sÀ‘r¿r¿q¿q¾p¾Žp¾Žo½Žo¥vW¼n¼Œn»Œn»Œn»ŒnºŒnº‹m¢tV¡sV¡sV¡sV sV sWŸsWŸsXžsXµŠpµŠp´ŠpœsY›sYšrZ˜r[–r\”q\‘p]¦†t£„tŸƒsœs€h\{e[vbYo^XhZV`USXPQNJMECJRS[47A+((MYkMYkMYkMZk(5F(5F(5FOHJT=+YML_SRZQQMGJABI2:H/T†Uy«Uy«Uy«Uy«Uy«Uy«‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸˆ¬Þˆ¬Þ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhšDhš'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}CgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™&J|&J|Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜;HY;HY;HY;HY;HY;HY>DM>DM;HY89<:+#9&B52I94ZHAxd[}g^k`†nc‹rey_R}bTeVƒgX…iYˆk[Šl\Œn]o^¥‡v§ˆvšvaœwažxa yb¢zb¤{b¤{a¼“x½“x¦|a§|a§|`§{`§{_§{_§{^§z^¾‘u¾‘t¾‘t¾s½s½r½r¥wZ¤wZ¤vY¤vY£vY£uX¢uX¢uX¢uX¹Œp¸Œp¸Œp·Œp·‹p¶‹p¶‹pµ‹qµ‹qtZ›t[šs\™s\˜s]–r]”r^’q^p^o^Šn^‡l^ƒj^h]{f\ub[n^YgZW_UTWPQOKOEEKST]JNY>=?JJIMYkMYk(5F(5F(5F(5F(5F)5G)5GK=4S<*XMLbWVYPPLGJ@AI/T†/T†Uy«Uy«Uy«‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞImŸImŸImŸIm ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞIm Im Im Im Im Im Im Im ˆ¬Þˆ¬Þˆ¬Þˆ¬Þ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Dh›Dh›Dh›Dh›DhšDhšDhšDhš'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜;HY;HY;HY;HY;HY;HYCIR>DMCIR;HYCIR.$0"8&?*G/V=+w[F{g^€kanXMs\Px_S{bU~dWfYƒhZ†j\ˆl]Šm^¢…v§ˆwªŠx­Œy¯y±Žz´zµz·‘z¹’z£{b£{b¤{b¥{b¥{a¥{a¥{`¥{`¥z_¥z_¥z^¼‘u¥y]¤y]¤x]¤x\£w\£w[¢w[¢v[¢v[¡v[¡v[¸r·r¶r¶ŒsµŒs´Œs´Œs²Œt±‹u°‹u˜t^–s_•s_“r_’r`q`p`¡…wž„v›‚v—€u“~twd]sb[l^ZeYW]TUUORLJOYYaRU^JOZ>>@!$)RXaMYk39B-3<-3<(5F)5G)5G)5G)5G)5GFDJK9*^K=YONg\\TLMIFJ:>I0T†0T†ImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞIm Im In In In In In In ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßIn In In In In ˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ß'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Di›Di›Dh›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}ChšChšChšChšChšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™&J}&J}&J}&J}&J|&J|&J|&J|&J|Bg™Bg™Bg™Bg™Bg™Bf™Bf™EM>EMCIR;HY;HYCIRCIR)6&8&@*H0I1!\B0}_JhTKjM8q[Pt]Sw`U{cW~eYg[ƒi\…k^‡m_Ÿ…v¢†w¥ˆx¨Šyª‹z­z¯Ž{±{²{³{´{žzdŸzd zc zc¡zc¸‘y¸‘y¸‘y¸‘x¸x¸x·w·w·w·wŸw_Ÿw_žw_µŽv´Žv³v²v²w±w°Œw¯Œw®Œw­‹w«‹xªŠx¨‰x¦‰x¥ˆx£‡x¡†xž…x›ƒw—v’~vŽ|t‰ys„vrh\YcXX[TUSNRIHOUXaNS^JFE>>A')+"%(4:C(5F(5F3:B3:B-3<-3<)5G)5G)5G)5G)5G)5GE:4O:*TKLbXWcZZPIKDCJIm Im Im Im ˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßIn In In In In In Jn Jn Jn Jn Jn ˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn ‰­ß‰­ß‰­ß‰­ßˆ­ßˆ­ßˆ­ßˆ­ß'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšChšChšChšChšChšChšCgšCgšCgšCgš&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J|&J|&J|Cg™Cg™Cg™Bg™Bg™Bg™EMCIRCIRCIR888DGNCJRCIRBBB(0 8&<)G0M5"X@0z^K†bFŠkUlXPp[Rs^TvaVzcX}fZg\i]™u›‚v„wŸ†x¢‡y¥‰z§Šz©‹{ªŒ{•ve–ve—we˜we°|°|±{²{²{²{²{²{±z±z±Žz±Žz±Žz°Žy™vb˜vb—vb–ub•ub•uc”tc“tc’sbscrcqc¢‡y †y…y›„x˜‚x•w’w|uˆytƒvs~sqyooslmVQTOLR[\dQU`KHHAAD:<@68; &�Z`i-4<%');AJ4:C4:C4:C-4<)5G)5G)5G)5G)6G)6G@84H8-N?5YPQmccoghd`dIn In In In In In ˆ¬ßˆ¬ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßˆ­ßJn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~Ei›Ei›Ei›Ei›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhšDhšChšChšChš&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J}Cg™Cg™Cg™Cg™B9;>68;����Z`iZ`iMZk)5G4:C-4<4:C4:C-4<;BJ)5G)6G)6G)6G)6G)6GC6-L;.leg„{{ypqhbeVYcJn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ßJn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn Jn ‰­ß‰­ß‰­ß‰­ß‰­ß‰­ß‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­à‰­àJn¡Jn¡Jn¡Jn¡Jn¡Jn¡Jn¡‰­à‰­à‰­à‰­à‰­à'L~'L~'L~'L~'L~'L~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšDhš'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}Cg™Cg™Cg™<535=AG=?D?AD==1(B3)B2&F4'E4)gTGlXJs^OzcTzaPqfethgvjhbVTcWUdXVeYWfZXg[Yh\Zi]Zi][j^\€us€ususts~tt~tt}tt|st{stut~tt|sszrsyqrwpquoqsmpqloXTXTQWPOULLSSJEA<:=99757335./2113)+.'),)+.8:="(���3@Q���������������JMPV\eT[cNZlNZlZ`iZ`iZ`iZ`iSYbY`h4;C.4=)6GCPaCPaCPaCPaCPaEQbZOGa_emhkŠƒ„nfgeaeJn¡Jn¡Jn¡Jn¡Jn¡Jn¡Š®àŠ®àŠ®àŠ®àŠ®àJo¡Jo¡Jo¡Jo¡Jo¡Jo¡Jo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Š®àŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡ƒ§Úƒ§Úƒ§Úƒ¨Úƒ¨Úƒ¨Úƒ¨Úƒ¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨ÚEjœEiœEiœEiœEiœ'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}Di›Di›Di›Di›Dh›Dh›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}$.>=I[=I[2)>0&A2'C3(I8-^OFbRHfUJjXMq^RwcVzfYfRDfQCdN@zdTqijrjksklrklrklrklqjmpjmpjmojmojmnimmimkhliflscYm`Xg\VbYT^VRE>;A<:>98:77645:873220/0,-/)+.*,/#%( &������15;5BS������������������KKKJMP]dlU[dNZlNZlZ`iTZcZaiZaiZ`iZ`iSZbŽ”LS[V]eDPbDPbDPbDPbDPbDPbWMF^^diei®”†…rkeaeJo¡Jo¡Jo¡Jo¡Š®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àŠ®àKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Š¯áŠ¯áŠ¯áŠ¯áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡ƒ¨Úƒ¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨ÛGk'L~'L~'L~'L~'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Di›Di›Di›Di›Di›'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}%/> ,>=I[=I[ ,> ,>#)2(.7#)2(.7#)2#)2#)2#)2(.7(.7(.767@D>A214$+3#%("$'###""""""&&&888888cB*}\I@!%+%!5*$:/(;0)<1*>3+@4+>1(bUKN@6OA6L=3QB8M?4_RKaTLbUMcVNcVNcVObVOaVOaUO`UO_UO^UO^TO\SOYRNWPNUOMWPKYSOWRN;63953:76755333,/2'),%(+"%(!' ���"&,KXi04:������������������JMP]_b^emU[dNZlNZlT[cU[dU[dU[d[aj•ž•ž•žˆŽ—–¥W]fDPbDPbDPbDPbDPbDPb‘nSž…w—|m¨‚ƒqjKo¡Ko¡Ko¡Š®àŠ®àŠ®àŠ®áŠ®áŠ®áŠ®áŠ®áŠ®áŠ¯áŠ¯áŠ¯áKo¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¡Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨Û„¨Û„¨Û„¨Û„©Û„©Û„©Û„©ÛGkGkGkGkGkGk'L~'L~'L~'L~'K~'K~'K~Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Ei›Di›Di›'K}'K}'K}'K}HlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}*2? ->=I[=I[ ,> ,> ,>#)2#)2#)2(.7(.7#)2#)2(.7(.7(.7(.7/28:79G@A<89',4#%(#%(######""""""8888888887'vS:‹jW;)� - &3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!' ���15;6CT37=������������������������MMMKMP^ad_enY`hNZlNZlU\dV\eŠ‘™Š™Š™–Ÿ–Ÿ–ž•ž“œ—¦Œ’›ƒ¡DQbDQbDQbDQbDQbMUc¤ƒ‘ylŸ‡|€oiKo¡Š¯áŠ¯áŠ¯áŠ¯áŠ¯áŠ¯áŠ¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯áKo¢Ko¢Ko¢Ko¢Ko¢Ko¢Ko¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢Kp¢‹¯â‹¯â‹¯â‹¯âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢„¨Ú„¨Ú„¨Ú„¨Ú„¨Ú„¨Û„¨Û„¨Û„¨Û„©Û„©Û„©Û„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©ÛGkžGkžGkžGkžGkžGkžGkžGkžGkž…©Û…©Ü…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}'K}'K}'K}'K}'K}HO\=J[=J[=J[ -> ,> ,>(.7#)2#)2(.7(.7(.7#)2(.7(.7(/7(/7)/8/28114H7,99@.05&,5$&)$$$######"""(((8888888888888884"nO9„gXˆjZE/ (�-" - %' %$#" ! !$ ���48>7CU:GX ���������������������������JJJLLLKMPagp_enNZlLPV˜Ÿ§Œ’›Œ’›Œ’›‹’š‹‘šŠ‘™‘— –Ÿ–Ÿ–Ÿ“œ“œ—¦„¢„¢DQbDQbDQbDQbNVc…uo‡rjѼ³º«§‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯áKp¢Kp¢Kp¢Kp¢Kp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢‹°â‹°â‹°â‹°âŒ°âŒ°âŒ°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢„¨Û„¨Û„¨Û„©Û„©Û„©Û„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©ÛGkžGkžGkžGlžGlžGlž…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž'K}'K}'K}'K}DhšDhšDhšIP\=J[=J[=J[=J[ -> ->(.7#)2#)2(.7(.7(.7#)2(.7(/7(/7)/8)/8)/803966:E?AC>A856,07%'*%')$$$######(((DDDBBB8888888880 cF1w]OcS{`QS;+57'   *  ��    ;?E7CU;HY=I[ ���������������������������������JJJMMMKMPacfbhq‘— ƒ¡ƒ¡‘— “œ“œ“œŒ“›Œ’›Œ’›‹‘š‘— ‘— —Ÿ™Ÿ¨”œ“œ“œ„‘¢„‘¢„‘¢„‘¢EQcHScNVd´¨§¿®¨Èµ®¯‘‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯á‹¯â‹¯â‹¯â‹¯â‹¯â‹¯â‹°â‹°â‹°â‹°â‹°â‹°â‹°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Œ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âLp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp¢Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£Lp£„©Û„©Û„©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Û…©Ü…©Ü…©ÜGlžGlž…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÝHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž‡«Ý‡«ÝDhšDhšDhšDhš=J[=J[=J[=J[=J[=J[ ->(/7#)2#)2(.7(.7(.7#*2(/7)/8)/8)/8)/8)08*0903:56:88@KBB=;@348*08&(+'(*%%%$$$(((EEE(((&&&���">-"bF3oXMs[Ow]Py^PqbpXMdH5R<,Q;, &%%#'-"'-&3DS_qP\nR_p>J\?K]AG@B::@66:-29'),)'%BBBFFFEEE)))))))))&&&��������������� ������������������������������������������@@@FFFACFZ\_[ajagp„¢„¢„¢ž¥­Ÿ¦®—¦–¥–ž•žŽ•Ž””œ“œ‘— —Ÿ›¡ªš ©™ ¨Ž•Ž”Ž”…‘£…‘£…‘£EQcGRcKTdPWd­¥§¿¯ª‹°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°ãŒ°ãŒ°ãŒ°ãŒ°ãLp£Lp£Lq£Lq£Lq£Lq£Lq£Lq£Lq£Œ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£…©Û…©Û…©Û…©Û…©Û…©Û…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHlžHlžHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«ÞŸ>J\>J\=J[=J[=J[=J[FLU39B#*2(/7)/7)/8$*3$*3$*3)/8)08*09*09*19',5(-5*.6.17338@<=G@BH@BXW]UUXLPWFHKDFHKKKHHH+++%%%%%%$$$###!!!!!!777777777777777777777AAAFFFACFACF\^aeltbhqDQbDQbDQbŸ¥®¡§°¡§°¡§°¡§°—¦–Ÿ”š£”š£“™¢’™¡’˜¡‘˜ ‘— ›¡ª›¡ªš ©•ž™Ÿ¨Ž”ERcERcERcERcHScLUdRXd|njŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°âŒ°ãŒ°ãŒ°ãŒ°ãŒ°ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£Mq£…©Ü…©Ü…©Ü…©Ü…©Ü…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬ÞŽŸŽŸŽŸŽŸ>J\=J[=J[FLUFLU(/7(/7*08*08%+3$*3$+3$+3*09*09*19&,5&,5'-6).6*/7-18NPURRVXUVc]^f^_[X]\XYTUZLQYKMPFHJ)))(((&&&%%%%%%$$$$$$###!!!!!!!!!777777777BBBEEEACGADGFIL\ckZ`iTZcDQbDQbDQbagpbiqcircir¢©±¢¨±¡¨°¡§°•œ¤•›¤”›£”š£“™¢’™¡’˜¡œ¢«œ¢«›¡ªš¡©•žY`hY_hERcERcERcGSdJTdNVdTYeLp¢Lp¢Œ°ãŒ°ãŒ°ãŒ°ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ãŒ±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ãMq£Mq£±ã±ã±ã±ä±ä±ä±ä±ä±ä±ä±ä±ä±ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²ä²äMq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤Mq¤…ªÜ…ªÜ…ªÜ…ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÝ†ªÝ†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞŽŸŽŸŽŸŽŸŽŸŽŸŽŸFLUFLUFLU)/8+08+08&+3&+3%+4%+4%+4*19+1:&,5'-5'-6(.6FLTHMTINUKOVOQWSTXYWX`[^lbac]_f_\a_aY\aRX_,.1*,.*+-***((('''&&&%%%%%%$$$$$$$$$###!!!!!!!!!!!!!!!%%%%%%%%%%%%"""""""""KKKJJJFFFGIL]_b^dm\bkV]eDQbEQcEQcEQccirdjsdksektdjsdjscir£©²¢¨±¢¨±–œ¥•œ¤•›¤”›£”š£“™¢’™¡£¬œ¢«›¢ª[ajZ`iOU^ERcERcFRdFRdITdLUdPWeVZeLp£Lq£Lq£Lq£±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ã±ä±ä±ä±ä±ä±ä²ä²ä²äMq£²ä²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äMr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤Mr¤†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«ÞHmŸHmŸHmŸ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ÞŽŸŽŸŽŸŽŸ‚Ž ‚Ž ‚Ž ‚Ž ”›£Š™ŠŽ•-18,18',3',4',4&,4%,4+1:,2:'-5DJSEKSEKTFLTFLUHMUINVKOWLPWQSYTUZWWZpjje^`offb\_h`]eaaCCG8;A27?-/2+-/.+)******)))((('''&&&&&&%%%%%%$$$$$$$$$$$$$$$$$$######???EEEEEEEEE((((((###&&&%%%HJMHJMHJMHJM_en]dlZ`i_enEQcEQcEQcEQcbhqektflufluflufluektektdksdjscjr£©²¢©±¢¨±–œ¥•œ¤•›¤”›£”š£“™¢£¬\ckQW`[ajZaiOU^FRdFRdFRdHSdKUdNVeRXeX\fLq£Mq£Mq£Mq£Mq£±ã±ã±ã±ã±ã±ä±ä±ä±ä±ä²ä²ä²ä²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äMr¤Mr¤Mr¤Mr¤Mr¤Ž²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åŽ²åNr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬ÞHmŸHmŸHmŸHmŸImŸImŸImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ‚Ž ”›£Š‘™‹•‹•PT[KOVJOV(-4(-4'-5'-5JOXEKSEKSEKTFLTFLTGMUGMUHNVIOWKPWLQXMRYPTZTV[\]a_^asljd^azporjkE@CLEBIEFEDG29A28A17@135,.1+-0+,/./1..0'),)))++++++++++++***FFFFFFACFACFEEEACFACFŠŒJLOJLOKQZ_en]clY_hU[dEQcEQcEQcEQcEQcagp[aj\bk\bkgnvgnvgmvgmvfluflueltektdksdjscjrcir¢©±—¦–œ¥•œ¤•›¤TZcSYbRYaRXaQW`[bj[ajZ`iFSdFSdGSdJTdLVePXeTZfZ]fMq£Mq£Mq£Mq£Mq£Mq£Mq£²ä²ä²ä²ä²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äŽ²äNr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Nr¤Ž²åŽ²åŽ²åŽ²åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³åŽ³å³å³å³å³å³å³å³åNr¤Nr¤Nr¤Nr¤Nr¤³å³å†ªÜ†ªÜ†ªÝHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸ‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡«Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬Þ‡¬ÞImŸImŸImŸImŸImŸImŸImŸImŸImŸImŸˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬Þˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ¬ßˆ­ß‚Ž ‚Ž ‚Ž ‚Ž ‚ ‚ ‚ ‚ ‚ …Œ”’•šŒ•‘”›LPVLPWKPW‹—‹—‹˜•‹‘™FLTFLTFLUGMUGMUHMVHNVINWIOWKPXLQYMRYNSZTX`X[a[]b]^c__ccacib`JDGi__aYYPJLD@C=;AKEDTQR@?A>>A;/5>.4=-4 - - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(Q_OS_SYMBIAN) -# define SRCDIR "" -#endif -typedef QMap QStringMap; -typedef QList 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("fileName"); - QTest::addColumn("lossy"); - QTest::addColumn("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("fileName"); - QTest::addColumn("format"); - QTest::addColumn("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 formats = QImageWriter::supportedImageFormats(); - QList sortedFormats = formats; - qSort(sortedFormats); - - // check that the list is sorted - QCOMPARE(formats, sortedFormats); - - QSet 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("format"); - QTest::addColumn("expectedFormat"); - QTest::addColumn("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 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("fileName"); - QTest::addColumn("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 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("fileName"); - QTest::addColumn("format"); - QTest::addColumn("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("filename"); - QTest::addColumn("expectedDotsPerMeterX"); - QTest::addColumn("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/qkeysequence/.gitignore b/tests/auto/qkeysequence/.gitignore deleted file mode 100644 index e06a7b0f43..0000000000 --- a/tests/auto/qkeysequence/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qkeysequence diff --git a/tests/auto/qkeysequence/keys_de.qm b/tests/auto/qkeysequence/keys_de.qm deleted file mode 100644 index 5d7aedd765..0000000000 Binary files a/tests/auto/qkeysequence/keys_de.qm and /dev/null differ diff --git a/tests/auto/qkeysequence/keys_de.ts b/tests/auto/qkeysequence/keys_de.ts deleted file mode 100644 index 1db18f1fdd..0000000000 --- a/tests/auto/qkeysequence/keys_de.ts +++ /dev/null @@ -1,61 +0,0 @@ - - - - tst_QKeySequence - - - Shift+K - Umschalt+K - - - - Ctrl+K - Strg+K - - - - Alt+K - Alt+K - - - - Shift++ - Umschalt++ - - - - Ctrl++ - Strg++ - - - - Alt++ - Alt++ - - - - Meta++ - Meta++ - - - - Shift+,, Shift++ - Umschalt+,, Umschalt++ - - - - Shift+,, Ctrl++ - Umschalt+,, Strg++ - - - - Shift+,, Alt++ - Umschalt+,, Alt++ - - - - Shift+,, Meta++ - Umschalt+,, Meta++ - - - diff --git a/tests/auto/qkeysequence/qkeysequence.pro b/tests/auto/qkeysequence/qkeysequence.pro deleted file mode 100644 index 6cfbe459ea..0000000000 --- a/tests/auto/qkeysequence/qkeysequence.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) - -QT += widgets widgets-private -QT += core-private gui-private - -SOURCES += tst_qkeysequence.cpp - -RESOURCES += qkeysequence.qrc diff --git a/tests/auto/qkeysequence/qkeysequence.qrc b/tests/auto/qkeysequence/qkeysequence.qrc deleted file mode 100644 index e224faaddd..0000000000 --- a/tests/auto/qkeysequence/qkeysequence.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - keys_de.qm - qt_de.qm - - diff --git a/tests/auto/qkeysequence/qt_de.qm b/tests/auto/qkeysequence/qt_de.qm deleted file mode 100644 index 595e4d7e8f..0000000000 Binary files a/tests/auto/qkeysequence/qt_de.qm and /dev/null differ diff --git a/tests/auto/qkeysequence/tst_qkeysequence.cpp b/tests/auto/qkeysequence/tst_qkeysequence.cpp deleted file mode 100644 index 5753fb8df4..0000000000 --- a/tests/auto/qkeysequence/tst_qkeysequence.cpp +++ /dev/null @@ -1,636 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -//TESTED_CLASS= -//TESTED_FILES= - -#ifdef Q_WS_MAC -#include -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("modifiers"); - QTest::addColumn("keycode"); - QTest::addColumn("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("modifiers"); - QTest::addColumn("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("standardKey"); - QTest::addColumn("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 bindings = QKeySequence::keyBindings(QKeySequence::Copy); - QList 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("string"); - QTest::addColumn("key"); - QTest::addColumn("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("strSequence"); - QTest::addColumn("neutralString"); - QTest::addColumn("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("transKey"); - QTest::addColumn("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("keycode"); - QTest::addColumn("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/qmatrixnxn/qmatrixnxn.pro b/tests/auto/qmatrixnxn/qmatrixnxn.pro deleted file mode 100644 index cf6e4a128e..0000000000 --- a/tests/auto/qmatrixnxn/qmatrixnxn.pro +++ /dev/null @@ -1,2 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qmatrixnxn.cpp diff --git a/tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp deleted file mode 100644 index 98a559af85..0000000000 --- a/tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp +++ /dev/null @@ -1,3385 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("factor"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("factor"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("factor"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("factor"); - QTest::addColumn("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("m1Values"); - QTest::addColumn("m2Values"); - QTest::addColumn("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("x"); - QTest::addColumn("y"); - QTest::addColumn("z"); - QTest::addColumn("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("x"); - QTest::addColumn("y"); - QTest::addColumn("z"); - QTest::addColumn("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("angle"); - QTest::addColumn("x"); - QTest::addColumn("y"); - QTest::addColumn("z"); - QTest::addColumn("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("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("mValues"); - QTest::addColumn("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(&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("x"); - QTest::addColumn("y"); - QTest::addColumn("width"); - QTest::addColumn("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("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(obj.property("matrix")); - QVERIFY(isSame(m2, uniqueValues4)); - - QMatrix4x4 m3(transposedValues4); - obj.setProperty("matrix", qVariantFromValue(m3)); - - m2 = qVariantValue(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() == QMetaType::QMatrix4x4); -} - -QTEST_APPLESS_MAIN(tst_QMatrixNxN) - -#include "tst_qmatrixnxn.moc" diff --git a/tests/auto/qmouseevent/.gitignore b/tests/auto/qmouseevent/.gitignore deleted file mode 100644 index 17cd6be116..0000000000 --- a/tests/auto/qmouseevent/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmouseevent diff --git a/tests/auto/qmouseevent/qmouseevent.pro b/tests/auto/qmouseevent/qmouseevent.pro deleted file mode 100644 index 58cebd3d06..0000000000 --- a/tests/auto/qmouseevent/qmouseevent.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qmouseevent.cpp diff --git a/tests/auto/qmouseevent/tst_qmouseevent.cpp b/tests/auto/qmouseevent/tst_qmouseevent.cpp deleted file mode 100644 index 5998aa0c08..0000000000 --- a/tests/auto/qmouseevent/tst_qmouseevent.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - - -#include -#include - -//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("buttonPressed"); - QTest::addColumn("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("buttonReleased"); - QTest::addColumn("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/qmouseevent_modal/.gitignore b/tests/auto/qmouseevent_modal/.gitignore deleted file mode 100644 index e15c9eb18c..0000000000 --- a/tests/auto/qmouseevent_modal/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmouseevent_modal diff --git a/tests/auto/qmouseevent_modal/qmouseevent_modal.pro b/tests/auto/qmouseevent_modal/qmouseevent_modal.pro deleted file mode 100644 index 2f28de2675..0000000000 --- a/tests/auto/qmouseevent_modal/qmouseevent_modal.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qmouseevent_modal.cpp - - - diff --git a/tests/auto/qmouseevent_modal/tst_qmouseevent_modal.cpp b/tests/auto/qmouseevent_modal/tst_qmouseevent_modal.cpp deleted file mode 100644 index 7006feeeb8..0000000000 --- a/tests/auto/qmouseevent_modal/tst_qmouseevent_modal.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - - -#include -#include -#include - -#include - - -//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/qmovie/.gitignore b/tests/auto/qmovie/.gitignore deleted file mode 100644 index 396e8cbc7d..0000000000 --- a/tests/auto/qmovie/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmovie diff --git a/tests/auto/qmovie/animations/comicsecard.gif b/tests/auto/qmovie/animations/comicsecard.gif deleted file mode 100644 index f064de065b..0000000000 Binary files a/tests/auto/qmovie/animations/comicsecard.gif and /dev/null differ diff --git a/tests/auto/qmovie/animations/corrupt.gif b/tests/auto/qmovie/animations/corrupt.gif deleted file mode 100644 index c1545eb0ed..0000000000 Binary files a/tests/auto/qmovie/animations/corrupt.gif and /dev/null differ diff --git a/tests/auto/qmovie/animations/dutch.mng b/tests/auto/qmovie/animations/dutch.mng deleted file mode 100644 index 4917fdee7a..0000000000 Binary files a/tests/auto/qmovie/animations/dutch.mng and /dev/null differ diff --git a/tests/auto/qmovie/animations/trolltech.gif b/tests/auto/qmovie/animations/trolltech.gif deleted file mode 100644 index df7eb92703..0000000000 Binary files a/tests/auto/qmovie/animations/trolltech.gif and /dev/null differ diff --git a/tests/auto/qmovie/qmovie.pro b/tests/auto/qmovie/qmovie.pro deleted file mode 100644 index 3e085ceeaf..0000000000 --- a/tests/auto/qmovie/qmovie.pro +++ /dev/null @@ -1,28 +0,0 @@ -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/qmovie/resources.qrc b/tests/auto/qmovie/resources.qrc deleted file mode 100644 index ce459a0e7e..0000000000 --- a/tests/auto/qmovie/resources.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - animations/corrupt.gif - - diff --git a/tests/auto/qmovie/tst_qmovie.cpp b/tests/auto/qmovie/tst_qmovie.cpp deleted file mode 100644 index 15c7f856b1..0000000000 --- a/tests/auto/qmovie/tst_qmovie.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include - -//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("fileName"); - QTest::addColumn("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/qpaintengine/.gitignore b/tests/auto/qpaintengine/.gitignore deleted file mode 100644 index e55942ea9f..0000000000 --- a/tests/auto/qpaintengine/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpaintengine diff --git a/tests/auto/qpaintengine/qpaintengine.pro b/tests/auto/qpaintengine/qpaintengine.pro deleted file mode 100644 index e37c1668ac..0000000000 --- a/tests/auto/qpaintengine/qpaintengine.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qpaintengine.h -############################################################ - -load(qttest_p4) - -SOURCES += tst_qpaintengine.cpp - - diff --git a/tests/auto/qpaintengine/tst_qpaintengine.cpp b/tests/auto/qpaintengine/tst_qpaintengine.cpp deleted file mode 100644 index ba9cc62a3d..0000000000 --- a/tests/auto/qpaintengine/tst_qpaintengine.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - -//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/qpainter/.gitignore b/tests/auto/qpainter/.gitignore deleted file mode 100644 index 33e0dbe945..0000000000 --- a/tests/auto/qpainter/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tst_qpainter -foo.png diff --git a/tests/auto/qpainter/drawEllipse/10x10SizeAt0x0.png b/tests/auto/qpainter/drawEllipse/10x10SizeAt0x0.png deleted file mode 100644 index f2ab9a776d..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/10x10SizeAt0x0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawEllipse/10x10SizeAt100x100.png b/tests/auto/qpainter/drawEllipse/10x10SizeAt100x100.png deleted file mode 100644 index b1c755b5b0..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/10x10SizeAt100x100.png and /dev/null differ diff --git a/tests/auto/qpainter/drawEllipse/10x10SizeAt200x200.png b/tests/auto/qpainter/drawEllipse/10x10SizeAt200x200.png deleted file mode 100644 index 0e30498da5..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/10x10SizeAt200x200.png and /dev/null differ diff --git a/tests/auto/qpainter/drawEllipse/13x100SizeAt0x0.png b/tests/auto/qpainter/drawEllipse/13x100SizeAt0x0.png deleted file mode 100644 index f00796a3ad..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/13x100SizeAt0x0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawEllipse/13x100SizeAt100x100.png b/tests/auto/qpainter/drawEllipse/13x100SizeAt100x100.png deleted file mode 100644 index a9a1a8a536..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/13x100SizeAt100x100.png and /dev/null differ diff --git a/tests/auto/qpainter/drawEllipse/13x100SizeAt200x200.png b/tests/auto/qpainter/drawEllipse/13x100SizeAt200x200.png deleted file mode 100644 index 0e30498da5..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/13x100SizeAt200x200.png and /dev/null differ diff --git a/tests/auto/qpainter/drawEllipse/200x200SizeAt0x0.png b/tests/auto/qpainter/drawEllipse/200x200SizeAt0x0.png deleted file mode 100644 index 67db116b90..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/200x200SizeAt0x0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawEllipse/200x200SizeAt100x100.png b/tests/auto/qpainter/drawEllipse/200x200SizeAt100x100.png deleted file mode 100644 index 7d32afa4a8..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/200x200SizeAt100x100.png and /dev/null differ diff --git a/tests/auto/qpainter/drawEllipse/200x200SizeAt200x200.png b/tests/auto/qpainter/drawEllipse/200x200SizeAt200x200.png deleted file mode 100644 index 0e30498da5..0000000000 Binary files a/tests/auto/qpainter/drawEllipse/200x200SizeAt200x200.png and /dev/null differ diff --git a/tests/auto/qpainter/drawLine_rop_bitmap/dst.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/dst.xbm deleted file mode 100644 index e645a0b86b..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/dst.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm deleted file mode 100644 index 303c799264..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm deleted file mode 100644 index 31333de879..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm deleted file mode 100644 index 9cc25ea147..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm deleted file mode 100644 index 869844dcee..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm deleted file mode 100644 index d058484fa8..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm deleted file mode 100644 index 3a2bc23468..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm deleted file mode 100644 index c74be41bbd..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm deleted file mode 100644 index 0cf8c3a82c..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm deleted file mode 100644 index 65474e16c5..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm deleted file mode 100644 index 144d8995b6..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm deleted file mode 100644 index ccb3d36fb4..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm deleted file mode 100644 index 4be8f51a80..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm deleted file mode 100644 index d53fbe00e1..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm deleted file mode 100644 index 06b51fcc68..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm deleted file mode 100644 index ab42472bb0..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm b/tests/auto/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm deleted file mode 100644 index 5ac892dd0b..0000000000 --- a/tests/auto/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop/dst1.png b/tests/auto/qpainter/drawPixmap_rop/dst1.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/dst1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/dst2.png b/tests/auto/qpainter/drawPixmap_rop/dst2.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/dst2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/dst3.png b/tests/auto/qpainter/drawPixmap_rop/dst3.png deleted file mode 100644 index 8a3d28f3ed..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/dst3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP0.png deleted file mode 100644 index fe017ac1ab..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP1.png deleted file mode 100644 index 82d938c023..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP2.png deleted file mode 100644 index 2b67b928e4..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP3.png deleted file mode 100644 index c95b5a10ba..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP4.png deleted file mode 100644 index bbe2a24530..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP5.png deleted file mode 100644 index 0158278b84..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP6.png deleted file mode 100644 index aa1f403075..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP7.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndNotROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP0.png deleted file mode 100644 index ebf8244eee..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP1.png deleted file mode 100644 index 88568bc330..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP2.png deleted file mode 100644 index 0ed6de2865..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP3.png deleted file mode 100644 index c2ff341e6b..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP4.png deleted file mode 100644 index e08c9acbe2..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP5.png deleted file mode 100644 index e9d7a57333..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP6.png deleted file mode 100644 index 01438a195c..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP7.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_AndROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP0.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP1.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP2.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP3.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP4.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP5.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP6.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP7.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_ClearROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP0.png deleted file mode 100644 index 587623d3e8..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP1.png deleted file mode 100644 index 10e7ae59d5..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP2.png deleted file mode 100644 index 5c14136eb4..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP3.png deleted file mode 100644 index 207f52564b..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP4.png deleted file mode 100644 index 6981cee080..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP5.png deleted file mode 100644 index 8b8de9892a..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP6.png deleted file mode 100644 index 9825c0539f..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP7.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_CopyROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP0.png deleted file mode 100644 index 8d26638c03..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP1.png deleted file mode 100644 index f5b33589ba..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP2.png deleted file mode 100644 index adc4ee3701..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP3.png deleted file mode 100644 index dccc94c43b..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP4.png deleted file mode 100644 index 4d207e7968..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP5.png deleted file mode 100644 index aa93d4d4a4..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP6.png deleted file mode 100644 index ad320f950b..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP7.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NandROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP0.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP1.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP2.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP3.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP4.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP5.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP6.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP7.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NopROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP0.png deleted file mode 100644 index 3e33bb1078..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP1.png deleted file mode 100644 index ce2b6f4e15..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP2.png deleted file mode 100644 index 9eddc9840b..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP3.png deleted file mode 100644 index 4ea9669dd3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP4.png deleted file mode 100644 index c64e0a5630..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP5.png deleted file mode 100644 index 1fe3def383..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP6.png deleted file mode 100644 index 9c294b04d9..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP7.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NorROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP0.png deleted file mode 100644 index 01c694cdcc..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP1.png deleted file mode 100644 index 4b11aa9c41..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP2.png deleted file mode 100644 index accbe42112..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP3.png deleted file mode 100644 index 3c58d4fac7..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP4.png deleted file mode 100644 index 3b0a41c396..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP5.png deleted file mode 100644 index 045ef33012..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP6.png deleted file mode 100644 index 3a83725938..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP7.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotAndROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png deleted file mode 100644 index 7c51fc16fa..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png deleted file mode 100644 index 8f519e8c52..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png deleted file mode 100644 index a0f9f60653..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png deleted file mode 100644 index 95931a4317..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png deleted file mode 100644 index f825d523b0..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png deleted file mode 100644 index 245a27ea2f..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png deleted file mode 100644 index b32020675b..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png deleted file mode 100644 index cff8926587..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP0.png deleted file mode 100644 index 3622f3a2b1..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP1.png deleted file mode 100644 index e31793e4a3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP2.png deleted file mode 100644 index 8e8237548b..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP3.png deleted file mode 100644 index f4b98914b4..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP4.png deleted file mode 100644 index b14fdba341..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP5.png deleted file mode 100644 index 129d7f3dc6..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP6.png deleted file mode 100644 index d894c5cb68..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP7.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotOrROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP0.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP1.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP2.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP3.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP4.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP5.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP6.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP7.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP0.png deleted file mode 100644 index b1e61504cd..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP1.png deleted file mode 100644 index 8cf29cde81..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP2.png deleted file mode 100644 index 99fedf8c04..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP3.png deleted file mode 100644 index bc220f546e..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP4.png deleted file mode 100644 index f48e8b9f4d..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP5.png deleted file mode 100644 index c5e3c0fc63..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP6.png deleted file mode 100644 index 13bb69f91b..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP7.png deleted file mode 100644 index 4a7ca7f9b3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_NotXorROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP0.png deleted file mode 100644 index 85b964301d..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP1.png deleted file mode 100644 index d92bf16044..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP2.png deleted file mode 100644 index bb81c5abe8..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP3.png deleted file mode 100644 index 9378f166cd..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP4.png deleted file mode 100644 index 2ea026eb6c..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP5.png deleted file mode 100644 index 8366d37eda..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP6.png deleted file mode 100644 index 39c36d1b52..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP7.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrNotROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP0.png deleted file mode 100644 index beb2bc35b8..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP1.png deleted file mode 100644 index 6ed17a72ed..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP2.png deleted file mode 100644 index 9e0b63c220..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP3.png deleted file mode 100644 index 6471b4aaa4..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP4.png deleted file mode 100644 index c158ea0d01..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP5.png deleted file mode 100644 index eb3deacc86..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP6.png deleted file mode 100644 index 51948b0ac9..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP7.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_OrROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP0.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP1.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP2.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP3.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP4.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP5.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP6.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP7.png deleted file mode 100644 index 00968ffd06..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_SetROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP0.png b/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP0.png deleted file mode 100644 index c2b009cac3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP0.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP1.png b/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP1.png deleted file mode 100644 index 42b0b3c308..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP1.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP2.png b/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP2.png deleted file mode 100644 index bc43614ab3..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP2.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP3.png b/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP3.png deleted file mode 100644 index 7486d4b3f4..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP3.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP4.png b/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP4.png deleted file mode 100644 index 8098634be4..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP4.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP5.png b/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP5.png deleted file mode 100644 index 8c5b9feb7c..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP5.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP6.png b/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP6.png deleted file mode 100644 index c7e51a1410..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP6.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP7.png b/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP7.png deleted file mode 100644 index 8605b64d93..0000000000 Binary files a/tests/auto/qpainter/drawPixmap_rop/res/res_XorROP7.png and /dev/null differ diff --git a/tests/auto/qpainter/drawPixmap_rop/src1.xbm b/tests/auto/qpainter/drawPixmap_rop/src1.xbm deleted file mode 100644 index f088d28c8c..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop/src1.xbm +++ /dev/null @@ -1,12 +0,0 @@ -#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/qpainter/drawPixmap_rop/src2-mask.xbm b/tests/auto/qpainter/drawPixmap_rop/src2-mask.xbm deleted file mode 100644 index bd73f9433c..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop/src2-mask.xbm +++ /dev/null @@ -1,16 +0,0 @@ -#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/qpainter/drawPixmap_rop/src2.xbm b/tests/auto/qpainter/drawPixmap_rop/src2.xbm deleted file mode 100644 index 40126a9d17..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop/src2.xbm +++ /dev/null @@ -1,16 +0,0 @@ -#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/qpainter/drawPixmap_rop/src3.xbm b/tests/auto/qpainter/drawPixmap_rop/src3.xbm deleted file mode 100644 index 2f2d5472a4..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop/src3.xbm +++ /dev/null @@ -1,12 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/dst.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/dst.xbm deleted file mode 100644 index 45543c8ebf..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/dst.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm deleted file mode 100644 index 303c799264..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm deleted file mode 100644 index 31333de879..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm deleted file mode 100644 index 9cc25ea147..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm deleted file mode 100644 index 869844dcee..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm deleted file mode 100644 index d058484fa8..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm deleted file mode 100644 index 3a2bc23468..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm deleted file mode 100644 index c74be41bbd..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm deleted file mode 100644 index 0cf8c3a82c..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm deleted file mode 100644 index 65474e16c5..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm deleted file mode 100644 index 144d8995b6..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm deleted file mode 100644 index ccb3d36fb4..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm deleted file mode 100644 index 4be8f51a80..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm deleted file mode 100644 index d53fbe00e1..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm deleted file mode 100644 index 06b51fcc68..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm deleted file mode 100644 index ab42472bb0..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm deleted file mode 100644 index 5ac892dd0b..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm deleted file mode 100644 index ac9031f1f1..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/src1.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/src1.xbm deleted file mode 100644 index d883569db2..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/src1.xbm +++ /dev/null @@ -1,6 +0,0 @@ -#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/qpainter/drawPixmap_rop_bitmap/src2.xbm b/tests/auto/qpainter/drawPixmap_rop_bitmap/src2.xbm deleted file mode 100644 index fb203df28a..0000000000 --- a/tests/auto/qpainter/drawPixmap_rop_bitmap/src2.xbm +++ /dev/null @@ -1,5 +0,0 @@ -#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/qpainter/qpainter.pro b/tests/auto/qpainter/qpainter.pro deleted file mode 100644 index 00307d3e58..0000000000 --- a/tests/auto/qpainter/qpainter.pro +++ /dev/null @@ -1,20 +0,0 @@ -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/qpainter/task217400.png b/tests/auto/qpainter/task217400.png deleted file mode 100644 index c12a602ba6..0000000000 Binary files a/tests/auto/qpainter/task217400.png and /dev/null differ diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp deleted file mode 100644 index ff4f7ad8eb..0000000000 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ /dev/null @@ -1,4697 +0,0 @@ -/**************************************************************************** -** -** 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 -#include "../../shared/util.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) -#include -#include -#endif -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#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("dest"); - QTest::addColumn("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 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("font"); - QTest::addColumn("pen"); - QTest::addColumn("brush"); - QTest::addColumn("backgroundColor"); - QTest::addColumn("backgroundMode"); - QTest::addColumn("brushOrigin"); - QTest::addColumn("clipRegion"); - QTest::addColumn("window"); - QTest::addColumn("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("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(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(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(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("path"); - QTest::addColumn("expectedBounds"); - QTest::addColumn("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("size"); - QTest::addColumn("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("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("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("rect"); - QTest::addColumn("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 -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(img); - testClipping(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("deviceSize"); - QTest::addColumn("region"); - - QTest::newRow("empty") << QSize(100, 100) << QRegion(); - QTest::newRow("simple rect") << QSize(100, 100) - << QRegion(QRect(5, 5, 10, 10)); - - QVector 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("imageSize"); - QTest::addColumn("path"); - QTest::addColumn("clipRect"); - QTest::addColumn("brush"); - QTest::addColumn("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("imageSize"); - QTest::addColumn("line"); - QTest::addColumn("clipRect"); - QTest::addColumn("pen"); - - QPen pen2(QColor(223, 223, 0, 223)); - pen2.setWidth(2); - - QVector 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("destFormat"); - QTest::addColumn("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 opacities = (QList() << 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 opacities = (QList() << 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 - -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("transform"); - QTest::addColumn("line"); - QTest::addColumn("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("format"); - QTest::addColumn("width"); - QTest::addColumn("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("width"); - QTest::addColumn("height"); - QTest::addColumn("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 discovered; - discovered.enqueue(QPoint(x, y)); - - QVector 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("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("x"); - QTest::addColumn("y"); - QTest::addColumn("w"); - QTest::addColumn("h"); - QTest::addColumn("srcFormat"); - QTest::addColumn("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("sourceFormat"); - QTest::addColumn("destFormat"); - QTest::addColumn("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("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(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(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 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/qpainter/utils/createImages/createImages.pro b/tests/auto/qpainter/utils/createImages/createImages.pro deleted file mode 100644 index ce2d341e92..0000000000 --- a/tests/auto/qpainter/utils/createImages/createImages.pro +++ /dev/null @@ -1,11 +0,0 @@ -###################################################################### -# 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/qpainter/utils/createImages/main.cpp b/tests/auto/qpainter/utils/createImages/main.cpp deleted file mode 100644 index 418c385717..0000000000 --- a/tests/auto/qpainter/utils/createImages/main.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -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 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/qpainterpath/.gitignore b/tests/auto/qpainterpath/.gitignore deleted file mode 100644 index 4e0e797989..0000000000 --- a/tests/auto/qpainterpath/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tst_qpainterpath -data diff --git a/tests/auto/qpainterpath/qpainterpath.pro b/tests/auto/qpainterpath/qpainterpath.pro deleted file mode 100644 index 9708222c99..0000000000 --- a/tests/auto/qpainterpath/qpainterpath.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qpainterpath.cpp - - - diff --git a/tests/auto/qpainterpath/tst_qpainterpath.cpp b/tests/auto/qpainterpath/tst_qpainterpath.cpp deleted file mode 100644 index 33315adc06..0000000000 --- a/tests/auto/qpainterpath/tst_qpainterpath.cpp +++ /dev/null @@ -1,1332 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - -#define _USE_MATH_DEFINES -#include - -//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("path"); - QTest::addColumn("pt"); - QTest::addColumn("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("path"); - QTest::addColumn("rect"); - QTest::addColumn("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("path"); - QTest::addColumn("rect"); - QTest::addColumn("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("path"); - QTest::addColumn("candidate"); - QTest::addColumn("contained"); - QTest::addColumn("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("path"); - QTest::addColumn("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("path"); - QTest::addColumn("pen"); - QTest::addColumn("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("rect"); - QTest::addColumn("angle"); - - QList 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("test"); - QTest::addColumn("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("path"); - QTest::addColumn("start"); - QTest::addColumn("middle"); - QTest::addColumn("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("path"); - QTest::addColumn("percent"); - QTest::addColumn("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("path"); - QTest::addColumn("point"); - QTest::addColumn("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 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 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/qpainterpathstroker/.gitignore b/tests/auto/qpainterpathstroker/.gitignore deleted file mode 100644 index e171c5da31..0000000000 --- a/tests/auto/qpainterpathstroker/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpainterpathstroker diff --git a/tests/auto/qpainterpathstroker/qpainterpathstroker.pro b/tests/auto/qpainterpathstroker/qpainterpathstroker.pro deleted file mode 100644 index b6f62a2eee..0000000000 --- a/tests/auto/qpainterpathstroker/qpainterpathstroker.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qpainterpathstroker.cpp - - - diff --git a/tests/auto/qpainterpathstroker/tst_qpainterpathstroker.cpp b/tests/auto/qpainterpathstroker/tst_qpainterpathstroker.cpp deleted file mode 100644 index 288263e5d7..0000000000 --- a/tests/auto/qpainterpathstroker/tst_qpainterpathstroker.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include - -#define _USE_MATH_DEFINES -#include - -//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/qpalette/.gitignore b/tests/auto/qpalette/.gitignore deleted file mode 100644 index 3c1aebac19..0000000000 --- a/tests/auto/qpalette/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpalette diff --git a/tests/auto/qpalette/qpalette.pro b/tests/auto/qpalette/qpalette.pro deleted file mode 100644 index 4b240e5f9c..0000000000 --- a/tests/auto/qpalette/qpalette.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qpalette.cpp - - - diff --git a/tests/auto/qpalette/tst_qpalette.cpp b/tests/auto/qpalette/tst_qpalette.cpp deleted file mode 100644 index b63b8bf7b0..0000000000 --- a/tests/auto/qpalette/tst_qpalette.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include "qpalette.h" -#include - -//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("role"); - QTest::addColumn("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/qpathclipper/.gitignore b/tests/auto/qpathclipper/.gitignore deleted file mode 100644 index a689eef0f6..0000000000 --- a/tests/auto/qpathclipper/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpathclipper diff --git a/tests/auto/qpathclipper/pathcompare.h b/tests/auto/qpathclipper/pathcompare.h deleted file mode 100644 index d80c189665..0000000000 --- a/tests/auto/qpathclipper/pathcompare.h +++ /dev/null @@ -1,126 +0,0 @@ -/**************************************************************************** -** -** 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 - -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/qpathclipper/paths.cpp b/tests/auto/qpathclipper/paths.cpp deleted file mode 100644 index 950c34614e..0000000000 --- a/tests/auto/qpathclipper/paths.cpp +++ /dev/null @@ -1,734 +0,0 @@ -/**************************************************************************** -** -** 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/qpathclipper/paths.h b/tests/auto/qpathclipper/paths.h deleted file mode 100644 index 89ef785857..0000000000 --- a/tests/auto/qpathclipper/paths.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** 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 - -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/qpathclipper/qpathclipper.pro b/tests/auto/qpathclipper/qpathclipper.pro deleted file mode 100644 index 2becd7dd03..0000000000 --- a/tests/auto/qpathclipper/qpathclipper.pro +++ /dev/null @@ -1,11 +0,0 @@ -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/qpathclipper/tst_qpathclipper.cpp b/tests/auto/qpathclipper/tst_qpathclipper.cpp deleted file mode 100644 index 57a56b2d1a..0000000000 --- a/tests/auto/qpathclipper/tst_qpathclipper.cpp +++ /dev/null @@ -1,1334 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - -#include - -class tst_QPathClipper : public QObject -{ - Q_OBJECT - -public: - tst_QPathClipper(); - virtual ~tst_QPathClipper(); - -private: - void clipTest(int subjectIndex, int clipIndex, QPathClipper::Operation op); - - QList 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("subject"); - QTest::addColumn("clip"); - QTest::addColumn("op"); - QTest::addColumn("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("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/qpen/.gitignore b/tests/auto/qpen/.gitignore deleted file mode 100644 index a9187367dc..0000000000 --- a/tests/auto/qpen/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpen diff --git a/tests/auto/qpen/qpen.pro b/tests/auto/qpen/qpen.pro deleted file mode 100644 index 53bd5e2b6e..0000000000 --- a/tests/auto/qpen/qpen.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qpen.cpp - - - diff --git a/tests/auto/qpen/tst_qpen.cpp b/tests/auto/qpen/tst_qpen.cpp deleted file mode 100644 index 64d725bc50..0000000000 --- a/tests/auto/qpen/tst_qpen.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include "qpen.h" -#include "qbrush.h" - -#include - -//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("pen1"); - QTest::addColumn("pen2"); - QTest::addColumn("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("pen"); - QTest::addColumn("brush"); - QTest::addColumn("width"); - QTest::addColumn("style"); - QTest::addColumn("capStyle"); - QTest::addColumn("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("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/qpicture/.gitignore b/tests/auto/qpicture/.gitignore deleted file mode 100644 index 0f391ffb80..0000000000 --- a/tests/auto/qpicture/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpicture diff --git a/tests/auto/qpicture/qpicture.pro b/tests/auto/qpicture/qpicture.pro deleted file mode 100644 index eb96b73487..0000000000 --- a/tests/auto/qpicture/qpicture.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qpicture.cpp - - - diff --git a/tests/auto/qpicture/tst_qpicture.cpp b/tests/auto/qpicture/tst_qpicture.cpp deleted file mode 100644 index 8661a2b2d0..0000000000 --- a/tests/auto/qpicture/tst_qpicture.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include - -//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("x"); - QTest::addColumn("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/qpixmap/.gitignore b/tests/auto/qpixmap/.gitignore deleted file mode 100644 index 8d4996f365..0000000000 --- a/tests/auto/qpixmap/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpixmap diff --git a/tests/auto/qpixmap/convertFromImage/task31722_0/img1.png b/tests/auto/qpixmap/convertFromImage/task31722_0/img1.png deleted file mode 100644 index 7991e9fb17..0000000000 Binary files a/tests/auto/qpixmap/convertFromImage/task31722_0/img1.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromImage/task31722_0/img2.png b/tests/auto/qpixmap/convertFromImage/task31722_0/img2.png deleted file mode 100644 index dca6d97dc3..0000000000 Binary files a/tests/auto/qpixmap/convertFromImage/task31722_0/img2.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromImage/task31722_1/img1.png b/tests/auto/qpixmap/convertFromImage/task31722_1/img1.png deleted file mode 100644 index 31e6e1aaa0..0000000000 Binary files a/tests/auto/qpixmap/convertFromImage/task31722_1/img1.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromImage/task31722_1/img2.png b/tests/auto/qpixmap/convertFromImage/task31722_1/img2.png deleted file mode 100644 index 0d48026898..0000000000 Binary files a/tests/auto/qpixmap/convertFromImage/task31722_1/img2.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp.ico b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp.ico deleted file mode 100644 index dbb55cd4db..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp.ico and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_16x16.png b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_16x16.png deleted file mode 100644 index f23f39818c..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_16x16.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_256x256.png b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_256x256.png deleted file mode 100644 index 293f1c5942..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_256x256.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_32x32.png b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_32x32.png deleted file mode 100644 index bfdb1fe035..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_32x32.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_48x48.png b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_48x48.png deleted file mode 100644 index 7dd2d13351..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_48x48.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp.ico b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp.ico deleted file mode 100644 index 4341a3355e..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp.ico and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_16x16.png b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_16x16.png deleted file mode 100644 index e9a995e19e..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_16x16.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_32x32.png b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_32x32.png deleted file mode 100644 index 41ef57f94d..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_32x32.png and /dev/null differ diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_48x48.png b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_48x48.png deleted file mode 100644 index 35d60d138b..0000000000 Binary files a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_48x48.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/designer.png b/tests/auto/qpixmap/images/designer.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/designer.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png b/tests/auto/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png deleted file mode 100644 index a4a19249c7..0000000000 Binary files a/tests/auto/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png b/tests/auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png deleted file mode 100644 index 1506af5a7e..0000000000 Binary files a/tests/auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_-10_dy_0_50_50_100_100.png b/tests/auto/qpixmap/images/dx_-10_dy_0_50_50_100_100.png deleted file mode 100644 index 8500ab1f5c..0000000000 Binary files a/tests/auto/qpixmap/images/dx_-10_dy_0_50_50_100_100.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.png deleted file mode 100644 index 2145c6124c..0000000000 Binary files a/tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png b/tests/auto/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_-10_50_50_100_100.png b/tests/auto/qpixmap/images/dx_0_dy_-10_50_50_100_100.png deleted file mode 100644 index 728ee79153..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_-10_50_50_100_100.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.png deleted file mode 100644 index e9d5850db7..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_0_50_50_100_100.png b/tests/auto/qpixmap/images/dx_0_dy_0_50_50_100_100.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_0_50_50_100_100.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_0_null.png b/tests/auto/qpixmap/images/dx_0_dy_0_null.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_0_null.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_10_50_50_100_100.png b/tests/auto/qpixmap/images/dx_0_dy_10_50_50_100_100.png deleted file mode 100644 index 7c09b17830..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_10_50_50_100_100.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.png deleted file mode 100644 index 70a63405e6..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_0_dy_1_null.png b/tests/auto/qpixmap/images/dx_0_dy_1_null.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_0_dy_1_null.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_10_dy_0_50_50_100_100.png b/tests/auto/qpixmap/images/dx_10_dy_0_50_50_100_100.png deleted file mode 100644 index 85abadaf98..0000000000 Binary files a/tests/auto/qpixmap/images/dx_10_dy_0_50_50_100_100.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.png deleted file mode 100644 index 3e03450c01..0000000000 Binary files a/tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_10_dy_10_50_50_100_100.png b/tests/auto/qpixmap/images/dx_10_dy_10_50_50_100_100.png deleted file mode 100644 index 315fbe087a..0000000000 Binary files a/tests/auto/qpixmap/images/dx_10_dy_10_50_50_100_100.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.png b/tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.png deleted file mode 100644 index d91dc71217..0000000000 Binary files a/tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_128_dy_128_64_64_128_128.png b/tests/auto/qpixmap/images/dx_128_dy_128_64_64_128_128.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_128_dy_128_64_64_128_128.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_128_dy_128_x_y_w_h.png b/tests/auto/qpixmap/images/dx_128_dy_128_x_y_w_h.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_128_dy_128_x_y_w_h.png and /dev/null differ diff --git a/tests/auto/qpixmap/images/dx_1_dy_0_null.png b/tests/auto/qpixmap/images/dx_1_dy_0_null.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/images/dx_1_dy_0_null.png and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_argb32.png b/tests/auto/qpixmap/loadFromData/designer_argb32.png deleted file mode 100644 index 55d8247cfc..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_argb32.png and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha.gif b/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha.gif deleted file mode 100644 index 26a6da33df..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha.gif and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha.png b/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha.png deleted file mode 100644 index 28cd2f06d1..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha.png and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif b/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif deleted file mode 100644 index 86a3a2e17d..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha.gif b/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha.gif deleted file mode 100644 index 49ec77b39b..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha.gif and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha.png b/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha.png deleted file mode 100644 index 09735a9752..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha.png and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif b/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif deleted file mode 100644 index f813c057d2..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_indexed8_with_alpha_animated.gif and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_rgb32.jpg b/tests/auto/qpixmap/loadFromData/designer_rgb32.jpg deleted file mode 100644 index 70f39c2154..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_rgb32.jpg and /dev/null differ diff --git a/tests/auto/qpixmap/loadFromData/designer_rgb32.png b/tests/auto/qpixmap/loadFromData/designer_rgb32.png deleted file mode 100644 index bca471d576..0000000000 Binary files a/tests/auto/qpixmap/loadFromData/designer_rgb32.png and /dev/null differ diff --git a/tests/auto/qpixmap/qpixmap.pro b/tests/auto/qpixmap/qpixmap.pro deleted file mode 100644 index fe156d547c..0000000000 --- a/tests/auto/qpixmap/qpixmap.pro +++ /dev/null @@ -1,33 +0,0 @@ -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/qpixmap/qpixmap.qrc b/tests/auto/qpixmap/qpixmap.qrc deleted file mode 100644 index 99fde61a29..0000000000 --- a/tests/auto/qpixmap/qpixmap.qrc +++ /dev/null @@ -1,29 +0,0 @@ - - - images/designer.png - images/dx_0_dy_0_50_50_100_100.png - images/dx_0_dy_0_null.png - images/dx_0_dy_0_x_y_w_h.png - images/dx_0_dy_-10_50_50_100_100.png - images/dx_0_dy_10_50_50_100_100.png - images/dx_0_dy_-10_x_y_w_h.png - images/dx_0_dy_10_x_y_w_h.png - images/dx_0_dy_-128_x_y_w_h.png - images/dx_0_dy_128_x_y_w_h.png - images/dx_0_dy_1_null.png - images/dx_-10_dy_0_50_50_100_100.png - images/dx_10_dy_0_50_50_100_100.png - images/dx_-10_dy_0_x_y_w_h.png - images/dx_10_dy_0_x_y_w_h.png - images/dx_-10_dy_-10_50_50_100_100.png - images/dx_10_dy_10_50_50_100_100.png - images/dx_-10_dy_-10_x_y_w_h.png - images/dx_10_dy_10_x_y_w_h.png - images/dx_-128_dy_0_x_y_w_h.png - images/dx_128_dy_0_x_y_w_h.png - images/dx_128_dy_128_64_64_128_128.png - images/dx_-128_dy_-128_x_y_w_h.png - images/dx_128_dy_128_x_y_w_h.png - images/dx_1_dy_0_null.png - - diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp deleted file mode 100644 index 38858e5503..0000000000 --- a/tests/auto/qpixmap/tst_qpixmap.cpp +++ /dev/null @@ -1,1787 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#ifdef Q_WS_WIN -#include -#endif - -#ifdef Q_WS_QWS -#include -#endif - -#ifdef Q_OS_SYMBIAN -#include -#include -#include -#include -#if !defined(QT_NO_OPENVG) -#include -#include -#endif -#endif - -#ifdef Q_WS_X11 -#include -#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("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("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("img1"); - QTest::addColumn("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("input"); - QTest::addColumn("dx"); - QTest::addColumn("dy"); - QTest::addColumn("rect"); - QTest::addColumn("exposed"); - QTest::addColumn("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("pixel"); - QTest::addColumn("syscolor"); - QTest::addColumn("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("pixmap"); - QTest::addColumn("mask"); - QTest::addColumn("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(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("red"); - QTest::addColumn("green"); - QTest::addColumn("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("image"); - QTest::addColumn("width"); - QTest::addColumn("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("format"); - QTest::addColumn("width"); - QTest::addColumn("height"); - QTest::addColumn("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("red"); - QTest::addColumn("green"); - QTest::addColumn("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 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("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("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("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(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(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(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/qpixmapcache/.gitignore b/tests/auto/qpixmapcache/.gitignore deleted file mode 100644 index 2bc572c2dd..0000000000 --- a/tests/auto/qpixmapcache/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpixmapcache diff --git a/tests/auto/qpixmapcache/qpixmapcache.pro b/tests/auto/qpixmapcache/qpixmapcache.pro deleted file mode 100644 index 1ffafd6c25..0000000000 --- a/tests/auto/qpixmapcache/qpixmapcache.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += gui-private -SOURCES += tst_qpixmapcache.cpp - - - diff --git a/tests/auto/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/qpixmapcache/tst_qpixmapcache.cpp deleted file mode 100644 index 9f7192dc1c..0000000000 --- a/tests/auto/qpixmapcache/tst_qpixmapcache.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#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(&key)); -} - -static QPixmapCache::KeyData** getPrivateRef(QPixmapCache::Key &key) -{ - return (reinterpret_cast(&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 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 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 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/qpixmapfilter/noise.png b/tests/auto/qpixmapfilter/noise.png deleted file mode 100644 index 1bebaf528e..0000000000 Binary files a/tests/auto/qpixmapfilter/noise.png and /dev/null differ diff --git a/tests/auto/qpixmapfilter/qpixmapfilter.pro b/tests/auto/qpixmapfilter/qpixmapfilter.pro deleted file mode 100644 index 21e10b7ab9..0000000000 --- a/tests/auto/qpixmapfilter/qpixmapfilter.pro +++ /dev/null @@ -1,13 +0,0 @@ -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/qpixmapfilter/tst_qpixmapfilter.cpp b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp deleted file mode 100644 index 5634285ad4..0000000000 --- a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -//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/qpolygon/.gitignore b/tests/auto/qpolygon/.gitignore deleted file mode 100644 index 7c9d48c848..0000000000 --- a/tests/auto/qpolygon/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpointarray diff --git a/tests/auto/qpolygon/qpolygon.pro b/tests/auto/qpolygon/qpolygon.pro deleted file mode 100644 index 186b704d17..0000000000 --- a/tests/auto/qpolygon/qpolygon.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qpolygon.cpp - -unix:!mac:!symbian:LIBS+=-lm - - diff --git a/tests/auto/qpolygon/tst_qpolygon.cpp b/tests/auto/qpolygon/tst_qpolygon.cpp deleted file mode 100644 index f47073a048..0000000000 --- a/tests/auto/qpolygon/tst_qpolygon.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - -#include -#include - - - -//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(0,0) << QPoint(10,10) << QPoint(-10,10)); - QPolygon p2(QVector() << 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/qprinter/.gitignore b/tests/auto/qprinter/.gitignore deleted file mode 100644 index 85de0e9675..0000000000 --- a/tests/auto/qprinter/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -tqpluginloader/st_qprinter -silly -test.pdf - diff --git a/tests/auto/qprinter/qprinter.pro b/tests/auto/qprinter/qprinter.pro deleted file mode 100644 index cbe4ad7986..0000000000 --- a/tests/auto/qprinter/qprinter.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += printsupport widgets -SOURCES += tst_qprinter.cpp - -mac*:CONFIG+=insignificant_test diff --git a/tests/auto/qprinter/tst_qprinter.cpp b/tests/auto/qprinter/tst_qprinter.cpp deleted file mode 100644 index a6b6895981..0000000000 --- a/tests/auto/qprinter/tst_qprinter.cpp +++ /dev/null @@ -1,1044 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef Q_WS_WIN -#include -#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("orientation"); - QTest::addColumn("withPainter"); - QTest::addColumn("resolution"); - QTest::addColumn("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("orientation"); - QTest::addColumn("fullpage"); - QTest::addColumn("pagesize"); - QTest::addColumn("width"); - QTest::addColumn("height"); - QTest::addColumn("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("resolution"); - QTest::addColumn("pageSize"); - QTest::addColumn("widthMMAfter"); - QTest::addColumn("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("left"); - QTest::addColumn("top"); - QTest::addColumn("right"); - QTest::addColumn("bottom"); - QTest::addColumn("unit"); - - QTest::newRow("data0") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Millimeter); - QTest::newRow("data1") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Point); - QTest::newRow("data2") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Inch); - QTest::newRow("data3") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Pica); - QTest::newRow("data4") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(QPrinter::Didot); - QTest::newRow("data5") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast(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(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 ø 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 ø 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/qprinterinfo/.gitignore b/tests/auto/qprinterinfo/.gitignore deleted file mode 100644 index fcef7c1997..0000000000 --- a/tests/auto/qprinterinfo/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qprinterinfo diff --git a/tests/auto/qprinterinfo/qprinterinfo.pro b/tests/auto/qprinterinfo/qprinterinfo.pro deleted file mode 100644 index 1bf799d6ce..0000000000 --- a/tests/auto/qprinterinfo/qprinterinfo.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qprinterinfo.cpp - -QT += printsupport network - -DEFINES += QT_USE_USING_NAMESPACE - diff --git a/tests/auto/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/qprinterinfo/tst_qprinterinfo.cpp deleted file mode 100644 index 7e5da4a6f8..0000000000 --- a/tests/auto/qprinterinfo/tst_qprinterinfo.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -#ifndef QT_NO_PRINTER -#include - -#ifdef Q_OS_UNIX -# include -# include -# include -#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 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 printers = QPrinterInfo::availablePrinters(); - - QCOMPARE(printers.size(), sysPrinters.size()); - - QHash 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 > hardSizes; - hardSizes - << QList() - << QList() - ; - 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 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 sizes = printers[i].supportedPaperSizes(); - qSort(sizes); - qSort(hardSizes[j]); - QCOMPARE(sizes, hardSizes[j]); - } - } - } -} - -void tst_QPrinterInfo::testConstructors() -{ - QList prns(QPrinterInfo::availablePrinters()); - - for (int c = 0; c < prns.size(); ++c) { - QList list1, list2; - list1 = prns[c].supportedPaperSizes(); - QPrinter pr(prns[c]); - list2 = QPrinterInfo(pr).supportedPaperSizes(); - QCOMPARE(list2, list1); - } -} - -void tst_QPrinterInfo::testAssignment() -{ - QList 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/qquaternion/qquaternion.pro b/tests/auto/qquaternion/qquaternion.pro deleted file mode 100644 index 6f740cfd42..0000000000 --- a/tests/auto/qquaternion/qquaternion.pro +++ /dev/null @@ -1,2 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qquaternion.cpp diff --git a/tests/auto/qquaternion/tst_qquaternion.cpp b/tests/auto/qquaternion/tst_qquaternion.cpp deleted file mode 100644 index 7bc50efeeb..0000000000 --- a/tests/auto/qquaternion/tst_qquaternion.cpp +++ /dev/null @@ -1,888 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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("x"); - QTest::addColumn("y"); - QTest::addColumn("z"); - QTest::addColumn("w"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("w1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("w2"); - QTest::addColumn("x3"); - QTest::addColumn("y3"); - QTest::addColumn("z3"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("w1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("w1"); - QTest::addColumn("factor"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("angle1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("angle2"); - QTest::addColumn("t"); - QTest::addColumn("x3"); - QTest::addColumn("y3"); - QTest::addColumn("z3"); - QTest::addColumn("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(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(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() == QMetaType::QQuaternion); -} - -QTEST_APPLESS_MAIN(tst_QQuaternion) - -#include "tst_qquaternion.moc" diff --git a/tests/auto/qrawfont/qrawfont.pro b/tests/auto/qrawfont/qrawfont.pro deleted file mode 100644 index 1f73055b00..0000000000 --- a/tests/auto/qrawfont/qrawfont.pro +++ /dev/null @@ -1,14 +0,0 @@ -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/qrawfont/testfont.ttf b/tests/auto/qrawfont/testfont.ttf deleted file mode 100644 index d6042d2e58..0000000000 Binary files a/tests/auto/qrawfont/testfont.ttf and /dev/null differ diff --git a/tests/auto/qrawfont/testfont_bold_italic.ttf b/tests/auto/qrawfont/testfont_bold_italic.ttf deleted file mode 100644 index 9f65ac8df7..0000000000 Binary files a/tests/auto/qrawfont/testfont_bold_italic.ttf and /dev/null differ diff --git a/tests/auto/qrawfont/tst_qrawfont.cpp b/tests/auto/qrawfont/tst_qrawfont.cpp deleted file mode 100644 index 1c18f2f1e8..0000000000 --- a/tests/auto/qrawfont/tst_qrawfont.cpp +++ /dev/null @@ -1,897 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include - -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("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("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("fileName"); - QTest::addColumn("expectedFamilyName"); - QTest::addColumn("style"); - QTest::addColumn("weight"); - QTest::addColumn("hintingPreference"); - QTest::addColumn("unitsPerEm"); - QTest::addColumn("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 glyphIndices = font.glyphIndexesForString(QLatin1String("Foobar")); - QVector expectedGlyphIndices; - expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; - - QCOMPARE(glyphIndices, expectedGlyphIndices); -} - -void tst_QRawFont::advances_data() -{ - QTest::addColumn("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 glyphIndices; - glyphIndices << 44 << 83 << 83 << 70 << 69 << 86; // "Foobar" - - bool supportsSubPixelPositions = font_d->fontEngine->supportsSubPixelPositions(); - QVector advances = font.advancesForGlyphIndexes(glyphIndices); - for (int i=0; i 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 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 expectedGlyphIndices; - expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; - - QCOMPARE(glyphs.glyphIndexes(), expectedGlyphIndices); - - QVERIFY(fontDatabase.removeApplicationFont(id)); -} - -void tst_QRawFont::fontTable_data() -{ - QTest::addColumn("tagName"); - QTest::addColumn("hintingPreference"); - QTest::addColumn("offset"); - QTest::addColumn("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(table.constData() + offset); - QCOMPARE(*value, expectedValue); -} - -typedef QList WritingSystemList; -Q_DECLARE_METATYPE(WritingSystemList) - -void tst_QRawFont::supportedWritingSystems_data() -{ - QTest::addColumn("fileName"); - QTest::addColumn("writingSystems"); - QTest::addColumn("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::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::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("fileName"); - QTest::addColumn("hintingPreference"); - QTest::addColumn("character"); - QTest::addColumn("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("fileName"); - QTest::addColumn("hintingPreference"); - QTest::addColumn("ucs4"); - QTest::addColumn("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("fileName"); - QTest::addColumn("hintingPreference"); - QTest::addColumn("familyName"); - QTest::addColumn("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("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("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("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 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("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/qregion/.gitignore b/tests/auto/qregion/.gitignore deleted file mode 100644 index 8be21c3736..0000000000 --- a/tests/auto/qregion/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qregion diff --git a/tests/auto/qregion/qregion.pro b/tests/auto/qregion/qregion.pro deleted file mode 100644 index 8dbb4844a0..0000000000 --- a/tests/auto/qregion/qregion.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) - -QT += gui-private - -SOURCES += tst_qregion.cpp - - - diff --git a/tests/auto/qregion/tst_qregion.cpp b/tests/auto/qregion/tst_qregion.cpp deleted file mode 100644 index 58d2034e41..0000000000 --- a/tests/auto/qregion/tst_qregion.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -#include -#include -#include -#ifdef Q_WS_X11 -#include -#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) -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("pa"); - QTest::addColumn("isEmpty"); - QTest::addColumn("numRects"); - QTest::addColumn >("rects"); - - QPolygon pa; - - - QTest::newRow("no points") << pa << true << 0 << QVector(); - pa = QPolygon() << QPoint(10,10); - QTest::newRow("one point") << pa << true << 0 << QVector(); - pa = QPolygon() << QPoint(10,10) << QPoint(10,20); - QTest::newRow("two points, horizontal") << pa << true << 0 << QVector(); - - pa = QPolygon() << QPoint(10,10) << QPoint(20,10); - QTest::newRow("two points, vertical") << pa << true << 0 << QVector(); - - pa = QPolygon() << QPoint(10,10) << QPoint(20,20); - QTest::newRow("two points, diagonal") << pa << true << 0 << QVector(); - - pa = QPolygon() << QPoint(10,10) << QPoint(15,15) << QPoint(10,15) << QPoint(10, 10) ; - QVector 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("r1"); - QTest::addColumn("r2"); - QTest::addColumn("intersects"); - // QTest::addColumn("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("r1"); - QTest::addColumn("r2"); - QTest::addColumn("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("region"); - QTest::addColumn("rect"); - QTest::addColumn("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("r1"); - QTest::addColumn("r2"); - QTest::addColumn("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 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("dest"); - QTest::addColumn("subtract"); - QTest::addColumn("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 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("r1"); - QTest::addColumn("r2"); - QTest::addColumn("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 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("dest"); - QTest::addColumn("arg"); - QTest::addColumn("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 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("region"); - QTest::addColumn("expected"); - - QTest::newRow("empty") << QRegion() << 0; - QTest::newRow("rect") << QRegion(10, 10, 10, 10) << 1; - - QRegion dest; - QVector 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("region"); - - QTest::newRow("QRegion") << QRegion(); - - QVector 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(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("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 ®ion); -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/qshortcut/.gitignore b/tests/auto/qshortcut/.gitignore deleted file mode 100644 index 3a17eb18e3..0000000000 --- a/tests/auto/qshortcut/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qshortcut diff --git a/tests/auto/qshortcut/qshortcut.pro b/tests/auto/qshortcut/qshortcut.pro deleted file mode 100644 index 3f68d2377e..0000000000 --- a/tests/auto/qshortcut/qshortcut.pro +++ /dev/null @@ -1,11 +0,0 @@ -load(qttest_p4) - -# Project Configuration ---------------------------------------------- -INCLUDEPATH += ../ - -# Normal Test Files -------------------------------------------------- -QT += widgets -HEADERS += -SOURCES += tst_qshortcut.cpp - - diff --git a/tests/auto/qshortcut/tst_qshortcut.cpp b/tests/auto/qshortcut/tst_qshortcut.cpp deleted file mode 100644 index a78e8cfd27..0000000000 --- a/tests/auto/qshortcut/tst_qshortcut.cpp +++ /dev/null @@ -1,1272 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 shortcuts; - QTextEdit *edit; - QString sbText; - Result ambigResult; -}; - -QT_BEGIN_NAMESPACE -template<> struct QMetaTypeId -{ enum { Defined = 1 }; static inline int qt_metatype_id() { return QMetaType::Int; } }; -template<> struct QMetaTypeId -{ enum { Defined = 1 }; static inline int qt_metatype_id() { return QMetaType::Int; } }; -template<> struct QMetaTypeId -{ 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(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(e); - if (ke->modifiers() && ke->key() > Qt::Key_Any - && ke->key() < Qt::Key_ydiaeresis) { - if (ke->modifiers() == Qt::ControlModifier) - insertPlainText(QString("").arg(char(ke->key()))); - else if (ke->modifiers() == Qt::AltModifier) - insertPlainText(QString("").arg(char(ke->key()))); - else if (ke->modifiers() == Qt::ShiftModifier) - insertPlainText(QString("").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("action"); - QTest::addColumn("testWidget"); - QTest::addColumn("txt"); - QTest::addColumn("k1"); - QTest::addColumn("c1"); - QTest::addColumn("k2"); - QTest::addColumn("c2"); - QTest::addColumn("k3"); - QTest::addColumn("c3"); - QTest::addColumn("k4"); - QTest::addColumn("c4"); - QTest::addColumn("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<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("")); - - sendKeyEvents(edit, Qt::Key_A, 'a'); // Send key to edit - QCOMPARE( currentResult, NoResult ); - QCOMPARE( ambigResult, NoResult ); - QVERIFY(edit->toPlainText().endsWith("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("")); - 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(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(k1), c, b1); - QTest::sendKeyEvent(QTest::Release, w, static_cast(k1), c, b1); - } - - if (k2 || c2.toAscii()) { - QString c(c2.unicode() == QChar::Null ? QString() : QString(c2)); - QTest::sendKeyEvent(QTest::Press, w, static_cast(k2), c, b2); - QTest::sendKeyEvent(QTest::Release, w, static_cast(k2), c, b2); - } - - if (k3 || c3.toAscii()) { - QString c(c3.unicode() == QChar::Null ? QString() : QString(c3)); - QTest::sendKeyEvent(QTest::Press, w, static_cast(k3), c, b3); - QTest::sendKeyEvent(QTest::Release, w, static_cast(k3), c, b3); - } - - if (k4 || c4.toAscii()) { - QString c(c4.unicode() == QChar::Null ? QString() : QString(c4)); - QTest::sendKeyEvent(QTest::Press, w, static_cast(k4), c, b4); - QTest::sendKeyEvent(QTest::Release, w, static_cast(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/qstatictext/qstatictext.pro b/tests/auto/qstatictext/qstatictext.pro deleted file mode 100644 index c8c36f81f7..0000000000 --- a/tests/auto/qstatictext/qstatictext.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets widgets-private -QT += core core-private gui gui-private -SOURCES += tst_qstatictext.cpp - diff --git a/tests/auto/qstatictext/tst_qstatictext.cpp b/tests/auto/qstatictext/tst_qstatictext.cpp deleted file mode 100644 index 79cbd692ea..0000000000 --- a/tests/auto/qstatictext/tst_qstatictext.cpp +++ /dev/null @@ -1,870 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -#include -#include - -#include -#include - -// #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(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("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("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("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("FOObar"); - 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; xXXXXX"); - staticText.setTextFormat(Qt::RichText); - p.drawStaticText(0, 0, staticText); - } - - QImage img = image.toImage(); - for (int x=0; xXXXXX"); - staticText.setTextFormat(Qt::RichText); - p.drawStaticText(0, 0, staticText); - } - - QImage img = image.toImage(); - for (int x=0; xitemCount, 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("AB"); - 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/qsyntaxhighlighter/.gitignore b/tests/auto/qsyntaxhighlighter/.gitignore deleted file mode 100644 index 3efe6efbe5..0000000000 --- a/tests/auto/qsyntaxhighlighter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsyntaxhighlighter diff --git a/tests/auto/qsyntaxhighlighter/qsyntaxhighlighter.pro b/tests/auto/qsyntaxhighlighter/qsyntaxhighlighter.pro deleted file mode 100644 index 30fb3a5283..0000000000 --- a/tests/auto/qsyntaxhighlighter/qsyntaxhighlighter.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qsyntaxhighlighter.cpp - - diff --git a/tests/auto/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp b/tests/auto/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp deleted file mode 100644 index 24ade2dc91..0000000000 --- a/tests/auto/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -//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 &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 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 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 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 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 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/qtextblock/.gitignore b/tests/auto/qtextblock/.gitignore deleted file mode 100644 index 648a522140..0000000000 --- a/tests/auto/qtextblock/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextblock diff --git a/tests/auto/qtextblock/qtextblock.pro b/tests/auto/qtextblock/qtextblock.pro deleted file mode 100644 index d50ef5ca78..0000000000 --- a/tests/auto/qtextblock/qtextblock.pro +++ /dev/null @@ -1,9 +0,0 @@ -load(qttest_p4) - -QT += widgets widgets-private -QT += core-private gui-private - -SOURCES += tst_qtextblock.cpp - - - diff --git a/tests/auto/qtextblock/tst_qtextblock.cpp b/tests/auto/qtextblock/tst_qtextblock.cpp deleted file mode 100644 index b04a6f5559..0000000000 --- a/tests/auto/qtextblock/tst_qtextblock.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#define protected public -#include -#undef protected -#include -#ifndef Q_WS_WIN -#include -#endif - - - -#include -#include - - -//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) 'helloworld' - * 2) '' - * (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/qtextcursor/.gitignore b/tests/auto/qtextcursor/.gitignore deleted file mode 100644 index b9b1f8e7d6..0000000000 --- a/tests/auto/qtextcursor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextcursor diff --git a/tests/auto/qtextcursor/qtextcursor.pro b/tests/auto/qtextcursor/qtextcursor.pro deleted file mode 100644 index 828b90ca16..0000000000 --- a/tests/auto/qtextcursor/qtextcursor.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qtextcursor.cpp - - - diff --git a/tests/auto/qtextcursor/tst_qtextcursor.cpp b/tests/auto/qtextcursor/tst_qtextcursor.cpp deleted file mode 100644 index 2b0ba422e0..0000000000 --- a/tests/auto/qtextcursor/tst_qtextcursor.cpp +++ /dev/null @@ -1,1862 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include -#include -#include - -//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) - -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("sl"); - QTest::addColumn >("movement"); - QTest::addColumn("finalPos"); - - QTest::newRow("startBlock1") << QStringList("Happy happy happy joy joy joy") - << (QList() << QVariant(QTextCursor::StartOfBlock)) << 0; - QTest::newRow("endBlock1") << QStringList("Happy happy happy joy joy joy") - << (QList() << QVariant(QTextCursor::StartOfBlock) - << QVariant(QTextCursor::EndOfBlock)) << 29; - QTest::newRow("startBlock2") << QStringList("Happy happy happy joy joy joy") - << (QList() << QVariant(QTextCursor::StartOfBlock) - << QVariant(QTextCursor::EndOfBlock) - << QVariant(QTextCursor::StartOfBlock)) << 0; - QTest::newRow("endBlock2") << QStringList("Happy happy happy joy joy joy") - << (QList() << 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(QTextCursor::StartOfBlock)) - << 18; - QTest::newRow("multiBlock2") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::StartOfBlock) - << QVariant(QTextCursor::EndOfBlock)) - << 29; - QTest::newRow("multiBlock3") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::StartOfBlock) - << QVariant(QTextCursor::StartOfBlock)) - << 18; - QTest::newRow("multiBlock4") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::Start) - << QVariant(QTextCursor::EndOfBlock)) - << 17; - QTest::newRow("multiBlock5") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::Start) - << QVariant(QTextCursor::EndOfBlock) - << QVariant(QTextCursor::EndOfBlock)) - << 17; - QTest::newRow("multiBlock6") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::End) - << QVariant(QTextCursor::StartOfBlock)) - << 18; - QTest::newRow("multiBlock7") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousBlock)) - << 0; - QTest::newRow("multiBlock8") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousBlock) - << QVariant(QTextCursor::EndOfBlock)) - << 17; - QTest::newRow("multiBlock9") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousBlock) - << QVariant(QTextCursor::NextBlock)) - << 18; - QTest::newRow("multiBlock10") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousBlock) - << QVariant(QTextCursor::NextBlock) - << QVariant(QTextCursor::NextBlock)) - << 18; - QTest::newRow("multiBlock11") << (QStringList() << QString("Happy happy happy") - << QString("Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousBlock) - << QVariant(QTextCursor::NextBlock) - << QVariant(QTextCursor::EndOfBlock)) - << 29; - QTest::newRow("PreviousWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousWord)) - << 26; - QTest::newRow("PreviousWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousWord) - << QVariant(QTextCursor::PreviousWord)) - << 22; - QTest::newRow("EndWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousWord) - << QVariant(QTextCursor::PreviousWord) - << QVariant(QTextCursor::EndOfWord)) - << 25; - QTest::newRow("NextWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousWord) - << QVariant(QTextCursor::PreviousWord) - << QVariant(QTextCursor::NextWord)) - << 26; - QTest::newRow("NextWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::Start) - << QVariant(QTextCursor::NextWord) - << QVariant(QTextCursor::EndOfWord)) - << 11; - QTest::newRow("StartWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousWord) - << QVariant(QTextCursor::PreviousWord) - << QVariant(QTextCursor::StartOfWord)) - << 22; - QTest::newRow("StartWord3") << (QStringList() << QString("Happy happy happy Joy Joy Joy")) - << (QList() << QVariant(QTextCursor::Start) - << QVariant(QTextCursor::NextWord) - << QVariant(QTextCursor::EndOfWord) - << QVariant(QTextCursor::StartOfWord)) - << 6; - - QTest::newRow("PreviousCharacter") << (QStringList() << QString("Happy happy Joy Joy")) - << (QList() << QVariant(QTextCursor::PreviousCharacter) - << QVariant(QTextCursor::PreviousCharacter)) - << 17; -} - -void tst_QTextCursor::navigation2() -{ - QFETCH(QStringList, sl); - QFETCH(QList, 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("

                just a simple paragraph.

                " - "" - "" - "" - "" - "
                Cell number 1another cellprevious
                is
                empty
                row 2foo barlast cell
                row 3a
                clear(); - doc->setHtml("tr>
                ab
                c
                "); - 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 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 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("text"); - QTest::addColumn("initialPosition"); - QTest::addColumn("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("text"); - QTest::addColumn("position"); - QTest::addColumn("anchor"); - QTest::addColumn("modifyPosition"); - QTest::addColumn("modifyAnchor"); - QTest::addColumn("insertText"); - QTest::addColumn("expectedPosition"); - QTest::addColumn("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("input"); - QTest::addColumn("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/qtextdocument/.gitignore b/tests/auto/qtextdocument/.gitignore deleted file mode 100644 index c14f0e2422..0000000000 --- a/tests/auto/qtextdocument/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextdocument diff --git a/tests/auto/qtextdocument/common.h b/tests/auto/qtextdocument/common.h deleted file mode 100644 index 1eaefdbfbe..0000000000 --- a/tests/auto/qtextdocument/common.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -#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 lastDocumentLengths; -}; - -#endif diff --git a/tests/auto/qtextdocument/qtextdocument.pro b/tests/auto/qtextdocument/qtextdocument.pro deleted file mode 100644 index 69517589cc..0000000000 --- a/tests/auto/qtextdocument/qtextdocument.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += core-private gui-private xml -HEADERS += common.h -SOURCES += tst_qtextdocument.cpp - - diff --git a/tests/auto/qtextdocument/tst_qtextdocument.cpp b/tests/auto/qtextdocument/tst_qtextdocument.cpp deleted file mode 100644 index c98a703acc..0000000000 --- a/tests/auto/qtextdocument/tst_qtextdocument.cpp +++ /dev/null @@ -1,2788 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 var1 = new MyAbstractTextDocumentLayout(0); - obj1.setDocumentLayout(var1); - QCOMPARE(static_cast(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("\n" - "" - "\n"); - htmlHead = htmlHead.arg(defaultFont.family()).arg(defaultFont.pointSizeF()).arg(defaultFont.weight() * 8).arg((defaultFont.italic() ? "italic" : "normal")); - - htmlTail = QString(""); -} - -void tst_QTextDocument::cleanup() -{ - cursor = QTextCursor(); - delete doc; - doc = 0; -} - -void tst_QTextDocument::isEmpty() -{ - QVERIFY(doc->isEmpty()); -} - -void tst_QTextDocument::find_data() -{ - QTest::addColumn("haystack"); - QTest::addColumn("needle"); - QTest::addColumn("flags"); - QTest::addColumn("from"); - QTest::addColumn("anchor"); - QTest::addColumn("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("haystack"); - QTest::addColumn("needle"); - QTest::addColumn("flags"); - QTest::addColumn("from"); - QTest::addColumn("anchor"); - QTest::addColumn("position"); - - // match integers 0 to 99 - QTest::newRow("1") << "23" << "^\\d\\d?$" << int(QTextDocument::FindCaseSensitively) << 0 << 0 << 2; - // match ampersands but not & - QTest::newRow("2") << "His & 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("Foobar Foobar Foobar Foobar"); - - 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;lineIdxlineCount();++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("stylesheet"); - QTest::addColumn("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("" - "" - "
                " - "Foobar" - "
                " - "" - "").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[] = "\n" - "\n" - ""; - QVERIFY(Qt::mightBeRichText(QString::fromLatin1(qtDocuHeader))); - QTest::addColumn("input"); - QTest::addColumn("result"); - - QTest::newRow("documentation-header") << QString("\n" - "\n" - "") - << true; - QTest::newRow("br-nospace") << QString("Test
                new line") << true; - QTest::newRow("br-space") << QString("Test
                new line") << true; - QTest::newRow("br-invalidspace") << QString("Test
                new line") << false; - QTest::newRow("invalid closing tag") << QString("Test
                ("input"); - QTest::addColumn("expectedOutput"); - - { - CREATE_DOC_AND_CURSOR(); - - cursor.insertText("Blah"); - - QTest::newRow("simple") << QTextDocumentFragment(&doc) << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - cursor.insertText("&<>"); - - QTest::newRow("entities") << QTextDocumentFragment(&doc) << QString("

                &<>

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setFontFamily("Times"); - cursor.insertText("Blah", fmt); - - QTest::newRow("font-family") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setFontFamily("Foo's Family"); - cursor.insertText("Blah", fmt); - - QTest::newRow("font-family-with-quotes1") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setFontFamily("Foo\"s Family"); - cursor.insertText("Blah", fmt); - - QTest::newRow("font-family-with-quotes2") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextBlockFormat fmt; - fmt.setNonBreakableLines(true); - cursor.insertBlock(fmt); - cursor.insertText("Blah"); - - QTest::newRow("pre") << QTextDocumentFragment(&doc) - << - QString("EMPTYBLOCK") + - QString("
                Blah
                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setFontPointSize(40); - cursor.insertText("Blah", fmt); - - QTest::newRow("font-size") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setProperty(QTextFormat::FontSizeIncrement, 2); - cursor.insertText("Blah", fmt); - - QTest::newRow("logical-font-size") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - 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("

                Foo

                \n

                Blub

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextBlockFormat fmt; - fmt.setLayoutDirection(Qt::RightToLeft); - cursor.insertBlock(fmt); - cursor.insertText("Blah"); - - QTest::newRow("rtl") << QTextDocumentFragment(&doc) - << - QString("EMPTYBLOCK") + - QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextBlockFormat fmt; - fmt.setAlignment(Qt::AlignJustify); - cursor.insertBlock(fmt); - cursor.insertText("Blah"); - - QTest::newRow("blockalign") << QTextDocumentFragment(&doc) - << - QString("EMPTYBLOCK") + - QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextBlockFormat fmt; - fmt.setAlignment(Qt::AlignCenter); - cursor.insertBlock(fmt); - cursor.insertText("Blah"); - - QTest::newRow("blockalign2") << QTextDocumentFragment(&doc) - << - QString("EMPTYBLOCK") + - QString("

                Blah

                "); - } - - { - 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("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextBlockFormat fmt; - fmt.setBackground(QColor("#0000ff")); - cursor.insertBlock(fmt); - cursor.insertText("Blah"); - - QTest::newRow("bgcolor") << QTextDocumentFragment(&doc) - << QString("EMPTYBLOCK") + - QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setFontWeight(40); - cursor.insertText("Blah", fmt); - - QTest::newRow("font-weight") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setFontItalic(true); - cursor.insertText("Blah", fmt); - - QTest::newRow("font-italic") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setFontUnderline(true); - fmt.setFontOverline(false); - cursor.insertText("Blah", fmt); - - QTest::newRow("text-decoration-1") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setForeground(QColor("#00ff00")); - cursor.insertText("Blah", fmt); - - QTest::newRow("color") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setBackground(QColor("#00ff00")); - cursor.insertText("Blah", fmt); - - QTest::newRow("span-bgcolor") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setVerticalAlignment(QTextCharFormat::AlignSubScript); - cursor.insertText("Blah", fmt); - - QTest::newRow("valign-sub") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setVerticalAlignment(QTextCharFormat::AlignSuperScript); - cursor.insertText("Blah", fmt); - - QTest::newRow("valign-super") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextCharFormat fmt; - fmt.setAnchor(true); - fmt.setAnchorName("blub"); - cursor.insertText("Blah", fmt); - - QTest::newRow("named anchor") << QTextDocumentFragment(&doc) - << QString("

                Blah

                "); - } - - { - 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("

                Blah

                "); - } - - { - 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("

                Blah

                "); - } - - { - 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("

                Blah

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - cursor.insertTable(2, 2); - - QTest::newRow("simpletable") << QTextDocumentFragment(&doc) - << QString("" - "\n\n\n" - "\n\n\n" - "
                "); - } - - { - 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("" - "\n\n\n" - "
                "); - } - - { - 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("" - "\n\n\n" - "\n\n\n" - "
                "); - } - - { - 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("" - "\n\n\n" - "\n\n\n" - "
                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextTableFormat fmt; - fmt.setHeaderRowCount(2); - cursor.insertTable(4, 2, fmt); - - QTest::newRow("tableheader") << QTextDocumentFragment(&doc) - << QString("" - "\n\n\n" - "\n\n\n" - "\n\n\n" - "\n\n\n" - "
                "); - } - - { - 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("" - "\n\n\n" - "\n\n\n" - "
                \n\n\n
                \n

                Hey

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextTableFormat fmt; - QVector 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("" - "\n\n\n\n" - "
                "); - } - - // ### 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("" - "\n\n" - "
                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - // ### fixme: use programmatic api as soon as we can create floats through it - const char html[] = "BlahBlubb"; - - QTest::newRow("image") << QTextDocumentFragment::fromHtml(QString::fromLatin1(html)) - << QString("

                BlahBlubb

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextImageFormat fmt; - fmt.setName("foo"); - fmt.setVerticalAlignment(QTextCharFormat::AlignMiddle); - cursor.insertImage(fmt); - - QTest::newRow("image-malign") << QTextDocumentFragment(&doc) - << QString("

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextImageFormat fmt; - fmt.setName("foo"); - fmt.setVerticalAlignment(QTextCharFormat::AlignTop); - cursor.insertImage(fmt); - - QTest::newRow("image-malign") << QTextDocumentFragment(&doc) - << QString("

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextImageFormat fmt; - fmt.setName("foo"); - cursor.insertImage(fmt); - cursor.insertImage(fmt); - - QTest::newRow("2images") << QTextDocumentFragment(&doc) - << QString("

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QString txt = QLatin1String("Blah"); - txt += QChar::LineSeparator; - txt += QLatin1String("Bar"); - cursor.insertText(txt); - - QTest::newRow("linebreaks") << QTextDocumentFragment(&doc) - << QString("

                Blah
                Bar

                "); - } - - { - 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("

                Blah

                "); - } - - { - 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("
                • Blubb
                • \n
                • Blah
                "); - } - - { - 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("
                • Blubb
                • \n
                • Blah
                "); - } - - { - 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("

                Test

                "); - } - - { - 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("
                • Blah
                "); - } - - { - 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

                Test

                "); - } - - { - 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("

                Test

                "); - } - - { - QTest::newRow("horizontal-ruler") << QTextDocumentFragment::fromHtml("
                ") - << - QString("EMPTYBLOCK") + - QString("
                "); - } - { - QTest::newRow("horizontal-ruler-with-width") << QTextDocumentFragment::fromHtml("
                ") - << - QString("EMPTYBLOCK") + - QString("
                "); - } - { - 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("\n\n
                \n

                Hello World

                "); - } - - { - 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("

                Test

                "); - QTest::newRow("nostylebrush") << QTextDocumentFragment(&doc) << QString("

                Test

                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - QTextTable *table = cursor.insertTable(2, 2); - table->mergeCells(0, 0, 1, 2); - QTextTableFormat fmt = table->format(); - QVector 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("" - "\n\n" - "\n\n\n" - "
                "); - } - - { - 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("

                Blah

                \n" - "

                Green " - "yellow" - " green

                "); - } - - { - 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("

                Blah

                "); - } - - { - 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("" - "\n\n" - "\n" - "\n\n" - "\n" - "
                \n" - "

                Blah

                "); - } - - { - 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("" - "\n\n" - "\n" - "\n\n" - "\n" - "
                \n" - "

                Blah

                "); - } - - { - 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("" - "\n\n\n" - "\n\n\n" - "
                "); - } - - { - CREATE_DOC_AND_CURSOR(); - - cursor.insertBlock(); - cursor.insertText("Foo"); - - cursor.block().setUserState(42); - - QTest::newRow("userstate") << QTextDocumentFragment(&doc) - << QString("EMPTYBLOCK") + - QString("

                Foo

                "); - } - - { - 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("

                Foo

                " - "\n

                Bar

                " - "\n\n\n
                "); - } - - { - 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("
                • Blah
                "); - } -} - -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", "


                \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("

                text text

                "); // 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("
                foo
                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(""), QString("")); - expected += QString("

                TestBlah

                ") + 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(""), QString("")); - expected += QString("

                Test

                ") + 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("\n" - "" - "\n" - "

                Blah

                " - ""); - - 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("\n" - "\n
                \n" - "

                Blah

                "); - - 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("

                Foo

                Bar

                Baz

                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(""); - 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(parent()); - QTextBlock block = doc->findBlock(from); - - QTestDocumentLayout *lout = qobject_cast(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(parent()); - QTextBlock block = doc->findBlock(from); - QTextCursor cursor(block); - - QTestDocumentLayout *lout = qobject_cast(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("" + title + "Hrm"); - 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("Mooo"); - 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("Mooo"); - 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 World"); - QCOMPARE(doc->toPlainText(), QLatin1String("Hello World")); -} - -void tst_QTextDocument::deleteTextObjectsOnClear() -{ - QPointer 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("

                test"); - QTextBlockFormat fmt = doc->begin().blockFormat(); - QVERIFY(fmt.background().color() == QColor("green")); - - doc->clear(); - cursor.insertHtml("

                test"); - fmt = doc->begin().blockFormat(); - QVERIFY(fmt.background().color() == QColor("green")); - - QTextDocument *clone = doc->clone(); - QCOMPARE(clone->defaultStyleSheet(), sheet); - cursor = QTextCursor(clone); - cursor.insertHtml("

                test"); - fmt = clone->begin().blockFormat(); - QVERIFY(fmt.background().color() == QColor("green")); - delete clone; - - cursor = QTextCursor(doc); - cursor.insertHtml("

                test"); - fmt = doc->begin().blockFormat(); - QVERIFY(fmt.background().color() == QColor("green")); - - doc->clear(); - cursor.insertHtml("

                test"); - fmt = doc->begin().blockFormat(); - QVERIFY(fmt.background().color() == QColor("red")); - - doc->clear(); - doc->setDefaultStyleSheet("invalid style sheet...."); - cursor.insertHtml("

                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("") - .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("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("

                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("
                Blah
                "); - -void tst_QTextDocument::backgroundImage_checkExpectedHtml(const QTextDocument &doc) -{ - QString expectedHtml("\n" - "" - "\n" - "" - "\n\n
                " - "\n

                Blah

                " - "
                "); - - 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("original"); - QTest::addColumn("expected"); - - QTest::newRow("1") << "Hello World\n" << "Hello World\n"; - QTest::newRow("2") << "#include " << "#include <QtCore>"; - QTest::newRow("3") << "

                plop -->

                " - << "<p class="cool"><a href="http://example.com/?foo=bar&amp;bar=foo">plop --&gt; </a></p>"; - QTest::newRow("4") << QString::fromUtf8("<\320\222\321\201>") << QString::fromUtf8("<\320\222\321\201>"); -} - -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/qtextdocumentfragment/.gitignore b/tests/auto/qtextdocumentfragment/.gitignore deleted file mode 100644 index 5c569834d3..0000000000 --- a/tests/auto/qtextdocumentfragment/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextdocumentfragment diff --git a/tests/auto/qtextdocumentfragment/qtextdocumentfragment.pro b/tests/auto/qtextdocumentfragment/qtextdocumentfragment.pro deleted file mode 100644 index e6ddd45f85..0000000000 --- a/tests/auto/qtextdocumentfragment/qtextdocumentfragment.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) - -QT += core-private gui-private - -SOURCES += tst_qtextdocumentfragment.cpp - - - diff --git a/tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp deleted file mode 100644 index 68c7a285ef..0000000000 --- a/tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp +++ /dev/null @@ -1,4030 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include - - -#include - -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 -#include -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[] = "" -"" -" " -" " -" " -" " -" " -" " -"
                First Cell" -" Second Cell" -"
                Third Cell" -"
                Fourth Cell" -" Fifth Cell" -"
                "; - 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[] = "" -"" -" " -" " -" " -"
                First Cell
                "; - 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("
                HeyBlah")); - QVERIFY(!fragment.isEmpty()); -} - -void tst_QTextDocumentFragment::tableImport2() -{ - { - const char html[] = "" - "" - "" - "" - "
                First CellSecond Cell
                Third CellFourth Cell
                "; - - 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[] = "" - "" - "" - "" - "
                First CellSecond Cell
                Third Cell" - " " - " " - " " - " " - "
                First Nested CellSecond Nested Cell
                Third Nested CellFourth Nested Cell
                Fifth Nested CellSixth Nested Cell
                "; - - 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[] = "" - "" - "
                First CellSecond Cell" - "
                Third CellFourth Cell" - "
                "; - - 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[] = "" - "" - "
                First CellSecond Cell" - "
                Third CellFourth Cell" - "
                "; - - 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[] = "

                "; - QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(QString::fromLatin1(html)); - QVERIFY(!fragment.isEmpty()); -} - -void tst_QTextDocumentFragment::tableImport4() -{ - const char html[] = "" - "" - "" - "
                blah
                blahblah
                "; - 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[] = "" - "" - " " - " " - " " - " " - "" - "" - " " - " " - "" - "
                FooBarBlehBlub
                AhhGah
                "; - - 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("TestBlah")); - QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), QString::fromLatin1("Test")); -} - -void tst_QTextDocumentFragment::html_listIndents1() -{ - const char html[] = "
                • Hey
                • Hah
                "; - 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[] = "
                • Hey

                  Hah

                "; - 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[] = "
                • Hah

                "; - 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[] = "
                • Foo

                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[] = "

                • Foo

                • Bar
                "; - 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[] = "
                • Outer List
                  • Nested Item 1
                "; - 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[] = "

                Test

                "; - 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[] = "

                Test

                "; - 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[] = "
                cell onecell two
                cell threecell four
                "; - 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[] = "
                Test\r\n
                Bar"; - setHtml(QString::fromLatin1(html)); - QVERIFY(!doc->toPlainText().contains('\r')); - QCOMPARE(doc->toPlainText(), QString("Test\nBar")); -} - -void tst_QTextDocumentFragment::unorderedListEnumeration() -{ - const char html[] = "
                    • Blah
                  "; - setHtml(QString::fromLatin1(html)); - cursor.movePosition(QTextCursor::End); - QVERIFY(cursor.currentList()); - QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListCircle); - - const char html2[] = "
                      • Blah
                    "; - 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[] = "

                    "; - setHtml(QString::fromLatin1(html)); - QVERIFY(!doc->isEmpty()); -} - -void tst_QTextDocumentFragment::ignoreStyleTags() -{ - const char html[] = "Hello"; - setHtml(QString::fromLatin1(html)); - QCOMPARE(doc->toPlainText(), QString("Hello")); -} - -void tst_QTextDocumentFragment::hrefAnchor() -{ - { - const char html[] = "blah"; - 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[] = "blah"; - 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[] = "ablah"; - 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[] = "

                    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("Text"); - - 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[] = "
                    Hey
                    "; - 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[] = "
                    Hey
                    "; - 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[] = "

                    Hey

                    "; - 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[] = "
                    "; - setHtml(QString::fromLatin1(html)); - QVERIFY(true); // don't crash with a failing assertion -} - -void tst_QTextDocumentFragment::emptyTable2() -{ - const char html[] = "

                    blah

                    "; - setHtml(QString::fromLatin1(html)); - QVERIFY(true); // don't crash with a failing assertion -} - -void tst_QTextDocumentFragment::emptyTable3() -{ - const char html[] = "
                    Foobar
                    "; - 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[] = "
                    Blah
                    Hm
                    "; - 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[] = "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[] = "

                    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[] = "

                    Blah

                    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 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[] = "Blah"; - 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[] = "Link"; - cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); - QVERIFY(true); - } - - { - const char html[] = "Test

                    "; - cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); - QCOMPARE(cursor.blockFormat().indent(), 3); -} - -void tst_QTextDocumentFragment::html_listIndent() -{ - const char html[] = "
                    • Blah
                    "; - cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); - QVERIFY(cursor.currentList()); - QCOMPARE(cursor.currentList()->format().indent(), 4); -} - -void tst_QTextDocumentFragment::html_whitespace_data() -{ - QTest::addColumn("html"); - QTest::addColumn("expectedPlainText"); - - QTest::newRow("1") << QString("This is some test with spaces between words") - << QString("This is some test with spaces between words"); - - QTest::newRow("2") << QString(" nowhitespacehereplease") - << QString::fromLatin1("nowhitespacehereplease"); - - QTest::newRow("3") << QString(" white space here ") - << QString::fromLatin1(" white space here "); - - QTest::newRow("4") << QString(" white space here ") - << QString::fromLatin1(" white space here "); - - QTest::newRow("5") << QString("
                    One Two Three\n" - "Four") - << QString::fromLatin1("One Two Three Four"); - - QTest::newRow("6") << QString("

                    Testing: BoldItalic Italic

                    ") - << QString("Testing: BoldItalic Italic"); - - QTest::newRow("7") << QString("
                    Blah
                    Foo
                    ") - << QString("\nBlah\n\nFoo\n"); - - QTest::newRow("8") << QString("
                    Blah
                    Blub") - << QString("\nBlah\nBlub"); - - QTest::newRow("task116492") << QString("

                    a b c

                    ") - << QString("a b c"); - - QTest::newRow("task121653") << QString("abc def") - << QString("abc def"); - - QTest::newRow("task122650") << QString("

                    Foo

                    Bar") - << QString("Foo\nBar"); - - QTest::newRow("task122650-2") << QString("

                    Foo

                    Bar") - << QString("Foo \nBar"); - - QTest::newRow("task122650-3") << QString("Before

                    \nTest
                    ") - << QString("Before\nTest"); - - QTest::newRow("br-with-whitespace") << QString("Foo
                    \nBlah") - << QString("Foo\nBlah"); - - QTest::newRow("collapse-p-with-newline") << QString("Foo

                    \n

                    \n

                    \n

                    \n

                    \n

                    \nBar") - << QString("Foo\nBar"); - - QTest::newRow("table") << QString("
                    Blah
                    \nTest") - << QString("\nBlah\nTest"); - - QTest::newRow("table2") << QString("\n
                    \nTest\n
                    ") - << QString("\nTest\n"); - - QTest::newRow("table3") << QString("
                    \nTest\n
                    \n \n
                    ") - << 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("") - + text - + QString(""); - - 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("" - "blah blah") - + text - + QString(""); - - 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("") - + text - + QString(""); - - cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); - - QCOMPARE(doc->toPlainText(), text); -} - -void tst_QTextDocumentFragment::html_listStart1() -{ - // don't create a block for the

                      element, even if there's some whitespace between - // it and the
                    • - const char html[] = "
                      • list item
                        • "; - 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[] = "
                            buggy, but text should appear
                          • list item
                            • "; - cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0])))); - - QCOMPARE(doc->blockCount(), 2); -} - -void tst_QTextDocumentFragment::html_cssMargin() -{ - const char html[] = "

                              Test

                              "; - 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[] = "@"; - cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); - QCOMPARE(doc->begin().begin().fragment().text(), QString("@")); -} - -void tst_QTextDocumentFragment::html_decEntities() -{ - const char html[] = "@"; - cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); - QCOMPARE(doc->begin().begin().fragment().text(), QString("@")); -} - -void tst_QTextDocumentFragment::html_thCentered() -{ - const char html[] = "
                              This should be centered
                              "; - 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[] = "" - "
                              1. elem 1
                              " - "
                              1. elem 1
                              " - ""; - - 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[] = "
                              • Foo
                              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[] = "Subby"; - const char superHtml[] = "Super"; - const char subHtmlCss[] = "Subby"; - const char superHtmlCss[] = "Super"; - const char alignmentInherited[] = "Subby"; - - 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[] = "Blue"; - setHtml(color); - QVERIFY(cursor.charFormat().foreground().color() == Qt::blue); - - const char rgbColor[] = "Blue"; - setHtml(rgbColor); - QVERIFY(cursor.charFormat().foreground().color() == Qt::blue); -} - -void tst_QTextDocumentFragment::obeyFragmentMarkersInImport() -{ - const char html[] = "This leading text should not appearTextThis 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%1This 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[] = "

                               

                              Two paragraphs

                              "; - 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[] = "

                              One paragraph

                              "; - setHtml(html); - - QCOMPARE(doc->blockCount(), 1); - QCOMPARE(cursor.blockFormat().leftMargin(), qreal(0)); - - const char html2[] = "

                              One paragraph"; - setHtml(html2); - QCOMPARE(doc->blockCount(), 1); - QCOMPARE(cursor.blockFormat().leftMargin(), qreal(0)); - - const char html3[] = "

                              Foo

                              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[] = "

                                Foo

                              Bar

                              "; - - setHtml(html); - - QCOMPARE(doc->blockCount(), 2); - - cursor = QTextCursor(doc); - QCOMPARE(cursor.block().next().blockFormat().indent(), 0); -} - -void tst_QTextDocumentFragment::html_emptyParagraphs4() -{ - const char html[] = "

                              foo

                              bar

                              "; - 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[] = "

                              foo

                              bar

                              "; - 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[] = "

                              Hah

                              "; - setHtml(html); - - QVERIFY(cursor.charFormat().foreground().color() == Qt::blue); - QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue); -} - -void tst_QTextDocumentFragment::html_fontSize() -{ - const char html[] = "Hah"; - setHtml(html); - - QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), -1); -} - -void tst_QTextDocumentFragment::html_fontSizeAdjustment() -{ - const char html[] = "Hah"; - 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[] = "Foo"; - setHtml(html); - - QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 50); - - const char html2[] = "Foo"; - setHtml(html2); - - QCOMPARE(cursor.charFormat().property(QTextFormat::FontPixelSize).toInt(), 50); - - const char html3[] = "Foo"; - setHtml(html3); - - QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), 1); -} - -void tst_QTextDocumentFragment::html_cssShorthandFont() -{ - { - const char html[] = "Foo"; - setHtml(html); - QCOMPARE(cursor.charFormat().property(QTextFormat::FontPixelSize).toInt(), 50); - QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("sans-serif")); - } - { - const char html[] = "Foo"; - setHtml(html); - QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 50); - QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("sans-serif")); - } - { - const char html[] = "Foo"; - setHtml(html); - QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 7); - QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("Times New Roman")); - } - { - const char html[] = "Foo"; - setHtml(html); - QCOMPARE(cursor.charFormat().property(QTextFormat::FontWeight).toInt(), int(QFont::Bold)); - QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 7); - } - { - const char html[] = "Foo"; - 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[] = "Foo"; - doc->setHtml(html); - - QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue); -} - -void tst_QTextDocumentFragment::html_qtBgColor() -{ - const char html[] = "Foo"; - doc->setHtml(html); - - QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue); -} - -void tst_QTextDocumentFragment::html_bodyBackground() -{ - const char html[] = "Foo"; - doc->setHtml(html); - - QVERIFY(doc->rootFrame()->frameFormat().background().style() == Qt::TexturePattern); -} - -void tst_QTextDocumentFragment::html_tableCellBackground() -{ - const char html[] = "
                              Foo
                              "; - 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[] = "Foo"; - doc->setHtml(html); - - QVERIFY(doc->rootFrame()->frameFormat().background().style() == Qt::TexturePattern); -} - -void tst_QTextDocumentFragment::css_tableCellBackground() -{ - const char html[] = "
                              Foo
                              "; - 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[] = "" - "" - "
                              Foo
                              "; - 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[] = "
                              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[] = "abcd"; - 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[] = "

                              • Foo
                                • In nested list
                              • Last item

                              "; - 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[] = "

                              Blah

                              "; - 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[] = "FooBar"; - 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[] = "

                              Foo"; - 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("

                              ") + input + QString::fromLatin1("

                              "); - 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[] = "BlahFoo"; - 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[] = "

                              "; - setHtml(html); - QCOMPARE(doc->blockCount(), 1); -} - -void tst_QTextDocumentFragment::html_closingTag() -{ - const char html[] = "text"; - setHtml(html); - - QVERIFY(!cursor.charFormat().fontItalic()); -} - -void tst_QTextDocumentFragment::html_anchorAroundImage() -{ - const char html[] = ""; - 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[] = "
                              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 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 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[] = "

                              Foo

                              "; - cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html))); - - QList 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[] = "
                              This should be centered
                              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[] = "
                              Test

                              Second Parag

                              "; - 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[] = "
                              Blah
                              "; - 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[] = "" -"" -" " -" " -" " -" " -" " -" " -" " -"
                              First Cell
                              Second CellThird Cell
                              "; - - 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("Hello World"); - 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("

                              foo

                              bar"); - QCOMPARE(doc->blockCount(), 2); -} - -void tst_QTextDocumentFragment::html_quotedFontFamily() -{ - setHtml("
                              Test
                              "); - QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar")); - - setHtml("
                              Test
                              "); - QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar")); - - setHtml("
                              Test
                              "); - QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar")); - - setHtml("
                              Test
                              "); - QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar")); - - setHtml("
                              Test
                              "); - 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(""); - QVERIFY(html.contains(str)); -} - -void tst_QTextDocumentFragment::html_spanBackgroundColor() -{ - setHtml("Foo"); - QVERIFY(doc->begin().begin().fragment().charFormat().background().color() == QColor(Qt::blue)); -} - -void tst_QTextDocumentFragment::html_brokenTitle_data() -{ - QTest::addColumn("html"); - QTest::addColumn("expectedBody"); - QTest::addColumn("expectedTitle"); - - QTest::newRow("brokentitle") << QString("Foo<b>bar</b>Blah") - << QString("Blah") << QString("Foo"); - QTest::newRow("brokentitle2") << QString("Foo<font color=red>i</font>t<font color=red>i</font>BlubBlah") - << QString("Blah") << QString("Foo"); - QTest::newRow("entities") << QString("Foo<barBlah") - << QString("Blah") << QString("FooFoo</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> 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>TestBlah")); - 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("html"); - QTest::addColumn("code"); - - for (int i = 0; i < MAX_ENTITY; ++i) { - QTest::newRow(entities[i].name) << QString("
                              &") + QString::fromLatin1(entities[i].name) + QString(";
                              ") - << 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("Blah")); - QCOMPARE(doc->toPlainText(), QString("Blah")); -} - -void tst_QTextDocumentFragment::html_directionWithHtml() -{ - doc->setHtml(QString::fromLatin1("

                              Test

                              RTL

                              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("

                              Test

                              RTL

                              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("HelloWorld"); - QCOMPARE(doc->toPlainText(), QString("HelloWorld")); -} - -void tst_QTextDocumentFragment::html_importImageWithoutAspectRatio() -{ - doc->setHtml(""); - 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(""); - 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(""); - 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 Test\nText then selecting all and copying will - // result in the following text on the clipboard (for text/html) - doc->setHtml(QString::fromLatin1("Test\nText\n\n")); - QCOMPARE(doc->toPlainText(), QString::fromLatin1("Test Text ")); -} - -QTEST_MAIN(tst_QTextDocumentFragment) -#include "tst_qtextdocumentfragment.moc" diff --git a/tests/auto/qtextdocumentlayout/.gitignore b/tests/auto/qtextdocumentlayout/.gitignore deleted file mode 100644 index 80671c70d0..0000000000 --- a/tests/auto/qtextdocumentlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextdocumentlayout diff --git a/tests/auto/qtextdocumentlayout/qtextdocumentlayout.pro b/tests/auto/qtextdocumentlayout/qtextdocumentlayout.pro deleted file mode 100644 index 32b05ce061..0000000000 --- a/tests/auto/qtextdocumentlayout/qtextdocumentlayout.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtextdocumentlayout.cpp - - diff --git a/tests/auto/qtextdocumentlayout/tst_qtextdocumentlayout.cpp b/tests/auto/qtextdocumentlayout/tst_qtextdocumentlayout.cpp deleted file mode 100644 index f5c72cd4d0..0000000000 --- a/tests/auto/qtextdocumentlayout/tst_qtextdocumentlayout.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include - -//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("
                              Column 1
                              Data

                              "); - QString html_text("bla bla bla bla bla bla bla bla
                              "); - QString html_end("
                              Column 1
                              Data
                              "); - - 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("
                              hello hello hello" - "thisisabigwordthisisabigwordthisisabigwordthisisabigwordthisisabigword" - "hello hello hello
                              "); - 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 = - "
                              "; - - 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/qtextformat/.gitignore b/tests/auto/qtextformat/.gitignore deleted file mode 100644 index 3e3be422fe..0000000000 --- a/tests/auto/qtextformat/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextformat diff --git a/tests/auto/qtextformat/qtextformat.pro b/tests/auto/qtextformat/qtextformat.pro deleted file mode 100644 index 30f6e50c61..0000000000 --- a/tests/auto/qtextformat/qtextformat.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qtextformat.h -############################################################ - -load(qttest_p4) - -SOURCES += tst_qtextformat.cpp - - diff --git a/tests/auto/qtextformat/tst_qtextformat.cpp b/tests/auto/qtextformat/tst_qtextformat.cpp deleted file mode 100644 index b235b112b6..0000000000 --- a/tests/auto/qtextformat/tst_qtextformat.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//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 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 &tabs, const QList &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 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 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/qtextlayout/.gitignore b/tests/auto/qtextlayout/.gitignore deleted file mode 100644 index 11758969db..0000000000 --- a/tests/auto/qtextlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextlayout diff --git a/tests/auto/qtextlayout/qtextlayout.pro b/tests/auto/qtextlayout/qtextlayout.pro deleted file mode 100644 index 6bf0065e4f..0000000000 --- a/tests/auto/qtextlayout/qtextlayout.pro +++ /dev/null @@ -1,12 +0,0 @@ -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/qtextlayout/tst_qtextlayout.cpp b/tests/auto/qtextlayout/tst_qtextlayout.cpp deleted file mode 100644 index 2414ab3e37..0000000000 --- a/tests/auto/qtextlayout/tst_qtextlayout.cpp +++ /dev/null @@ -1,1506 +0,0 @@ -/**************************************************************************** -** -** 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 - - - -#include -#include - -#include - - -#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("text"); - QTest::addColumn("startPos"); - QTest::addColumn("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 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 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 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 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 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 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/qtextlist/.gitignore b/tests/auto/qtextlist/.gitignore deleted file mode 100644 index f1c4f6acab..0000000000 --- a/tests/auto/qtextlist/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextlist diff --git a/tests/auto/qtextlist/qtextlist.pro b/tests/auto/qtextlist/qtextlist.pro deleted file mode 100644 index f66fb96dd0..0000000000 --- a/tests/auto/qtextlist/qtextlist.pro +++ /dev/null @@ -1,9 +0,0 @@ -load(qttest_p4) - -QT += core-private gui-private - -SOURCES += tst_qtextlist.cpp -HEADERS += ../qtextdocument/common.h - - - diff --git a/tests/auto/qtextlist/tst_qtextlist.cpp b/tests/auto/qtextlist/tst_qtextlist.cpp deleted file mode 100644 index 164dd6fc68..0000000000 --- a/tests/auto/qtextlist/tst_qtextlist.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#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 - - /* - * 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 - - /* - * 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 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("format"); - QTest::addColumn("number"); - QTest::addColumn("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/qtextobject/.gitignore b/tests/auto/qtextobject/.gitignore deleted file mode 100644 index 6a3da09549..0000000000 --- a/tests/auto/qtextobject/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextobject diff --git a/tests/auto/qtextobject/qtextobject.pro b/tests/auto/qtextobject/qtextobject.pro deleted file mode 100644 index e87a364ab6..0000000000 --- a/tests/auto/qtextobject/qtextobject.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qtextobject.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qtextobject.cpp - - diff --git a/tests/auto/qtextobject/tst_qtextobject.cpp b/tests/auto/qtextobject/tst_qtextobject.cpp deleted file mode 100644 index 0d1773e3fa..0000000000 --- a/tests/auto/qtextobject/tst_qtextobject.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include - -//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/qtextodfwriter/.gitignore b/tests/auto/qtextodfwriter/.gitignore deleted file mode 100644 index 791445d7a9..0000000000 --- a/tests/auto/qtextodfwriter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextodfwriter diff --git a/tests/auto/qtextodfwriter/qtextodfwriter.pro b/tests/auto/qtextodfwriter/qtextodfwriter.pro deleted file mode 100644 index f5e2c09fa0..0000000000 --- a/tests/auto/qtextodfwriter/qtextodfwriter.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qtextodfwriter.cpp - -!symbian:DEFINES += SRCDIR=\\\"$$PWD\\\" -symbian:INCLUDEPATH+=$$[QT_INSTALL_PREFIX]/include/QtGui/private diff --git a/tests/auto/qtextodfwriter/tst_qtextodfwriter.cpp b/tests/auto/qtextodfwriter/tst_qtextodfwriter.cpp deleted file mode 100644 index 765afce66e..0000000000 --- a/tests/auto/qtextodfwriter/tst_qtextodfwriter.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_SYMBIAN -#define SRCDIR "." -#endif - -#include - -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(" 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("input"); - QTest::addColumn("xml"); - - QTest::newRow("empty") << "" << - ""; - QTest::newRow("spaces") << "foobar word" << - "foobar word"; - QTest::newRow("starting spaces") << " starting spaces" << - "starting spaces"; - QTest::newRow("trailing spaces") << "trailing spaces " << - "trailing spaces "; - QTest::newRow("tab") << "word\ttab x" << - "wordtab x"; - QTest::newRow("tab2") << "word\t\ttab\tx" << - "wordtabx"; - QTest::newRow("misc") << "foobar word\ttab x" << - "foobar wordtab x"; - QTest::newRow("misc2") << "\t \tFoo" << - " Foo"; - QTest::newRow("linefeed") << QString("line1%1line2").arg(QChar(0x2028)) << - "line1line2"; - QTest::newRow("spaces") << "The quick brown fox jumped over the lazy dog" << - "The quick brown fox jumped over the lazy dog"; -} - -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("htmlInput"); - QTest::addColumn("cursorPosition"); - QTest::addColumn("xml"); - - QString text1 = "NormalbolditalicBold/Italic"; - QTest::newRow("normal") << text1 << 2 << - ""; - QTest::newRow("bold") << text1 << 10 << - ""; - QTest::newRow("italic") << text1 << 14 << - ""; - QTest::newRow("bold+italic") << text1 << 25 << - ""; - QString colorText = " Color Text "; - QTest::newRow("green/red") << colorText << 3 << - ""; - -} - -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 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( - "" - "" - "" - "" - "" - "" - "" - ""); - 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( - "" - "" - //"" - //"")+ QChar(0x25cf) + QString::fromLatin1("" // 0x25cf is a bullet - "ListItem 2" - "" - ""); - - 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( - "" - "" - //"" - //"")+ QChar(0x25cf) + QString::fromLatin1("" // 0x25cf is a bullet - "Cars" - "" - "" - "" - "" - "Model T" - "" - "" - "Kitt" - "" - "" - "" - "" - "Animals" - "" - "" - "" - "" - "Foo" - "" - "" - "Bar"); - - // 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("= 0); - QVERIFY(result.indexOf("= 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( - "foo" - "Bar" - "" - "baz" - "" - ""); - - 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( - "" - "" - "" - "" - "" - "a" - "" - "" - "b" - "" - "" - "" - "" - "c" - "" - "" - "d" - "" - "" - "" - "" - "e" - "" - "" - "" - ""); - - QCOMPARE(getContentFromXml(), xml); -} - -QTEST_MAIN(tst_QTextOdfWriter) -#include "tst_qtextodfwriter.moc" diff --git a/tests/auto/qtextpiecetable/.gitignore b/tests/auto/qtextpiecetable/.gitignore deleted file mode 100644 index 720b01f79f..0000000000 --- a/tests/auto/qtextpiecetable/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextpiecetable diff --git a/tests/auto/qtextpiecetable/qtextpiecetable.pro b/tests/auto/qtextpiecetable/qtextpiecetable.pro deleted file mode 100644 index cfbbe2bca5..0000000000 --- a/tests/auto/qtextpiecetable/qtextpiecetable.pro +++ /dev/null @@ -1,9 +0,0 @@ -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/qtextpiecetable/tst_qtextpiecetable.cpp b/tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp deleted file mode 100644 index ddaf84134d..0000000000 --- a/tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp +++ /dev/null @@ -1,1155 +0,0 @@ -/**************************************************************************** -** -** 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 - -#define protected public - -#include -#undef protected -#include -#include -#include -#include -#include -#include -#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 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 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/qtextscriptengine/.gitignore b/tests/auto/qtextscriptengine/.gitignore deleted file mode 100644 index e51a335099..0000000000 --- a/tests/auto/qtextscriptengine/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextscriptengine diff --git a/tests/auto/qtextscriptengine/generate/generate.pro b/tests/auto/qtextscriptengine/generate/generate.pro deleted file mode 100644 index 354e0e5cdf..0000000000 --- a/tests/auto/qtextscriptengine/generate/generate.pro +++ /dev/null @@ -1,14 +0,0 @@ -###################################################################### -# 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/qtextscriptengine/generate/main.cpp b/tests/auto/qtextscriptengine/generate/main.cpp deleted file mode 100644 index 06caa34b4d..0000000000 --- a/tests/auto/qtextscriptengine/generate/main.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -#define private public -#include -#include -#include -#include -#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 diff --git a/tests/auto/qtextscriptengine/qtextscriptengine.pro b/tests/auto/qtextscriptengine/qtextscriptengine.pro deleted file mode 100644 index 0f5076e2ed..0000000000 --- a/tests/auto/qtextscriptengine/qtextscriptengine.pro +++ /dev/null @@ -1,7 +0,0 @@ -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/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp deleted file mode 100644 index cbed675cb7..0000000000 --- a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp +++ /dev/null @@ -1,1304 +0,0 @@ -/**************************************************************************** -** -** 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 - -#ifdef Q_WS_X11 -#undef private -#endif - -#include - - - -#if defined(Q_WS_X11) || defined(Q_WS_MAC) -#define private public -#include -#include -#undef private -#else -#include -#include -#endif - -#include -#include - - - - - -//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("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/qtexttable/.gitignore b/tests/auto/qtexttable/.gitignore deleted file mode 100644 index 876aa75c0a..0000000000 --- a/tests/auto/qtexttable/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtexttable diff --git a/tests/auto/qtexttable/qtexttable.pro b/tests/auto/qtexttable/qtexttable.pro deleted file mode 100644 index 611b706fc4..0000000000 --- a/tests/auto/qtexttable/qtexttable.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtexttable.cpp - - - diff --git a/tests/auto/qtexttable/tst_qtexttable.cpp b/tests/auto/qtexttable/tst_qtexttable.cpp deleted file mode 100644 index 83343811d8..0000000000 --- a/tests/auto/qtexttable/tst_qtexttable.cpp +++ /dev/null @@ -1,1004 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include -#include - -//TESTED_FILES= - -typedef QList 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(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 table1 = QTextCursor(cursor).insertTable(4, 4); - QPointer table2 = QTextCursor(cursor).insertTable(4, 4); - QPointer 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 table1 = QTextCursor(cursor).insertTable(4, 4); - QPointer table2 = QTextCursor(cursor).insertTable(4, 4); - QPointer 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("rows"); - QTest::addColumn("columns"); - QTest::addColumn >("merge"); - QTest::addColumn >("insert"); - - QTest::newRow("2x3, merge two, insert one") << 2 << 3 << (QList() << 1 << 2 << 2) - << (QList() << 1 << 1) ; - QTest::newRow("3x4, merge three, insert one") << 3 << 4 << (QList() << 1 << 3 << 3) - << (QList() << 1 << 1) ; - QTest::newRow("4x3, merge two, insert two") << 4 << 3 << (QList() << 1 << 4 << 2) - << (QList() << 1 << 2) ; - QTest::newRow("4x4, merge middle two, insert one") << 4 << 4 << (QList() << 1 << 4 << 2) - << (QList() << 1 << 1) ; -} - -void tst_QTextTable::QTBUG11282_insertBeforeMergedEnding() -{ - QFETCH(int, rows); - QFETCH(int, columns); - QFETCH(QList, merge); - QFETCH(QList, 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/qtouchevent/qtouchevent.pro b/tests/auto/qtouchevent/qtouchevent.pro deleted file mode 100644 index 55f99b6cdd..0000000000 --- a/tests/auto/qtouchevent/qtouchevent.pro +++ /dev/null @@ -1,3 +0,0 @@ -SOURCES=tst_qtouchevent.cpp -TARGET=tst_qtouchevent -QT += testlib widgets diff --git a/tests/auto/qtouchevent/tst_qtouchevent.cpp b/tests/auto/qtouchevent/tst_qtouchevent.cpp deleted file mode 100644 index f0347e39ff..0000000000 --- a/tests/auto/qtouchevent/tst_qtouchevent.cpp +++ /dev/null @@ -1,1398 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -class tst_QTouchEventWidget : public QWidget -{ -public: - QList 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(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(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(event)->touchPoints(); - event->setAccepted(acceptTouchEnd); - if (deleteInTouchEnd) - delete this; - break; - default: - return QWidget::event(event); - } - return true; - } -}; - -class tst_QTouchEventGraphicsItem : public QGraphicsItem -{ -public: - QList 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(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(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(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 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() << 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 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() << 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 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() << 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() << 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 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() << 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() << 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() << 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() << 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() << 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() << 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 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 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 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 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 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 pl = leftWidget, pc = centerWidget, pr = rightWidget; - - QList 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/qtransform/.gitignore b/tests/auto/qtransform/.gitignore deleted file mode 100644 index f1da0161e7..0000000000 --- a/tests/auto/qtransform/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtransform diff --git a/tests/auto/qtransform/qtransform.pro b/tests/auto/qtransform/qtransform.pro deleted file mode 100644 index 92bef8ce38..0000000000 --- a/tests/auto/qtransform/qtransform.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -HEADERS += -SOURCES += tst_qtransform.cpp - -unix:!mac:!symbian:LIBS+=-lm - - diff --git a/tests/auto/qtransform/tst_qtransform.cpp b/tests/auto/qtransform/tst_qtransform.cpp deleted file mode 100644 index f8319c9e13..0000000000 --- a/tests/auto/qtransform/tst_qtransform.cpp +++ /dev/null @@ -1,807 +0,0 @@ -/**************************************************************************** -** -** 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 -#include "qtransform.h" -#include -#include -#include - -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("matrix"); - QTest::addColumn("src"); - QTest::addColumn("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("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/qvectornd/qvectornd.pro b/tests/auto/qvectornd/qvectornd.pro deleted file mode 100644 index 6346199444..0000000000 --- a/tests/auto/qvectornd/qvectornd.pro +++ /dev/null @@ -1,2 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qvectornd.cpp diff --git a/tests/auto/qvectornd/tst_qvectornd.cpp b/tests/auto/qvectornd/tst_qvectornd.cpp deleted file mode 100644 index 37c1949dc2..0000000000 --- a/tests/auto/qvectornd/tst_qvectornd.cpp +++ /dev/null @@ -1,2142 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -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("x"); - QTest::addColumn("y"); - QTest::addColumn("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("x"); - QTest::addColumn("y"); - QTest::addColumn("z"); - QTest::addColumn("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("x"); - QTest::addColumn("y"); - QTest::addColumn("z"); - QTest::addColumn("w"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("x3"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("x3"); - QTest::addColumn("y3"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("w1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("w2"); - QTest::addColumn("x3"); - QTest::addColumn("y3"); - QTest::addColumn("z3"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("x3"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("x3"); - QTest::addColumn("y3"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("w1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("w2"); - QTest::addColumn("x3"); - QTest::addColumn("y3"); - QTest::addColumn("z3"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("factor"); - QTest::addColumn("x2"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("factor"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("w1"); - QTest::addColumn("factor"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("x3"); - QTest::addColumn("y3"); - QTest::addColumn("z3"); - QTest::addColumn("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("x1"); // Point on plane - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("x2"); // Normal to plane - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("x3"); // Point to test for distance - QTest::addColumn("y3"); - QTest::addColumn("z3"); - QTest::addColumn("x4"); // Second point on plane - QTest::addColumn("y4"); - QTest::addColumn("z4"); - QTest::addColumn("x5"); // Third point on plane - QTest::addColumn("y5"); - QTest::addColumn("z5"); - QTest::addColumn("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("x1"); // Point on line - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("x2"); // Direction of the line - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("x3"); // Point to test for distance - QTest::addColumn("y3"); - QTest::addColumn("z3"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("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("x1"); - QTest::addColumn("y1"); - QTest::addColumn("z1"); - QTest::addColumn("w1"); - QTest::addColumn("x2"); - QTest::addColumn("y2"); - QTest::addColumn("z2"); - QTest::addColumn("w2"); - QTest::addColumn("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(obj.property("vector2D")); - QCOMPARE(v2.x(), (qreal)1.0f); - QCOMPARE(v2.y(), (qreal)2.0f); - - QVector3D v3 = qVariantValue(obj.property("vector3D")); - QCOMPARE(v3.x(), (qreal)3.0f); - QCOMPARE(v3.y(), (qreal)4.0f); - QCOMPARE(v3.z(), (qreal)5.0f); - - QVector4D v4 = qVariantValue(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(obj.property("vector2D")); - QCOMPARE(v2.x(), (qreal)-1.0f); - QCOMPARE(v2.y(), (qreal)-2.0f); - - v3 = qVariantValue(obj.property("vector3D")); - QCOMPARE(v3.x(), (qreal)-3.0f); - QCOMPARE(v3.y(), (qreal)-4.0f); - QCOMPARE(v3.z(), (qreal)-5.0f); - - v4 = qVariantValue(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() == QMetaType::QVector2D); - QVERIFY(qMetaTypeId() == QMetaType::QVector3D); - QVERIFY(qMetaTypeId() == QMetaType::QVector4D); -} - -QTEST_APPLESS_MAIN(tst_QVectorND) - -#include "tst_qvectornd.moc" diff --git a/tests/auto/qvolatileimage/qvolatileimage.pro b/tests/auto/qvolatileimage/qvolatileimage.pro deleted file mode 100644 index 45d80b85f2..0000000000 --- a/tests/auto/qvolatileimage/qvolatileimage.pro +++ /dev/null @@ -1,10 +0,0 @@ -load(qttest_p4) - -QT += gui-private widgets - -SOURCES += tst_qvolatileimage.cpp - -symbian { - TARGET.EPOCHEAPSIZE = 0x200000 0x800000 - LIBS += -lfbscli -} diff --git a/tests/auto/qvolatileimage/tst_qvolatileimage.cpp b/tests/auto/qvolatileimage/tst_qvolatileimage.cpp deleted file mode 100644 index bacca66dcd..0000000000 --- a/tests/auto/qvolatileimage/tst_qvolatileimage.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#ifdef Q_OS_SYMBIAN -#include -#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(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(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/qwmatrix/.gitignore b/tests/auto/qwmatrix/.gitignore deleted file mode 100644 index c983191769..0000000000 --- a/tests/auto/qwmatrix/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qwmatrix diff --git a/tests/auto/qwmatrix/qwmatrix.pro b/tests/auto/qwmatrix/qwmatrix.pro deleted file mode 100644 index bab298bc93..0000000000 --- a/tests/auto/qwmatrix/qwmatrix.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qwmatrix.cpp - -unix:!mac:!symbian:LIBS+=-lm - - diff --git a/tests/auto/qwmatrix/tst_qwmatrix.cpp b/tests/auto/qwmatrix/tst_qwmatrix.cpp deleted file mode 100644 index 0e7372d9d8..0000000000 --- a/tests/auto/qwmatrix/tst_qwmatrix.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -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("matrix"); - QTest::addColumn("src"); - QTest::addColumn("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/qzip/.gitignore b/tests/auto/qzip/.gitignore deleted file mode 100644 index 2d7dfbe70c..0000000000 --- a/tests/auto/qzip/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qzip diff --git a/tests/auto/qzip/qzip.pro b/tests/auto/qzip/qzip.pro deleted file mode 100644 index 683da62e37..0000000000 --- a/tests/auto/qzip/qzip.pro +++ /dev/null @@ -1,11 +0,0 @@ -load(qttest_p4) -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/qzip/testdata/symlink.zip b/tests/auto/qzip/testdata/symlink.zip deleted file mode 100644 index 027f96477a..0000000000 Binary files a/tests/auto/qzip/testdata/symlink.zip and /dev/null differ diff --git a/tests/auto/qzip/testdata/test.zip b/tests/auto/qzip/testdata/test.zip deleted file mode 100644 index a57ba4e2a9..0000000000 Binary files a/tests/auto/qzip/testdata/test.zip and /dev/null differ diff --git a/tests/auto/qzip/tst_qzip.cpp b/tests/auto/qzip/tst_qzip.cpp deleted file mode 100644 index 0955ac069f..0000000000 --- a/tests/auto/qzip/tst_qzip.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -#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 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 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 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 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" -- cgit v1.2.3